From bd7d5dd1b2a2723894e5b8dd24c6093d8651f83b Mon Sep 17 00:00:00 2001 From: DanielS Date: Thu, 9 Jul 2026 21:49:50 +0200 Subject: [PATCH] db: create core schema for products, categories, global rules and orders --- .../20260709220000_consolidated_schema.sql | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 shop/supabase/migrations/20260709220000_consolidated_schema.sql diff --git a/shop/supabase/migrations/20260709220000_consolidated_schema.sql b/shop/supabase/migrations/20260709220000_consolidated_schema.sql new file mode 100644 index 0000000..fdc00da --- /dev/null +++ b/shop/supabase/migrations/20260709220000_consolidated_schema.sql @@ -0,0 +1,107 @@ +-- Migration: Consolidated Schema for CASPOS +-- Purpose: Complete definition of core webshop structures, global rules, and order split support. + +CREATE TABLE IF NOT EXISTS public.companies ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + name TEXT NOT NULL, + street TEXT, + zip TEXT, + city TEXT, + email TEXT, + created_at TIMESTAMPTZ DEFAULT now() +); + +CREATE TABLE IF NOT EXISTS public.users ( + id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE, + role TEXT NOT NULL DEFAULT 'partner' CHECK (role IN ('partner', 'admin')), + company_id UUID REFERENCES public.companies(id) ON DELETE SET NULL, + created_at TIMESTAMPTZ DEFAULT now() +); + +CREATE TABLE IF NOT EXISTS public.end_customers ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + partner_id UUID REFERENCES public.companies(id) ON DELETE CASCADE, + company_name TEXT, + first_name TEXT, + last_name TEXT, + street TEXT, + zip TEXT, + city TEXT, + email TEXT, + bank_iban TEXT, + bank_bic TEXT, + bank_name TEXT, + bank_owner TEXT, + is_anonymized BOOLEAN DEFAULT false NOT NULL, + created_at TIMESTAMPTZ DEFAULT now() +); + +CREATE TABLE IF NOT EXISTS public.categories ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + name TEXT NOT NULL, + is_required BOOLEAN DEFAULT false NOT NULL, + allow_multiple BOOLEAN DEFAULT false NOT NULL, + sort_order INTEGER DEFAULT 0 NOT NULL, + show_in_branches BOOLEAN DEFAULT true NOT NULL, + preselect BOOLEAN DEFAULT false NOT NULL, + resets_others BOOLEAN DEFAULT false NOT NULL, + created_at TIMESTAMPTZ DEFAULT now() +); + +CREATE TABLE IF NOT EXISTS public.products ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + category_id UUID REFERENCES public.categories(id) ON DELETE RESTRICT, + name TEXT NOT NULL, + base_price DECIMAL(10,2) DEFAULT 0.00 NOT NULL, + tax_rate DECIMAL(5,2) DEFAULT 19.00 NOT NULL, + billing_interval TEXT DEFAULT 'monthly' NOT NULL CHECK (billing_interval IN ('one_time', 'monthly')), + show_in_branches BOOLEAN DEFAULT true NOT NULL, + created_at TIMESTAMPTZ DEFAULT now() +); + +CREATE TABLE IF NOT EXISTS public.modules ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + product_id UUID REFERENCES public.products(id) ON DELETE CASCADE, + category_id UUID REFERENCES public.categories(id) ON DELETE RESTRICT, + name TEXT NOT NULL, + price DECIMAL(10,2) DEFAULT 0.00 NOT NULL, + has_quantity BOOLEAN DEFAULT false NOT NULL, + created_at TIMESTAMPTZ DEFAULT now() +); + +CREATE TABLE IF NOT EXISTS public.global_inclusions ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + trigger_product_id UUID NOT NULL REFERENCES public.products(id) ON DELETE CASCADE, + included_module_id UUID NOT NULL REFERENCES public.modules(id) ON DELETE CASCADE, + created_at TIMESTAMPTZ DEFAULT now(), + UNIQUE (trigger_product_id, included_module_id) +); + +CREATE TABLE IF NOT EXISTS public.global_exclusions ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + product_id UUID NOT NULL REFERENCES public.products(id) ON DELETE CASCADE, + excluded_product_id UUID REFERENCES public.products(id) ON DELETE CASCADE, + excluded_module_id UUID REFERENCES public.modules(id) ON DELETE CASCADE, + created_at TIMESTAMPTZ DEFAULT now(), + CHECK ( + (excluded_product_id IS NOT NULL AND excluded_module_id IS NULL) OR + (excluded_product_id IS NULL AND excluded_module_id IS NOT NULL) + ) +); + +CREATE TABLE IF NOT EXISTS public.orders ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + user_id UUID REFERENCES auth.users(id) ON DELETE SET NULL, + company_id UUID REFERENCES public.companies(id) ON DELETE RESTRICT, + end_customer_id UUID REFERENCES public.end_customers(id) ON DELETE RESTRICT, + order_number TEXT NOT NULL UNIQUE, + order_hash TEXT, + type TEXT NOT NULL CHECK (type IN ('purchase', 'subscription')), + payment_method TEXT NOT NULL, + total_price DECIMAL(10,2) DEFAULT 0.00 NOT NULL, + customer_snapshot JSONB NOT NULL, + order_snapshot JSONB NOT NULL, + pdf_url TEXT, + status TEXT DEFAULT 'pending' NOT NULL CHECK (status IN ('pending', 'active', 'completed', 'cancelled')), + created_at TIMESTAMPTZ DEFAULT now() +);