db to user_id
Some checks failed
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Failing after 40s
Some checks failed
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Failing after 40s
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
-- ============================================================================
|
||||
-- 1. Users - This replaces the Supabase `auth.users` table.
|
||||
CREATE TABLE IF NOT EXISTS public.users (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
user_id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
email TEXT NOT NULL UNIQUE,
|
||||
password_hash TEXT,
|
||||
refresh_token TEXT,
|
||||
@@ -23,8 +23,8 @@ CREATE INDEX IF NOT EXISTS idx_users_refresh_token ON public.users(refresh_token
|
||||
-- 2. Log key user activities for analytics.
|
||||
-- This needs to be created early as many triggers will insert into it.
|
||||
CREATE TABLE IF NOT EXISTS public.activity_log (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID REFERENCES public.users(id) ON DELETE SET NULL,
|
||||
activity_log_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID REFERENCES public.users(user_id) ON DELETE SET NULL,
|
||||
action TEXT NOT NULL,
|
||||
display_text TEXT NOT NULL,
|
||||
icon TEXT,
|
||||
@@ -38,32 +38,31 @@ CREATE INDEX IF NOT EXISTS idx_activity_log_user_id ON public.activity_log(user_
|
||||
-- 3. for public user profiles.
|
||||
-- This table is linked to the users table and stores non-sensitive user data.
|
||||
CREATE TABLE IF NOT EXISTS public.profiles (
|
||||
id UUID PRIMARY KEY REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
user_id UUID PRIMARY KEY REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
full_name TEXT,
|
||||
avatar_url TEXT,
|
||||
preferences JSONB,
|
||||
role TEXT CHECK (role IN ('admin', 'user')),
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
created_by UUID REFERENCES public.users(id) ON DELETE SET NULL,
|
||||
updated_by UUID REFERENCES public.users(id) ON DELETE SET NULL
|
||||
created_by UUID REFERENCES public.users(user_id) ON DELETE SET NULL,
|
||||
updated_by UUID REFERENCES public.users(user_id) ON DELETE SET NULL
|
||||
);
|
||||
COMMENT ON TABLE public.profiles IS 'Stores public-facing user data, linked to the public.users table.';
|
||||
|
||||
-- 4. The 'stores' table for normalized store data.
|
||||
CREATE TABLE IF NOT EXISTS public.stores (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
store_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
logo_url TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
created_by UUID REFERENCES public.users(id) ON DELETE SET NULL
|
||||
);
|
||||
created_by UUID REFERENCES public.users(user_id) ON DELETE SET NULL
|
||||
COMMENT ON TABLE public.stores IS 'Stores metadata for grocery store chains (e.g., Safeway, Kroger).';
|
||||
|
||||
-- 5. The 'categories' table for normalized category data.
|
||||
CREATE TABLE IF NOT EXISTS public.categories (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
category_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL
|
||||
@@ -72,11 +71,11 @@ COMMENT ON TABLE public.categories IS 'Stores a predefined list of grocery item
|
||||
|
||||
-- 6. flyers' table
|
||||
CREATE TABLE IF NOT EXISTS public.flyers (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
flyer_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
file_name TEXT NOT NULL,
|
||||
image_url TEXT NOT NULL,
|
||||
checksum TEXT UNIQUE,
|
||||
store_id BIGINT REFERENCES public.stores(id),
|
||||
store_id BIGINT REFERENCES public.stores(store_id),
|
||||
valid_from DATE,
|
||||
valid_to DATE,
|
||||
store_address TEXT,
|
||||
@@ -95,23 +94,23 @@ COMMENT ON COLUMN public.flyers.store_address IS 'The physical store address if
|
||||
|
||||
-- 7. The 'master_grocery_items' table. This is the master dictionary.
|
||||
CREATE TABLE IF NOT EXISTS public.master_grocery_items (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
master_grocery_item_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
category_id BIGINT REFERENCES public.categories(id),
|
||||
category_id BIGINT REFERENCES public.categories(category_id),
|
||||
is_allergen BOOLEAN DEFAULT false,
|
||||
allergy_info JSONB,
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
created_by UUID REFERENCES public.users(id) ON DELETE SET NULL
|
||||
created_by UUID REFERENCES public.users(user_id) ON DELETE SET NULL
|
||||
);
|
||||
COMMENT ON TABLE public.master_grocery_items IS 'The master dictionary of canonical grocery items. Each item has a unique name and is linked to a category.';
|
||||
CREATE INDEX IF NOT EXISTS idx_master_grocery_items_category_id ON public.master_grocery_items(category_id);
|
||||
|
||||
-- 8. The 'user_watched_items' table. This links to the master list.
|
||||
CREATE TABLE IF NOT EXISTS public.user_watched_items (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
master_item_id BIGINT NOT NULL REFERENCES public.master_grocery_items(id) ON DELETE CASCADE,
|
||||
user_watched_item_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID NOT NULL REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
master_item_id BIGINT NOT NULL REFERENCES public.master_grocery_items(master_grocery_item_id) ON DELETE CASCADE,
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
UNIQUE(user_id, master_item_id)
|
||||
@@ -121,19 +120,19 @@ CREATE INDEX IF NOT EXISTS idx_user_watched_items_master_item_id ON public.user_
|
||||
|
||||
-- 9. The 'flyer_items' table. This stores individual items from flyers.
|
||||
CREATE TABLE IF NOT EXISTS public.flyer_items (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
flyer_id BIGINT REFERENCES public.flyers(id) ON DELETE CASCADE,
|
||||
flyer_item_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
flyer_id BIGINT REFERENCES public.flyers(flyer_id) ON DELETE CASCADE,
|
||||
item TEXT NOT NULL,
|
||||
price_display TEXT NOT NULL,
|
||||
price_in_cents INTEGER,
|
||||
quantity_num NUMERIC,
|
||||
quantity TEXT NOT NULL,
|
||||
category_id BIGINT REFERENCES public.categories(id),
|
||||
category_id BIGINT REFERENCES public.categories(category_id),
|
||||
category_name TEXT,
|
||||
unit_price JSONB,
|
||||
view_count INTEGER DEFAULT 0 NOT NULL,
|
||||
click_count INTEGER DEFAULT 0 NOT NULL,
|
||||
master_item_id BIGINT REFERENCES public.master_grocery_items(id),
|
||||
master_item_id BIGINT REFERENCES public.master_grocery_items(master_grocery_item_id),
|
||||
product_id BIGINT,
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL
|
||||
);
|
||||
@@ -159,8 +158,8 @@ CREATE INDEX IF NOT EXISTS flyer_items_item_trgm_idx ON public.flyer_items USING
|
||||
|
||||
-- 10. For user-defined alerts on watched items.
|
||||
CREATE TABLE IF NOT EXISTS public.user_alerts (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_watched_item_id BIGINT NOT NULL REFERENCES public.user_watched_items(id) ON DELETE CASCADE,
|
||||
user_alert_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_watched_item_id BIGINT NOT NULL REFERENCES public.user_watched_items(user_watched_item_id) ON DELETE CASCADE,
|
||||
alert_type TEXT NOT NULL CHECK (alert_type IN ('PRICE_BELOW', 'PERCENT_OFF_AVERAGE')),
|
||||
threshold_value NUMERIC NOT NULL,
|
||||
is_active BOOLEAN DEFAULT true NOT NULL,
|
||||
@@ -174,8 +173,8 @@ CREATE INDEX IF NOT EXISTS idx_user_alerts_user_watched_item_id ON public.user_a
|
||||
|
||||
-- 11. Store notifications for users.
|
||||
CREATE TABLE IF NOT EXISTS public.notifications (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
notification_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID NOT NULL REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
content TEXT NOT NULL,
|
||||
link_url TEXT,
|
||||
is_read BOOLEAN DEFAULT false NOT NULL,
|
||||
@@ -189,8 +188,8 @@ CREATE INDEX IF NOT EXISTS idx_notifications_user_id ON public.notifications(use
|
||||
|
||||
-- 12. Store individual store locations with geographic data.
|
||||
CREATE TABLE IF NOT EXISTS public.store_locations (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
store_id BIGINT NOT NULL REFERENCES public.stores(id) ON DELETE CASCADE,
|
||||
store_location_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
store_id BIGINT NOT NULL REFERENCES public.stores(store_id) ON DELETE CASCADE,
|
||||
address TEXT NOT NULL,
|
||||
city TEXT,
|
||||
province_state TEXT,
|
||||
@@ -208,10 +207,10 @@ CREATE INDEX IF NOT EXISTS store_locations_geo_idx ON public.store_locations USI
|
||||
|
||||
-- 13. For aggregated, historical price data for master items.
|
||||
CREATE TABLE IF NOT EXISTS public.item_price_history (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
master_item_id BIGINT NOT NULL REFERENCES public.master_grocery_items(id) ON DELETE CASCADE,
|
||||
item_price_history_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
master_item_id BIGINT NOT NULL REFERENCES public.master_grocery_items(master_grocery_item_id) ON DELETE CASCADE,
|
||||
summary_date DATE NOT NULL,
|
||||
store_location_id BIGINT REFERENCES public.store_locations(id) ON DELETE CASCADE,
|
||||
store_location_id BIGINT REFERENCES public.store_locations(store_location_id) ON DELETE CASCADE,
|
||||
min_price_in_cents INTEGER,
|
||||
max_price_in_cents INTEGER,
|
||||
avg_price_in_cents INTEGER,
|
||||
@@ -231,8 +230,8 @@ CREATE INDEX IF NOT EXISTS idx_item_price_history_store_location_id ON public.it
|
||||
|
||||
-- 14. Map various names to a single master grocery item.
|
||||
CREATE TABLE IF NOT EXISTS public.master_item_aliases (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
master_item_id BIGINT NOT NULL REFERENCES public.master_grocery_items(id) ON DELETE CASCADE,
|
||||
master_item_alias_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
master_item_id BIGINT NOT NULL REFERENCES public.master_grocery_items(master_grocery_item_id) ON DELETE CASCADE,
|
||||
alias TEXT NOT NULL UNIQUE,
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL
|
||||
@@ -243,8 +242,8 @@ CREATE INDEX IF NOT EXISTS idx_master_item_aliases_master_item_id ON public.mast
|
||||
|
||||
-- 15. For user shopping lists.
|
||||
CREATE TABLE IF NOT EXISTS public.shopping_lists (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
shopping_list_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID NOT NULL REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL
|
||||
@@ -254,9 +253,9 @@ CREATE INDEX IF NOT EXISTS idx_shopping_lists_user_id ON public.shopping_lists(u
|
||||
|
||||
-- 16. For items in a user's shopping list.
|
||||
CREATE TABLE IF NOT EXISTS public.shopping_list_items (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
shopping_list_id BIGINT NOT NULL REFERENCES public.shopping_lists(id) ON DELETE CASCADE,
|
||||
master_item_id BIGINT REFERENCES public.master_grocery_items(id),
|
||||
shopping_list_item_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
shopping_list_id BIGINT NOT NULL REFERENCES public.shopping_lists(shopping_list_id) ON DELETE CASCADE,
|
||||
master_item_id BIGINT REFERENCES public.master_grocery_items(master_grocery_item_id),
|
||||
custom_item_name TEXT,
|
||||
quantity NUMERIC DEFAULT 1 NOT NULL,
|
||||
is_purchased BOOLEAN DEFAULT false NOT NULL,
|
||||
@@ -273,10 +272,10 @@ CREATE INDEX IF NOT EXISTS idx_shopping_list_items_master_item_id ON public.shop
|
||||
|
||||
-- 17. Manage shared access to shopping lists.
|
||||
CREATE TABLE IF NOT EXISTS public.shared_shopping_lists (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
shopping_list_id BIGINT NOT NULL REFERENCES public.shopping_lists(id) ON DELETE CASCADE,
|
||||
shared_by_user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
shared_with_user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
shared_shopping_list_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
shopping_list_id BIGINT NOT NULL REFERENCES public.shopping_lists(shopping_list_id) ON DELETE CASCADE,
|
||||
shared_by_user_id UUID NOT NULL REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
shared_with_user_id UUID NOT NULL REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
permission_level TEXT NOT NULL CHECK (permission_level IN ('view', 'edit')),
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
@@ -289,8 +288,8 @@ CREATE INDEX IF NOT EXISTS idx_shared_shopping_lists_shared_with_user_id ON publ
|
||||
|
||||
-- 18. Store a user's collection of planned meals for a date range.
|
||||
CREATE TABLE IF NOT EXISTS public.menu_plans (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
menu_plan_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID NOT NULL REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
start_date DATE NOT NULL,
|
||||
end_date DATE NOT NULL,
|
||||
@@ -303,10 +302,10 @@ CREATE INDEX IF NOT EXISTS idx_menu_plans_user_id ON public.menu_plans(user_id);
|
||||
|
||||
-- 19. Manage shared access to menu plans.
|
||||
CREATE TABLE IF NOT EXISTS public.shared_menu_plans (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
menu_plan_id BIGINT NOT NULL REFERENCES public.menu_plans(id) ON DELETE CASCADE,
|
||||
shared_by_user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
shared_with_user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
shared_menu_plan_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
menu_plan_id BIGINT NOT NULL REFERENCES public.menu_plans(menu_plan_id) ON DELETE CASCADE,
|
||||
shared_by_user_id UUID NOT NULL REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
shared_with_user_id UUID NOT NULL REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
permission_level TEXT NOT NULL CHECK (permission_level IN ('view', 'edit')),
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
@@ -319,9 +318,9 @@ CREATE INDEX IF NOT EXISTS idx_shared_menu_plans_shared_with_user_id ON public.s
|
||||
|
||||
-- 20. Store user-submitted corrections for flyer items.
|
||||
CREATE TABLE IF NOT EXISTS public.suggested_corrections (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
flyer_item_id BIGINT NOT NULL REFERENCES public.flyer_items(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES public.users(id),
|
||||
suggested_correction_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
flyer_item_id BIGINT NOT NULL REFERENCES public.flyer_items(flyer_item_id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES public.users(user_id),
|
||||
correction_type TEXT NOT NULL,
|
||||
suggested_value TEXT NOT NULL,
|
||||
status TEXT DEFAULT 'pending' NOT NULL,
|
||||
@@ -339,10 +338,10 @@ CREATE INDEX IF NOT EXISTS idx_suggested_corrections_user_id ON public.suggested
|
||||
|
||||
-- 21. For prices submitted directly by users from in-store.
|
||||
CREATE TABLE IF NOT EXISTS public.user_submitted_prices (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID NOT NULL REFERENCES public.users(id),
|
||||
master_item_id BIGINT NOT NULL REFERENCES public.master_grocery_items(id),
|
||||
store_id BIGINT NOT NULL REFERENCES public.stores(id),
|
||||
user_submitted_price_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID NOT NULL REFERENCES public.users(user_id),
|
||||
master_item_id BIGINT NOT NULL REFERENCES public.master_grocery_items(master_grocery_item_id),
|
||||
store_id BIGINT NOT NULL REFERENCES public.stores(store_id),
|
||||
price_in_cents INTEGER NOT NULL,
|
||||
photo_url TEXT,
|
||||
upvotes INTEGER DEFAULT 0 NOT NULL,
|
||||
@@ -358,8 +357,8 @@ CREATE INDEX IF NOT EXISTS idx_user_submitted_prices_master_item_id ON public.us
|
||||
|
||||
-- 22. Log flyer items that could not be automatically matched to a master item.
|
||||
CREATE TABLE IF NOT EXISTS public.unmatched_flyer_items (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
flyer_item_id BIGINT NOT NULL REFERENCES public.flyer_items(id) ON DELETE CASCADE,
|
||||
unmatched_flyer_item_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
flyer_item_id BIGINT NOT NULL REFERENCES public.flyer_items(flyer_item_id) ON DELETE CASCADE,
|
||||
status TEXT DEFAULT 'pending' NOT NULL CHECK (status IN ('pending', 'reviewed', 'ignored')),
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
reviewed_at TIMESTAMPTZ,
|
||||
@@ -371,10 +370,10 @@ CREATE INDEX IF NOT EXISTS idx_unmatched_flyer_items_flyer_item_id ON public.unm
|
||||
|
||||
-- 23. Store brand information.
|
||||
CREATE TABLE IF NOT EXISTS public.brands (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
brand_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
logo_url TEXT,
|
||||
store_id BIGINT REFERENCES public.stores(id) ON DELETE SET NULL,
|
||||
store_id BIGINT REFERENCES public.stores(store_id) ON DELETE SET NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL
|
||||
);
|
||||
@@ -383,9 +382,9 @@ COMMENT ON COLUMN public.brands.store_id IS 'If this is a store-specific brand (
|
||||
|
||||
-- 24. For specific products, linking a master item with a brand and size.
|
||||
CREATE TABLE IF NOT EXISTS public.products (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
master_item_id BIGINT NOT NULL REFERENCES public.master_grocery_items(id),
|
||||
brand_id BIGINT REFERENCES public.brands(id),
|
||||
product_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
master_item_id BIGINT NOT NULL REFERENCES public.master_grocery_items(master_grocery_item_id),
|
||||
brand_id BIGINT REFERENCES public.brands(brand_id),
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
size TEXT,
|
||||
@@ -403,8 +402,8 @@ CREATE INDEX IF NOT EXISTS idx_products_brand_id ON public.products(brand_id);
|
||||
|
||||
-- 25. Linking table for when one flyer is valid for multiple locations.
|
||||
CREATE TABLE IF NOT EXISTS public.flyer_locations (
|
||||
flyer_id BIGINT NOT NULL REFERENCES public.flyers(id) ON DELETE CASCADE,
|
||||
store_location_id BIGINT NOT NULL REFERENCES public.store_locations(id) ON DELETE CASCADE,
|
||||
flyer_id BIGINT NOT NULL REFERENCES public.flyers(flyer_id) ON DELETE CASCADE,
|
||||
store_location_id BIGINT NOT NULL REFERENCES public.store_locations(store_location_id) ON DELETE CASCADE,
|
||||
PRIMARY KEY (flyer_id, store_location_id),
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL
|
||||
@@ -415,9 +414,9 @@ CREATE INDEX IF NOT EXISTS idx_flyer_locations_store_location_id ON public.flyer
|
||||
|
||||
-- 26. Store recipes, which can be user-created or pre-populated.
|
||||
CREATE TABLE IF NOT EXISTS public.recipes (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
original_recipe_id BIGINT REFERENCES public.recipes(id) ON DELETE SET NULL,
|
||||
recipe_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
original_recipe_id BIGINT REFERENCES public.recipes(recipe_id) ON DELETE SET NULL,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
instructions TEXT,
|
||||
@@ -452,9 +451,9 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_recipes_unique_system_recipe_name ON publi
|
||||
|
||||
-- 27. For ingredients required for each recipe.
|
||||
CREATE TABLE IF NOT EXISTS public.recipe_ingredients (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
recipe_id BIGINT NOT NULL REFERENCES public.recipes(id) ON DELETE CASCADE,
|
||||
master_item_id BIGINT NOT NULL REFERENCES public.master_grocery_items(id),
|
||||
recipe_ingredient_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
recipe_id BIGINT NOT NULL REFERENCES public.recipes(recipe_id) ON DELETE CASCADE,
|
||||
master_item_id BIGINT NOT NULL REFERENCES public.master_grocery_items(master_grocery_item_id),
|
||||
quantity NUMERIC NOT NULL,
|
||||
unit TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
@@ -467,9 +466,9 @@ CREATE INDEX IF NOT EXISTS idx_recipe_ingredients_master_item_id ON public.recip
|
||||
|
||||
-- 28. Suggest ingredient substitutions for a recipe.
|
||||
CREATE TABLE IF NOT EXISTS public.recipe_ingredient_substitutions (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
recipe_ingredient_id BIGINT NOT NULL REFERENCES public.recipe_ingredients(id) ON DELETE CASCADE,
|
||||
substitute_master_item_id BIGINT NOT NULL REFERENCES public.master_grocery_items(id) ON DELETE CASCADE,
|
||||
recipe_ingredient_substitution_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
recipe_ingredient_id BIGINT NOT NULL REFERENCES public.recipe_ingredients(recipe_ingredient_id) ON DELETE CASCADE,
|
||||
substitute_master_item_id BIGINT NOT NULL REFERENCES public.master_grocery_items(master_grocery_item_id) ON DELETE CASCADE,
|
||||
notes TEXT,
|
||||
UNIQUE(recipe_ingredient_id, substitute_master_item_id),
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
@@ -481,7 +480,7 @@ CREATE INDEX IF NOT EXISTS idx_recipe_ingredient_substitutions_substitute_master
|
||||
|
||||
-- 29. Store a predefined list of tags for recipes.
|
||||
CREATE TABLE IF NOT EXISTS public.tags (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
tag_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL
|
||||
@@ -490,8 +489,8 @@ COMMENT ON TABLE public.tags IS 'Stores tags for categorizing recipes, e.g., "Ve
|
||||
|
||||
-- 30. Associate multiple tags with a recipe.
|
||||
CREATE TABLE IF NOT EXISTS public.recipe_tags (
|
||||
recipe_id BIGINT NOT NULL REFERENCES public.recipes(id) ON DELETE CASCADE,
|
||||
tag_id BIGINT NOT NULL REFERENCES public.tags(id) ON DELETE CASCADE,
|
||||
recipe_id BIGINT NOT NULL REFERENCES public.recipes(recipe_id) ON DELETE CASCADE,
|
||||
tag_id BIGINT NOT NULL REFERENCES public.tags(tag_id) ON DELETE CASCADE,
|
||||
PRIMARY KEY (recipe_id, tag_id),
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL
|
||||
@@ -502,7 +501,7 @@ CREATE INDEX IF NOT EXISTS idx_recipe_tags_tag_id ON public.recipe_tags(tag_id);
|
||||
|
||||
-- 31. Store a predefined list of kitchen appliances.
|
||||
CREATE TABLE IF NOT EXISTS public.appliances (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
appliance_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL
|
||||
@@ -511,8 +510,8 @@ COMMENT ON TABLE public.appliances IS 'A predefined list of kitchen appliances (
|
||||
|
||||
-- 32. Associate recipes with required appliances.
|
||||
CREATE TABLE IF NOT EXISTS public.recipe_appliances (
|
||||
recipe_id BIGINT NOT NULL REFERENCES public.recipes(id) ON DELETE CASCADE,
|
||||
appliance_id BIGINT NOT NULL REFERENCES public.appliances(id) ON DELETE CASCADE,
|
||||
recipe_id BIGINT NOT NULL REFERENCES public.recipes(recipe_id) ON DELETE CASCADE,
|
||||
appliance_id BIGINT NOT NULL REFERENCES public.appliances(appliance_id) ON DELETE CASCADE,
|
||||
PRIMARY KEY (recipe_id, appliance_id),
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL
|
||||
@@ -523,9 +522,9 @@ CREATE INDEX IF NOT EXISTS idx_recipe_appliances_appliance_id ON public.recipe_a
|
||||
|
||||
-- 33. Store individual user ratings for recipes.
|
||||
CREATE TABLE IF NOT EXISTS public.recipe_ratings (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
recipe_id BIGINT NOT NULL REFERENCES public.recipes(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
recipe_rating_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
recipe_id BIGINT NOT NULL REFERENCES public.recipes(recipe_id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
rating INTEGER NOT NULL CHECK (rating >= 1 AND rating <= 5),
|
||||
comment TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
@@ -538,10 +537,10 @@ CREATE INDEX IF NOT EXISTS idx_recipe_ratings_user_id ON public.recipe_ratings(u
|
||||
|
||||
-- 34. For user comments on recipes to enable discussion.
|
||||
CREATE TABLE IF NOT EXISTS public.recipe_comments (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
recipe_id BIGINT NOT NULL REFERENCES public.recipes(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
parent_comment_id BIGINT REFERENCES public.recipe_comments(id) ON DELETE CASCADE,
|
||||
recipe_comment_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
recipe_id BIGINT NOT NULL REFERENCES public.recipes(recipe_id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
parent_comment_id BIGINT REFERENCES public.recipe_comments(recipe_comment_id) ON DELETE CASCADE,
|
||||
content TEXT NOT NULL,
|
||||
status TEXT DEFAULT 'visible' NOT NULL CHECK (status IN ('visible', 'hidden', 'reported')),
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
@@ -555,8 +554,8 @@ CREATE INDEX IF NOT EXISTS idx_recipe_comments_parent_comment_id ON public.recip
|
||||
|
||||
-- 35. For users to define locations within their pantry.
|
||||
CREATE TABLE IF NOT EXISTS public.pantry_locations (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
pantry_location_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID NOT NULL REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
@@ -567,9 +566,9 @@ CREATE INDEX IF NOT EXISTS idx_pantry_locations_user_id ON public.pantry_locatio
|
||||
|
||||
-- 36. Associate a recipe with a specific date and meal type within a menu plan.
|
||||
CREATE TABLE IF NOT EXISTS public.planned_meals (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
menu_plan_id BIGINT NOT NULL REFERENCES public.menu_plans(id) ON DELETE CASCADE,
|
||||
recipe_id BIGINT NOT NULL REFERENCES public.recipes(id) ON DELETE CASCADE,
|
||||
planned_meal_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
menu_plan_id BIGINT NOT NULL REFERENCES public.menu_plans(menu_plan_id) ON DELETE CASCADE,
|
||||
recipe_id BIGINT NOT NULL REFERENCES public.recipes(recipe_id) ON DELETE CASCADE,
|
||||
plan_date DATE NOT NULL,
|
||||
meal_type TEXT NOT NULL,
|
||||
servings_to_cook INTEGER,
|
||||
@@ -583,13 +582,13 @@ CREATE INDEX IF NOT EXISTS idx_planned_meals_recipe_id ON public.planned_meals(r
|
||||
|
||||
-- 37. Track the grocery items a user currently has in their pantry.
|
||||
CREATE TABLE IF NOT EXISTS public.pantry_items (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
master_item_id BIGINT NOT NULL REFERENCES public.master_grocery_items(id) ON DELETE CASCADE,
|
||||
pantry_item_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID NOT NULL REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
master_item_id BIGINT NOT NULL REFERENCES public.master_grocery_items(master_grocery_item_id) ON DELETE CASCADE,
|
||||
quantity NUMERIC NOT NULL,
|
||||
unit TEXT,
|
||||
best_before_date DATE,
|
||||
pantry_location_id BIGINT REFERENCES public.pantry_locations(id) ON DELETE SET NULL,
|
||||
pantry_location_id BIGINT REFERENCES public.pantry_locations(pantry_location_id) ON DELETE SET NULL,
|
||||
notification_sent_at TIMESTAMPTZ,
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
UNIQUE(user_id, master_item_id, unit)
|
||||
@@ -604,8 +603,8 @@ CREATE INDEX IF NOT EXISTS idx_pantry_items_pantry_location_id ON public.pantry_
|
||||
|
||||
-- 38. Store password reset tokens.
|
||||
CREATE TABLE IF NOT EXISTS public.password_reset_tokens (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
password_reset_token_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID NOT NULL REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
token_hash TEXT NOT NULL UNIQUE,
|
||||
expires_at TIMESTAMPTZ NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
@@ -619,8 +618,8 @@ CREATE INDEX IF NOT EXISTS idx_password_reset_tokens_token_hash ON public.passwo
|
||||
|
||||
-- 39. Store unit conversion factors for specific master grocery items.
|
||||
CREATE TABLE IF NOT EXISTS public.unit_conversions (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
master_item_id BIGINT NOT NULL REFERENCES public.master_grocery_items(id) ON DELETE CASCADE,
|
||||
unit_conversion_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
master_item_id BIGINT NOT NULL REFERENCES public.master_grocery_items(master_grocery_item_id) ON DELETE CASCADE,
|
||||
from_unit TEXT NOT NULL,
|
||||
to_unit TEXT NOT NULL,
|
||||
factor NUMERIC NOT NULL,
|
||||
@@ -634,9 +633,9 @@ CREATE INDEX IF NOT EXISTS idx_unit_conversions_master_item_id ON public.unit_co
|
||||
|
||||
-- 40. For users to create their own private aliases for items.
|
||||
CREATE TABLE IF NOT EXISTS public.user_item_aliases (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
master_item_id BIGINT NOT NULL REFERENCES public.master_grocery_items(id) ON DELETE CASCADE,
|
||||
user_item_alias_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID NOT NULL REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
master_item_id BIGINT NOT NULL REFERENCES public.master_grocery_items(master_grocery_item_id) ON DELETE CASCADE,
|
||||
alias TEXT NOT NULL,
|
||||
UNIQUE(user_id, alias),
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
@@ -648,8 +647,8 @@ CREATE INDEX IF NOT EXISTS idx_user_item_aliases_master_item_id ON public.user_i
|
||||
|
||||
-- 41. For users to mark their favorite recipes.
|
||||
CREATE TABLE IF NOT EXISTS public.favorite_recipes (
|
||||
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
recipe_id BIGINT NOT NULL REFERENCES public.recipes(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
recipe_id BIGINT NOT NULL REFERENCES public.recipes(recipe_id) ON DELETE CASCADE,
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
PRIMARY KEY (user_id, recipe_id),
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL
|
||||
@@ -660,8 +659,8 @@ CREATE INDEX IF NOT EXISTS idx_favorite_recipes_recipe_id ON public.favorite_rec
|
||||
|
||||
-- 42. For users to mark their favorite stores.
|
||||
CREATE TABLE IF NOT EXISTS public.favorite_stores (
|
||||
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
store_id BIGINT NOT NULL REFERENCES public.stores(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
store_id BIGINT NOT NULL REFERENCES public.stores(store_id) ON DELETE CASCADE,
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
PRIMARY KEY (user_id, store_id),
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL
|
||||
@@ -672,8 +671,8 @@ CREATE INDEX IF NOT EXISTS idx_favorite_stores_store_id ON public.favorite_store
|
||||
|
||||
-- 43. For users to group recipes into collections.
|
||||
CREATE TABLE IF NOT EXISTS public.recipe_collections (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
recipe_collection_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID NOT NULL REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
@@ -684,8 +683,8 @@ CREATE INDEX IF NOT EXISTS idx_recipe_collections_user_id ON public.recipe_colle
|
||||
|
||||
-- 44. Associate recipes with a user's collection.
|
||||
CREATE TABLE IF NOT EXISTS public.recipe_collection_items (
|
||||
collection_id BIGINT NOT NULL REFERENCES public.recipe_collections(id) ON DELETE CASCADE,
|
||||
recipe_id BIGINT NOT NULL REFERENCES public.recipes(id) ON DELETE CASCADE,
|
||||
collection_id BIGINT NOT NULL REFERENCES public.recipe_collections(recipe_collection_id) ON DELETE CASCADE,
|
||||
recipe_id BIGINT NOT NULL REFERENCES public.recipes(recipe_id) ON DELETE CASCADE,
|
||||
added_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
PRIMARY KEY (collection_id, recipe_id),
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL
|
||||
@@ -696,8 +695,8 @@ CREATE INDEX IF NOT EXISTS idx_recipe_collection_items_recipe_id ON public.recip
|
||||
|
||||
-- 45. Log user search queries for analysis.
|
||||
CREATE TABLE IF NOT EXISTS public.search_queries (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID REFERENCES public.users(id) ON DELETE SET NULL,
|
||||
search_query_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID REFERENCES public.users(user_id) ON DELETE SET NULL,
|
||||
query_text TEXT NOT NULL,
|
||||
result_count INTEGER,
|
||||
was_successful BOOLEAN,
|
||||
@@ -710,9 +709,9 @@ CREATE INDEX IF NOT EXISTS idx_search_queries_user_id ON public.search_queries(u
|
||||
|
||||
-- 46. Store historical records of completed shopping trips.
|
||||
CREATE TABLE IF NOT EXISTS public.shopping_trips (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
shopping_list_id BIGINT REFERENCES public.shopping_lists(id) ON DELETE SET NULL,
|
||||
shopping_trip_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID NOT NULL REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
shopping_list_id BIGINT REFERENCES public.shopping_lists(shopping_list_id) ON DELETE SET NULL,
|
||||
completed_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
total_spent_cents INTEGER,
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL
|
||||
@@ -724,9 +723,9 @@ CREATE INDEX IF NOT EXISTS idx_shopping_trips_shopping_list_id ON public.shoppin
|
||||
|
||||
-- 47. Store the items purchased during a specific shopping trip.
|
||||
CREATE TABLE IF NOT EXISTS public.shopping_trip_items (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
shopping_trip_id BIGINT NOT NULL REFERENCES public.shopping_trips(id) ON DELETE CASCADE,
|
||||
master_item_id BIGINT REFERENCES public.master_grocery_items(id),
|
||||
shopping_trip_item_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
shopping_trip_id BIGINT NOT NULL REFERENCES public.shopping_trips(shopping_trip_id) ON DELETE CASCADE,
|
||||
master_item_id BIGINT REFERENCES public.master_grocery_items(master_grocery_item_id),
|
||||
custom_item_name TEXT,
|
||||
quantity NUMERIC NOT NULL,
|
||||
price_paid_cents INTEGER,
|
||||
@@ -741,7 +740,7 @@ CREATE INDEX IF NOT EXISTS idx_shopping_trip_items_master_item_id ON public.shop
|
||||
|
||||
-- 48. Store predefined dietary restrictions (diets and allergies).
|
||||
CREATE TABLE IF NOT EXISTS public.dietary_restrictions (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
dietary_restriction_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
type TEXT NOT NULL CHECK (type IN ('diet', 'allergy')),
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
@@ -751,8 +750,8 @@ COMMENT ON TABLE public.dietary_restrictions IS 'A predefined list of common die
|
||||
|
||||
-- 49. For a user's specific dietary restrictions.
|
||||
CREATE TABLE IF NOT EXISTS public.user_dietary_restrictions (
|
||||
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
restriction_id BIGINT NOT NULL REFERENCES public.dietary_restrictions(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
restriction_id BIGINT NOT NULL REFERENCES public.dietary_restrictions(dietary_restriction_id) ON DELETE CASCADE,
|
||||
PRIMARY KEY (user_id, restriction_id),
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL
|
||||
@@ -763,8 +762,8 @@ CREATE INDEX IF NOT EXISTS idx_user_dietary_restrictions_restriction_id ON publi
|
||||
|
||||
-- 50. For a user's owned kitchen appliances.
|
||||
CREATE TABLE IF NOT EXISTS public.user_appliances (
|
||||
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
appliance_id BIGINT NOT NULL REFERENCES public.appliances(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
appliance_id BIGINT NOT NULL REFERENCES public.appliances(appliance_id) ON DELETE CASCADE,
|
||||
PRIMARY KEY (user_id, appliance_id),
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL
|
||||
@@ -775,8 +774,8 @@ CREATE INDEX IF NOT EXISTS idx_user_appliances_appliance_id ON public.user_appli
|
||||
|
||||
-- 51. Manage the social graph (following relationships).
|
||||
CREATE TABLE IF NOT EXISTS public.user_follows (
|
||||
follower_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
following_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
follower_id UUID NOT NULL REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
following_id UUID NOT NULL REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
PRIMARY KEY (follower_id, following_id),
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
@@ -788,9 +787,9 @@ CREATE INDEX IF NOT EXISTS idx_user_follows_following_id ON public.user_follows(
|
||||
|
||||
-- 52. Store uploaded user receipts for purchase tracking and analysis.
|
||||
CREATE TABLE IF NOT EXISTS public.receipts (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
||||
store_id BIGINT REFERENCES public.stores(id),
|
||||
receipt_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
user_id UUID NOT NULL REFERENCES public.users(user_id) ON DELETE CASCADE,
|
||||
store_id BIGINT REFERENCES public.stores(store_id),
|
||||
receipt_image_url TEXT NOT NULL,
|
||||
transaction_date TIMESTAMPTZ,
|
||||
total_amount_cents INTEGER,
|
||||
@@ -806,13 +805,13 @@ CREATE INDEX IF NOT EXISTS idx_receipts_store_id ON public.receipts(store_id);
|
||||
|
||||
-- 53. Store individual line items extracted from a user receipt.
|
||||
CREATE TABLE IF NOT EXISTS public.receipt_items (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
receipt_id BIGINT NOT NULL REFERENCES public.receipts(id) ON DELETE CASCADE,
|
||||
receipt_item_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
receipt_id BIGINT NOT NULL REFERENCES public.receipts(receipt_id) ON DELETE CASCADE,
|
||||
raw_item_description TEXT NOT NULL,
|
||||
quantity NUMERIC DEFAULT 1 NOT NULL,
|
||||
price_paid_cents INTEGER NOT NULL,
|
||||
master_item_id BIGINT REFERENCES public.master_grocery_items(id),
|
||||
product_id BIGINT REFERENCES public.products(id),
|
||||
master_item_id BIGINT REFERENCES public.master_grocery_items(master_grocery_item_id),
|
||||
product_id BIGINT REFERENCES public.products(product_id),
|
||||
status TEXT DEFAULT 'unmatched' NOT NULL CHECK (status IN ('unmatched', 'matched', 'needs_review', 'ignored')),
|
||||
created_at TIMESTAMPTZ DEFAULT now() NOT NULL,
|
||||
updated_at TIMESTAMPTZ DEFAULT now() NOT NULL
|
||||
|
||||
Reference in New Issue
Block a user