@quantyapp/quanty-mcp-server 1.0.6 → 1.0.8

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.
@@ -15,6 +15,7 @@ export interface BankItem {
15
15
  unit: string;
16
16
  unitCost: number;
17
17
  itemType?: string;
18
+ composition?: BankItem[];
18
19
  }
19
20
  export interface BankCategory {
20
21
  id: string;
@@ -31,7 +32,8 @@ export declare function listBanks(auth: AuthContext): Promise<BankSummary[]>;
31
32
  */
32
33
  export declare function getBankCategories(bankId: string): Promise<BankCategory[]>;
33
34
  /**
34
- * Searches items in a bank by text
35
+ * CORRIGIDO: Busca recursiva completa em todos os níveis da árvore
36
+ * Busca em: categorias, subcategorias (infinitos níveis), itens e composições
35
37
  */
36
38
  export declare function searchBankItems(bankId: string, query: string, limit?: number): Promise<BankItem[]>;
37
39
  /**
@@ -43,7 +45,11 @@ export declare function prepareImportItem(budgetId: string, bankItem: BankItem):
43
45
  data: any;
44
46
  };
45
47
  /**
46
- * Gets a specific item from a bank by ID
48
+ * CORRIGIDO: Busca recursiva completa por ID em todos os níveis
47
49
  */
48
50
  export declare function getBankItemById(bankId: string, itemId: string): Promise<BankItem | null>;
51
+ /**
52
+ * NOVA FUNÇÃO: Lista todos os itens de uma categoria específica
53
+ */
54
+ export declare function getCategoryItems(bankId: string, categoryId: string): Promise<BankItem[]>;
49
55
  //# sourceMappingURL=bankService.d.ts.map
@@ -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;CACrB;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;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAmBzE;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAgB/E;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CA0C5G;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC7B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,QAAQ,GACnB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,GAAG,CAAA;CAAE,CAchD;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAsC9F"}
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,QAAQ,EAAE,CAAC;CAC5B;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;AAED;;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,CAyG5G;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC7B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,QAAQ,GACnB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,GAAG,CAAA;CAAE,CAgBhD;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAuD9F;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAiD9F"}
@@ -3,7 +3,6 @@ import { supabase } from './supabase.js';
3
3
  * Lists available composition banks for the tenant
4
4
  */
5
5
  export async function listBanks(auth) {
6
- // Get public banks, tenant's private banks, and subscribed banks
7
6
  const { data, error } = await supabase
8
7
  .from('composition_banks')
9
8
  .select('id, title, description, author_name, region, visibility, categories, tenant_id')
@@ -37,13 +36,28 @@ export async function getBankCategories(bankId) {
37
36
  id: c.id,
38
37
  code: c.code,
39
38
  name: c.name,
40
- itemCount: (c.items || []).length + (c.children || []).reduce((sum, child) => sum + (child.items || []).length, 0)
39
+ itemCount: countItemsRecursive(c)
41
40
  }));
42
41
  }
43
42
  /**
44
- * Searches items in a bank by text
43
+ * Conta itens recursivamente em uma categoria
45
44
  */
