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
82 lines
4.2 KiB
SQL
82 lines
4.2 KiB
SQL
-- v2.1_suppliers.sql
|
|
-- Mejora #3: Proveedores y Órdenes de Compra
|
|
--
|
|
-- Adds supplier management and purchase order workflow to tenant databases.
|
|
--
|
|
-- Workflow:
|
|
-- 1. Create supplier (suppliers table)
|
|
-- 2. Create PO with items (purchase_orders + purchase_order_items)
|
|
-- 3. Send PO to supplier (status = 'sent')
|
|
-- 4. Receive partial or full delivery (status = 'partial' | 'received')
|
|
-- → On receive: update stock via inventory_engine.record_purchase()
|
|
-- → On receive: create accounting entry via record_purchase_entry()
|
|
|
|
-- ═══════════════════════════════════════════════════════════════════════════
|
|
-- SUPPLIERS
|
|
-- ═══════════════════════════════════════════════════════════════════════════
|
|
CREATE TABLE IF NOT EXISTS suppliers (
|
|
id SERIAL PRIMARY KEY,
|
|
name VARCHAR(200) NOT NULL,
|
|
contact_name VARCHAR(200),
|
|
phone VARCHAR(50),
|
|
email VARCHAR(200),
|
|
rfc VARCHAR(13),
|
|
address TEXT,
|
|
payment_terms VARCHAR(100), -- e.g., "30 dias", "contado"
|
|
notes TEXT,
|
|
is_active BOOLEAN DEFAULT true,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_suppliers_active ON suppliers(is_active);
|
|
CREATE INDEX IF NOT EXISTS idx_suppliers_name ON suppliers(name);
|
|
|
|
-- ═══════════════════════════════════════════════════════════════════════════
|
|
-- PURCHASE ORDERS
|
|
-- ═══════════════════════════════════════════════════════════════════════════
|
|
CREATE TABLE IF NOT EXISTS purchase_orders (
|
|
id SERIAL PRIMARY KEY,
|
|
supplier_id INTEGER REFERENCES suppliers(id) ON DELETE SET NULL,
|
|
branch_id INTEGER REFERENCES branches(id),
|
|
employee_id INTEGER REFERENCES employees(id),
|
|
status VARCHAR(20) DEFAULT 'draft' NOT NULL, -- draft, sent, partial, received, cancelled
|
|
subtotal NUMERIC(12,2) DEFAULT 0 NOT NULL,
|
|
tax_total NUMERIC(12,2) DEFAULT 0 NOT NULL,
|
|
total NUMERIC(12,2) DEFAULT 0 NOT NULL,
|
|
currency VARCHAR(3) DEFAULT 'MXN',
|
|
exchange_rate NUMERIC(12,6) DEFAULT 1.0,
|
|
notes TEXT,
|
|
supplier_invoice VARCHAR(100),
|
|
expected_date DATE,
|
|
sent_at TIMESTAMPTZ,
|
|
received_at TIMESTAMPTZ,
|
|
cancelled_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_po_supplier ON purchase_orders(supplier_id);
|
|
CREATE INDEX IF NOT EXISTS idx_po_status ON purchase_orders(status);
|
|
CREATE INDEX IF NOT EXISTS idx_po_branch ON purchase_orders(branch_id);
|
|
CREATE INDEX IF NOT EXISTS idx_po_created ON purchase_orders(created_at DESC);
|
|
|
|
-- ═══════════════════════════════════════════════════════════════════════════
|
|
-- PURCHASE ORDER ITEMS
|
|
-- ═══════════════════════════════════════════════════════════════════════════
|
|
CREATE TABLE IF NOT EXISTS purchase_order_items (
|
|
id SERIAL PRIMARY KEY,
|
|
po_id INTEGER NOT NULL REFERENCES purchase_orders(id) ON DELETE CASCADE,
|
|
inventory_id INTEGER REFERENCES inventory(id) ON DELETE SET NULL,
|
|
part_number VARCHAR(100),
|
|
name VARCHAR(300),
|
|
quantity INTEGER NOT NULL DEFAULT 1,
|
|
received_qty INTEGER DEFAULT 0,
|
|
unit_price NUMERIC(12,2) NOT NULL DEFAULT 0,
|
|
subtotal NUMERIC(12,2) NOT NULL DEFAULT 0,
|
|
notes TEXT,
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_poi_po ON purchase_order_items(po_id);
|
|
CREATE INDEX IF NOT EXISTS idx_poi_inventory ON purchase_order_items(inventory_id);
|