Files
spsays-bff/internal/repository/sadhna_repo.go
T

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()
}