feat(orders): implement order ingestion pipeline, review ratings schema, and [Family] exclusion
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
-- Create order_reviews table
|
||||
CREATE TABLE IF NOT EXISTS order_reviews (
|
||||
id SERIAL PRIMARY KEY,
|
||||
transaction_id INTEGER NOT NULL UNIQUE REFERENCES transactions(id) ON DELETE CASCADE,
|
||||
rating TEXT,
|
||||
order_again BOOLEAN,
|
||||
note TEXT,
|
||||
item_verdicts JSONB NOT NULL DEFAULT '[]',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Add source_message_id to expense_metadata
|
||||
ALTER TABLE expense_metadata ADD COLUMN IF NOT EXISTS source_message_id TEXT;
|
||||
|
||||
-- 1. Admit 'credits' as a payment method.
|
||||
ALTER TABLE transactions DROP CONSTRAINT IF EXISTS transactions_payment_method_check;
|
||||
ALTER TABLE transactions ADD CONSTRAINT transactions_payment_method_check
|
||||
CHECK (payment_method IS NULL OR payment_method IN
|
||||
('card','cash','bank_transfer','credits','other'));
|
||||
|
||||
-- 2. Idempotency key (I7). Partial: rows without an order_reference
|
||||
-- (manual entries) are unaffected.
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS uq_expense_source_order
|
||||
ON expense_metadata (source, order_reference)
|
||||
WHERE order_reference IS NOT NULL;
|
||||
|
||||
-- 3. I1 as a database-level guard, not just workflow logic.
|
||||
-- Scoped to pipeline-created rows so manual/statement rows are untouched.
|
||||
ALTER TABLE transactions DROP CONSTRAINT IF EXISTS chk_ingested_orders_after_cutover;
|
||||
ALTER TABLE transactions ADD CONSTRAINT chk_ingested_orders_after_cutover
|
||||
CHECK (
|
||||
payment_method IS DISTINCT FROM 'credits'
|
||||
OR transaction_date >= DATE '2026-01-09'
|
||||
);
|
||||
|
||||
-- 4. Constrain the review verdict (§6.1).
|
||||
ALTER TABLE order_reviews DROP CONSTRAINT IF EXISTS chk_order_review_rating;
|
||||
ALTER TABLE order_reviews ADD CONSTRAINT chk_order_review_rating
|
||||
CHECK (rating IS NULL OR rating IN ('again','fine','never'));
|
||||
@@ -184,6 +184,7 @@ model transactions {
|
||||
reconciled_with transactions? @relation("reconciled", fields: [reconciled_with_id], references: [id], onDelete: SetNull)
|
||||
reconciled_by transactions[] @relation("reconciled")
|
||||
expense_metadata expense_metadata?
|
||||
order_review order_reviews?
|
||||
}
|
||||
|
||||
model expense_metadata {
|
||||
@@ -193,6 +194,7 @@ model expense_metadata {
|
||||
paperless_doc_id Int? @unique
|
||||
source_email_subject String?
|
||||
source_email_from String?
|
||||
source_message_id String?
|
||||
payment_method String?
|
||||
payment_method_detail String?
|
||||
order_reference String?
|
||||
@@ -205,6 +207,20 @@ model expense_metadata {
|
||||
extraction_model String? @default("gemini-2.5-flash")
|
||||
created_at DateTime? @default(now())
|
||||
transaction transactions? @relation(fields: [transaction_id], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([source, order_reference], name: "uq_expense_source_order")
|
||||
}
|
||||
|
||||
model order_reviews {
|
||||
id Int @id @default(autoincrement())
|
||||
transaction_id Int @unique
|
||||
rating String?
|
||||
order_again Boolean?
|
||||
note String?
|
||||
item_verdicts Json @default("[]")
|
||||
created_at DateTime @default(now())
|
||||
updated_at DateTime @updatedAt
|
||||
transaction transactions @relation(fields: [transaction_id], references: [id], onDelete: Cascade)
|
||||
}
|
||||
|
||||
model rule_apply_runs {
|
||||
|
||||
Reference in New Issue
Block a user