@quantyapp/quanty-mcp-server 1.0.7 → 1.0.9
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/core/bankService.d.ts +12 -2
- package/dist/core/bankService.d.ts.map +1 -1
- package/dist/core/bankService.js +65 -43
- package/dist/core/budgetService.d.ts +3 -0
- package/dist/core/budgetService.d.ts.map +1 -1
- package/dist/core/budgetService.js +38 -10
- package/dist/mcp/index.js +9 -19
- package/package.json +1 -1
|
@@ -8,6 +8,15 @@ export interface BankSummary {
|
|
|
8
8
|
visibility: 'public' | 'private' | 'subscription';
|
|
9
9
|
categoryCount: number;
|
|
10
10
|
}
|
|
11
|
+
export interface CompositionInput {
|
|
12
|
+
id: string;
|
|
13
|
+
code: string;
|
|
14
|
+
description: string;
|
|
15
|
+
unit: string;
|
|
16
|
+
quantity: number;
|
|
17
|
+
unitCost: number;
|
|
18
|
+
itemType?: string;
|
|
19
|
+
}
|
|
11
20
|
export interface BankItem {
|
|
12
21
|
id: string;
|
|
13
22
|
code: string;
|
|
@@ -15,7 +24,8 @@ export interface BankItem {
|
|
|
15
24
|
unit: string;
|
|
16
25
|
unitCost: number;
|
|
17
26
|
itemType?: string;
|
|
18
|
-
|
|
27
|
+
isComposition: boolean;
|
|
28
|
+
composition?: CompositionInput[];
|
|
19
29
|
}
|
|
20
30
|
export interface BankCategory {
|
|
21
31
|
id: string;
|
|
@@ -39,7 +49,7 @@ export declare function searchBankItems(bankId: string, query: string, limit?: n
|
|
|
39
49
|
/**
|
|
40
50
|
* Prepares importing an item from bank to budget
|
|
41
51
|
*/
|
|
42
|
-
export declare function prepareImportItem(budgetId: string, bankItem: BankItem): {
|
|
52
|
+
export declare function prepareImportItem(budgetId: string, bankItem: BankItem, quantity: number): {
|
|
43
53
|
action: string;
|
|
44
54
|
preview: string;
|
|
45
55
|
data: any;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bankService.d.ts","sourceRoot":"","sources":["../../src/core/bankService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,MAAM,WAAW,WAAW;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,QAAQ,GAAG,SAAS,GAAG,cAAc,CAAC;IAClD,aAAa,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,QAAQ;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"bankService.d.ts","sourceRoot":"","sources":["../../src/core/bankService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,MAAM,WAAW,WAAW;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,QAAQ,GAAG,SAAS,GAAG,cAAc,CAAC;IAClD,aAAa,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACpC;AAED,MAAM,WAAW,YAAY;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACrB;AA+CD;;GAEG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAkBzE;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAgB/E;AAgBD;;;GAGG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAwF5G;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC7B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,MAAM,GACjB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,GAAG,CAAA;CAAE,CA+BhD;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CA+C9F;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAyC9F"}
|
package/dist/core/bankService.js
CHANGED
|
@@ -1,4 +1,46 @@
|
|
|
1
1
|
import { supabase } from './supabase.js';
|
|
2
|
+
// === HELPER FUNCTIONS FOR COMPOSITION PARSING ===
|
|
3
|
+
function isItemComposition(item) {
|
|
4
|
+
if (item.composition && Array.isArray(item.composition) && item.composition.length > 0)
|
|
5
|
+
return true;
|
|
6
|
+
if (item.itemType?.toLowerCase().includes('compos'))
|
|
7
|
+
return true;
|
|
8
|
+
if (item.code?.startsWith('C.'))
|
|
9
|
+
return true;
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
function extractCompositionInputs(item) {
|
|
13
|
+
const sources = ['composition', 'children', 'insumos', 'items', 'components'];
|
|
14
|
+
for (const key of sources) {
|
|
15
|
+
if (item[key] && Array.isArray(item[key]) && item[key].length > 0) {
|
|
16
|
+
return item[key].map((input) => ({
|
|
17
|
+
id: input.id || crypto.randomUUID(),
|
|
18
|
+
code: input.code || '',
|
|
19
|
+
description: input.description || '',
|
|
20
|
+
unit: input.unit || '',
|
|
21
|
+
quantity: input.quantity || input.coefficient || input.coeficiente || 0,
|
|
22
|
+
unitCost: input.unitCost || input.unit_cost || 0,
|
|
23
|
+
itemType: input.itemType || input.type || 'INSUMO'
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
function toBankItem(item) {
|
|
30
|
+
const isComp = isItemComposition(item);
|
|
31
|
+
const inputs = extractCompositionInputs(item);
|
|
32
|
+
return {
|
|
33
|
+
id: item.id,
|
|
34
|
+
code: item.code || '',
|
|
35
|
+
description: item.description || '',
|
|
36
|
+
unit: item.unit || '',
|
|
37
|
+
unitCost: item.unitCost || 0,
|
|
38
|
+
itemType: isComp ? 'Composição' : (item.itemType || 'Insumo'),
|
|
39
|
+
isComposition: isComp,
|
|
40
|
+
composition: inputs.length > 0 ? inputs : undefined
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
// ===============================================
|
|
2
44
|
/**
|
|
3
45
|
* Lists available composition banks for the tenant
|
|
4
46
|
*/
|
|
@@ -91,29 +133,10 @@ export async function searchBankItems(bankId, query, limit = 50) {
|
|
|
91
133
|
return true;
|
|
92
134
|
if (matchesQuery(item)) {
|
|
93
135
|
seenIds.add(item.id);
|
|
94
|
-
results.push(
|
|
95
|
-
id: item.id,
|
|
96
|
-
code: item.code || '',
|
|
97
|
-
description: item.description || '',
|
|
98
|
-
unit: item.unit || '',
|
|
99
|
-
unitCost: item.unitCost || 0,
|
|
100
|
-
itemType: item.itemType || detectItemType(item),
|
|
101
|
-
composition: item.composition // Mantém referência para importação
|
|
102
|
-
});
|
|
136
|
+
results.push(toBankItem(item)); // Usa o Helper toBankItem
|
|
103
137
|
}
|
|
104
138
|
return results.length < limit;
|
|
105
139
|
}
|
|
106
|
-
/**
|
|
107
|
-
* Detecta o tipo do item baseado na estrutura
|
|
108
|
-
*/
|
|
109
|
-
function detectItemType(item) {
|
|
110
|
-
if (item.composition && item.composition.length > 0) {
|
|
111
|
-
return 'Composição';
|
|
112
|
-
}
|
|
113
|
-
if (item.itemType)
|
|
114
|
-
return item.itemType;
|
|
115
|
-
return 'Insumo';
|
|
116
|
-
}
|
|
117
140
|
/**
|
|
118
141
|
* RECURSÃO PROFUNDA: Busca em qualquer estrutura de nós
|
|
119
142
|
* Suporta: items, children, composition, categories
|
|
@@ -142,6 +165,8 @@ export async function searchBankItems(bankId, query, limit = 50) {
|
|
|
142
165
|
return false;
|
|
143
166
|
}
|
|
144
167
|
// Busca recursiva em todas as propriedades que podem conter filhos
|
|
168
|
+
// NOTA: 'composition' e 'items' dentro de um item podem ser ignorados se quisermos só buscar itens "pai"
|
|
169
|
+
// mas para profundidade máxima vamos varrer tudo. O addIfMatches filtra duplicatas pelo ID.
|
|
145
170
|
const childKeys = ['items', 'children', 'composition', 'categories', 'rows'];
|
|
146
171
|
for (const key of childKeys) {
|
|
147
172
|
if (node[key] && Array.isArray(node[key])) {
|
|
@@ -159,19 +184,32 @@ export async function searchBankItems(bankId, query, limit = 50) {
|
|
|
159
184
|
/**
|
|
160
185
|
* Prepares importing an item from bank to budget
|
|
161
186
|
*/
|
|
162
|
-
export function prepareImportItem(budgetId, bankItem) {
|
|
187
|
+
export function prepareImportItem(budgetId, bankItem, quantity) {
|
|
188
|
+
let compositionForBudget = undefined;
|
|
189
|
+
if (bankItem.isComposition && bankItem.composition && bankItem.composition.length > 0) {
|
|
190
|
+
compositionForBudget = bankItem.composition.map(input => ({
|
|
191
|
+
id: crypto.randomUUID(),
|
|
192
|
+
code: input.code,
|
|
193
|
+
description: input.description,
|
|
194
|
+
unit: input.unit,
|
|
195
|
+
quantity: input.quantity,
|
|
196
|
+
unitCost: input.unitCost,
|
|
197
|
+
itemType: input.itemType
|
|
198
|
+
}));
|
|
199
|
+
}
|
|
163
200
|
return {
|
|
164
201
|
action: 'import_item',
|
|
165
|
-
preview: `Importar "${bankItem.description}" (${bankItem.unit}) do banco para o orçamento`,
|
|
202
|
+
preview: `Importar "${bankItem.description}" (${quantity} ${bankItem.unit}) do banco para o orçamento`,
|
|
166
203
|
data: {
|
|
167
204
|
budgetId,
|
|
168
205
|
item: {
|
|
206
|
+
code: bankItem.code,
|
|
169
207
|
description: bankItem.description,
|
|
170
208
|
unit: bankItem.unit,
|
|
171
|
-
quantity:
|
|
209
|
+
quantity: quantity,
|
|
172
210
|
unitCost: bankItem.unitCost,
|
|
173
|
-
isComposition:
|
|
174
|
-
composition:
|
|
211
|
+
isComposition: bankItem.isComposition,
|
|
212
|
+
composition: compositionForBudget
|
|
175
213
|
}
|
|
176
214
|
}
|
|
177
215
|
};
|
|
@@ -206,15 +244,7 @@ export async function getBankItemById(bankId, itemId) {
|
|
|
206
244
|
if (typeof node === 'object') {
|
|
207
245
|
// Verifica se é o item procurado
|
|
208
246
|
if (node.id === itemId) {
|
|
209
|
-
foundItem =
|
|
210
|
-
id: node.id,
|
|
211
|
-
code: node.code || '',
|
|
212
|
-
description: node.description || '',
|
|
213
|
-
unit: node.unit || '',
|
|
214
|
-
unitCost: node.unitCost || 0,
|
|
215
|
-
itemType: node.itemType,
|
|
216
|
-
composition: node.composition
|
|
217
|
-
};
|
|
247
|
+
foundItem = toBankItem(node); // USA O HELPER
|
|
218
248
|
return true;
|
|
219
249
|
}
|
|
220
250
|
// Busca em filhos
|
|
@@ -258,15 +288,7 @@ export async function getCategoryItems(bankId, categoryId) {
|
|
|
258
288
|
function extractItems(node) {
|
|
259
289
|
if (node.items) {
|
|
260
290
|
for (const item of node.items) {
|
|
261
|
-
items.push(
|
|
262
|
-
id: item.id,
|
|
263
|
-
code: item.code || '',
|
|
264
|
-
description: item.description || '',
|
|
265
|
-
unit: item.unit || '',
|
|
266
|
-
unitCost: item.unitCost || 0,
|
|
267
|
-
itemType: item.itemType,
|
|
268
|
-
composition: item.composition
|
|
269
|
-
});
|
|
291
|
+
items.push(toBankItem(item));
|
|
270
292
|
}
|
|
271
293
|
}
|
|
272
294
|
if (node.children) {
|
|
@@ -9,6 +9,7 @@ export interface BudgetRow {
|
|
|
9
9
|
unitCost: number;
|
|
10
10
|
isComposition?: boolean;
|
|
11
11
|
bdiType?: 'Principal' | 'Diferenciado';
|
|
12
|
+
composition?: BudgetRow[];
|
|
12
13
|
}
|
|
13
14
|
export interface Budget {
|
|
14
15
|
id: string;
|
|
@@ -67,6 +68,7 @@ export declare function prepareAddItem(budgetId: string, item: {
|
|
|
67
68
|
};
|
|
68
69
|
/**
|
|
69
70
|
* Executes adding an item
|
|
71
|
+
* CORRIGIDO: Busca dados RAW e preserva estrutura original do campo 'data'
|
|
70
72
|
*/
|
|
71
73
|
export declare function executeAddItem(auth: AuthContext, data: any): Promise<void>;
|
|
72
74
|
/**
|
|
@@ -79,6 +81,7 @@ export declare function prepareDeleteItem(budgetId: string, itemId: string, item
|
|
|
79
81
|
};
|
|
80
82
|
/**
|
|
81
83
|
* Executes item deletion
|
|
84
|
+
* CORRIGIDO: Busca dados RAW e preserva estrutura original
|
|
82
85
|
*/
|
|
83
86
|
export declare function executeDeleteItem(auth: AuthContext, data: any): Promise<void>;
|
|
84
87
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"budgetService.d.ts","sourceRoot":"","sources":["../../src/core/budgetService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,MAAM,WAAW,SAAS;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,OAAO,CAAC,EAAE,WAAW,GAAG,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"budgetService.d.ts","sourceRoot":"","sources":["../../src/core/budgetService.ts"],"names":[],"mappings":"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"}
|
|
@@ -56,6 +56,23 @@ export async function getBudget(auth, budgetId) {
|
|
|
56
56
|
bdiDiferenciado: data.data?.bdiDiferenciado || 0
|
|
57
57
|
};
|
|
58
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Busca os dados RAW do orçamento (sem transformação)
|
|
61
|
+
* Necessário para updates que preservem a estrutura original do campo 'data'
|
|
62
|
+
*/
|
|
63
|
+
async function getRawBudgetData(budgetId) {
|
|
64
|
+
const { data, error } = await supabase
|
|
65
|
+
.from('budgets')
|
|
66
|
+
.select('data')
|
|
67
|
+
.eq('id', budgetId)
|
|
68
|
+
.single();
|
|
69
|
+
if (error) {
|
|
70
|
+
if (error.code === 'PGRST116')
|
|
71
|
+
return null;
|
|
72
|
+
throw new Error(`Failed to get budget data: ${error.message}`);
|
|
73
|
+
}
|
|
74
|
+
return data?.data || null;
|
|
75
|
+
}
|
|
59
76
|
/**
|
|
60
77
|
* Creates a new budget (returns preview for confirmation)
|
|
61
78
|
*/
|
|
@@ -114,26 +131,33 @@ export function prepareAddItem(budgetId, item) {
|
|
|
114
131
|
}
|
|
115
132
|
/**
|
|
116
133
|
* Executes adding an item
|
|
134
|
+
* CORRIGIDO: Busca dados RAW e preserva estrutura original do campo 'data'
|
|
117
135
|
*/
|
|
118
136
|
export async function executeAddItem(auth, data) {
|
|
119
|
-
|
|
120
|
-
|
|
137
|
+
// Busca os dados RAW do orçamento (estrutura original do banco)
|
|
138
|
+
const rawData = await getRawBudgetData(data.budgetId);
|
|
139
|
+
if (!rawData)
|
|
121
140
|
throw new Error('Budget not found');
|
|
122
141
|
const newRow = {
|
|
123
142
|
id: crypto.randomUUID(),
|
|
124
143
|
level: 0,
|
|
125
|
-
code: '',
|
|
144
|
+
code: data.item.code || '',
|
|
126
145
|
description: data.item.description,
|
|
127
146
|
unit: data.item.unit,
|
|
128
147
|
quantity: data.item.quantity,
|
|
129
148
|
unitCost: data.item.unitCost,
|
|
130
|
-
isComposition: false
|
|
149
|
+
isComposition: data.item.isComposition || false,
|
|
150
|
+
composition: data.item.composition || undefined
|
|
151
|
+
};
|
|
152
|
+
// Atualiza apenas o array de rows, mantendo toda a estrutura original
|
|
153
|
+
const updatedData = {
|
|
154
|
+
...rawData,
|
|
155
|
+
rows: [...(rawData.rows || []), newRow]
|
|
131
156
|
};
|
|
132
|
-
const updatedRows = [...budget.rows, newRow];
|
|
133
157
|
const { error } = await supabase
|
|
134
158
|
.from('budgets')
|
|
135
159
|
.update({
|
|
136
|
-
data:
|
|
160
|
+
data: updatedData,
|
|
137
161
|
last_modified: new Date().toISOString()
|
|
138
162
|
})
|
|
139
163
|
.eq('id', data.budgetId);
|
|
@@ -152,16 +176,20 @@ export function prepareDeleteItem(budgetId, itemId, itemDescription) {
|
|
|
152
176
|
}
|
|
153
177
|
/**
|
|
154
178
|
* Executes item deletion
|
|
179
|
+
* CORRIGIDO: Busca dados RAW e preserva estrutura original
|
|
155
180
|
*/
|
|
156
181
|
export async function executeDeleteItem(auth, data) {
|
|
157
|
-
const
|
|
158
|
-
if (!
|
|
182
|
+
const rawData = await getRawBudgetData(data.budgetId);
|
|
183
|
+
if (!rawData)
|
|
159
184
|
throw new Error('Budget not found');
|
|
160
|
-
const
|
|
185
|
+
const updatedData = {
|
|
186
|
+
...rawData,
|
|
187
|
+
rows: (rawData.rows || []).filter((r) => r.id !== data.itemId)
|
|
188
|
+
};
|
|
161
189
|
const { error } = await supabase
|
|
162
190
|
.from('budgets')
|
|
163
191
|
.update({
|
|
164
|
-
data:
|
|
192
|
+
data: updatedData,
|
|
165
193
|
last_modified: new Date().toISOString()
|
|
166
194
|
})
|
|
167
195
|
.eq('id', data.budgetId);
|
package/dist/mcp/index.js
CHANGED
|
@@ -362,31 +362,19 @@ async function handleToolCall(auth, name, args) {
|
|
|
362
362
|
descricao: i.description,
|
|
363
363
|
unidade: i.unit,
|
|
364
364
|
custo_unitario: i.unitCost,
|
|
365
|
-
tipo: i.itemType
|
|
365
|
+
tipo: i.itemType,
|
|
366
|
+
is_composicao: i.isComposition,
|
|
367
|
+
qtd_insumos: i.composition?.length || 0
|
|
366
368
|
}))
|
|
367
369
|
};
|
|
368
370
|
}
|
|
369
371
|
// === WRITE (with confirmation) ===
|
|
370
372
|
case 'quanty_importar_item': {
|
|
371
|
-
// Primeiro buscamos os detalhes do item no banco para preparar a importação
|
|
372
|
-
// Como prepareImportItem precisa do objeto BankItem completo, vamos simular ou buscar
|
|
373
|
-
// Para simplificar, vamos usar uma busca direta pelo ID no banco via searchBankItems (ajustando a query seria ideal, mas aqui vamos assumir que o ID é suficiente ou implementaremos um getBankItem)
|
|
374
|
-
// Melhor abordagem: vamos buscar o item específico.
|
|
375
|
-
// O bankService não tem getBankItem exposto, então vamos adicionar uma busca rápida ou usar search
|
|
376
|
-
const items = await bankService.searchBankItems(args.banco_id, ''); // Busca ampla é ruim.
|
|
377
|
-
// Vamos adicionar uma função getBankItem no bankService ou buscar na lista filtrada.
|
|
378
|
-
// WORKAROUND: Vamos criar a pendência com os dados mínimos e deixar o execute resolver ou
|
|
379
|
-
// implementar getBankItem no bankService agora.
|
|
380
|
-
// Vamos assumir que o usuário passou dados válidos e deixar a validação para o execute se possível.
|
|
381
|
-
// Mas prepareImportItem pede um BankItem.
|
|
382
|
-
// Vamos adicionar getBankItemById no bankService agora.
|
|
383
373
|
const item = await bankService.getBankItemById(args.banco_id, args.banco_item_id);
|
|
384
374
|
if (!item)
|
|
385
375
|
return { erro: 'Item não encontrado no banco de dados.' };
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
prepared.data.item.quantity = args.quantidade;
|
|
389
|
-
prepared.preview = prepared.preview.replace('quantidade: 0', `quantidade: ${args.quantidade}`); // Ajuste cosmético se houver
|
|
376
|
+
// Passa a quantidade diretamente para o preparador
|
|
377
|
+
const prepared = bankService.prepareImportItem(args.orcamento_id, item, args.quantidade);
|
|
390
378
|
const pendingId = generatePendingId();
|
|
391
379
|
pendingOperations.set(pendingId, {
|
|
392
380
|
action: prepared.action,
|
|
@@ -395,8 +383,10 @@ async function handleToolCall(auth, name, args) {
|
|
|
395
383
|
});
|
|
396
384
|
return {
|
|
397
385
|
pending_id: pendingId,
|
|
398
|
-
preview:
|
|
399
|
-
|
|
386
|
+
preview: prepared.preview,
|
|
387
|
+
is_composicao: item.isComposition,
|
|
388
|
+
qtd_insumos: item.composition?.length || 0,
|
|
389
|
+
mensagem: 'Use quanty_executar para confirmar.'
|
|
400
390
|
};
|
|
401
391
|
}
|
|
402
392
|
case 'quanty_preparar_orcamento': {
|
package/package.json
CHANGED