CREATE TABLE discounts ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), campaign_id UUID NULL, organization_id UUID NOT NULL, code VARCHAR(50) NOT NULL, name VARCHAR(255) NOT NULL, type VARCHAR(20) NOT NULL CHECK (type IN ('percentage', 'fixed_amount', 'free_product')), value DECIMAL(15,2) NOT NULL, min_purchase_qty INT DEFAULT 0, min_purchase_amount DECIMAL(15,2) DEFAULT 0, start_date DATE NOT NULL, end_date DATE NOT NULL, usage_limit_per_customer INT DEFAULT NULL, usage_limit_total INT DEFAULT NULL, usage_count INT DEFAULT 0, customer_type VARCHAR(20) DEFAULT 'all' CHECK (customer_type IN ('all', 'member', 'vip')), is_stackable BOOLEAN DEFAULT FALSE, is_active BOOLEAN DEFAULT TRUE, priority INT DEFAULT 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (campaign_id) REFERENCES campaigns(id) ON DELETE SET NULL, FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE, CONSTRAINT chk_discount_ownership CHECK (campaign_id IS NOT NULL OR organization_id IS NOT NULL), CONSTRAINT unique_code_per_org UNIQUE (organization_id, code) ); CREATE INDEX idx_discounts_campaign ON discounts(campaign_id); CREATE INDEX idx_discounts_organization ON discounts(organization_id); CREATE INDEX idx_discounts_code ON discounts(code); CREATE INDEX idx_discounts_active ON discounts(is_active); CREATE INDEX idx_discounts_dates ON discounts(start_date, end_date); CREATE INDEX idx_discounts_customer_type ON discounts(customer_type); CREATE TABLE discount_outlets ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), discount_id UUID NOT NULL, outlet_id UUID NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (discount_id) REFERENCES discounts(id) ON DELETE CASCADE, FOREIGN KEY (outlet_id) REFERENCES outlets(id) ON DELETE CASCADE, CONSTRAINT unique_discount_outlet UNIQUE (discount_id, outlet_id) ); CREATE INDEX idx_discount_outlets_discount ON discount_outlets(discount_id); CREATE INDEX idx_discount_outlets_outlet ON discount_outlets(outlet_id); CREATE TABLE discount_products ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), discount_id UUID NOT NULL, product_id UUID NOT NULL, rule_type VARCHAR(20) NOT NULL CHECK (rule_type IN ('required', 'free', 'excluded')), quantity INT DEFAULT 1, free_quantity INT DEFAULT 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (discount_id) REFERENCES discounts(id) ON DELETE CASCADE, FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE ); CREATE INDEX idx_discount_products_discount ON discount_products(discount_id); CREATE INDEX idx_discount_products_product ON discount_products(product_id); CREATE TABLE discount_categories ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), discount_id UUID NOT NULL, category_id UUID NOT NULL, rule_type VARCHAR(20) NOT NULL CHECK (rule_type IN ('included', 'excluded')), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (discount_id) REFERENCES discounts(id) ON DELETE CASCADE, FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE ); CREATE INDEX idx_discount_categories_discount ON discount_categories(discount_id); CREATE INDEX idx_discount_categories_category ON discount_categories(category_id); CREATE TABLE order_discounts ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), order_id UUID NOT NULL, outlet_id UUID NOT NULL, discount_id UUID NOT NULL, discount_amount DECIMAL(15,2) NOT NULL, applied_rules JSON, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE, FOREIGN KEY (outlet_id) REFERENCES outlets(id) ON DELETE RESTRICT, FOREIGN KEY (discount_id) REFERENCES discounts(id) ON DELETE RESTRICT ); CREATE INDEX idx_order_discounts_order ON order_discounts(order_id); CREATE INDEX idx_order_discounts_outlet ON order_discounts(outlet_id); CREATE INDEX idx_order_discounts_discount ON order_discounts(discount_id);