Marketplace móvil para negocios locales mexicanos. Estructura inicial: - apps/backend (NestJS API) - apps/frontend (React Web) - apps/mobile (Expo/React Native) - apps/mcp-server (Claude MCP Server) - apps/whatsapp-service (WhatsApp Business API) - database/ (PostgreSQL DDL) - docs/ (Documentación) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
149 lines
4.5 KiB
SQL
149 lines
4.5 KiB
SQL
-- =============================================================================
|
|
-- 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();
|