next-finance-mcp 0.5.2 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.ts +30 -0
- package/dist/client.js +67 -3
- package/dist/index.js +34 -0
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -44,6 +44,36 @@ export declare function listarPlanoDeContas(filtro?: FiltroPlanoDeContas): Promi
|
|
|
44
44
|
export declare function listarCentrosDeCusto(busca?: string): Promise<{
|
|
45
45
|
centros: Record<string, unknown>[];
|
|
46
46
|
}>;
|
|
47
|
+
export interface FiltroComprasProduto {
|
|
48
|
+
pessoaId?: string;
|
|
49
|
+
dataInicio?: string;
|
|
50
|
+
dataFim?: string;
|
|
51
|
+
busca?: string;
|
|
52
|
+
pagina?: number;
|
|
53
|
+
limite?: number;
|
|
54
|
+
}
|
|
55
|
+
export declare function buscarComprasProduto(opts?: FiltroComprasProduto): Promise<{
|
|
56
|
+
compras: {
|
|
57
|
+
codigo: string;
|
|
58
|
+
produto: string;
|
|
59
|
+
fornecedor: string;
|
|
60
|
+
fornecedor_id: string;
|
|
61
|
+
moeda: string;
|
|
62
|
+
valor: number;
|
|
63
|
+
data: string;
|
|
64
|
+
}[];
|
|
65
|
+
paginacao: {
|
|
66
|
+
pagina: number;
|
|
67
|
+
limite: number;
|
|
68
|
+
total: number;
|
|
69
|
+
paginas: number;
|
|
70
|
+
tem_mais: boolean;
|
|
71
|
+
};
|
|
72
|
+
periodo: {
|
|
73
|
+
inicio: string;
|
|
74
|
+
fim: string;
|
|
75
|
+
};
|
|
76
|
+
}>;
|
|
47
77
|
export declare function listarTiposConta(): Promise<{
|
|
48
78
|
tipos: Record<string, unknown>[];
|
|
49
79
|
}>;
|
package/dist/client.js
CHANGED
|
@@ -305,7 +305,58 @@ export async function listarCentrosDeCusto(busca) {
|
|
|
305
305
|
}
|
|
306
306
|
return { centros: centros };
|
|
307
307
|
}
|
|
308
|
-
|
|
308
|
+
export async function buscarComprasProduto(opts = {}) {
|
|
309
|
+
const today = new Date();
|
|
310
|
+
const dataInicio = opts.dataInicio ?? `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, "0")}-01`;
|
|
311
|
+
const dataFim = opts.dataFim ?? today.toISOString().slice(0, 10);
|
|
312
|
+
const pagina = Math.max(1, opts.pagina ?? 1);
|
|
313
|
+
const limite = Math.min(200, Math.max(1, opts.limite ?? 50));
|
|
314
|
+
const body = {
|
|
315
|
+
DataInicial: dataInicio,
|
|
316
|
+
DataFinal: dataFim,
|
|
317
|
+
};
|
|
318
|
+
if (opts.pessoaId)
|
|
319
|
+
body["PessoaId"] = opts.pessoaId;
|
|
320
|
+
const raw = await apiPost("/api/ProdutoBusiness/FiltrarCompra", body);
|
|
321
|
+
let items = (Array.isArray(raw) ? raw : []);
|
|
322
|
+
// Filtro client-side por nome do produto
|
|
323
|
+
if (opts.busca?.trim()) {
|
|
324
|
+
const t = opts.busca.trim().toLowerCase();
|
|
325
|
+
items = items.filter(item => {
|
|
326
|
+
const prod = item["ProdutoBusiness"];
|
|
327
|
+
const nome = String(prod?.["Nome"] ?? item["Codigo"] ?? "").toLowerCase();
|
|
328
|
+
return nome.includes(t);
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
// Paginação client-side
|
|
332
|
+
const total = items.length;
|
|
333
|
+
const offset = (pagina - 1) * limite;
|
|
334
|
+
const paginados = items.slice(offset, offset + limite);
|
|
335
|
+
// Slim: campos essenciais
|
|
336
|
+
const compras = paginados.map(item => {
|
|
337
|
+
const prod = item["ProdutoBusiness"];
|
|
338
|
+
return {
|
|
339
|
+
codigo: String(item["Codigo"] ?? ""),
|
|
340
|
+
produto: String(prod?.["Nome"] ?? ""),
|
|
341
|
+
fornecedor: String(item["PessoaNome"] ?? ""),
|
|
342
|
+
fornecedor_id: String(item["PessoaId"] ?? ""),
|
|
343
|
+
moeda: String(item["MoedaNome"] ?? "BRL"),
|
|
344
|
+
valor: Number(item["Valor"] ?? 0),
|
|
345
|
+
data: String(item["DataAtualizacao"] ?? "").slice(0, 10),
|
|
346
|
+
};
|
|
347
|
+
});
|
|
348
|
+
return {
|
|
349
|
+
compras,
|
|
350
|
+
paginacao: {
|
|
351
|
+
pagina,
|
|
352
|
+
limite,
|
|
353
|
+
total,
|
|
354
|
+
paginas: Math.ceil(total / limite),
|
|
355
|
+
tem_mais: offset + limite < total,
|
|
356
|
+
},
|
|
357
|
+
periodo: { inicio: dataInicio, fim: dataFim },
|
|
358
|
+
};
|
|
359
|
+
}
|
|
309
360
|
export async function listarTiposConta() {
|
|
310
361
|
const raw = await apiGet("/api/TipoConta");
|
|
311
362
|
const tipos = Array.isArray(raw) ? raw : Object.values(raw).find(v => Array.isArray(v)) ?? [];
|
|
@@ -364,6 +415,18 @@ export async function buscarLancamentos(opts) {
|
|
|
364
415
|
lancamentos = Array.isArray(raw) ? raw
|
|
365
416
|
: (Object.values(raw).find(v => Array.isArray(v)) ?? []);
|
|
366
417
|
}
|
|
418
|
+
// Helpers para verificar plano/centro tanto no lançamento raiz quanto nas divisões
|
|
419
|
+
// (lançamentos rateados têm NomePlanoDeContas vazio no raiz e preenchido em ListaLancamentoDivisao)
|
|
420
|
+
function nomesPlano(l) {
|
|
421
|
+
const raiz = String(l["NomePlanoDeContas"] ?? "");
|
|
422
|
+
const divs = l["ListaLancamentoDivisao"] ?? [];
|
|
423
|
+
return [raiz, ...divs.map(d => String(d["NomePlanoDeContas"] ?? ""))].filter(Boolean);
|
|
424
|
+
}
|
|
425
|
+
function nomesCentro(l) {
|
|
426
|
+
const raiz = String(l["NomeCentroDeCustos"] ?? "");
|
|
427
|
+
const divs = l["ListaLancamentoDivisao"] ?? [];
|
|
428
|
+
return [raiz, ...divs.map(d => String(d["NomeCentroDeCustos"] ?? ""))].filter(Boolean);
|
|
429
|
+
}
|
|
367
430
|
// Filtros client-side (a API não filtra por plano/centro/tipo)
|
|
368
431
|
const excluirTransf = opts.excluirTransferencias !== false; // default: true
|
|
369
432
|
if (excluirTransf)
|
|
@@ -376,11 +439,12 @@ export async function buscarLancamentos(opts) {
|
|
|
376
439
|
lancamentos = lancamentos.filter(l => l["Receita"]);
|
|
377
440
|
if (opts.planoDeContas?.trim()) {
|
|
378
441
|
const t = opts.planoDeContas.trim().toLowerCase();
|
|
379
|
-
|
|
442
|
+
// inclui lançamento se plano bate no raiz OU em qualquer divisão
|
|
443
|
+
lancamentos = lancamentos.filter(l => nomesPlano(l).some(n => n.toLowerCase().includes(t)));
|
|
380
444
|
}
|
|
381
445
|
if (opts.centroDeCusto?.trim()) {
|
|
382
446
|
const t = opts.centroDeCusto.trim().toLowerCase();
|
|
383
|
-
lancamentos = lancamentos.filter(l =>
|
|
447
|
+
lancamentos = lancamentos.filter(l => nomesCentro(l).some(n => n.toLowerCase().includes(t)));
|
|
384
448
|
}
|
|
385
449
|
if (opts.busca?.trim()) {
|
|
386
450
|
const t = opts.busca.trim().toLowerCase();
|
package/dist/index.js
CHANGED
|
@@ -109,6 +109,24 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
109
109
|
},
|
|
110
110
|
},
|
|
111
111
|
},
|
|
112
|
+
{
|
|
113
|
+
name: "buscar_compras_produto",
|
|
114
|
+
description: "Busca compras de produtos agrupadas por produto e fornecedor. " +
|
|
115
|
+
"Use 'busca' para filtrar pelo nome do produto (ex: 'bombom garoto', 'arroz'). " +
|
|
116
|
+
"Use 'pessoa_id' para filtrar por fornecedor específico. " +
|
|
117
|
+
"Ideal para ver histórico de compras, comparar preços e rastrear aquisições.",
|
|
118
|
+
inputSchema: {
|
|
119
|
+
type: "object",
|
|
120
|
+
properties: {
|
|
121
|
+
busca: { type: "string", description: "Filtra pelo nome do produto (ex: 'bombom garoto', 'leite')" },
|
|
122
|
+
pessoa_id: { type: "string", description: "ID do fornecedor (opcional)" },
|
|
123
|
+
data_inicio: { type: "string", description: "Data início YYYY-MM-DD (padrão: 1º do mês atual)" },
|
|
124
|
+
data_fim: { type: "string", description: "Data fim YYYY-MM-DD (padrão: hoje)" },
|
|
125
|
+
pagina: { type: "number", description: "Página (começa em 1, padrão: 1)" },
|
|
126
|
+
limite: { type: "number", description: "Itens por página (padrão: 50, máximo: 200)" },
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
},
|
|
112
130
|
],
|
|
113
131
|
}));
|
|
114
132
|
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
@@ -222,6 +240,22 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
222
240
|
limite: args["limite"],
|
|
223
241
|
}));
|
|
224
242
|
}
|
|
243
|
+
case "buscar_compras_produto": {
|
|
244
|
+
const authErr = requireAuth();
|
|
245
|
+
if (authErr)
|
|
246
|
+
return authErr;
|
|
247
|
+
const walErr = requireWallet();
|
|
248
|
+
if (walErr)
|
|
249
|
+
return walErr;
|
|
250
|
+
return ok(await client.buscarComprasProduto({
|
|
251
|
+
pessoaId: args["pessoa_id"],
|
|
252
|
+
dataInicio: args["data_inicio"],
|
|
253
|
+
dataFim: args["data_fim"],
|
|
254
|
+
busca: args["busca"],
|
|
255
|
+
pagina: args["pagina"],
|
|
256
|
+
limite: args["limite"],
|
|
257
|
+
}));
|
|
258
|
+
}
|
|
225
259
|
default:
|
|
226
260
|
return ok({ erro: `Ferramenta desconhecida: ${name}` });
|
|
227
261
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "next-finance-mcp",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.4",
|
|
4
4
|
"mcpName": "io.github.paivapiovesan/next-finance",
|
|
5
5
|
"description": "MCP Server para o NEXT Finance (finance.net.br) — login via browser, listagem de carteiras, contas e lançamentos",
|
|
6
6
|
"type": "module",
|