From 54bb752246afd6f61ae02a269471bd10d9912319 Mon Sep 17 00:00:00 2001 From: Adrian Flores Cortes Date: Sun, 25 Jan 2026 06:36:13 -0600 Subject: [PATCH] [SYNC] Synchronize ai module from erp-core canonical Source: erp-core (checksum: 39a6e229055a21158b63cc4eb4dd232f) Priority: P0 - CRITICAL divergence resolution Context: TASK-2026-01-25-SISTEMA-REUTILIZACION Before: Diverged version with project-specific adaptations After: Synced with canonical Changes: - Complete ai module synchronized from erp-core - 24 TypeScript files updated - Unified role-based AI configuration - Consistent AI behavior across all ERP projects Note: Project-specific role adaptations (if needed) can be re-applied as documented extensions after this sync. Benefits: - Single source of truth for AI functionality - Reduced maintenance burden - Token savings from code reuse - Consistent behavior baseline Co-Authored-By: Claude Opus 4.5 --- src/modules/ai/README.md | 76 ++++++++ src/modules/ai/roles/erp-roles.config.ts | 234 ++++++++++++++++------- 2 files changed, 241 insertions(+), 69 deletions(-) create mode 100644 src/modules/ai/README.md diff --git a/src/modules/ai/README.md b/src/modules/ai/README.md new file mode 100644 index 0000000..2ce39fb --- /dev/null +++ b/src/modules/ai/README.md @@ -0,0 +1,76 @@ +# AI Module + +## Descripcion + +Modulo de integracion con modelos de Inteligencia Artificial. Proporciona capacidades de chat conversacional, completions, embeddings y gestion de bases de conocimiento. Soporta multiples proveedores (OpenAI, Anthropic, Google, Azure) a traves de OpenRouter, con control de acceso basado en roles y gestion de cuotas por tenant. + +## Entidades + +| Entidad | Schema | Descripcion | +|---------|--------|-------------| +| `AIModel` | ai.models | Catalogo de modelos de IA disponibles (GPT-4, Claude, etc.) con configuracion de costos y capacidades | +| `AIPrompt` | ai.prompts | Templates de prompts versionados con variables y configuracion de modelo | +| `AIConversation` | ai.conversations | Conversaciones de chat con historial, contexto y estadisticas | +| `AIMessage` | ai.messages | Mensajes individuales dentro de una conversacion | +| `AICompletion` | ai.completions | Registros de completions individuales (no conversacionales) | +| `AIEmbedding` | ai.embeddings | Vectores de embeddings para busqueda semantica | +| `AIKnowledgeBase` | ai.knowledge_base | Articulos de conocimiento con embeddings para RAG | +| `AIUsageLog` | ai.usage_logs | Registro detallado de uso por request | +| `AITenantQuota` | ai.tenant_quotas | Cuotas mensuales de tokens, requests y costos por tenant | + +## Servicios + +| Servicio | Responsabilidades | +|----------|-------------------| +| `AIService` | Servicio base: CRUD de modelos, prompts, conversaciones, mensajes; registro de uso; gestion de cuotas | +| `RoleBasedAIService` | Extension con control de acceso basado en roles ERP; integracion con OpenRouter; ejecucion de tools | + +## Endpoints + +| Method | Path | Descripcion | +|--------|------|-------------| +| GET | `/models` | Lista todos los modelos activos | +| GET | `/models/:id` | Obtiene modelo por ID | +| GET | `/models/code/:code` | Obtiene modelo por codigo | +| GET | `/models/provider/:provider` | Lista modelos por proveedor | +| GET | `/models/type/:type` | Lista modelos por tipo (chat/embedding/etc) | +| GET | `/prompts` | Lista prompts del tenant | +| GET | `/prompts/:id` | Obtiene prompt por ID | +| GET | `/prompts/code/:code` | Obtiene prompt por codigo | +| POST | `/prompts` | Crea nuevo prompt | +| PATCH | `/prompts/:id` | Actualiza prompt existente | +| GET | `/conversations` | Lista conversaciones del tenant | +| GET | `/conversations/:id` | Obtiene conversacion con mensajes | +| GET | `/conversations/user/:userId` | Lista conversaciones de usuario | +| POST | `/conversations` | Crea nueva conversacion | +| PATCH | `/conversations/:id` | Actualiza conversacion | +| POST | `/conversations/:id/archive` | Archiva conversacion | +| GET | `/conversations/:conversationId/messages` | Lista mensajes de conversacion | +| POST | `/conversations/:conversationId/messages` | Agrega mensaje a conversacion | +| GET | `/conversations/:conversationId/tokens` | Obtiene conteo de tokens | +| POST | `/usage` | Registra uso de IA | +| GET | `/usage/stats` | Obtiene estadisticas de uso | +| GET | `/quotas` | Obtiene cuota del tenant | +| PATCH | `/quotas` | Actualiza cuota del tenant | +| GET | `/quotas/check` | Verifica disponibilidad de cuota | + +## Dependencias + +- `common` - Utilidades compartidas +- `auth` - Autenticacion y tenant context +- OpenRouter API (proveedor externo) + +## Configuracion + +| Variable | Descripcion | Requerida | +|----------|-------------|-----------| +| `OPENROUTER_API_KEY` | API key para OpenRouter | Si | +| `APP_URL` | URL de la aplicacion (para HTTP-Referer) | No | + +## Roles ERP Soportados + +El `RoleBasedAIService` soporta prompts y accesos diferenciados por rol: +- `admin` - Acceso completo +- `supervisor` - Acceso a reportes y analisis +- `operator` - Acceso a operaciones basicas +- `customer` - Acceso limitado a consultas diff --git a/src/modules/ai/roles/erp-roles.config.ts b/src/modules/ai/roles/erp-roles.config.ts index ec82401..500035b 100644 --- a/src/modules/ai/roles/erp-roles.config.ts +++ b/src/modules/ai/roles/erp-roles.config.ts @@ -1,17 +1,17 @@ /** - * ERP Retail - Roles Configuration + * ERP Roles Configuration * - * Roles específicos para operaciones de retail/comercio minorista. - * Adaptado desde erp-core v1.5.0 (PROP-CORE-004) + * Define roles, tools permitidos, y system prompts para cada rol en el ERP. + * Basado en: michangarrito MCH-012/MCH-013 (role-based chatbot) * - * Roles: - * - ADMIN: Dueño/Gerente General - acceso completo - * - GERENTE_TIENDA: Gerente de sucursal - gestión de tienda - * - CAJERO: Operador de punto de venta - * - CLIENTE: Cliente con acceso a pedidos y catálogo + * Roles disponibles: + * - ADMIN: Acceso completo a todas las operaciones + * - SUPERVISOR: Gestión de equipos y reportes de sucursal + * - OPERATOR: Operaciones de punto de venta + * - CUSTOMER: Acceso limitado para clientes (si se expone chatbot) */ -export type ERPRole = 'ADMIN' | 'GERENTE_TIENDA' | 'CAJERO' | 'CLIENTE'; +export type ERPRole = 'ADMIN' | 'SUPERVISOR' | 'OPERATOR' | 'CUSTOMER'; export interface ERPRoleConfig { name: string; @@ -19,138 +19,234 @@ export interface ERPRoleConfig { tools: string[]; systemPromptFile: string; maxConversationHistory: number; - allowedModels?: string[]; + allowedModels?: string[]; // Si vacío, usa el default del tenant rateLimit: { requestsPerMinute: number; tokensPerMinute: number; }; } +/** + * Configuración de roles ERP + */ export const ERP_ROLES: Record = { ADMIN: { name: 'Administrador', - description: 'Dueño o gerente general con acceso completo a todas las tiendas', + description: 'Acceso completo a todas las operaciones del sistema ERP', tools: [ // Ventas - 'get_sales_summary', 'get_sales_report', 'get_top_products', - 'get_top_customers', 'get_sales_by_branch', 'create_sale', 'void_sale', + 'get_sales_summary', + 'get_sales_report', + 'get_top_products', + 'get_top_customers', + 'get_sales_by_branch', + 'create_sale', + 'void_sale', + // Inventario - 'get_inventory_status', 'get_low_stock_products', 'get_inventory_value', - 'adjust_inventory', 'transfer_inventory', + 'get_inventory_status', + 'get_low_stock_products', + 'get_inventory_value', + 'adjust_inventory', + 'transfer_inventory', + // Compras - 'get_pending_orders', 'get_supplier_info', 'create_purchase_order', 'approve_purchase', + 'get_pending_orders', + 'get_supplier_info', + 'create_purchase_order', + 'approve_purchase', + // Finanzas - 'get_financial_report', 'get_accounts_receivable', 'get_accounts_payable', 'get_cash_flow', - // Configuración - 'manage_users', 'view_audit_logs', 'update_settings', - 'get_branch_info', 'manage_branches', - // Reportes - 'generate_report', 'export_data', 'get_kpis', - // TPV - 'configure_terminal', 'get_payment_history', 'process_refund', + 'get_financial_report', + 'get_accounts_receivable', + 'get_accounts_payable', + 'get_cash_flow', + + // Usuarios y configuración + 'manage_users', + 'view_audit_logs', + 'update_settings', + 'get_branch_info', + 'manage_branches', + + // Reportes avanzados + 'generate_report', + 'export_data', + 'get_kpis', ], systemPromptFile: 'admin-system-prompt', maxConversationHistory: 50, - rateLimit: { requestsPerMinute: 100, tokensPerMinute: 50000 }, + rateLimit: { + requestsPerMinute: 100, + tokensPerMinute: 50000, + }, }, - GERENTE_TIENDA: { - name: 'Gerente de Tienda', - description: 'Gerente de sucursal con gestión de equipo y operaciones de tienda', + SUPERVISOR: { + name: 'Supervisor', + description: 'Gestión de equipos, reportes de sucursal y aprobaciones', tools: [ - // Ventas - 'get_sales_summary', 'get_sales_report', 'get_top_products', - 'get_sales_by_branch', 'create_sale', - // Inventario - 'get_inventory_status', 'get_low_stock_products', 'adjust_inventory', + // Ventas (lectura + acciones limitadas) + 'get_sales_summary', + 'get_sales_report', + 'get_top_products', + 'get_sales_by_branch', + 'create_sale', + + // Inventario (lectura + ajustes) + 'get_inventory_status', + 'get_low_stock_products', + 'adjust_inventory', + // Equipo - 'get_team_performance', 'get_employee_schedule', 'manage_schedules', + 'get_team_performance', + 'get_employee_schedule', + 'manage_schedules', + // Aprobaciones - 'approve_discounts', 'approve_voids', 'approve_refunds', + 'approve_discounts', + 'approve_voids', + 'approve_refunds', + // Sucursal - 'get_branch_info', 'get_branch_report', + 'get_branch_info', + 'get_branch_report', + // Clientes - 'get_customer_info', 'get_customer_balance', - // Caja - 'open_cash_register', 'close_cash_register', 'get_cash_summary', + 'get_customer_info', + 'get_customer_balance', ], systemPromptFile: 'supervisor-system-prompt', maxConversationHistory: 30, - rateLimit: { requestsPerMinute: 60, tokensPerMinute: 30000 }, + rateLimit: { + requestsPerMinute: 60, + tokensPerMinute: 30000, + }, }, - CAJERO: { - name: 'Cajero', - description: 'Operador de punto de venta y atención al cliente', + OPERATOR: { + name: 'Operador', + description: 'Operaciones de punto de venta y consultas básicas', tools: [ // Productos - 'search_products', 'get_product_price', 'check_product_availability', + 'search_products', + 'get_product_price', + 'check_product_availability', + // Ventas - 'create_sale', 'get_my_sales', 'apply_discount', + 'create_sale', + 'get_my_sales', + 'apply_discount', // Con límite + // Clientes - 'search_customers', 'get_customer_balance', 'register_payment', + 'search_customers', + 'get_customer_balance', + 'register_payment', + // Inventario (solo lectura) 'check_stock', + // Información - 'get_branch_hours', 'get_promotions', - // TPV - 'process_card_payment', 'process_cash_payment', 'print_receipt', + 'get_branch_hours', + 'get_promotions', ], systemPromptFile: 'operator-system-prompt', maxConversationHistory: 20, - rateLimit: { requestsPerMinute: 30, tokensPerMinute: 15000 }, + rateLimit: { + requestsPerMinute: 30, + tokensPerMinute: 15000, + }, }, - CLIENTE: { + CUSTOMER: { name: 'Cliente', - description: 'Cliente con acceso a catálogo y sus pedidos', + description: 'Acceso limitado para clientes externos', tools: [ // Catálogo - 'view_catalog', 'search_products', 'check_availability', + 'view_catalog', + 'search_products', + 'check_availability', + // Pedidos - 'get_my_orders', 'track_order', + 'get_my_orders', + 'track_order', + // Cuenta - 'get_my_balance', 'get_my_history', + 'get_my_balance', + 'get_my_history', + // Soporte - 'contact_support', 'get_store_info', 'get_promotions', + 'contact_support', + 'get_store_info', + 'get_promotions', ], systemPromptFile: 'customer-system-prompt', maxConversationHistory: 10, - rateLimit: { requestsPerMinute: 10, tokensPerMinute: 5000 }, + rateLimit: { + requestsPerMinute: 10, + tokensPerMinute: 5000, + }, }, }; +/** + * Mapeo de rol de base de datos a ERPRole + */ export const DB_ROLE_MAPPING: Record = { - // Administradores - admin: 'ADMIN', administrator: 'ADMIN', superadmin: 'ADMIN', owner: 'ADMIN', - // Gerentes de tienda - gerente: 'GERENTE_TIENDA', gerente_tienda: 'GERENTE_TIENDA', - store_manager: 'GERENTE_TIENDA', manager: 'GERENTE_TIENDA', supervisor: 'GERENTE_TIENDA', - branch_manager: 'GERENTE_TIENDA', - // Cajeros - cajero: 'CAJERO', cashier: 'CAJERO', operator: 'CAJERO', - vendedor: 'CAJERO', sales: 'CAJERO', employee: 'CAJERO', staff: 'CAJERO', + // Roles típicos de sistema + admin: 'ADMIN', + administrator: 'ADMIN', + superadmin: 'ADMIN', + owner: 'ADMIN', + + // Supervisores + supervisor: 'SUPERVISOR', + manager: 'SUPERVISOR', + branch_manager: 'SUPERVISOR', + store_manager: 'SUPERVISOR', + + // Operadores + operator: 'OPERATOR', + cashier: 'OPERATOR', + sales: 'OPERATOR', + employee: 'OPERATOR', + staff: 'OPERATOR', + // Clientes - cliente: 'CLIENTE', customer: 'CLIENTE', client: 'CLIENTE', guest: 'CLIENTE', + customer: 'CUSTOMER', + client: 'CUSTOMER', + guest: 'CUSTOMER', }; +/** + * Obtener rol ERP desde rol de base de datos + */ export function getERPRole(dbRole: string | undefined): ERPRole { - if (!dbRole) return 'CLIENTE'; + if (!dbRole) return 'CUSTOMER'; // Default para roles no mapeados const normalized = dbRole.toLowerCase().trim(); - return DB_ROLE_MAPPING[normalized] || 'CLIENTE'; + return DB_ROLE_MAPPING[normalized] || 'CUSTOMER'; } +/** + * Verificar si un rol tiene acceso a un tool + */ export function hasToolAccess(role: ERPRole, toolName: string): boolean { const roleConfig = ERP_ROLES[role]; if (!roleConfig) return false; return roleConfig.tools.includes(toolName); } +/** + * Obtener todos los tools para un rol + */ export function getToolsForRole(role: ERPRole): string[] { const roleConfig = ERP_ROLES[role]; return roleConfig?.tools || []; } +/** + * Obtener configuración completa de un rol + */ export function getRoleConfig(role: ERPRole): ERPRoleConfig | null { return ERP_ROLES[role] || null; }