package models import ( "encoding/json" "errors" "log" "time" ) type AbsenceType struct { Id int8 `json:"abwesenheit_id"` Name string `json:"abwesenheit_name"` WorkTime int8 `json:"arbeitszeit_equivalent"` } type Absence struct { Day time.Time CounterId int CardUID string AbwesenheitTyp AbsenceType DateFrom time.Time DateTo time.Time } func NewAbsence(card_uid string, abwesenheit_typ int, datum time.Time) (Absence, error) { if abwesenheit_typ < 0 { return Absence{ CardUID: card_uid, AbwesenheitTyp: AbsenceType{0, "Custom absence", 100}, DateFrom: datum, }, nil } _absenceType, ok := GetAbsenceTypesCached()[int8(abwesenheit_typ)] if !ok { return Absence{}, errors.New("Invalid absencetype") } return Absence{ CardUID: card_uid, AbwesenheitTyp: _absenceType, DateFrom: datum, }, nil } func (a *Absence) Date() time.Time { return a.Day.Truncate(24 * time.Hour) } func (a *Absence) TimeWorkVirtual(u User) time.Duration { return a.TimeWorkReal(u) } func (a *Absence) TimeWorkReal(u User) time.Duration { if a.AbwesenheitTyp.WorkTime > 1 { return time.Duration(u.ArbeitszeitPerTag * float32(time.Hour)).Round(time.Minute) } return 0 } func (a *Absence) TimePauseReal(u User) (work, pause time.Duration) { return 0, 0 } func (a *Absence) TimeOvertimeReal(u User) time.Duration { if a.AbwesenheitTyp.WorkTime > 1 { return 0 } return -u.ArbeitszeitProTag() } func (a *Absence) ToString() string { return "Abwesenheit" } func (a *Absence) IsWorkDay() bool { return false } func (a *Absence) IsKurzArbeit() bool { return false } func (a *Absence) GetDayProgress(u User) int8 { return 100 } func (a *Absence) RequiresAction() bool { return false } func (a *Absence) Insert() error { qStr, err := DB.Prepare(`INSERT INTO abwesenheit (card_uid, abwesenheit_typ, datum_from, datum_to) VALUES ($1, $2, $3, $4) RETURNING counter_id;`) if err != nil { log.Println("Error preparing sql Statement", err) return err } defer qStr.Close() err = qStr.QueryRow(a.CardUID, a.AbwesenheitTyp.Id, a.DateFrom, a.DateTo).Scan(&a.CounterId) if err != nil { log.Println("Error executing insert statement", err) return err } return nil } func GetAbsenceById(counterId int) (Absence, error) { var absence Absence = Absence{CounterId: counterId} qStr, err := DB.Prepare("SELECT card_uid, abwesenheit_typ, datum_from, datum_to FROM abwesenheit WHERE counter_id = $1;") if err != nil { return absence, err } defer qStr.Close() err = qStr.QueryRow(counterId).Scan(&absence.CardUID, &absence.AbwesenheitTyp.Id, &absence.DateFrom, &absence.DateTo) if err != nil { return absence, err } return absence, nil } func GetAbsencesByCardUID(card_uid string, tsFrom time.Time, tsTo time.Time) ([]Absence, error) { var absences []Absence // qStr, err := DB.Prepare(`SELECT counter_id, abwesenheit_typ, datum_from, datum_to FROM abwesenheit WHERE card_uid = $1 AND datum_from <= $2 AND datum_to >= $3 ORDER BY datum_from;`) qStr, err := DB.Prepare(` SELECT ab.counter_id, gs::DATE AS work_date, ab.card_uid, ab.datum_from, ab.datum_to, jsonb_build_object( 'abwesenheit_id', sat.abwesenheit_id, 'abwesenheit_name', sat.abwesenheit_name, 'arbeitszeit_equivalent', sat.arbeitszeit_equivalent ) AS abwesenheit_info FROM generate_series( $2, $3, INTERVAL '1 day' ) gs JOIN abwesenheit ab ON ab.card_uid = $1 AND ab.datum_from::DATE <= gs::DATE AND ab.datum_to::DATE >= gs::DATE LEFT JOIN s_abwesenheit_typen sat ON ab.abwesenheit_typ = sat.abwesenheit_id ORDER BY gs::DATE, ab.counter_id; `) if err != nil { return absences, err } defer qStr.Close() rows, err := qStr.Query(card_uid, tsFrom, tsTo) if err != nil { return absences, err } defer rows.Close() for rows.Next() { var absence Absence var abwesenheitsTyp []byte if err := rows.Scan(&absence.CounterId, &absence.Day, &absence.CardUID, &absence.DateFrom, &absence.DateTo, &abwesenheitsTyp); err != nil { return absences, err } err = json.Unmarshal(abwesenheitsTyp, &absence.AbwesenheitTyp) if err != nil { log.Println("Error parsing abwesenheitsTyp to JSON!", err) return absences, nil } absences = append(absences, absence) } if err = rows.Err(); err != nil { return absences, err } return absences, nil } func GetAbsenceTypes() (map[int8]AbsenceType, error) { var types = make(map[int8]AbsenceType) qStr, err := DB.Prepare("SELECT abwesenheit_id, abwesenheit_name, arbeitszeit_equivalent FROM s_abwesenheit_typen;") if err != nil { return types, err } defer qStr.Close() rows, err := qStr.Query() if err != nil { log.Println("Error getting abwesenheit rows!", err) return types, err } defer rows.Close() for rows.Next() { var absenceType AbsenceType if err := rows.Scan(&absenceType.Id, &absenceType.Name, &absenceType.WorkTime); err != nil { log.Println("Error scanning absence row!", err) } types[absenceType.Id] = absenceType } return types, nil } func GetAbsenceTypesCached() map[int8]AbsenceType { types, err := definedTypes.Get("s_abwesenheit_typen") if err != nil { return map[int8]AbsenceType{} } return types.(map[int8]AbsenceType) } func GetAbsenceTypeById(absenceTypeId int8) (AbsenceType, error) { var absenceType AbsenceType = AbsenceType{Id: absenceTypeId} qStr, err := DB.Prepare("SELECT abwesenheit_name, arbeitszeit_equivalent FROM s_abwesenheit_typen WHERE abwesenheit_id = $1;") if err != nil { return absenceType, err } defer qStr.Close() err = qStr.QueryRow(absenceTypeId).Scan(&absenceType.Name, &absenceType.WorkTime) if err != nil { return absenceType, err } return absenceType, nil }