next-finance-mcp 0.9.21 → 0.9.22

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 CHANGED
@@ -121,7 +121,10 @@ export declare function buscarComprasProduto(opts?: FiltroComprasProduto): Promi
121
121
  fornecedor: string;
122
122
  moeda: string;
123
123
  valor: number;
124
+ quantidade: number;
125
+ valor_total: number;
124
126
  data: string;
127
+ observacao: string;
125
128
  }[];
126
129
  paginacao: {
127
130
  pagina: number;
@@ -200,6 +203,9 @@ export interface ItemDespesaSlim {
200
203
  valor: number;
201
204
  desconto: number;
202
205
  valor_total: number;
206
+ valor_bruto?: number;
207
+ valor_total_bruto?: number;
208
+ desconto_aplicado?: number;
203
209
  }
204
210
  export interface DespesaSlim {
205
211
  data: string;
package/dist/client.js CHANGED
@@ -851,15 +851,22 @@ export async function buscarComprasProduto(opts = {}) {
851
851
  const total = items.length;
852
852
  const offset = (pagina - 1) * limite;
853
853
  const paginados = items.slice(offset, offset + limite);
854
- // Slim: apenas campos legíveis — sem IDs
854
+ // Slim: apenas campos legíveis — sem IDs.
855
+ // Nota: o endpoint /api/ProdutoBusiness/FiltrarCompra retorna o produto cadastrado
856
+ // (agregação por produto). Não traz a Despesa pai, então NÃO há como ratear desconto
857
+ // a nível de documento aqui. Use ultimo_preco_produto para obter o preço REAL pago
858
+ // (que cruza com Despesa/FiltrarDespesaServProd e aplica desconto proporcional).
855
859
  const compras = paginados.map(item => {
856
860
  const prod = item["ProdutoBusiness"];
857
861
  return {
858
- produto: String(prod?.["Nome"] ?? ""),
862
+ produto: String(prod?.["Descricao"] ?? prod?.["Nome"] ?? item["Codigo"] ?? ""),
859
863
  fornecedor: String(item["PessoaNome"] ?? ""),
860
864
  moeda: String(item["MoedaNome"] ?? "BRL"),
861
- valor: Number(item["Valor"] ?? 0),
865
+ valor: Number(item["Valor"] ?? 0), // preço bruto unitário (sem ratear desconto)
866
+ quantidade: Number(item["Quantidade"] ?? 0),
867
+ valor_total: Number(item["ValorTotal"] ?? 0),
862
868
  data: String(item["DataAtualizacao"] ?? "").slice(0, 10),
869
+ observacao: "Preço bruto sem desconto da nota. Para preço real pago, use 'ultimo_preco_produto'.",
863
870
  };
864
871
  });
865
872
  return {
@@ -1088,15 +1095,43 @@ async function resolverIdFornecedor(nome) {
1088
1095
  const primeiro = arr[0];
1089
1096
  return String(primeiro["Id"] ?? "");
1090
1097
  }
1091
- function slimItemDespesa(i) {
1098
+ /** Calcula valores REAIS (com desconto da nota distribuído) para um item de DespesaServProd.
1099
+ * Pode receber a Despesa pai inline (do FiltrarDespesaServProd) ou separadamente. */
1100
+ function aplicarDescontoProporcional(item, despesa) {
1101
+ const qtd = Number(item["Quantidade"] ?? 0);
1102
+ const valorBruto = Number(item["Valor"] ?? 0);
1103
+ const totalBruto = Number(item["ValorTotal"] ?? (qtd > 0 ? qtd * valorBruto : valorBruto));
1104
+ if (!despesa)
1105
+ return { precoUnitario: valorBruto, valorTotal: totalBruto };
1106
+ const despBruto = Number(despesa["Valor"] ?? 0);
1107
+ const despLiquido = Number(despesa["ValorLiquido"] ?? despBruto);
1108
+ if (despBruto <= 0 || Math.abs(despBruto - despLiquido) < 0.01) {
1109
+ return { precoUnitario: valorBruto, valorTotal: totalBruto };
1110
+ }
1111
+ const fator = despLiquido / despBruto;
1112
+ const totalReal = Math.round(totalBruto * fator * 100) / 100;
1113
+ const precoReal = qtd > 0 ? Math.round((totalReal / qtd) * 100) / 100 : valorBruto * fator;
1114
+ return {
1115
+ precoUnitario: precoReal,
1116
+ valorTotal: totalReal,
1117
+ descontoAplicado: Math.round((totalBruto - totalReal) * 100) / 100,
1118
+ precoUnitarioBruto: valorBruto,
1119
+ valorTotalBruto: totalBruto,
1120
+ };
1121
+ }
1122
+ function slimItemDespesa(i, despesa) {
1123
+ const calc = aplicarDescontoProporcional(i, despesa);
1092
1124
  return {
1093
1125
  descricao: String(i["DescricaoServProd"] ?? "").trim(),
1094
1126
  codigo: i["Codigo"] ? String(i["Codigo"]).trim() : undefined,
1095
1127
  quantidade: Number(i["Quantidade"] ?? 0),
1096
1128
  unidade: i["UnidadeMedida"] ? String(i["UnidadeMedida"]).trim() : undefined,
1097
- valor: Number(i["Valor"] ?? 0),
1129
+ valor: calc.precoUnitario,
1098
1130
  desconto: Number(i["Desconto"] ?? 0),
1099
- valor_total: Number(i["ValorTotal"] ?? 0),
1131
+ valor_total: calc.valorTotal,
1132
+ valor_bruto: calc.precoUnitarioBruto,
1133
+ valor_total_bruto: calc.valorTotalBruto,
1134
+ desconto_aplicado: calc.descontoAplicado,
1100
1135
  };
1101
1136
  }
1102
1137
  function slimDespesa(d, comItens) {
@@ -1110,7 +1145,8 @@ function slimDespesa(d, comItens) {
1110
1145
  valor_liquido: Number(d["ValorLiquido"] ?? 0),
1111
1146
  };
1112
1147
  if (comItens && itensRaw.length > 0) {
1113
- result.itens = itensRaw.map(slimItemDespesa);
1148
+ // Passa a despesa pai (d) pra distribuir descontos proporcionalmente
1149
+ result.itens = itensRaw.map(i => slimItemDespesa(i, d));
1114
1150
  }
1115
1151
  return result;
1116
1152
  }
@@ -1179,19 +1215,23 @@ export async function buscarItensDespesa(opts = {}) {
1179
1215
  const total = itens.length;
1180
1216
  const inicio = (pagina - 1) * limite;
1181
1217
  const resultado = itens.slice(inicio, inicio + limite).map(i => {
1182
- const despesa = i["Despesa"] ?? {};
1218
+ const despesa = i["Despesa"] ?? null;
1219
+ const calc = aplicarDescontoProporcional(i, despesa);
1183
1220
  return {
1184
1221
  descricao: String(i["DescricaoServProd"] ?? "").trim(),
1185
1222
  codigo: i["Codigo"] ? String(i["Codigo"]).trim() : undefined,
1186
1223
  quantidade: Number(i["Quantidade"] ?? 0),
1187
1224
  unidade: i["UnidadeMedida"] ? String(i["UnidadeMedida"]).trim() : undefined,
1188
- valor: Number(i["Valor"] ?? 0),
1225
+ valor: calc.precoUnitario, // REAL pago
1189
1226
  desconto: Number(i["Desconto"] ?? 0),
1190
- valor_total: Number(i["ValorTotal"] ?? 0),
1227
+ valor_total: calc.valorTotal, // REAL pago
1228
+ valor_bruto: calc.precoUnitarioBruto,
1229
+ valor_total_bruto: calc.valorTotalBruto,
1230
+ desconto_aplicado: calc.descontoAplicado,
1191
1231
  // Dados do documento pai — sem IDs
1192
- data: String(despesa["Data"] ?? "").slice(0, 10),
1193
- numero: String(despesa["Numero"] ?? "").trim(),
1194
- fornecedor: String(despesa["PessoaNome"] ?? "").trim(),
1232
+ data: String(despesa?.["Data"] ?? "").slice(0, 10),
1233
+ numero: String(despesa?.["Numero"] ?? "").trim(),
1234
+ fornecedor: String(despesa?.["PessoaNome"] ?? "").trim(),
1195
1235
  };
1196
1236
  });
1197
1237
  return {
@@ -1541,36 +1581,16 @@ export async function ultimoPrecoProduto(opts) {
1541
1581
  const dataIso = String(it["DataAtualizacao"] ?? "");
1542
1582
  const despesa = it["Despesa"] ?? null;
1543
1583
  const data = dataIso || String(despesa?.["Data"] ?? "");
1544
- const qtd = Number(it["Quantidade"] ?? 0);
1545
- const valorBruto = Number(it["Valor"] ?? 0);
1546
- const totalBruto = Number(it["ValorTotal"] ?? (qtd > 0 ? qtd * valorBruto : valorBruto));
1547
- // Distribui descontos a nível de despesa proporcionalmente ao valor do item.
1548
- // Despesa.Valor = total bruto; Despesa.ValorLiquido = líquido pago.
1549
- // Fator = ValorLiquido / Valor (entre 0 e 1).
1550
- let precoUnitarioReal = valorBruto;
1551
- let totalReal = totalBruto;
1552
- let descontoAplicado;
1553
- let precoBrutoOut;
1554
- if (despesa) {
1555
- const despBruto = Number(despesa["Valor"] ?? 0);
1556
- const despLiquido = Number(despesa["ValorLiquido"] ?? despBruto);
1557
- if (despBruto > 0 && Math.abs(despBruto - despLiquido) > 0.01) {
1558
- const fator = despLiquido / despBruto;
1559
- totalReal = Math.round(totalBruto * fator * 100) / 100;
1560
- precoUnitarioReal = qtd > 0 ? Math.round((totalReal / qtd) * 100) / 100 : valorBruto * fator;
1561
- descontoAplicado = Math.round((totalBruto - totalReal) * 100) / 100;
1562
- precoBrutoOut = valorBruto;
1563
- }
1564
- }
1584
+ const calc = aplicarDescontoProporcional(it, despesa);
1565
1585
  return {
1566
1586
  data: data.slice(0, 10),
1567
1587
  produto: nomeProd.trim(),
1568
1588
  fornecedor: String(it["PessoaNome"] ?? despesa?.["PessoaNome"] ?? "").trim(),
1569
- preco_unitario: precoUnitarioReal,
1570
- quantidade: qtd,
1571
- valor_total: totalReal,
1572
- preco_unitario_bruto: precoBrutoOut,
1573
- desconto_aplicado: descontoAplicado,
1589
+ preco_unitario: calc.precoUnitario,
1590
+ quantidade: Number(it["Quantidade"] ?? 0),
1591
+ valor_total: calc.valorTotal,
1592
+ preco_unitario_bruto: calc.precoUnitarioBruto,
1593
+ desconto_aplicado: calc.descontoAplicado,
1574
1594
  moeda: it["MoedaNome"] ? String(it["MoedaNome"]) : undefined,
1575
1595
  };
1576
1596
  })
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
8
8
  import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
9
9
  import * as client from "./client.js";
10
10
  import { openLoginUI } from "./login-server.js";
11
- const server = new Server({ name: "next-finance-mcp", version: "0.9.21" }, { capabilities: { tools: {} } });
11
+ const server = new Server({ name: "next-finance-mcp", version: "0.9.22" }, { capabilities: { tools: {} } });
12
12
  // ── Ferramentas ─────────────────────────────────────────────────────────────
13
13
  server.setRequestHandler(ListToolsRequestSchema, async () => ({
14
14
  tools: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "next-finance-mcp",
3
- "version": "0.9.21",
3
+ "version": "0.9.22",
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",