FASE 4-5-6: Infraestructura, CRM, Service Orders, Notificaciones, Ahorro, Logistica, API Publica

FASE 4:
- Redis cache de stock con fallback graceful
- Multi-moneda (MXN/USD) con contabilidad en MXN
- Proveedores y ordenes de compra completo
- Meilisearch 1.5M+ partes indexadas
- Metabase KPIs con dashboard auto-generado

FASE 5:
- CRM mejorado: activities, tags, loyalty program, analytics
- Imagenes de partes: upload, resize, thumbnails WebP
- Ordenes de servicio Kanban: received->diagnosis->repair->ready->delivered
- Garantias/RMA, alertas de reorden, multi-sucursal
- Stubs BNPL (APLAZO) y ERP Sync (Aspel/Contpaqi)

FASE 6:
- Notificaciones automaticas: push/WhatsApp/email/in-app
- Reportes de ahorro vs retail_price
- Logistica + tracking: DHL, FedEx, Estafeta, 99min, Uber
- API Publica: API keys, rate limiting, catalog search

Migraciones: v1.9-v3.0
Tests: 93/93 pasando
Backup: nexus_backup_20260427_045859.tar.gz
This commit is contained in:
Nexus Dev
2026-04-27 05:23:30 +00:00
parent b70cb3042b
commit 9ff3dc4c8b
71 changed files with 10939 additions and 420 deletions

View File

@@ -0,0 +1,100 @@
-- v1.8 Performance indexes and FK fixes
-- Applied to each tenant database
-- ═══════════════════════════════════════════════════════════════════════════
-- PERFORMANCE INDEXES
-- ═══════════════════════════════════════════════════════════════════════════
-- Stock queries (used thousands of times per day)
CREATE INDEX IF NOT EXISTS idx_inv_ops_inventory_branch ON inventory_operations(inventory_id, branch_id);
CREATE INDEX IF NOT EXISTS idx_inv_ops_inventory_type_created ON inventory_operations(inventory_id, operation_type, created_at);
CREATE INDEX IF NOT EXISTS idx_inv_ops_inventory_created_desc ON inventory_operations(inventory_id, created_at DESC);
-- Cash register lookups
CREATE INDEX IF NOT EXISTS idx_cash_movements_register ON cash_movements(register_id);
CREATE INDEX IF NOT EXISTS idx_sales_register_status ON sales(register_id, status);
-- Inventory filtering
CREATE INDEX IF NOT EXISTS idx_inventory_branch_active ON inventory(branch_id, is_active);
-- Transaction tables
CREATE INDEX IF NOT EXISTS idx_sale_items_inventory ON sale_items(inventory_id);
CREATE INDEX IF NOT EXISTS idx_sale_payments_sale ON sale_payments(sale_id);
CREATE INDEX IF NOT EXISTS idx_sale_payments_register ON sale_payments(register_id);
CREATE INDEX IF NOT EXISTS idx_layaway_items_inventory ON layaway_items(inventory_id);
CREATE INDEX IF NOT EXISTS idx_layaway_items_layaway ON layaway_items(layaway_id);
CREATE INDEX IF NOT EXISTS idx_return_items_inventory ON return_items(inventory_id);
CREATE INDEX IF NOT EXISTS idx_return_items_return ON return_items(return_id);
-- Employees and permissions
CREATE INDEX IF NOT EXISTS idx_employees_email ON employees(email);
CREATE INDEX IF NOT EXISTS idx_employees_branch ON employees(branch_id);
CREATE INDEX IF NOT EXISTS idx_employee_permissions_employee ON employee_permissions(employee_id);
-- Customers and fleet
CREATE INDEX IF NOT EXISTS idx_customers_phone ON customers(phone);
CREATE INDEX IF NOT EXISTS idx_fleet_vehicles_branch_vin ON fleet_vehicles(branch_id, vin);
CREATE INDEX IF NOT EXISTS idx_fleet_maintenance_schedules_next_due ON fleet_maintenance_schedules(next_due_at);
-- WhatsApp and quotations
CREATE INDEX IF NOT EXISTS idx_whatsapp_messages_status ON whatsapp_messages(status);
CREATE INDEX IF NOT EXISTS idx_whatsapp_messages_related ON whatsapp_messages(related_type, related_id);
CREATE INDEX IF NOT EXISTS idx_quotations_branch ON quotations(branch_id);
-- Accounting
CREATE INDEX IF NOT EXISTS idx_accounts_parent ON accounts(parent_id);
CREATE INDEX IF NOT EXISTS idx_journal_entries_date ON journal_entries(date);
CREATE INDEX IF NOT EXISTS idx_fiscal_periods_year_month ON fiscal_periods(year, month);
-- Physical counts
CREATE INDEX IF NOT EXISTS idx_physical_counts_branch_status ON physical_counts(branch_id, status);
CREATE INDEX IF NOT EXISTS idx_physical_count_lines_inventory ON physical_count_lines(inventory_id);
-- ═══════════════════════════════════════════════════════════════════════════
-- FOREIGN KEY FIXES
-- ═══════════════════════════════════════════════════════════════════════════
-- Sale dependencies
ALTER TABLE sale_items
ADD CONSTRAINT fk_sale_items_sale FOREIGN KEY (sale_id) REFERENCES sales(id) ON DELETE CASCADE;
ALTER TABLE sale_payments
ADD CONSTRAINT fk_sale_payments_sale FOREIGN KEY (sale_id) REFERENCES sales(id) ON DELETE CASCADE;
-- Quotation dependencies
ALTER TABLE quotation_items
ADD CONSTRAINT fk_quotation_items_quotation FOREIGN KEY (quotation_id) REFERENCES quotations(id) ON DELETE CASCADE;
-- Layaway dependencies
ALTER TABLE layaway_items
ADD CONSTRAINT fk_layaway_items_layaway FOREIGN KEY (layaway_id) REFERENCES layaways(id) ON DELETE CASCADE;
-- Return dependencies
ALTER TABLE return_items
ADD CONSTRAINT fk_return_items_return FOREIGN KEY (return_id) REFERENCES returns(id) ON DELETE CASCADE;
ALTER TABLE return_items
ADD CONSTRAINT fk_return_items_sale_item FOREIGN KEY (sale_item_id) REFERENCES sale_items(id) ON DELETE SET NULL;
-- Cash movements
ALTER TABLE cash_movements
ADD CONSTRAINT fk_cash_movements_register FOREIGN KEY (register_id) REFERENCES cash_registers(id) ON DELETE CASCADE;
-- ═══════════════════════════════════════════════════════════════════════════
-- DATA TYPE NORMALIZATION
-- ═══════════════════════════════════════════════════════════════════════════
ALTER TABLE physical_counts ALTER COLUMN created_at TYPE TIMESTAMPTZ;
-- ═══════════════════════════════════════════════════════════════════════════
-- CONSTRAINT IMPROVEMENTS
-- ═══════════════════════════════════════════════════════════════════════════
-- Ensure unique entry numbers per date (fiscal period approximation)
-- Note: journal_entries uses 'date' column, not period_year/month
CREATE UNIQUE INDEX IF NOT EXISTS idx_journal_entries_unique_number
ON journal_entries(date, entry_number);
-- Add CHECK constraint for sales.status (idempotent for VARCHAR)
-- Note: PostgreSQL does not support adding CHECK constraints via IF NOT EXISTS
-- This is left as documentation; apply manually if needed:
-- ALTER TABLE sales ADD CONSTRAINT chk_sales_status
-- CHECK (status IN ('completed', 'cancelled', 'returned', 'partially_returned'));