Initial commit (unpacked platform)

This commit is contained in:
Sven (AAMOS AI)
2026-08-05 19:21:11 +07:00
commit ac5340195a
314 changed files with 57584 additions and 0 deletions
+79
View File
@@ -0,0 +1,79 @@
import {
boolean,
date,
doublePrecision,
index,
pgTable,
text,
uuid,
integer,
} from "drizzle-orm/pg-core";
import { createdAt, unitEnum } from "./_shared.js";
import { households } from "./households.js";
import { canonicalIngredients } from "./ingredients.js";
import { products } from "./products.js";
/** Kvitton (spec §12): lager + budget + prishistorik + matsvinnsvärde. */
export const receipts = pgTable(
"receipts",
{
id: uuid("id").primaryKey().defaultRandom(),
householdId: uuid("household_id")
.notNull()
.references(() => households.id, { onDelete: "cascade" }),
storeName: text("store_name"),
purchaseDate: date("purchase_date"),
totalMinor: integer("total_minor"),
discountMinor: integer("discount_minor"),
imageUrl: text("image_url"),
scanJobId: uuid("scan_job_id"),
status: text("status").notNull().default("pending"),
createdAt: createdAt(),
},
(t) => [index("receipts_household_idx").on(t.householdId, t.purchaseDate)],
);
export const receiptLines = pgTable(
"receipt_lines",
{
id: uuid("id").primaryKey().defaultRandom(),
receiptId: uuid("receipt_id")
.notNull()
.references(() => receipts.id, { onDelete: "cascade" }),
rawText: text("raw_text").notNull(),
normalizedName: text("normalized_name"),
canonicalIngredientId: text("canonical_ingredient_id").references(
() => canonicalIngredients.id,
),
productId: uuid("product_id").references(() => products.id),
quantity: doublePrecision("quantity"),
unit: unitEnum("unit"),
unitPriceMinor: integer("unit_price_minor"),
totalPriceMinor: integer("total_price_minor"),
confidence: doublePrecision("confidence").notNull().default(0),
verifiedByUser: boolean("verified_by_user").notNull().default(false),
addedToInventory: boolean("added_to_inventory").notNull().default(false),
},
(t) => [index("receipt_lines_receipt_idx").on(t.receiptId)],
);
/** Prishistorik per ingrediens/produkt grund för budget och prognoser (spec §12, §26). */
export const priceObservations = pgTable(
"price_observations",
{
id: uuid("id").primaryKey().defaultRandom(),
canonicalIngredientId: text("canonical_ingredient_id").references(
() => canonicalIngredients.id,
),
productId: uuid("product_id").references(() => products.id),
storeName: text("store_name"),
priceMinor: integer("price_minor").notNull(),
quantity: doublePrecision("quantity"),
unit: unitEnum("unit"),
pricePerKgMinor: integer("price_per_kg_minor"),
observedAt: date("observed_at").notNull(),
source: text("source").notNull().default("receipt"),
createdAt: createdAt(),
},
(t) => [index("price_observations_ingredient_idx").on(t.canonicalIngredientId, t.observedAt)],
);