michangarrito/database/schemas/02-functions.sql
rckrdmrd 5a49ad0185 [INTEGRATION] feat: Integrate template-saas scopes and database objects
## Documentation
- Align MCH-029 to MCH-032 with template-saas modules (SAAS-008 to SAAS-015)
- Create MCH-034 (Analytics) and MCH-035 (Reports) from SAAS-016/017
- Update PLAN-DESARROLLO.md with Phase 7 and 8
- Update _MAP.md indexes (35 total epics)

## Database (5 new schemas, 14 tables)
- Add storage schema: buckets, files, signed_urls
- Add webhooks schema: endpoints, deliveries
- Add audit schema: logs, retention_policies
- Add features schema: flags, tenant_flags (14 seeds)
- Add analytics schema: metrics, events, reports, report_schedules
- Add auth.oauth_connections for MCH-030
- Add timestamptz_to_date() IMMUTABLE function
- Update EXPECTED_SCHEMAS in recreate-database.sh

## Analysis Reports
- ANALISIS-INTEGRACION-TEMPLATE-SAAS-2026-01-13.md
- VALIDACION-COHERENCIA-2026-01-13.md
- GAP-ANALYSIS-BD-2026-01-13.md
- REPORTE-EJECUCION-2026-01-13.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 07:10:55 -06:00

125 lines
3.7 KiB
PL/PgSQL

-- =============================================================================
-- MICHANGARRITO - 02 FUNCTIONS
-- =============================================================================
-- Funciones utilitarias del sistema
-- =============================================================================
-- Función para actualizar updated_at automáticamente
CREATE OR REPLACE FUNCTION update_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Función IMMUTABLE para convertir TIMESTAMPTZ a DATE
-- Necesaria para índices funcionales sobre campos de fecha
-- Usa timezone fijo America/Mexico_City para consistencia
CREATE OR REPLACE FUNCTION public.timestamptz_to_date(ts TIMESTAMPTZ)
RETURNS DATE AS $$
SELECT (ts AT TIME ZONE 'America/Mexico_City')::date;
$$ LANGUAGE SQL IMMUTABLE PARALLEL SAFE;
COMMENT ON FUNCTION public.timestamptz_to_date IS 'Convierte TIMESTAMPTZ a DATE usando timezone America/Mexico_City (IMMUTABLE para indices)';
-- Función para generar número de ticket
CREATE OR REPLACE FUNCTION sales.generate_ticket_number(p_tenant_id UUID)
RETURNS VARCHAR(20) AS $$
DECLARE
v_date TEXT;
v_sequence INTEGER;
v_ticket VARCHAR(20);
BEGIN
v_date := TO_CHAR(CURRENT_DATE, 'YYMMDD');
SELECT COALESCE(MAX(
CAST(SUBSTRING(ticket_number FROM 8) AS INTEGER)
), 0) + 1
INTO v_sequence
FROM sales.sales
WHERE tenant_id = p_tenant_id
AND ticket_number LIKE v_date || '-%';
v_ticket := v_date || '-' || LPAD(v_sequence::TEXT, 4, '0');
RETURN v_ticket;
END;
$$ LANGUAGE plpgsql;
-- Función para generar número de pedido
CREATE OR REPLACE FUNCTION orders.generate_order_number(p_tenant_id UUID)
RETURNS VARCHAR(20) AS $$
DECLARE
v_date TEXT;
v_sequence INTEGER;
v_order VARCHAR(20);
BEGIN
v_date := TO_CHAR(CURRENT_DATE, 'YYMMDD');
SELECT COALESCE(MAX(
CAST(SUBSTRING(order_number FROM 8) AS INTEGER)
), 0) + 1
INTO v_sequence
FROM orders.orders
WHERE tenant_id = p_tenant_id
AND order_number LIKE 'P' || v_date || '-%';
v_order := 'P' || v_date || '-' || LPAD(v_sequence::TEXT, 4, '0');
RETURN v_order;
END;
$$ LANGUAGE plpgsql;
-- Función para actualizar balance de fiados del cliente
CREATE OR REPLACE FUNCTION customers.update_customer_fiado_balance()
RETURNS TRIGGER AS $$
BEGIN
UPDATE customers.customers
SET current_fiado_balance = (
SELECT COALESCE(SUM(remaining_amount), 0)
FROM customers.fiados
WHERE customer_id = COALESCE(NEW.customer_id, OLD.customer_id)
AND status IN ('pending', 'partial', 'overdue')
),
updated_at = NOW()
WHERE id = COALESCE(NEW.customer_id, OLD.customer_id);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Función para actualizar stock después de venta
CREATE OR REPLACE FUNCTION inventory.update_stock_on_sale()
RETURNS TRIGGER AS $$
BEGIN
IF TG_OP = 'INSERT' THEN
-- Registrar movimiento de inventario
INSERT INTO inventory.inventory_movements (
tenant_id, product_id, movement_type, quantity,
previous_stock, new_stock, reference_type, reference_id
)
SELECT
s.tenant_id,
NEW.product_id,
'sale',
-NEW.quantity,
p.stock_quantity,
p.stock_quantity - NEW.quantity,
'sale',
NEW.sale_id
FROM sales.sales s
JOIN catalog.products p ON p.id = NEW.product_id
WHERE s.id = NEW.sale_id;
-- Actualizar stock del producto
UPDATE catalog.products
SET stock_quantity = stock_quantity - NEW.quantity,
updated_at = NOW()
WHERE id = NEW.product_id;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;