413 lines
19 KiB
PL/PgSQL
413 lines
19 KiB
PL/PgSQL
-- Migration 00001: Initial Schema for KitchenStock
|
|
|
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
|
|
|
-- Enums
|
|
CREATE TYPE household_role AS ENUM ('OWNER', 'ADMIN', 'MEMBER', 'VIEWER');
|
|
CREATE TYPE aldi_region_type AS ENUM ('NORD', 'SUED', 'UNSPECIFIED');
|
|
CREATE TYPE unit_type AS ENUM ('COUNT', 'WEIGHT', 'VOLUME', 'OTHER');
|
|
CREATE TYPE stock_movement_reason AS ENUM ('PURCHASE', 'CONSUMED', 'CORRECTION', 'INVENTORY', 'EXPIRED', 'DISCARDED', 'TRANSFER', 'INITIAL');
|
|
CREATE TYPE shopping_list_status AS ENUM ('ACTIVE', 'COMPLETED', 'ARCHIVED');
|
|
CREATE TYPE price_type AS ENUM ('REGULAR', 'OFFER', 'LOYALTY', 'UNKNOWN');
|
|
CREATE TYPE source_kind AS ENUM ('USER_PURCHASE', 'USER_ESTIMATE', 'OFFICIAL_RETAILER', 'OFFICIAL_PROSPECT', 'GEMINI_GROUNDED', 'HISTORICAL_AVERAGE', 'AI_ESTIMATE');
|
|
CREATE TYPE confidence_level AS ENUM ('HIGH', 'MEDIUM', 'LOW');
|
|
CREATE TYPE budget_period AS ENUM ('WEEKLY', 'MONTHLY', 'CUSTOM');
|
|
CREATE TYPE inventory_session_status AS ENUM ('OPEN', 'COMPLETED', 'CANCELLED');
|
|
CREATE TYPE diet_type AS ENUM ('OMNIVORE', 'VEGETARIAN', 'VEGAN', 'PESCETARIAN', 'CUSTOM');
|
|
CREATE TYPE pending_action_status AS ENUM ('PENDING', 'CONFIRMED', 'REJECTED', 'EXPIRED');
|
|
|
|
-- Trigger to update updated_at
|
|
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
NEW.updated_at = NOW();
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- 1. Profiles
|
|
CREATE TABLE IF NOT EXISTS public.profiles (
|
|
id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
|
|
display_name TEXT NOT NULL,
|
|
avatar_path TEXT,
|
|
locale TEXT NOT NULL DEFAULT 'de-DE',
|
|
timezone TEXT NOT NULL DEFAULT 'Europe/Berlin',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- 2. Households
|
|
CREATE TABLE IF NOT EXISTS public.households (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
name TEXT NOT NULL,
|
|
currency TEXT NOT NULL DEFAULT 'EUR',
|
|
locale TEXT NOT NULL DEFAULT 'de-DE',
|
|
timezone TEXT NOT NULL DEFAULT 'Europe/Berlin',
|
|
postal_code TEXT,
|
|
city TEXT,
|
|
aldi_region aldi_region_type NOT NULL DEFAULT 'UNSPECIFIED',
|
|
default_servings INT NOT NULL DEFAULT 2 CHECK (default_servings > 0),
|
|
owner_id UUID NOT NULL REFERENCES public.profiles(id) ON DELETE CASCADE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- 3. Household Members
|
|
CREATE TABLE IF NOT EXISTS public.household_members (
|
|
household_id UUID NOT NULL REFERENCES public.households(id) ON DELETE CASCADE,
|
|
user_id UUID NOT NULL REFERENCES public.profiles(id) ON DELETE CASCADE,
|
|
role household_role NOT NULL DEFAULT 'MEMBER',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
PRIMARY KEY (household_id, user_id)
|
|
);
|
|
|
|
-- 4. Categories
|
|
CREATE TABLE IF NOT EXISTS public.categories (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
household_id UUID NOT NULL REFERENCES public.households(id) ON DELETE CASCADE,
|
|
name TEXT NOT NULL,
|
|
icon TEXT,
|
|
sort_order INT NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- 5. Locations (supports nesting)
|
|
CREATE TABLE IF NOT EXISTS public.locations (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
household_id UUID NOT NULL REFERENCES public.households(id) ON DELETE CASCADE,
|
|
parent_location_id UUID REFERENCES public.locations(id) ON DELETE SET NULL,
|
|
name TEXT NOT NULL,
|
|
icon TEXT,
|
|
sort_order INT NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- 6. Units
|
|
CREATE TABLE IF NOT EXISTS public.units (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
household_id UUID REFERENCES public.households(id) ON DELETE CASCADE, -- NULL for system defaults
|
|
name TEXT NOT NULL,
|
|
abbreviation TEXT NOT NULL,
|
|
unit_type unit_type NOT NULL DEFAULT 'COUNT',
|
|
allows_decimals BOOLEAN NOT NULL DEFAULT false,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- 7. Products
|
|
CREATE TABLE IF NOT EXISTS public.products (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
household_id UUID NOT NULL REFERENCES public.households(id) ON DELETE CASCADE,
|
|
category_id UUID REFERENCES public.categories(id) ON DELETE SET NULL,
|
|
default_location_id UUID REFERENCES public.locations(id) ON DELETE SET NULL,
|
|
default_unit_id UUID REFERENCES public.units(id) ON DELETE SET NULL,
|
|
name TEXT NOT NULL,
|
|
brand TEXT,
|
|
description TEXT,
|
|
barcode TEXT,
|
|
image_path TEXT,
|
|
package_size NUMERIC(10, 3) NOT NULL DEFAULT 1.0,
|
|
package_unit TEXT NOT NULL DEFAULT 'Stück',
|
|
minimum_quantity NUMERIC(10, 3) NOT NULL DEFAULT 0.0 CHECK (minimum_quantity >= 0),
|
|
favorite BOOLEAN NOT NULL DEFAULT false,
|
|
preferred_store TEXT,
|
|
estimated_price_cents INT CHECK (estimated_price_cents >= 0),
|
|
price_updated_at TIMESTAMPTZ,
|
|
archived BOOLEAN NOT NULL DEFAULT false,
|
|
created_by UUID REFERENCES public.profiles(id) ON DELETE SET NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- 8. Inventory Batches
|
|
CREATE TABLE IF NOT EXISTS public.inventory_batches (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
household_id UUID NOT NULL REFERENCES public.households(id) ON DELETE CASCADE,
|
|
product_id UUID NOT NULL REFERENCES public.products(id) ON DELETE CASCADE,
|
|
location_id UUID REFERENCES public.locations(id) ON DELETE SET NULL,
|
|
quantity NUMERIC(10, 3) NOT NULL DEFAULT 0.0 CHECK (quantity >= 0),
|
|
expiration_date DATE,
|
|
purchase_date DATE,
|
|
purchase_price_cents INT CHECK (purchase_price_cents >= 0),
|
|
store TEXT,
|
|
lot_number TEXT,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- 9. Stock Movements
|
|
CREATE TABLE IF NOT EXISTS public.stock_movements (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
household_id UUID NOT NULL REFERENCES public.households(id) ON DELETE CASCADE,
|
|
product_id UUID NOT NULL REFERENCES public.products(id) ON DELETE CASCADE,
|
|
batch_id UUID REFERENCES public.inventory_batches(id) ON DELETE SET NULL,
|
|
quantity_before NUMERIC(10, 3) NOT NULL,
|
|
quantity_change NUMERIC(10, 3) NOT NULL,
|
|
quantity_after NUMERIC(10, 3) NOT NULL CHECK (quantity_after >= 0),
|
|
reason stock_movement_reason NOT NULL,
|
|
note TEXT,
|
|
created_by UUID REFERENCES public.profiles(id) ON DELETE SET NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- 10. Shopping Lists
|
|
CREATE TABLE IF NOT EXISTS public.shopping_lists (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
household_id UUID NOT NULL REFERENCES public.households(id) ON DELETE CASCADE,
|
|
name TEXT NOT NULL DEFAULT 'Einkaufsliste',
|
|
status shopping_list_status NOT NULL DEFAULT 'ACTIVE',
|
|
created_by UUID REFERENCES public.profiles(id) ON DELETE SET NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- 11. Shopping List Items
|
|
CREATE TABLE IF NOT EXISTS public.shopping_list_items (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
shopping_list_id UUID NOT NULL REFERENCES public.shopping_lists(id) ON DELETE CASCADE,
|
|
product_id UUID REFERENCES public.products(id) ON DELETE SET NULL,
|
|
custom_name TEXT,
|
|
quantity NUMERIC(10, 3) NOT NULL DEFAULT 1.0 CHECK (quantity > 0),
|
|
unit_id UUID REFERENCES public.units(id) ON DELETE SET NULL,
|
|
estimated_unit_price_cents INT CHECK (estimated_unit_price_cents >= 0),
|
|
selected_store TEXT,
|
|
checked BOOLEAN NOT NULL DEFAULT false,
|
|
automatically_added BOOLEAN NOT NULL DEFAULT false,
|
|
notes TEXT,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- 12. Purchases
|
|
CREATE TABLE IF NOT EXISTS public.purchases (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
household_id UUID NOT NULL REFERENCES public.households(id) ON DELETE CASCADE,
|
|
store TEXT NOT NULL,
|
|
purchase_date TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
total_price_cents INT NOT NULL DEFAULT 0 CHECK (total_price_cents >= 0),
|
|
receipt_image_path TEXT,
|
|
notes TEXT,
|
|
created_by UUID REFERENCES public.profiles(id) ON DELETE SET NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- 13. Purchase Items
|
|
CREATE TABLE IF NOT EXISTS public.purchase_items (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
purchase_id UUID NOT NULL REFERENCES public.purchases(id) ON DELETE CASCADE,
|
|
product_id UUID REFERENCES public.products(id) ON DELETE SET NULL,
|
|
quantity NUMERIC(10, 3) NOT NULL DEFAULT 1.0 CHECK (quantity > 0),
|
|
unit_price_cents INT NOT NULL CHECK (unit_price_cents >= 0),
|
|
total_price_cents INT NOT NULL CHECK (total_price_cents >= 0),
|
|
package_size NUMERIC(10, 3),
|
|
package_unit TEXT,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- 14. Price Observations
|
|
CREATE TABLE IF NOT EXISTS public.price_observations (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
household_id UUID NOT NULL REFERENCES public.households(id) ON DELETE CASCADE,
|
|
product_id UUID REFERENCES public.products(id) ON DELETE SET NULL,
|
|
product_name TEXT NOT NULL,
|
|
brand TEXT,
|
|
package_size NUMERIC(10, 3),
|
|
package_unit TEXT,
|
|
price_cents INT NOT NULL CHECK (price_cents >= 0),
|
|
base_price_cents INT CHECK (base_price_cents >= 0),
|
|
base_price_unit TEXT,
|
|
retailer TEXT NOT NULL,
|
|
price_type price_type NOT NULL DEFAULT 'REGULAR',
|
|
postal_code TEXT,
|
|
region TEXT,
|
|
source_url TEXT,
|
|
source_title TEXT,
|
|
observed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
valid_from DATE,
|
|
valid_until DATE,
|
|
confidence confidence_level NOT NULL DEFAULT 'MEDIUM',
|
|
exact_match BOOLEAN NOT NULL DEFAULT true,
|
|
verified BOOLEAN NOT NULL DEFAULT false,
|
|
source_kind source_kind NOT NULL DEFAULT 'USER_ESTIMATE',
|
|
created_by UUID REFERENCES public.profiles(id) ON DELETE SET NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- 15. Budgets
|
|
CREATE TABLE IF NOT EXISTS public.budgets (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
household_id UUID NOT NULL REFERENCES public.households(id) ON DELETE CASCADE,
|
|
name TEXT NOT NULL,
|
|
period budget_period NOT NULL DEFAULT 'MONTHLY',
|
|
amount_cents INT NOT NULL CHECK (amount_cents >= 0),
|
|
warning_threshold_percent INT NOT NULL DEFAULT 80 CHECK (warning_threshold_percent BETWEEN 1 AND 100),
|
|
start_date DATE NOT NULL,
|
|
end_date DATE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- 16. Inventory Sessions
|
|
CREATE TABLE IF NOT EXISTS public.inventory_sessions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
household_id UUID NOT NULL REFERENCES public.households(id) ON DELETE CASCADE,
|
|
location_id UUID REFERENCES public.locations(id) ON DELETE SET NULL,
|
|
status inventory_session_status NOT NULL DEFAULT 'OPEN',
|
|
started_by UUID REFERENCES public.profiles(id) ON DELETE SET NULL,
|
|
started_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
completed_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- 17. Inventory Session Items
|
|
CREATE TABLE IF NOT EXISTS public.inventory_session_items (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
session_id UUID NOT NULL REFERENCES public.inventory_sessions(id) ON DELETE CASCADE,
|
|
product_id UUID NOT NULL REFERENCES public.products(id) ON DELETE CASCADE,
|
|
expected_quantity NUMERIC(10, 3) NOT NULL DEFAULT 0.0,
|
|
counted_quantity NUMERIC(10, 3) NOT NULL DEFAULT 0.0,
|
|
difference NUMERIC(10, 3) NOT NULL DEFAULT 0.0,
|
|
confirmed BOOLEAN NOT NULL DEFAULT false,
|
|
notes TEXT,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- 18. Dietary Preferences
|
|
CREATE TABLE IF NOT EXISTS public.dietary_preferences (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
household_id UUID NOT NULL UNIQUE REFERENCES public.households(id) ON DELETE CASCADE,
|
|
diet_type diet_type NOT NULL DEFAULT 'OMNIVORE',
|
|
excluded_ingredients TEXT[] NOT NULL DEFAULT '{}',
|
|
allergens TEXT[] NOT NULL DEFAULT '{}',
|
|
preferred_cuisines TEXT[] NOT NULL DEFAULT '{}',
|
|
maximum_preparation_minutes INT,
|
|
maximum_meal_budget_cents INT,
|
|
default_servings INT NOT NULL DEFAULT 2,
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- 19. Recipes
|
|
CREATE TABLE IF NOT EXISTS public.recipes (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
household_id UUID NOT NULL REFERENCES public.households(id) ON DELETE CASCADE,
|
|
title TEXT NOT NULL,
|
|
description TEXT,
|
|
servings INT NOT NULL DEFAULT 2,
|
|
preparation_minutes INT,
|
|
difficulty TEXT,
|
|
estimated_cost_cents INT,
|
|
inventory_coverage_percent INT NOT NULL DEFAULT 0,
|
|
ingredients_json JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
steps_json JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
dietary_tags TEXT[] NOT NULL DEFAULT '{}',
|
|
allergen_warnings TEXT[] NOT NULL DEFAULT '{}',
|
|
source_information_json JSONB,
|
|
created_by_ai BOOLEAN NOT NULL DEFAULT false,
|
|
created_by UUID REFERENCES public.profiles(id) ON DELETE SET NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- 20. Meal Plans
|
|
CREATE TABLE IF NOT EXISTS public.meal_plans (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
household_id UUID NOT NULL REFERENCES public.households(id) ON DELETE CASCADE,
|
|
name TEXT NOT NULL,
|
|
start_date DATE NOT NULL,
|
|
end_date DATE NOT NULL,
|
|
estimated_total_cost_cents INT,
|
|
plan_json JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
created_by UUID REFERENCES public.profiles(id) ON DELETE SET NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- 21. AI Settings
|
|
CREATE TABLE IF NOT EXISTS public.ai_settings (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
household_id UUID NOT NULL UNIQUE REFERENCES public.households(id) ON DELETE CASCADE,
|
|
enabled BOOLEAN NOT NULL DEFAULT true,
|
|
preferred_retailers TEXT[] NOT NULL DEFAULT '{"KAUFLAND", "REWE", "ALDI_NORD", "ALDI_SUED", "LIDL"}',
|
|
allow_google_search BOOLEAN NOT NULL DEFAULT true,
|
|
daily_request_limit INT NOT NULL DEFAULT 30 CHECK (daily_request_limit > 0),
|
|
automatic_price_updates BOOLEAN NOT NULL DEFAULT false,
|
|
price_update_interval_days INT NOT NULL DEFAULT 14 CHECK (price_update_interval_days > 0),
|
|
maximum_products_per_price_request INT NOT NULL DEFAULT 20 CHECK (maximum_products_per_price_request > 0),
|
|
save_chat_history BOOLEAN NOT NULL DEFAULT true,
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- 22. AI Request Logs
|
|
CREATE TABLE IF NOT EXISTS public.ai_request_logs (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
household_id UUID NOT NULL REFERENCES public.households(id) ON DELETE CASCADE,
|
|
user_id UUID REFERENCES public.profiles(id) ON DELETE SET NULL,
|
|
feature TEXT NOT NULL,
|
|
model TEXT NOT NULL,
|
|
grounding_used BOOLEAN NOT NULL DEFAULT false,
|
|
input_token_count INT,
|
|
output_token_count INT,
|
|
latency_ms INT,
|
|
successful BOOLEAN NOT NULL DEFAULT true,
|
|
error_code TEXT,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- 23. AI Pending Actions
|
|
CREATE TABLE IF NOT EXISTS public.ai_pending_actions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
household_id UUID NOT NULL REFERENCES public.households(id) ON DELETE CASCADE,
|
|
user_id UUID NOT NULL REFERENCES public.profiles(id) ON DELETE CASCADE,
|
|
action_type TEXT NOT NULL,
|
|
payload_json JSONB NOT NULL,
|
|
status pending_action_status NOT NULL DEFAULT 'PENDING',
|
|
expires_at TIMESTAMPTZ NOT NULL DEFAULT (NOW() + INTERVAL '24 hours'),
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
confirmed_at TIMESTAMPTZ
|
|
);
|
|
|
|
-- 24. Rate Limit Events
|
|
CREATE TABLE IF NOT EXISTS public.rate_limit_events (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id UUID NOT NULL REFERENCES public.profiles(id) ON DELETE CASCADE,
|
|
action TEXT NOT NULL,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
-- Triggers for updated_at
|
|
CREATE TRIGGER trg_profiles_updated_at BEFORE UPDATE ON public.profiles FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER trg_households_updated_at BEFORE UPDATE ON public.households FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER trg_categories_updated_at BEFORE UPDATE ON public.categories FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER trg_locations_updated_at BEFORE UPDATE ON public.locations FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER trg_products_updated_at BEFORE UPDATE ON public.products FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER trg_inventory_batches_updated_at BEFORE UPDATE ON public.inventory_batches FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER trg_shopping_lists_updated_at BEFORE UPDATE ON public.shopping_lists FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER trg_shopping_list_items_updated_at BEFORE UPDATE ON public.shopping_list_items FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER trg_purchases_updated_at BEFORE UPDATE ON public.purchases FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER trg_budgets_updated_at BEFORE UPDATE ON public.budgets FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER trg_inventory_session_items_updated_at BEFORE UPDATE ON public.inventory_session_items FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER trg_dietary_preferences_updated_at BEFORE UPDATE ON public.dietary_preferences FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER trg_recipes_updated_at BEFORE UPDATE ON public.recipes FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER trg_meal_plans_updated_at BEFORE UPDATE ON public.meal_plans FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER trg_ai_settings_updated_at BEFORE UPDATE ON public.ai_settings FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
|
|
-- Indexes for optimal query performance
|
|
CREATE INDEX idx_household_members_user ON public.household_members(user_id);
|
|
CREATE INDEX idx_products_household ON public.products(household_id);
|
|
CREATE INDEX idx_products_category ON public.products(category_id);
|
|
CREATE INDEX idx_products_location ON public.products(default_location_id);
|
|
CREATE INDEX idx_products_barcode ON public.products(barcode);
|
|
CREATE INDEX idx_inventory_batches_product ON public.inventory_batches(product_id);
|
|
CREATE INDEX idx_inventory_batches_household ON public.inventory_batches(household_id);
|
|
CREATE INDEX idx_inventory_batches_exp ON public.inventory_batches(expiration_date);
|
|
CREATE INDEX idx_stock_movements_product ON public.stock_movements(product_id);
|
|
CREATE INDEX idx_stock_movements_household ON public.stock_movements(household_id);
|
|
CREATE INDEX idx_shopping_list_items_list ON public.shopping_list_items(shopping_list_id);
|
|
CREATE INDEX idx_purchases_household_date ON public.purchases(household_id, purchase_date);
|
|
CREATE INDEX idx_price_observations_product ON public.price_observations(product_id);
|
|
CREATE INDEX idx_price_observations_observed ON public.price_observations(observed_at);
|
|
CREATE INDEX idx_rate_limit_events_user_action ON public.rate_limit_events(user_id, action, created_at);
|