package themis import ( "context" "fmt" "time" "github.com/rs/zerolog/log" ) func (s *Store) AddAbsence(ctx context.Context, session time.Time, userId string) error { if session.Weekday() != time.Monday { log.Debug().Msg(fmt.Sprintf("%s is not a monday", session)) return fmt.Errorf("not a monday") } defer s.Audit(&AuditableEvent{ userId: userId, eventType: EventAbsence, }) tx, err := s.db.Begin() if err != nil { return fmt.Errorf("failed to begin transaction: %w", err) } defer tx.Commit() //nolint:errcheck stmt, err := s.db.PrepareContext(ctx, "INSERT INTO absences (session_date, userid) VALUES (?, ?)") if err != nil { return fmt.Errorf("failed to prepare absence query: %w", err) } _, err = stmt.ExecContext(ctx, session.Format(time.DateOnly), userId) if err != nil { return fmt.Errorf("failed to insert absence: %w", err) } return nil } func (s *Store) GetAbsentees(ctx context.Context, session time.Time) ([]string, error) { log.Debug().Time("session", session).Msg("getting list of absentees") tx, err := s.db.Begin() if err != nil { return nil, fmt.Errorf("failed to begin transaction: %w", err) } defer tx.Commit() //nolint:errcheck stmt, err := s.db.PrepareContext(ctx, `SELECT userid FROM absences WHERE session_date = ?`) if err != nil { return nil, fmt.Errorf("failed to prepare query: %w", err) } rows, err := stmt.QueryContext(ctx, session.Format(time.DateOnly)) if err != nil { return nil, fmt.Errorf("failed to execute query: %w", err) } absentees := make([]string, 0) for rows.Next() { var abs string err = rows.Scan(&abs) if err != nil { return nil, fmt.Errorf("failed to scan row: %w", err) } absentees = append(absentees, abs) } return absentees, nil } // map session_date -> list of absentees type Schedule map[string][]string func (s *Store) GetSchedule(ctx context.Context, from, to time.Time) (Schedule, error) { log.Debug().Time("from", from).Time("to", to).Msg("getting next sessions schedule") schedule := make(Schedule) initSchedule(schedule, from, to) tx, err := s.db.Begin() if err != nil { return nil, fmt.Errorf("failed to begin transaction: %w", err) } defer tx.Commit() //nolint:errcheck stmt, err := s.db.PrepareContext(ctx, `SELECT session_date, userid FROM absences WHERE session_date BETWEEN ? AND ? ORDER BY session_date ASC`) if err != nil { return nil, fmt.Errorf("failed to prepare query: %w", err) } rows, err := stmt.QueryContext(ctx, from.Format(time.DateOnly), to.Format(time.DateOnly)) if err != nil { return nil, fmt.Errorf("failed to execute query: %w", err) } for rows.Next() { var date string var user string err = rows.Scan(&date, &user) if err != nil { return nil, fmt.Errorf("failed to scan row: %w", err) } if _, ok := schedule[date]; ok { schedule[date] = append(schedule[date], user) } else { schedule[date] = []string{user} } } return schedule, nil } func initSchedule(schedule Schedule, from, to time.Time) { for from.Before(to) || from.Equal(to) { schedule[from.Format(time.DateOnly)] = []string{} from = from.AddDate(0, 0, 7) } }