68 lines
2.5 KiB
Go
68 lines
2.5 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/prabhupadasays/spsays-bff/internal/model"
|
|
)
|
|
|
|
// SadhnaRepo wraps Postgres access for sadhna_logs — the chanting half of
|
|
// a day's sādhana. The posting half lives in the posts table and is read
|
|
// via PostRepo.PostedDates, so this repo stays small.
|
|
type SadhnaRepo struct{ pg *Postgres }
|
|
|
|
func NewSadhnaRepo(pg *Postgres) *SadhnaRepo { return &SadhnaRepo{pg: pg} }
|
|
|
|
// UpsertToday records (or updates) the given day's chanting progress for
|
|
// the user. The caller passes the UTC calendar date explicitly (rather
|
|
// than relying on the DB's CURRENT_DATE) so day bucketing stays identical
|
|
// to PostedDates' `AT TIME ZONE 'UTC'`. chantDone is decided by the caller
|
|
// — rounds_completed >= the user's current target — and frozen into the
|
|
// row so later target changes don't rewrite past days. Returns the row.
|
|
func (r *SadhnaRepo) UpsertToday(ctx context.Context, userID string, logDate time.Time, rounds int, chantDone bool) (*model.SadhnaLog, error) {
|
|
var l model.SadhnaLog
|
|
err := r.pg.Pool.QueryRow(ctx, `
|
|
INSERT INTO sadhna_logs (user_id, log_date, rounds_completed, chant_done)
|
|
VALUES ($1, $2, $3, $4)
|
|
ON CONFLICT (user_id, log_date) DO UPDATE
|
|
SET rounds_completed = EXCLUDED.rounds_completed,
|
|
chant_done = EXCLUDED.chant_done,
|
|
updated_at = now()
|
|
RETURNING id, user_id, log_date, rounds_completed, chant_done, created_at, updated_at`,
|
|
userID, logDate, rounds, chantDone,
|
|
).Scan(&l.ID, &l.UserID, &l.LogDate, &l.RoundsCompleted, &l.ChantDone, &l.CreatedAt, &l.UpdatedAt)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("upsert sadhna log: %w", err)
|
|
}
|
|
return &l, nil
|
|
}
|
|
|
|
// ListSince returns the user's sadhna logs on or after `since`, newest
|
|
// first. The window bounds the streak/growth computation; a few hundred
|
|
// rows at most.
|
|
func (r *SadhnaRepo) ListSince(ctx context.Context, userID string, since time.Time) ([]model.SadhnaLog, error) {
|
|
rows, err := r.pg.Pool.Query(ctx, `
|
|
SELECT id, user_id, log_date, rounds_completed, chant_done, created_at, updated_at
|
|
FROM sadhna_logs
|
|
WHERE user_id = $1 AND log_date >= $2
|
|
ORDER BY log_date DESC`,
|
|
userID, since,
|
|
)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("list sadhna logs: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
var out []model.SadhnaLog
|
|
for rows.Next() {
|
|
var l model.SadhnaLog
|
|
if err := rows.Scan(&l.ID, &l.UserID, &l.LogDate, &l.RoundsCompleted, &l.ChantDone, &l.CreatedAt, &l.UpdatedAt); err != nil {
|
|
return nil, fmt.Errorf("scan sadhna log: %w", err)
|
|
}
|
|
out = append(out, l)
|
|
}
|
|
return out, rows.Err()
|
|
}
|