-- ============================================================================= -- MICHANGARRITO - 06 SALES -- ============================================================================= -- Ventas, pagos y cortes de caja -- ============================================================================= -- Ventas CREATE TABLE IF NOT EXISTS sales.sales ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE, ticket_number VARCHAR(20) NOT NULL, subtotal DECIMAL(10,2) NOT NULL, discount_amount DECIMAL(10,2) DEFAULT 0, discount_percent DECIMAL(5,2) DEFAULT 0, tax_amount DECIMAL(10,2) DEFAULT 0, total DECIMAL(10,2) NOT NULL, payment_method VARCHAR(20) NOT NULL, payment_status VARCHAR(20) DEFAULT 'completed', payment_reference TEXT, cash_received DECIMAL(10,2), change_amount DECIMAL(10,2), customer_id UUID, is_fiado BOOLEAN DEFAULT false, fiado_id UUID, created_by UUID REFERENCES auth.users(id), notes TEXT, status VARCHAR(20) DEFAULT 'completed', cancelled_at TIMESTAMPTZ, cancelled_reason TEXT, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX idx_sales_tenant ON sales.sales(tenant_id); CREATE INDEX idx_sales_ticket ON sales.sales(tenant_id, ticket_number); CREATE INDEX idx_sales_date ON sales.sales(tenant_id, created_at); CREATE INDEX idx_sales_customer ON sales.sales(customer_id); CREATE TRIGGER update_sales_updated_at BEFORE UPDATE ON sales.sales FOR EACH ROW EXECUTE FUNCTION update_updated_at(); -- Items de venta CREATE TABLE IF NOT EXISTS sales.sale_items ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), sale_id UUID NOT NULL REFERENCES sales.sales(id) ON DELETE CASCADE, product_id UUID REFERENCES catalog.products(id), product_name VARCHAR(100) NOT NULL, product_sku VARCHAR(50), quantity DECIMAL(10,3) NOT NULL, unit_price DECIMAL(10,2) NOT NULL, discount_amount DECIMAL(10,2) DEFAULT 0, subtotal DECIMAL(10,2) NOT NULL, created_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX idx_sale_items_sale ON sales.sale_items(sale_id); CREATE INDEX idx_sale_items_product ON sales.sale_items(product_id); -- Trigger para actualizar inventario en ventas CREATE TRIGGER update_inventory_on_sale AFTER INSERT ON sales.sale_items FOR EACH ROW EXECUTE FUNCTION inventory.update_stock_on_sale(); -- Pagos CREATE TABLE IF NOT EXISTS sales.payments ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE, sale_id UUID REFERENCES sales.sales(id), fiado_id UUID, subscription_id UUID, method VARCHAR(20) NOT NULL, provider VARCHAR(20), amount DECIMAL(10,2) NOT NULL, fee_amount DECIMAL(10,2) DEFAULT 0, net_amount DECIMAL(10,2), external_id TEXT, external_status VARCHAR(20), receipt_url TEXT, status VARCHAR(20) DEFAULT 'pending', metadata JSONB, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX idx_payments_tenant ON sales.payments(tenant_id); CREATE INDEX idx_payments_sale ON sales.payments(sale_id); CREATE INDEX idx_payments_external ON sales.payments(external_id); CREATE TRIGGER update_payments_updated_at BEFORE UPDATE ON sales.payments FOR EACH ROW EXECUTE FUNCTION update_updated_at(); -- Cortes de caja CREATE TABLE IF NOT EXISTS sales.daily_closures ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE, closure_date DATE NOT NULL, opened_at TIMESTAMPTZ, closed_at TIMESTAMPTZ, expected_cash DECIMAL(10,2) DEFAULT 0, expected_card DECIMAL(10,2) DEFAULT 0, expected_other DECIMAL(10,2) DEFAULT 0, expected_total DECIMAL(10,2) DEFAULT 0, actual_cash DECIMAL(10,2), actual_card DECIMAL(10,2), actual_other DECIMAL(10,2), actual_total DECIMAL(10,2), cash_difference DECIMAL(10,2), total_sales INTEGER DEFAULT 0, total_cancelled INTEGER DEFAULT 0, total_fiados DECIMAL(10,2) DEFAULT 0, closed_by UUID REFERENCES auth.users(id), notes TEXT, status VARCHAR(20) DEFAULT 'open', created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW(), UNIQUE(tenant_id, closure_date) ); CREATE TRIGGER update_daily_closures_updated_at BEFORE UPDATE ON sales.daily_closures FOR EACH ROW EXECUTE FUNCTION update_updated_at();