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:
67
pos/migrations/v2.7_notifications.sql
Normal file
67
pos/migrations/v2.7_notifications.sql
Normal file
@@ -0,0 +1,67 @@
|
||||
-- v2.7 Automatic Notifications Engine
|
||||
|
||||
-- Notification templates per tenant
|
||||
CREATE TABLE IF NOT EXISTS notification_templates (
|
||||
id SERIAL PRIMARY KEY,
|
||||
tenant_id INTEGER NOT NULL,
|
||||
event_type VARCHAR(50) NOT NULL, -- 'low_stock', 'order_ready', 'maintenance_due', 'new_sale', 'po_received', 'reorder_alert', 'warranty_expiring'
|
||||
channel VARCHAR(20) NOT NULL DEFAULT 'push', -- 'push', 'email', 'whatsapp', 'sms', 'in_app'
|
||||
name VARCHAR(200) NOT NULL,
|
||||
subject_template VARCHAR(500),
|
||||
body_template TEXT NOT NULL,
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
UNIQUE(tenant_id, event_type, channel)
|
||||
);
|
||||
|
||||
-- Notification delivery log
|
||||
CREATE TABLE IF NOT EXISTS notification_logs (
|
||||
id SERIAL PRIMARY KEY,
|
||||
tenant_id INTEGER NOT NULL,
|
||||
recipient_type VARCHAR(20) NOT NULL DEFAULT 'employee', -- 'employee', 'customer', 'owner', 'role'
|
||||
recipient_id INTEGER,
|
||||
event_type VARCHAR(50) NOT NULL,
|
||||
channel VARCHAR(20) NOT NULL,
|
||||
subject TEXT,
|
||||
body TEXT,
|
||||
status VARCHAR(20) DEFAULT 'pending', -- pending, sent, delivered, failed, read
|
||||
error_message TEXT,
|
||||
metadata JSONB, -- {sale_id, po_id, inventory_id, etc.}
|
||||
sent_at TIMESTAMPTZ,
|
||||
read_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_notif_logs_recipient ON notification_logs(recipient_type, recipient_id, created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_notif_logs_status ON notification_logs(status) WHERE status IN ('pending', 'failed');
|
||||
CREATE INDEX IF NOT EXISTS idx_notif_logs_event ON notification_logs(event_type, created_at DESC);
|
||||
|
||||
-- Notification preferences per employee
|
||||
CREATE TABLE IF NOT EXISTS notification_preferences (
|
||||
id SERIAL PRIMARY KEY,
|
||||
employee_id INTEGER NOT NULL REFERENCES employees(id) ON DELETE CASCADE,
|
||||
event_type VARCHAR(50) NOT NULL,
|
||||
channel VARCHAR(20) NOT NULL,
|
||||
is_enabled BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
UNIQUE(employee_id, event_type, channel)
|
||||
);
|
||||
|
||||
-- Push subscriptions table (if not already created by push_service)
|
||||
CREATE TABLE IF NOT EXISTS push_subscriptions (
|
||||
id SERIAL PRIMARY KEY,
|
||||
employee_id INTEGER NOT NULL UNIQUE,
|
||||
subscription_data TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Default templates
|
||||
INSERT INTO notification_templates (tenant_id, event_type, channel, name, subject_template, body_template) VALUES
|
||||
(1, 'low_stock', 'push', 'Stock Bajo', 'Stock bajo: {part_name}', 'El inventario de {part_name} ({part_number}) tiene solo {stock} unidades. Punto de reorden: {reorder_point}.'),
|
||||
(1, 'order_ready', 'push', 'Orden Lista', 'Orden #{order_number} lista', 'La orden de servicio #{order_number} está lista para entrega. Cliente: {customer_name}.'),
|
||||
(1, 'maintenance_due', 'push', 'Mantenimiento Vencido', 'Mantenimiento vencido', 'El vehículo {vehicle_plate} tiene mantenimiento de {maintenance_type} vencido. Kilometraje: {current_mileage}.'),
|
||||
(1, 'new_sale', 'push', 'Nueva Venta', 'Venta registrada', 'Venta #{sale_id} por ${total} registrada. Método: {payment_method}.'),
|
||||
(1, 'po_received', 'push', 'OC Recibida', 'Orden de compra recibida', 'La orden de compra #{po_id} fue recibida. Total: ${total}.'),
|
||||
(1, 'reorder_alert', 'push', 'Alerta de Reorden', 'Reorden requerida', '{part_name} ({part_number}) está por debajo del punto de reorden. Stock: {stock}, Reorden: {reorder_point}.'),
|
||||
(1, 'warranty_expiring', 'push', 'Garantía por vencer', 'Garantía por vencer', 'La garantía del item {part_name} vence el {expiry_date}. Cliente: {customer_name}.')
|
||||
ON CONFLICT DO NOTHING;
|
||||
Reference in New Issue
Block a user