// 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"` }