111 lines
3.5 KiB
Go
111 lines
3.5 KiB
Go
// Package models defines the core data structures shared across the app.
|
|
// These are plain Go structs — no ORM tags, no magic.
|
|
package models
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// ── Database models (match table columns exactly) ─────────────────────────────
|
|
|
|
type Receipt struct {
|
|
ID uuid.UUID `json:"id"`
|
|
StoreName *string `json:"store_name"`
|
|
ReceiptDate time.Time `json:"receipt_date"`
|
|
ImageURL *string `json:"image_url"`
|
|
City *string `json:"city"`
|
|
SubmittedAt time.Time `json:"submitted_at"`
|
|
}
|
|
|
|
type LineItem struct {
|
|
ID uuid.UUID `json:"id"`
|
|
ReceiptID uuid.UUID `json:"receipt_id"`
|
|
RawName string `json:"raw_name"`
|
|
CanonicalName *string `json:"canonical_name"`
|
|
Category *string `json:"category"`
|
|
PriceCents int `json:"price_cents"`
|
|
Quantity float64 `json:"quantity"`
|
|
}
|
|
|
|
type PriceSnapshot struct {
|
|
CanonicalName string `json:"canonical_name"`
|
|
YearMonth time.Time `json:"year_month"`
|
|
AvgPriceCents int `json:"avg_price_cents"`
|
|
SampleCount int `json:"sample_count"`
|
|
}
|
|
|
|
type PriceMover struct {
|
|
CanonicalName string `json:"canonical_name"`
|
|
CurrentPriceCents int `json:"current_price_cents"`
|
|
PrevPriceCents int `json:"prev_price_cents"`
|
|
PctChange float64 `json:"pct_change"`
|
|
}
|
|
|
|
type InflationSummary struct {
|
|
FromDate time.Time `json:"from_date"`
|
|
ToDate time.Time `json:"to_date"`
|
|
PurchasingPower float64 `json:"purchasing_power"` // e.g. 58.3 means $1 → $0.583
|
|
ItemCount int `json:"item_count"`
|
|
}
|
|
|
|
// ── Insert params (what the API layer passes to db.Queries) ───────────────────
|
|
|
|
type InsertReceiptParams struct {
|
|
StoreName *string
|
|
ReceiptDate time.Time
|
|
ImageURL *string
|
|
City *string
|
|
}
|
|
|
|
type InsertLineItemParams struct {
|
|
ReceiptID uuid.UUID
|
|
RawName string
|
|
CanonicalName *string
|
|
Category *string
|
|
PriceCents int
|
|
Quantity float64
|
|
}
|
|
|
|
// ── API request/response shapes ───────────────────────────────────────────────
|
|
|
|
// SubmitReceiptRequest is the JSON body (or form data) for POST /api/receipts
|
|
type SubmitReceiptRequest struct {
|
|
StoreName string `json:"store_name"`
|
|
ReceiptDate string `json:"receipt_date"` // ISO 8601: "2024-03-15"
|
|
City string `json:"city"`
|
|
Items []ItemInput `json:"items"`
|
|
}
|
|
|
|
type ItemInput struct {
|
|
Name string `json:"name"` // raw name as on the receipt
|
|
Price float64 `json:"price"` // in dollars, e.g. 3.99
|
|
Quantity float64 `json:"quantity"` // default 1
|
|
}
|
|
|
|
// SubmitReceiptResponse is returned after a successful submission
|
|
type SubmitReceiptResponse struct {
|
|
ReceiptID uuid.UUID `json:"receipt_id"`
|
|
ItemsAdded int `json:"items_added"`
|
|
Message string `json:"message"`
|
|
}
|
|
|
|
// PriceHistoryResponse is returned by GET /api/items/:name/history
|
|
type PriceHistoryResponse struct {
|
|
CanonicalName string `json:"canonical_name"`
|
|
DataPoints []PriceDataPoint `json:"data_points"`
|
|
}
|
|
|
|
type PriceDataPoint struct {
|
|
Month string `json:"month"` // "2024-03"
|
|
AvgPrice float64 `json:"avg_price"` // in dollars
|
|
SampleCount int `json:"sample_count"`
|
|
}
|
|
|
|
// ErrorResponse is the standard shape for all API errors
|
|
type ErrorResponse struct {
|
|
Error string `json:"error"`
|
|
Details string `json:"details,omitempty"`
|
|
}
|