[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,
|
||||
CustomersToolsService,
|
||||
FiadosToolsService,
|
||||
SalesToolsService,
|
||||
FinancialToolsService,
|
||||
BranchToolsService,
|
||||
} from './tools';
|
||||
|
||||
export interface McpModuleOptions {
|
||||
@ -48,6 +51,9 @@ export class McpModule {
|
||||
this.toolRegistry.registerProvider(new OrdersToolsService());
|
||||
this.toolRegistry.registerProvider(new CustomersToolsService());
|
||||
this.toolRegistry.registerProvider(new FiadosToolsService());
|
||||
this.toolRegistry.registerProvider(new SalesToolsService());
|
||||
this.toolRegistry.registerProvider(new FinancialToolsService());
|
||||
this.toolRegistry.registerProvider(new BranchToolsService());
|
||||
|
||||
// MCP Server Service
|
||||
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 { CustomersToolsService } from './customers-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