package calendar import ( "context" "encoding/json" "time" "github.com/jackc/pgx/v5/pgxpool" ) type HolidayRecord struct { ID string `json:"id"` Date string `json:"date"` Name string `json:"name"` Type string `json:"type"` Source string `json:"source"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } type Store struct { db *pgxpool.Pool } func NewStore(db *pgxpool.Pool) Store { return Store{db: db} } func (s Store) ListHolidaysByYear(ctx context.Context, year int) ([]HolidayRecord, error) { rows, err := s.db.Query(ctx, ` SELECT id::text, date::text, name, type, source, created_at, updated_at FROM holidays WHERE date >= make_date($1, 1, 1) AND date < make_date($1 + 1, 1, 1) ORDER BY date ASC, name ASC `, year) if err != nil { return nil, err } defer rows.Close() holidays := []HolidayRecord{} for rows.Next() { var holiday HolidayRecord if err := rows.Scan( &holiday.ID, &holiday.Date, &holiday.Name, &holiday.Type, &holiday.Source, &holiday.CreatedAt, &holiday.UpdatedAt, ); err != nil { return nil, err } holidays = append(holidays, holiday) } return holidays, rows.Err() } func (s Store) UpsertHolidays(ctx context.Context, source string, holidays []Holiday) error { for _, holiday := range holidays { payload, err := json.Marshal(holiday) if err != nil { return err } if _, err := s.db.Exec(ctx, ` INSERT INTO holidays (date, name, type, source, raw_payload) VALUES ($1, $2, $3, $4, $5::jsonb) ON CONFLICT (date, source, name) DO UPDATE SET type = EXCLUDED.type, raw_payload = EXCLUDED.raw_payload, updated_at = now() `, holiday.Date, holiday.Name, holiday.Type, source, string(payload)); err != nil { return err } } return nil }