ProofedMesh/services/admin-api/internal/store/store.go
CTO Agent 65514559dc
Some checks failed
validate / Rego (opa fmt + opa test) (push) Successful in 12s
validate / JSON Schema (ajv) (push) Has been cancelled
services: add admin-api Go service (per-diem rates CRUD, in-memory + Postgres stub store, HTML templates, 13/13 go tests pass, go vet clean)
2026-10-25 17:28:14 +00:00

50 lines
2.2 KiB
Go

// Package store abstracts the per_diem_rates storage so the HTTP layer can be
// tested without a real Postgres and so the Postgres backend can be swapped
// against an in-memory fake for dev loops.
package store
import (
"context"
"errors"
"time"
"basicstack.de/proofedmesh/services/admin-api/internal/model"
)
// ErrNotFound is returned by Get and Retire when the rate_id does not exist.
var ErrNotFound = errors.New("per_diem_rate: not found")
// ErrOverlap is returned by Create when the new rate would overlap an existing
// (country, city) range. Mirrors the Postgres EXCLUDE constraint.
var ErrOverlap = errors.New("per_diem_rate: overlaps an existing active range for (country, city)")
// ErrAlreadyRetired is returned by Retire when the rate is already retired
// (valid_to IS NOT NULL and in the past).
var ErrAlreadyRetired = errors.New("per_diem_rate: already retired")
// ListFilter narrows a List call. Zero value lists everything.
type ListFilter struct {
Country string // "" = any
ActiveOnly bool // if true, only rates with valid_to IS NULL or valid_to >= today
}
// RateStore is implemented by both the in-memory store (for tests + dev) and
// the Postgres store (for prod). All methods are side-effect-free apart from
// their obvious effect and all honour ctx cancellation.
type RateStore interface {
List(ctx context.Context, f ListFilter) ([]model.Rate, error)
Get(ctx context.Context, rateID string) (model.Rate, error)
// Create inserts a new rate, returning the finalised row (rate_id is
// assigned by the backend). The attestation ref is set later via
// AttachAttestation when the Signing Service has produced it.
Create(ctx context.Context, in model.NewRateInput, createdBy string, now time.Time) (model.Rate, error)
// Retire sets valid_to on the rate; subsequent lookups by valid_on past
// that date must not return it.
Retire(ctx context.Context, rateID string, validTo time.Time, performedBy string, now time.Time) (model.Rate, error)
// AttachAttestation attaches the signed attestation reference to a rate.
// Called after Create or Retire once the Signing Service responded.
AttachAttestation(ctx context.Context, rateID string, attestationRef string) error
}