initial boilerplate
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
// 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"`
|
||||
}
|
||||
Reference in New Issue
Block a user