init
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
-- Phase 2: topic-based wantlists + items
|
||||
-- A "list" is a topic (clothes, gear, …). An "item" is a thing the user covets,
|
||||
-- usually backed by a pasted product URL. Price/metadata columns are filled by the
|
||||
-- Phase 3 refetch worker (generic Shopify .json adapter, etc.) and stay NULL until then.
|
||||
|
||||
CREATE TABLE lists (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
emoji TEXT, -- optional decorative glyph
|
||||
description TEXT,
|
||||
position INTEGER NOT NULL DEFAULT 0, -- manual ordering
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_lists_user ON lists(user_id);
|
||||
|
||||
CREATE TYPE item_status AS ENUM ('coveted', 'acquired', 'renounced');
|
||||
|
||||
CREATE TABLE items (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
list_id UUID NOT NULL REFERENCES lists(id) ON DELETE CASCADE,
|
||||
title TEXT NOT NULL,
|
||||
url TEXT, -- pasted product URL (Phase 3 tracks this)
|
||||
note TEXT,
|
||||
status item_status NOT NULL DEFAULT 'coveted',
|
||||
target_price NUMERIC(12, 2), -- alert threshold the user sets
|
||||
position INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
-- Filled by the Phase 3 fetcher; NULL until first successful fetch.
|
||||
title_fetched TEXT,
|
||||
current_price NUMERIC(12, 2),
|
||||
currency TEXT, -- ISO 4217, e.g. 'EUR'
|
||||
image_url TEXT,
|
||||
in_stock BOOLEAN,
|
||||
source TEXT, -- adapter that produced the data, e.g. 'shopify'
|
||||
fetched_at TIMESTAMPTZ,
|
||||
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_items_list ON items(list_id);
|
||||
CREATE INDEX idx_items_url ON items(url) WHERE url IS NOT NULL;
|
||||
|
||||
CREATE TRIGGER trg_lists_updated
|
||||
BEFORE UPDATE ON lists
|
||||
FOR EACH ROW EXECUTE FUNCTION set_updated_at();
|
||||
|
||||
CREATE TRIGGER trg_items_updated
|
||||
BEFORE UPDATE ON items
|
||||
FOR EACH ROW EXECUTE FUNCTION set_updated_at();
|
||||
@@ -0,0 +1,25 @@
|
||||
-- Phase 3: price tracking. The refetch worker pulls product data for items that
|
||||
-- carry a URL (generic Shopify .json adapter first), updates the item's metadata
|
||||
-- columns, and appends a row to price_history on every successful fetch.
|
||||
|
||||
-- Per-item tracking control + last fetch outcome.
|
||||
ALTER TABLE items
|
||||
ADD COLUMN track_enabled BOOLEAN NOT NULL DEFAULT true,
|
||||
ADD COLUMN last_error TEXT,
|
||||
ADD COLUMN checked_at TIMESTAMPTZ; -- last fetch attempt (success or failure)
|
||||
|
||||
-- Append-only price observations. One row per successful fetch.
|
||||
CREATE TABLE price_history (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
item_id UUID NOT NULL REFERENCES items(id) ON DELETE CASCADE,
|
||||
price NUMERIC(12, 2) NOT NULL,
|
||||
currency TEXT NOT NULL,
|
||||
in_stock BOOLEAN,
|
||||
fetched_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_price_history_item ON price_history(item_id, fetched_at DESC);
|
||||
|
||||
-- Worker scan: trackable items that have a URL, cheapest checked first.
|
||||
CREATE INDEX idx_items_trackable ON items(checked_at NULLS FIRST)
|
||||
WHERE url IS NOT NULL AND track_enabled;
|
||||
@@ -0,0 +1,6 @@
|
||||
-- Phase 4: price-drop notifications.
|
||||
-- Tracks when we last emailed the owner that an item reached its target price.
|
||||
-- NULL = "armed": a future drop to/under target will notify. Stamped non-NULL
|
||||
-- after sending; cleared (re-armed) when the price rises back above target.
|
||||
ALTER TABLE items
|
||||
ADD COLUMN notified_at TIMESTAMPTZ;
|
||||
Reference in New Issue
Block a user