46
- export async function searchBankItems(bankId, query, limit = 20) {
45
+ function countItemsRecursive(node) {
46
+ let count = 0;
47
+ if (node.items)
48
+ count += node.items.length;
49
+ if (node.children) {
50
+ for (const child of node.children) {
51
+ count += countItemsRecursive(child);
52
+ }
53
+ }
54
+ return count;
55
+ }
56
+ /**
57
+ * CORRIGIDO: Busca recursiva completa em todos os níveis da árvore
58
+ * Busca em: categorias, subcategorias (infinitos níveis), itens e composições
59
+ */
60
+ export async function searchBankItems(bankId, query, limit = 50) {
47
61
  const { data, error } = await supabase
48
62
  .from('composition_banks')
49
63
  .select('categories')
@@ -52,37 +66,94 @@ export async function searchBankItems(bankId, query, limit = 20) {
52
66
  if (error)
53
67
  throw new Error(`Failed to search bank: ${error.message}`);
54
68
  const results = [];
55
- const queryLower = query.toLowerCase();
56
- function searchInItems(items) {
57
- for (const item of items) {
58
- if (item.description?.toLowerCase().includes(queryLower) ||
59
- item.code?.toLowerCase().includes(queryLower)) {
60
- results.push({
61
- id: item.id,
62
- code: item.code,
63
- description: item.description,
64
- unit: item.unit,
65
- unitCost: item.unitCost || 0,
66
- itemType: item.itemType
67
- });
68
- if (results.length >= limit)
69
- return;
70
- }
71
- if (item.children)
72
- searchInItems(item.children);
69
+ const seenIds = new Set(); // Evitar duplicatas
70
+ const queryLower = (query || '').toLowerCase().trim();
71
+ /**
72
+ * Verifica se um item corresponde à busca
73
+ */
74
+ function matchesQuery(item) {
75
+ // Se não há query, retorna todos
76
+ if (!queryLower)
77
+ return true;
78
+ const description = (item.description || '').toLowerCase();
79
+ const code = (item.code || '').toLowerCase();
80
+ return description.includes(queryLower) || code.includes(queryLower);
81
+ }
82
+ /**
83
+ * Adiciona item aos resultados se corresponder à busca
84
+ */
85
+ function addIfMatches(item) {
86
+ if (results.length >= limit)
87
+ return false;
88
+ if (!item || !item.id)
89
+ return true;
90
+ if (seenIds.has(item.id))
91
+ return true;
92
+ if (matchesQuery(item)) {
93
+ 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
+ });
103
+ }
104
+ return results.length < limit;
105
+ }
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';
73
112
  }
113
+ if (item.itemType)
114
+ return item.itemType;
115
+ return 'Insumo';
74
116
  }
75
- function searchInCategories(categories) {
76
- for (const cat of categories) {
77
- if (cat.items)
78
- searchInItems(cat.items);
79
- if (cat.children)
80
- searchInCategories(cat.children);
81
- if (results.length >= limit)
82
- return;
117
+ /**
118
+ * RECURSÃO PROFUNDA: Busca em qualquer estrutura de nós
119
+ * Suporta: items, children, composition, categories
120
+ */
121
+ function searchRecursive(node) {
122
+ if (!node || results.length >= limit)
123
+ return results.length < limit;
124
+ // Se é um array, itera sobre cada elemento
125
+ if (Array.isArray(node)) {
126
+ for (const element of node) {
127
+ if (!searchRecursive(element))
128
+ return false;
129
+ }
130
+ return true;
131
+ }
132
+ // Se é um objeto (item ou categoria)
133
+ if (typeof node === 'object') {
134
+ // Verifica se é um item (tem code ou description ou unit)
135
+ const isItem = node.code !== undefined ||
136
+ node.description !== undefined ||
137
+ node.unit !== undefined ||
138
+ node.unitCost !== undefined;
139
+ // Se parece ser um item, tenta adicionar
140
+ if (isItem && node.id) {
141
+ if (!addIfMatches(node))
142
+ return false;
143
+ }
144
+ // Busca recursiva em todas as propriedades que podem conter filhos
145
+ const childKeys = ['items', 'children', 'composition', 'categories', 'rows'];
146
+ for (const key of childKeys) {
147
+ if (node[key] && Array.isArray(node[key])) {
148
+ if (!searchRecursive(node[key]))
149
+ return false;
150
+ }
151
+ }
83
152
  }
153
+ return true;
84
154
  }
85
- searchInCategories(data?.categories || []);
155
+ // Inicia a busca a partir das categorias
156
+ searchRecursive(data?.categories || []);
86
157
  return results;
87
158
  }
88
159
  /**
@@ -97,14 +168,16 @@ export function prepareImportItem(budgetId, bankItem) {
97
168
  item: {
98
169
  description: bankItem.description,
99
170
  unit: bankItem.unit,
100
- quantity: 0, // User will fill in quantity
101
- unitCost: bankItem.unitCost
171
+ quantity: 0,
172
+ unitCost: bankItem.unitCost,
173
+ isComposition: !!(bankItem.composition && bankItem.composition.length > 0),
174
+ composition: bankItem.composition // Traz os insumos junto
102
175
  }
103
176
  }
104
177
  };
105
178
  }
106
179
  /**
107
- * Gets a specific item from a bank by ID
180
+ * CORRIGIDO: Busca recursiva completa por ID em todos os níveis
108
181
  */
109
182
  export async function getBankItemById(bankId, itemId) {
110
183
  const { data, error } = await supabase
@@ -115,33 +188,96 @@ export async function getBankItemById(bankId, itemId) {
115
188
  if (error)
116
189
  return null;
117
190
  let foundItem = null;
118
- function search(items) {
119
- for (const item of items) {
120
- if (item.id === itemId) {
191
+ /**
192
+ * Busca recursiva por ID em qualquer nível da árvore
193
+ */
194
+ function findById(node) {
195
+ if (!node || foundItem)
196
+ return false;
197
+ // Se é um array
198
+ if (Array.isArray(node)) {
199
+ for (const element of node) {
200
+ if (findById(element))
201
+ return true;
202
+ }
203
+ return false;
204
+ }
205
+ // Se é um objeto
206
+ if (typeof node === 'object') {
207
+ // Verifica se é o item procurado
208
+ if (node.id === itemId) {
121
209
  foundItem = {
122
- id: item.id,
123
- code: item.code,
124
- description: item.description,
125
- unit: item.unit,
126
- unitCost: item.unitCost || 0,
127
- itemType: item.itemType
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
128
217
  };
129
- return;
218
+ return true;
219
+ }
220
+ // Busca em filhos
221
+ const childKeys = ['items', 'children', 'composition', 'categories', 'rows'];
222
+ for (const key of childKeys) {
223
+ if (node[key] && Array.isArray(node[key])) {
224
+ if (findById(node[key]))
225
+ return true;
226
+ }
227
+ }
228
+ }
229
+ return false;
230
+ }
231
+ findById(data?.categories || []);
232
+ return foundItem;
233
+ }
234
+ /**
235
+ * NOVA FUNÇÃO: Lista todos os itens de uma categoria específica
236
+ */
237
+ export async function getCategoryItems(bankId, categoryId) {
238
+ const { data, error } = await supabase
239
+ .from('composition_banks')
240
+ .select('categories')
241
+ .eq('id', bankId)
242
+ .single();
243
+ if (error)
244
+ throw new Error(`Failed to get bank: ${error.message}`);
245
+ const items = [];
246
+ function findCategory(nodes) {
247
+ for (const node of nodes) {
248
+ if (node.id === categoryId)
249
+ return node;
250
+ if (node.children) {
251
+ const found = findCategory(node.children);
252
+ if (found)
253
+ return found;
130
254
  }
131
- if (item.children)
132
- search(item.children);
133
255
  }
256
+ return null;
134
257
  }
135
- function searchCats(categories) {
136
- for (const cat of categories) {
137
- if (foundItem)
138
- return;
139
- if (cat.items)
140
- search(cat.items);
141
- if (cat.children)
142
- searchCats(cat.children);
258
+ function extractItems(node) {
259
+ if (node.items) {
260
+ 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
+ });
270
+ }
271
+ }
272
+ if (node.children) {
273
+ for (const child of node.children) {
274
+ extractItems(child);
275
+ }
143
276
  }
144
277
  }
145
- searchCats(data?.categories || []);
146
- return foundItem;
278
+ const category = findCategory(data?.categories || []);
279
+ if (category) {
280
+ extractItems(category);
281
+ }
282
+ return items;
147
283
  }
@@ -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":"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"}
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
- const budget = await getBudget(auth, data.budgetId);
120
- if (!budget)
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: { ...budget, rows: updatedRows },
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 budget = await getBudget(auth, data.budgetId);
158
- if (!budget)
182
+ const rawData = await getRawBudgetData(data.budgetId);
183
+ if (!rawData)
159
184
  throw new Error('Budget not found');
160
- const updatedRows = budget.rows.filter(r => r.id !== data.itemId);
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: { ...budget, rows: updatedRows },
192
+ data: updatedData,
165
193
  last_modified: new Date().toISOString()
166
194
  })
167
195
  .eq('id', data.budgetId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantyapp/quanty-mcp-server",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "MCP Server para conectar Claude Desktop ao Quanty - Sistema de Orçamentos de Engenharia",
5
5
  "type": "module",
6
6
  "main": "dist/mcp/index.js",