[TASK-2026-01-25-ERP-INTEGRACIONES] feat(mcp): Add ERP-specific MCP tools
- Add SalesToolsService with 7 tools (sales summary, reports, top products/customers) - Add FinancialToolsService with 5 tools (reports, accounts receivable/payable, cash flow, KPIs) - Add BranchToolsService with 6 tools (branch info, reports, team performance, schedules) - Register new tool providers in MCP module - Total: 18 new MCP tools for ERP operations Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
fd8a0a508e
commit
3bfa564d43
@ -9,6 +9,9 @@ import {
|
|||||||
OrdersToolsService,
|
OrdersToolsService,
|
||||||
CustomersToolsService,
|
CustomersToolsService,
|
||||||
FiadosToolsService,
|
FiadosToolsService,
|
||||||
|
SalesToolsService,
|
||||||
|
FinancialToolsService,
|
||||||
|
BranchToolsService,
|
||||||
} from './tools';
|
} from './tools';
|
||||||
|
|
||||||
export interface McpModuleOptions {
|
export interface McpModuleOptions {
|
||||||
@ -48,6 +51,9 @@ export class McpModule {
|
|||||||
this.toolRegistry.registerProvider(new OrdersToolsService());
|
this.toolRegistry.registerProvider(new OrdersToolsService());
|
||||||
this.toolRegistry.registerProvider(new CustomersToolsService());
|
this.toolRegistry.registerProvider(new CustomersToolsService());
|
||||||
this.toolRegistry.registerProvider(new FiadosToolsService());
|
this.toolRegistry.registerProvider(new FiadosToolsService());
|
||||||
|
this.toolRegistry.registerProvider(new SalesToolsService());
|
||||||
|
this.toolRegistry.registerProvider(new FinancialToolsService());
|
||||||
|
this.toolRegistry.registerProvider(new BranchToolsService());
|
||||||
|
|
||||||
// MCP Server Service
|
// MCP Server Service
|
||||||
this.mcpService = new McpServerService(this.toolRegistry, toolLogger);
|
this.mcpService = new McpServerService(this.toolRegistry, toolLogger);
|
||||||
|
|||||||
292
src/modules/mcp/tools/branch-tools.service.ts
Normal file
292
src/modules/mcp/tools/branch-tools.service.ts
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
import {
|
||||||
|
McpToolProvider,
|
||||||
|
McpToolDefinition,
|
||||||
|
McpToolHandler,
|
||||||
|
McpContext,
|
||||||
|
} from '../interfaces';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Branch Tools Service
|
||||||
|
* Provides MCP tools for branch management and team operations.
|
||||||
|
* Used by: ADMIN, SUPERVISOR roles
|
||||||
|
*/
|
||||||
|
export class BranchToolsService implements McpToolProvider {
|
||||||
|
getTools(): McpToolDefinition[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: 'get_branch_info',
|
||||||
|
description: 'Obtiene informacion de una sucursal',
|
||||||
|
category: 'branches',
|
||||||
|
parameters: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
branch_id: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'uuid',
|
||||||
|
description: 'ID de la sucursal (usa la actual si no se especifica)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
returns: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
id: { type: 'string' },
|
||||||
|
name: { type: 'string' },
|
||||||
|
address: { type: 'string' },
|
||||||
|
phone: { type: 'string' },
|
||||||
|
operating_hours: { type: 'object' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'get_branch_report',
|
||||||
|
description: 'Genera reporte de desempeno de sucursal',
|
||||||
|
category: 'branches',
|
||||||
|
parameters: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
branch_id: { type: 'string', format: 'uuid' },
|
||||||
|
period: {
|
||||||
|
type: 'string',
|
||||||
|
enum: ['today', 'week', 'month'],
|
||||||
|
default: 'today',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
returns: { type: 'object' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'get_team_performance',
|
||||||
|
description: 'Obtiene metricas de desempeno del equipo',
|
||||||
|
category: 'branches',
|
||||||
|
parameters: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
branch_id: { type: 'string', format: 'uuid' },
|
||||||
|
period: {
|
||||||
|
type: 'string',
|
||||||
|
enum: ['today', 'week', 'month'],
|
||||||
|
default: 'today',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
returns: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
team_size: { type: 'number' },
|
||||||
|
members: { type: 'array' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'get_employee_schedule',
|
||||||
|
description: 'Obtiene horarios de empleados',
|
||||||
|
category: 'branches',
|
||||||
|
parameters: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
branch_id: { type: 'string', format: 'uuid' },
|
||||||
|
date: { type: 'string', format: 'date' },
|
||||||
|
employee_id: { type: 'string', format: 'uuid' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
returns: { type: 'array', items: { type: 'object' } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'get_branch_hours',
|
||||||
|
description: 'Obtiene horarios de atencion de la sucursal',
|
||||||
|
category: 'branches',
|
||||||
|
parameters: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
branch_id: { type: 'string', format: 'uuid' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
returns: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
regular: { type: 'object' },
|
||||||
|
holidays: { type: 'array' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'get_promotions',
|
||||||
|
description: 'Obtiene promociones activas',
|
||||||
|
category: 'branches',
|
||||||
|
parameters: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
branch_id: { type: 'string', format: 'uuid' },
|
||||||
|
active_only: { type: 'boolean', default: true },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
returns: { type: 'array', items: { type: 'object' } },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
getHandler(toolName: string): McpToolHandler | undefined {
|
||||||
|
const handlers: Record<string, McpToolHandler> = {
|
||||||
|
get_branch_info: this.getBranchInfo.bind(this),
|
||||||
|
get_branch_report: this.getBranchReport.bind(this),
|
||||||
|
get_team_performance: this.getTeamPerformance.bind(this),
|
||||||
|
get_employee_schedule: this.getEmployeeSchedule.bind(this),
|
||||||
|
get_branch_hours: this.getBranchHours.bind(this),
|
||||||
|
get_promotions: this.getPromotions.bind(this),
|
||||||
|
};
|
||||||
|
return handlers[toolName];
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getBranchInfo(
|
||||||
|
params: { branch_id?: string },
|
||||||
|
context: McpContext
|
||||||
|
): Promise<any> {
|
||||||
|
// TODO: Connect to BranchesService
|
||||||
|
const branchId = params.branch_id || context.branchId;
|
||||||
|
return {
|
||||||
|
id: branchId,
|
||||||
|
name: 'Sucursal Centro',
|
||||||
|
code: 'SUC-001',
|
||||||
|
type: 'store',
|
||||||
|
address: {
|
||||||
|
street: 'Av. Principal 123',
|
||||||
|
city: 'Ciudad de Mexico',
|
||||||
|
state: 'CDMX',
|
||||||
|
postal_code: '06600',
|
||||||
|
},
|
||||||
|
phone: '+52 55 1234 5678',
|
||||||
|
email: 'centro@erp.com',
|
||||||
|
manager: {
|
||||||
|
id: 'mgr-001',
|
||||||
|
name: 'Juan Perez',
|
||||||
|
},
|
||||||
|
operating_hours: {
|
||||||
|
monday: { open: '09:00', close: '20:00' },
|
||||||
|
tuesday: { open: '09:00', close: '20:00' },
|
||||||
|
wednesday: { open: '09:00', close: '20:00' },
|
||||||
|
thursday: { open: '09:00', close: '20:00' },
|
||||||
|
friday: { open: '09:00', close: '20:00' },
|
||||||
|
saturday: { open: '10:00', close: '18:00' },
|
||||||
|
sunday: { open: 'closed', close: 'closed' },
|
||||||
|
},
|
||||||
|
message: 'Conectar a BranchesService real',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getBranchReport(
|
||||||
|
params: { branch_id?: string; period?: string },
|
||||||
|
context: McpContext
|
||||||
|
): Promise<any> {
|
||||||
|
// TODO: Connect to ReportsService
|
||||||
|
return {
|
||||||
|
branch_id: params.branch_id || context.branchId,
|
||||||
|
period: params.period || 'today',
|
||||||
|
sales: {
|
||||||
|
total: 15750.00,
|
||||||
|
count: 42,
|
||||||
|
avg_ticket: 375.00,
|
||||||
|
},
|
||||||
|
inventory: {
|
||||||
|
value: 250000.00,
|
||||||
|
low_stock_items: 5,
|
||||||
|
out_of_stock: 2,
|
||||||
|
},
|
||||||
|
staff: {
|
||||||
|
present: 8,
|
||||||
|
absent: 1,
|
||||||
|
late: 0,
|
||||||
|
},
|
||||||
|
goals: {
|
||||||
|
sales_target: 20000.00,
|
||||||
|
progress: 78.75,
|
||||||
|
},
|
||||||
|
message: 'Conectar a ReportsService real',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getTeamPerformance(
|
||||||
|
params: { branch_id?: string; period?: string },
|
||||||
|
context: McpContext
|
||||||
|
): Promise<any> {
|
||||||
|
// TODO: Connect to HRService + SalesService
|
||||||
|
return {
|
||||||
|
branch_id: params.branch_id || context.branchId,
|
||||||
|
period: params.period || 'today',
|
||||||
|
team_size: 8,
|
||||||
|
members: [
|
||||||
|
{ name: 'Ana Garcia', role: 'Vendedor', sales: 4500.00, transactions: 12, avg_ticket: 375.00 },
|
||||||
|
{ name: 'Carlos Lopez', role: 'Vendedor', sales: 3800.00, transactions: 10, avg_ticket: 380.00 },
|
||||||
|
{ name: 'Maria Rodriguez', role: 'Cajero', sales: 2500.00, transactions: 8, avg_ticket: 312.50 },
|
||||||
|
],
|
||||||
|
top_performer: 'Ana Garcia',
|
||||||
|
message: 'Conectar a HRService real',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getEmployeeSchedule(
|
||||||
|
params: { branch_id?: string; date?: string; employee_id?: string },
|
||||||
|
context: McpContext
|
||||||
|
): Promise<any[]> {
|
||||||
|
// TODO: Connect to ScheduleService
|
||||||
|
const date = params.date || new Date().toISOString().split('T')[0];
|
||||||
|
return [
|
||||||
|
{ employee: 'Ana Garcia', shift: 'morning', start: '09:00', end: '15:00', status: 'confirmed' },
|
||||||
|
{ employee: 'Carlos Lopez', shift: 'afternoon', start: '15:00', end: '21:00', status: 'confirmed' },
|
||||||
|
{ employee: 'Maria Rodriguez', shift: 'morning', start: '09:00', end: '15:00', status: 'confirmed' },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getBranchHours(
|
||||||
|
params: { branch_id?: string },
|
||||||
|
context: McpContext
|
||||||
|
): Promise<any> {
|
||||||
|
// TODO: Connect to BranchesService
|
||||||
|
return {
|
||||||
|
regular: {
|
||||||
|
monday: { open: '09:00', close: '20:00' },
|
||||||
|
tuesday: { open: '09:00', close: '20:00' },
|
||||||
|
wednesday: { open: '09:00', close: '20:00' },
|
||||||
|
thursday: { open: '09:00', close: '20:00' },
|
||||||
|
friday: { open: '09:00', close: '20:00' },
|
||||||
|
saturday: { open: '10:00', close: '18:00' },
|
||||||
|
sunday: 'Cerrado',
|
||||||
|
},
|
||||||
|
holidays: [
|
||||||
|
{ date: '2026-01-01', name: 'Año Nuevo', status: 'closed' },
|
||||||
|
{ date: '2026-02-03', name: 'Dia de la Constitucion', status: 'closed' },
|
||||||
|
],
|
||||||
|
next_closed: '2026-02-03',
|
||||||
|
message: 'Conectar a BranchesService real',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getPromotions(
|
||||||
|
params: { branch_id?: string; active_only?: boolean },
|
||||||
|
context: McpContext
|
||||||
|
): Promise<any[]> {
|
||||||
|
// TODO: Connect to PromotionsService
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
id: 'promo-001',
|
||||||
|
name: '2x1 en productos seleccionados',
|
||||||
|
type: 'bogo',
|
||||||
|
discount: 50,
|
||||||
|
start_date: '2026-01-20',
|
||||||
|
end_date: '2026-01-31',
|
||||||
|
status: 'active',
|
||||||
|
applicable_products: ['category:electronics'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'promo-002',
|
||||||
|
name: '10% descuento con tarjeta',
|
||||||
|
type: 'percentage',
|
||||||
|
discount: 10,
|
||||||
|
start_date: '2026-01-01',
|
||||||
|
end_date: '2026-03-31',
|
||||||
|
status: 'active',
|
||||||
|
conditions: ['payment_method:card'],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
291
src/modules/mcp/tools/financial-tools.service.ts
Normal file
291
src/modules/mcp/tools/financial-tools.service.ts
Normal file
@ -0,0 +1,291 @@
|
|||||||
|
import {
|
||||||
|
McpToolProvider,
|
||||||
|
McpToolDefinition,
|
||||||
|
McpToolHandler,
|
||||||
|
McpContext,
|
||||||
|
} from '../interfaces';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Financial Tools Service
|
||||||
|
* Provides MCP tools for financial reporting and analysis.
|
||||||
|
* Used by: ADMIN role only
|
||||||
|
*/
|
||||||
|
export class FinancialToolsService implements McpToolProvider {
|
||||||
|
getTools(): McpToolDefinition[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: 'get_financial_report',
|
||||||
|
description: 'Genera reporte financiero (ingresos, gastos, utilidad)',
|
||||||
|
category: 'financial',
|
||||||
|
parameters: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
type: {
|
||||||
|
type: 'string',
|
||||||
|
enum: ['income', 'expenses', 'profit', 'summary'],
|
||||||
|
description: 'Tipo de reporte',
|
||||||
|
default: 'summary',
|
||||||
|
},
|
||||||
|
start_date: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'date',
|
||||||
|
description: 'Fecha inicial',
|
||||||
|
},
|
||||||
|
end_date: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'date',
|
||||||
|
description: 'Fecha final',
|
||||||
|
},
|
||||||
|
branch_id: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'uuid',
|
||||||
|
description: 'Filtrar por sucursal',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ['type'],
|
||||||
|
},
|
||||||
|
returns: { type: 'object' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'get_accounts_receivable',
|
||||||
|
description: 'Obtiene cuentas por cobrar (clientes que deben)',
|
||||||
|
category: 'financial',
|
||||||
|
parameters: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
status: {
|
||||||
|
type: 'string',
|
||||||
|
enum: ['all', 'current', 'overdue'],
|
||||||
|
default: 'all',
|
||||||
|
},
|
||||||
|
min_amount: { type: 'number' },
|
||||||
|
limit: { type: 'number', default: 50 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
returns: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
total: { type: 'number' },
|
||||||
|
count: { type: 'number' },
|
||||||
|
accounts: { type: 'array' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'get_accounts_payable',
|
||||||
|
description: 'Obtiene cuentas por pagar (deudas a proveedores)',
|
||||||
|
category: 'financial',
|
||||||
|
parameters: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
status: {
|
||||||
|
type: 'string',
|
||||||
|
enum: ['all', 'current', 'overdue'],
|
||||||
|
default: 'all',
|
||||||
|
},
|
||||||
|
due_date_before: { type: 'string', format: 'date' },
|
||||||
|
limit: { type: 'number', default: 50 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
returns: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
total: { type: 'number' },
|
||||||
|
count: { type: 'number' },
|
||||||
|
accounts: { type: 'array' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'get_cash_flow',
|
||||||
|
description: 'Analiza flujo de caja (entradas y salidas)',
|
||||||
|
category: 'financial',
|
||||||
|
parameters: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
period: {
|
||||||
|
type: 'string',
|
||||||
|
enum: ['week', 'month', 'quarter'],
|
||||||
|
default: 'month',
|
||||||
|
},
|
||||||
|
branch_id: { type: 'string', format: 'uuid' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
returns: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
inflows: { type: 'number' },
|
||||||
|
outflows: { type: 'number' },
|
||||||
|
net_flow: { type: 'number' },
|
||||||
|
by_category: { type: 'array' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'get_kpis',
|
||||||
|
description: 'Obtiene indicadores clave de desempeno (KPIs)',
|
||||||
|
category: 'financial',
|
||||||
|
parameters: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
period: {
|
||||||
|
type: 'string',
|
||||||
|
enum: ['month', 'quarter', 'year'],
|
||||||
|
default: 'month',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
returns: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
gross_margin: { type: 'number' },
|
||||||
|
net_margin: { type: 'number' },
|
||||||
|
inventory_turnover: { type: 'number' },
|
||||||
|
avg_collection_days: { type: 'number' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
getHandler(toolName: string): McpToolHandler | undefined {
|
||||||
|
const handlers: Record<string, McpToolHandler> = {
|
||||||
|
get_financial_report: this.getFinancialReport.bind(this),
|
||||||
|
get_accounts_receivable: this.getAccountsReceivable.bind(this),
|
||||||
|
get_accounts_payable: this.getAccountsPayable.bind(this),
|
||||||
|
get_cash_flow: this.getCashFlow.bind(this),
|
||||||
|
get_kpis: this.getKPIs.bind(this),
|
||||||
|
};
|
||||||
|
return handlers[toolName];
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getFinancialReport(
|
||||||
|
params: { type: string; start_date?: string; end_date?: string; branch_id?: string },
|
||||||
|
context: McpContext
|
||||||
|
): Promise<any> {
|
||||||
|
// TODO: Connect to FinancialService
|
||||||
|
return {
|
||||||
|
type: params.type,
|
||||||
|
period: {
|
||||||
|
start: params.start_date || new Date().toISOString().split('T')[0],
|
||||||
|
end: params.end_date || new Date().toISOString().split('T')[0],
|
||||||
|
},
|
||||||
|
income: 125000.00,
|
||||||
|
expenses: 85000.00,
|
||||||
|
gross_profit: 40000.00,
|
||||||
|
net_profit: 32000.00,
|
||||||
|
breakdown: {
|
||||||
|
sales: 120000.00,
|
||||||
|
services: 5000.00,
|
||||||
|
cost_of_goods: 65000.00,
|
||||||
|
operating_expenses: 20000.00,
|
||||||
|
taxes: 8000.00,
|
||||||
|
},
|
||||||
|
message: 'Conectar a FinancialService real',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getAccountsReceivable(
|
||||||
|
params: { status?: string; min_amount?: number; limit?: number },
|
||||||
|
context: McpContext
|
||||||
|
): Promise<any> {
|
||||||
|
// TODO: Connect to AccountsService
|
||||||
|
return {
|
||||||
|
total: 45000.00,
|
||||||
|
count: 12,
|
||||||
|
overdue_total: 15000.00,
|
||||||
|
overdue_count: 4,
|
||||||
|
accounts: [
|
||||||
|
{
|
||||||
|
customer: 'Cliente A',
|
||||||
|
amount: 5000.00,
|
||||||
|
due_date: '2026-01-20',
|
||||||
|
days_overdue: 5,
|
||||||
|
status: 'overdue',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
customer: 'Cliente B',
|
||||||
|
amount: 8000.00,
|
||||||
|
due_date: '2026-02-01',
|
||||||
|
days_overdue: 0,
|
||||||
|
status: 'current',
|
||||||
|
},
|
||||||
|
].slice(0, params.limit || 50),
|
||||||
|
message: 'Conectar a AccountsService real',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getAccountsPayable(
|
||||||
|
params: { status?: string; due_date_before?: string; limit?: number },
|
||||||
|
context: McpContext
|
||||||
|
): Promise<any> {
|
||||||
|
// TODO: Connect to AccountsService
|
||||||
|
return {
|
||||||
|
total: 32000.00,
|
||||||
|
count: 8,
|
||||||
|
overdue_total: 5000.00,
|
||||||
|
overdue_count: 2,
|
||||||
|
accounts: [
|
||||||
|
{
|
||||||
|
supplier: 'Proveedor X',
|
||||||
|
amount: 12000.00,
|
||||||
|
due_date: '2026-01-28',
|
||||||
|
status: 'current',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
supplier: 'Proveedor Y',
|
||||||
|
amount: 5000.00,
|
||||||
|
due_date: '2026-01-15',
|
||||||
|
days_overdue: 10,
|
||||||
|
status: 'overdue',
|
||||||
|
},
|
||||||
|
].slice(0, params.limit || 50),
|
||||||
|
message: 'Conectar a AccountsService real',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getCashFlow(
|
||||||
|
params: { period?: string; branch_id?: string },
|
||||||
|
context: McpContext
|
||||||
|
): Promise<any> {
|
||||||
|
// TODO: Connect to FinancialService
|
||||||
|
return {
|
||||||
|
period: params.period || 'month',
|
||||||
|
inflows: 95000.00,
|
||||||
|
outflows: 72000.00,
|
||||||
|
net_flow: 23000.00,
|
||||||
|
opening_balance: 45000.00,
|
||||||
|
closing_balance: 68000.00,
|
||||||
|
by_category: [
|
||||||
|
{ category: 'Ventas', type: 'inflow', amount: 90000.00 },
|
||||||
|
{ category: 'Cobranzas', type: 'inflow', amount: 5000.00 },
|
||||||
|
{ category: 'Compras', type: 'outflow', amount: 55000.00 },
|
||||||
|
{ category: 'Nomina', type: 'outflow', amount: 12000.00 },
|
||||||
|
{ category: 'Gastos operativos', type: 'outflow', amount: 5000.00 },
|
||||||
|
],
|
||||||
|
message: 'Conectar a FinancialService real',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getKPIs(
|
||||||
|
params: { period?: string },
|
||||||
|
context: McpContext
|
||||||
|
): Promise<any> {
|
||||||
|
// TODO: Connect to AnalyticsService
|
||||||
|
return {
|
||||||
|
period: params.period || 'month',
|
||||||
|
gross_margin: 32.5,
|
||||||
|
net_margin: 18.2,
|
||||||
|
inventory_turnover: 4.5,
|
||||||
|
avg_collection_days: 28,
|
||||||
|
current_ratio: 1.8,
|
||||||
|
quick_ratio: 1.2,
|
||||||
|
return_on_assets: 12.5,
|
||||||
|
trends: {
|
||||||
|
gross_margin_change: 2.1,
|
||||||
|
net_margin_change: 1.5,
|
||||||
|
},
|
||||||
|
message: 'Conectar a AnalyticsService real',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,3 +3,6 @@ export { InventoryToolsService } from './inventory-tools.service';
|
|||||||
export { OrdersToolsService } from './orders-tools.service';
|
export { OrdersToolsService } from './orders-tools.service';
|
||||||
export { CustomersToolsService } from './customers-tools.service';
|
export { CustomersToolsService } from './customers-tools.service';
|
||||||
export { FiadosToolsService } from './fiados-tools.service';
|
export { FiadosToolsService } from './fiados-tools.service';
|
||||||
|
export { SalesToolsService } from './sales-tools.service';
|
||||||
|
export { FinancialToolsService } from './financial-tools.service';
|
||||||
|
export { BranchToolsService } from './branch-tools.service';
|
||||||
|
|||||||
329
src/modules/mcp/tools/sales-tools.service.ts
Normal file
329
src/modules/mcp/tools/sales-tools.service.ts
Normal file
@ -0,0 +1,329 @@
|
|||||||
|
import {
|
||||||
|
McpToolProvider,
|
||||||
|
McpToolDefinition,
|
||||||
|
McpToolHandler,
|
||||||
|
McpContext,
|
||||||
|
} from '../interfaces';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sales Tools Service
|
||||||
|
* Provides MCP tools for sales management and reporting.
|
||||||
|
* Used by: ADMIN, SUPERVISOR, OPERATOR roles
|
||||||
|
*/
|
||||||
|
export class SalesToolsService implements McpToolProvider {
|
||||||
|
getTools(): McpToolDefinition[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: 'get_sales_summary',
|
||||||
|
description: 'Obtiene resumen de ventas del dia, semana o mes',
|
||||||
|
category: 'sales',
|
||||||
|
parameters: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
period: {
|
||||||
|
type: 'string',
|
||||||
|
enum: ['today', 'week', 'month', 'year'],
|
||||||
|
description: 'Periodo del resumen',
|
||||||
|
default: 'today',
|
||||||
|
},
|
||||||
|
branch_id: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'uuid',
|
||||||
|
description: 'Filtrar por sucursal (opcional)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
returns: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
total_sales: { type: 'number' },
|
||||||
|
transaction_count: { type: 'number' },
|
||||||
|
average_ticket: { type: 'number' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'get_sales_report',
|
||||||
|
description: 'Genera reporte detallado de ventas por rango de fechas',
|
||||||
|
category: 'sales',
|
||||||
|
parameters: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
start_date: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'date',
|
||||||
|
description: 'Fecha inicial (YYYY-MM-DD)',
|
||||||
|
},
|
||||||
|
end_date: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'date',
|
||||||
|
description: 'Fecha final (YYYY-MM-DD)',
|
||||||
|
},
|
||||||
|
group_by: {
|
||||||
|
type: 'string',
|
||||||
|
enum: ['day', 'week', 'month', 'branch', 'category', 'seller'],
|
||||||
|
description: 'Agrupar resultados por',
|
||||||
|
default: 'day',
|
||||||
|
},
|
||||||
|
branch_id: {
|
||||||
|
type: 'string',
|
||||||
|
format: 'uuid',
|
||||||
|
description: 'Filtrar por sucursal',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ['start_date', 'end_date'],
|
||||||
|
},
|
||||||
|
returns: { type: 'array', items: { type: 'object' } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'get_top_products',
|
||||||
|
description: 'Obtiene los productos mas vendidos',
|
||||||
|
category: 'sales',
|
||||||
|
parameters: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
period: {
|
||||||
|
type: 'string',
|
||||||
|
enum: ['today', 'week', 'month', 'year'],
|
||||||
|
default: 'month',
|
||||||
|
},
|
||||||
|
limit: { type: 'number', default: 10 },
|
||||||
|
branch_id: { type: 'string', format: 'uuid' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
returns: { type: 'array', items: { type: 'object' } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'get_top_customers',
|
||||||
|
description: 'Obtiene los clientes con mas compras',
|
||||||
|
category: 'sales',
|
||||||
|
parameters: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
period: {
|
||||||
|
type: 'string',
|
||||||
|
enum: ['month', 'quarter', 'year'],
|
||||||
|
default: 'month',
|
||||||
|
},
|
||||||
|
limit: { type: 'number', default: 10 },
|
||||||
|
order_by: {
|
||||||
|
type: 'string',
|
||||||
|
enum: ['amount', 'transactions'],
|
||||||
|
default: 'amount',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
returns: { type: 'array', items: { type: 'object' } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'get_sales_by_branch',
|
||||||
|
description: 'Compara ventas entre sucursales',
|
||||||
|
category: 'sales',
|
||||||
|
parameters: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
period: {
|
||||||
|
type: 'string',
|
||||||
|
enum: ['today', 'week', 'month'],
|
||||||
|
default: 'today',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
returns: { type: 'array', items: { type: 'object' } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'get_my_sales',
|
||||||
|
description: 'Obtiene las ventas del usuario actual (operador)',
|
||||||
|
category: 'sales',
|
||||||
|
parameters: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
period: {
|
||||||
|
type: 'string',
|
||||||
|
enum: ['today', 'week', 'month'],
|
||||||
|
default: 'today',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
returns: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
total: { type: 'number' },
|
||||||
|
count: { type: 'number' },
|
||||||
|
sales: { type: 'array' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'create_sale',
|
||||||
|
description: 'Registra una nueva venta',
|
||||||
|
category: 'sales',
|
||||||
|
parameters: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
items: {
|
||||||
|
type: 'array',
|
||||||
|
items: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
product_id: { type: 'string', format: 'uuid' },
|
||||||
|
quantity: { type: 'number', minimum: 1 },
|
||||||
|
unit_price: { type: 'number' },
|
||||||
|
discount: { type: 'number', default: 0 },
|
||||||
|
},
|
||||||
|
required: ['product_id', 'quantity'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
customer_id: { type: 'string', format: 'uuid' },
|
||||||
|
payment_method: {
|
||||||
|
type: 'string',
|
||||||
|
enum: ['cash', 'card', 'transfer', 'credit'],
|
||||||
|
},
|
||||||
|
notes: { type: 'string' },
|
||||||
|
},
|
||||||
|
required: ['items', 'payment_method'],
|
||||||
|
},
|
||||||
|
returns: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
sale_id: { type: 'string' },
|
||||||
|
total: { type: 'number' },
|
||||||
|
status: { type: 'string' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
getHandler(toolName: string): McpToolHandler | undefined {
|
||||||
|
const handlers: Record<string, McpToolHandler> = {
|
||||||
|
get_sales_summary: this.getSalesSummary.bind(this),
|
||||||
|
get_sales_report: this.getSalesReport.bind(this),
|
||||||
|
get_top_products: this.getTopProducts.bind(this),
|
||||||
|
get_top_customers: this.getTopCustomers.bind(this),
|
||||||
|
get_sales_by_branch: this.getSalesByBranch.bind(this),
|
||||||
|
get_my_sales: this.getMySales.bind(this),
|
||||||
|
create_sale: this.createSale.bind(this),
|
||||||
|
};
|
||||||
|
return handlers[toolName];
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getSalesSummary(
|
||||||
|
params: { period?: string; branch_id?: string },
|
||||||
|
context: McpContext
|
||||||
|
): Promise<any> {
|
||||||
|
// TODO: Connect to SalesService
|
||||||
|
const period = params.period || 'today';
|
||||||
|
return {
|
||||||
|
period,
|
||||||
|
branch_id: params.branch_id || 'all',
|
||||||
|
total_sales: 15750.00,
|
||||||
|
transaction_count: 42,
|
||||||
|
average_ticket: 375.00,
|
||||||
|
comparison: {
|
||||||
|
previous_period: 14200.00,
|
||||||
|
change_percent: 10.9,
|
||||||
|
},
|
||||||
|
message: 'Conectar a SalesService real',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getSalesReport(
|
||||||
|
params: { start_date: string; end_date: string; group_by?: string; branch_id?: string },
|
||||||
|
context: McpContext
|
||||||
|
): Promise<any[]> {
|
||||||
|
// TODO: Connect to SalesService
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
date: params.start_date,
|
||||||
|
total: 5250.00,
|
||||||
|
count: 15,
|
||||||
|
avg_ticket: 350.00,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: params.end_date,
|
||||||
|
total: 4800.00,
|
||||||
|
count: 12,
|
||||||
|
avg_ticket: 400.00,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getTopProducts(
|
||||||
|
params: { period?: string; limit?: number; branch_id?: string },
|
||||||
|
context: McpContext
|
||||||
|
): Promise<any[]> {
|
||||||
|
// TODO: Connect to SalesService
|
||||||
|
return [
|
||||||
|
{ rank: 1, product: 'Producto A', quantity: 150, revenue: 7500.00 },
|
||||||
|
{ rank: 2, product: 'Producto B', quantity: 120, revenue: 6000.00 },
|
||||||
|
{ rank: 3, product: 'Producto C', quantity: 100, revenue: 5000.00 },
|
||||||
|
].slice(0, params.limit || 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getTopCustomers(
|
||||||
|
params: { period?: string; limit?: number; order_by?: string },
|
||||||
|
context: McpContext
|
||||||
|
): Promise<any[]> {
|
||||||
|
// TODO: Connect to CustomersService
|
||||||
|
return [
|
||||||
|
{ rank: 1, customer: 'Cliente A', total: 25000.00, transactions: 15 },
|
||||||
|
{ rank: 2, customer: 'Cliente B', total: 18000.00, transactions: 12 },
|
||||||
|
].slice(0, params.limit || 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getSalesByBranch(
|
||||||
|
params: { period?: string },
|
||||||
|
context: McpContext
|
||||||
|
): Promise<any[]> {
|
||||||
|
// TODO: Connect to SalesService + BranchesService
|
||||||
|
return [
|
||||||
|
{ branch: 'Sucursal Centro', total: 8500.00, count: 25 },
|
||||||
|
{ branch: 'Sucursal Norte', total: 7250.00, count: 17 },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getMySales(
|
||||||
|
params: { period?: string },
|
||||||
|
context: McpContext
|
||||||
|
): Promise<any> {
|
||||||
|
// TODO: Connect to SalesService with context.userId
|
||||||
|
return {
|
||||||
|
user_id: context.userId,
|
||||||
|
period: params.period || 'today',
|
||||||
|
total: 3500.00,
|
||||||
|
count: 8,
|
||||||
|
sales: [
|
||||||
|
{ id: 'sale-1', total: 450.00, time: '10:30' },
|
||||||
|
{ id: 'sale-2', total: 680.00, time: '11:45' },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async createSale(
|
||||||
|
params: {
|
||||||
|
items: Array<{ product_id: string; quantity: number; unit_price?: number; discount?: number }>;
|
||||||
|
customer_id?: string;
|
||||||
|
payment_method: string;
|
||||||
|
notes?: string;
|
||||||
|
},
|
||||||
|
context: McpContext
|
||||||
|
): Promise<any> {
|
||||||
|
// TODO: Connect to SalesService
|
||||||
|
const total = params.items.reduce((sum, item) => {
|
||||||
|
const price = item.unit_price || 100; // Default price for demo
|
||||||
|
const discount = item.discount || 0;
|
||||||
|
return sum + (price * item.quantity * (1 - discount / 100));
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
return {
|
||||||
|
sale_id: `SALE-${Date.now()}`,
|
||||||
|
total,
|
||||||
|
items_count: params.items.length,
|
||||||
|
payment_method: params.payment_method,
|
||||||
|
status: 'completed',
|
||||||
|
created_by: context.userId,
|
||||||
|
message: 'Conectar a SalesService real',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user