@accounter/server 0.0.9-alpha-20251211132246-b18259e59cbca0d25dd94d8260a61b55a2f3b458 → 0.0.9-alpha-20251211161610-5ba6aa4ba27b2cc52460d8b17757dad51478bc4a

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.
Files changed (22) hide show
  1. package/CHANGELOG.md +5 -5
  2. package/dist/green-invoice-graphql/src/mesh-artifacts/index.d.ts +1 -1
  3. package/dist/server/src/modules/charges/helpers/common.helper.js +19 -13
  4. package/dist/server/src/modules/charges/helpers/common.helper.js.map +1 -1
  5. package/dist/server/src/modules/charges/resolvers/charge-suggestions/charge-suggestions.resolver.js +561 -545
  6. package/dist/server/src/modules/charges/resolvers/charge-suggestions/charge-suggestions.resolver.js.map +1 -1
  7. package/dist/server/src/modules/charges/resolvers/charges.resolver.js +179 -140
  8. package/dist/server/src/modules/charges/resolvers/charges.resolver.js.map +1 -1
  9. package/dist/server/src/modules/charges/resolvers/common.js +45 -26
  10. package/dist/server/src/modules/charges/resolvers/common.js.map +1 -1
  11. package/dist/server/src/modules/charges/resolvers/financial-charges.resolver.js +31 -25
  12. package/dist/server/src/modules/charges/resolvers/financial-charges.resolver.js.map +1 -1
  13. package/dist/server/src/shared/errors.d.ts +1 -0
  14. package/dist/server/src/shared/errors.js +7 -0
  15. package/dist/server/src/shared/errors.js.map +1 -1
  16. package/package.json +1 -1
  17. package/src/modules/charges/helpers/common.helper.ts +24 -19
  18. package/src/modules/charges/resolvers/charge-suggestions/charge-suggestions.resolver.ts +588 -574
  19. package/src/modules/charges/resolvers/charges.resolver.ts +192 -157
  20. package/src/modules/charges/resolvers/common.ts +48 -31
  21. package/src/modules/charges/resolvers/financial-charges.resolver.ts +31 -27
  22. package/src/shared/errors.ts +8 -0
@@ -1,6 +1,7 @@
1
1
  import { GraphQLError } from 'graphql';
2
2
  import { UUID_REGEX } from '../../../../shared/constants.js';
3
3
  import { ChargeTypeEnum } from '../../../../shared/enums.js';
4
+ import { errorSimplifier } from '../../../../shared/errors.js';
4
5
  import { suggestionDataSchema } from '../../../financial-entities/helpers/business-suggestion-data-schema.helper.js';
5
6
  import { BusinessesProvider } from '../../../financial-entities/providers/businesses.provider.js';
6
7
  import { ChargeTagsProvider } from '../../../tags/providers/charge-tags.provider.js';
@@ -11,545 +12,550 @@ import { calculateTotalAmount, getChargeBusinesses } from '../../helpers/common.
11
12
  import { ChargesProvider } from '../../providers/charges.provider.js';
12
13
  import { missingConversionInfoSuggestions } from './conversion-suggeestions.resolver.js';
13
14
  const missingInfoSuggestions = async (DbCharge, _, context, __) => {
14
- const { injector, adminContext } = context;
15
- const { poalimBusinessId, etherScanBusinessId, krakenBusinessId, etanaBusinessId } = adminContext.financialAccounts;
16
- const [chargeType, tags] = await Promise.all([
17
- getChargeType(DbCharge, context),
18
- context.injector.get(ChargeTagsProvider).getTagsByChargeIDLoader.load(DbCharge.id),
19
- ]);
20
- // if all required fields are filled, no need for suggestions
21
- if (!!tags.length && !!DbCharge.user_description?.trim()) {
22
- return null;
23
- }
24
- if (chargeType === ChargeTypeEnum.Conversion) {
25
- return missingConversionInfoSuggestions(DbCharge, _, context, __);
26
- }
27
- const [formattedAmount, { allBusinessIds, mainBusinessId }] = await Promise.all([
28
- calculateTotalAmount(DbCharge.id, injector, adminContext.defaultLocalCurrency),
29
- getChargeBusinesses(DbCharge.id, injector),
30
- ]);
31
- const chargeAmount = formattedAmount?.raw ?? 0;
32
- // if charge has a businesses, use it's suggestion data
33
- if (mainBusinessId) {
34
- const business = await injector
35
- .get(BusinessesProvider)
36
- .getBusinessByIdLoader.load(mainBusinessId);
37
- if (business?.suggestion_data) {
15
+ try {
16
+ const { injector, adminContext } = context;
17
+ const { poalimBusinessId, etherScanBusinessId, krakenBusinessId, etanaBusinessId } = adminContext.financialAccounts;
18
+ const [chargeType, tags] = await Promise.all([
19
+ getChargeType(DbCharge, context),
20
+ context.injector.get(ChargeTagsProvider).getTagsByChargeIDLoader.load(DbCharge.id),
21
+ ]);
22
+ // if all required fields are filled, no need for suggestions
23
+ if (!!tags.length && !!DbCharge.user_description?.trim()) {
24
+ return null;
25
+ }
26
+ if (chargeType === ChargeTypeEnum.Conversion) {
27
+ return missingConversionInfoSuggestions(DbCharge, _, context, __);
28
+ }
29
+ const [formattedAmount, { allBusinessIds, mainBusinessId }] = await Promise.all([
30
+ calculateTotalAmount(DbCharge.id, injector, adminContext.defaultLocalCurrency),
31
+ getChargeBusinesses(DbCharge.id, injector),
32
+ ]);
33
+ const chargeAmount = formattedAmount?.raw ?? 0;
34
+ // if charge has a businesses, use it's suggestion data
35
+ if (mainBusinessId) {
36
+ const business = await injector
37
+ .get(BusinessesProvider)
38
+ .getBusinessByIdLoader.load(mainBusinessId);
39
+ if (business?.suggestion_data) {
40
+ const { data: suggestionData, error, success, } = suggestionDataSchema.safeParse(business.suggestion_data);
41
+ if (!success) {
42
+ console.error('Failed to parse suggestion data for business', {
43
+ businessId: business.id,
44
+ error,
45
+ });
46
+ throw new GraphQLError('Failed to parse suggestion data for business');
47
+ }
48
+ return {
49
+ description: suggestionData.description,
50
+ tags: await Promise.all((suggestionData.tags ?? []).map(tag => UUID_REGEX.test(tag)
51
+ ? injector.get(TagsProvider).getTagByIDLoader.load(tag)
52
+ : injector.get(TagsProvider).getTagByNameLoader.load(tag))).then(tags => tags.filter(Boolean)),
53
+ };
54
+ }
55
+ }
56
+ if (allBusinessIds.length > 1) {
57
+ const isKrakenIncluded = krakenBusinessId && allBusinessIds.includes(krakenBusinessId);
58
+ const isEtherscanIncluded = etherScanBusinessId && allBusinessIds.includes(etherScanBusinessId);
59
+ const isEtanaIncluded = etanaBusinessId && allBusinessIds.includes(etanaBusinessId);
60
+ const isPoalimIncluded = poalimBusinessId && allBusinessIds.includes(poalimBusinessId);
61
+ if (isKrakenIncluded && isEtherscanIncluded) {
62
+ return {
63
+ description: 'Etherscan to Kraken transfer',
64
+ tags: await injector
65
+ .get(TagsProvider)
66
+ .getTagByNameLoader.load('financial')
67
+ .then(res => (res ? [res] : [])),
68
+ };
69
+ }
70
+ if (isKrakenIncluded && isEtanaIncluded) {
71
+ return {
72
+ description: 'Kraken to Etana transfer',
73
+ tags: await injector
74
+ .get(TagsProvider)
75
+ .getTagByNameLoader.load('financial')
76
+ .then(res => (res ? [res] : [])),
77
+ };
78
+ }
79
+ if (isPoalimIncluded && isEtanaIncluded) {
80
+ return {
81
+ description: 'Etana to Poalim transfer',
82
+ tags: await injector
83
+ .get(TagsProvider)
84
+ .getTagByNameLoader.load('financial')
85
+ .then(res => (res ? [res] : [])),
86
+ };
87
+ }
88
+ }
89
+ const allBusinesses = await injector.get(BusinessesProvider).getAllBusinesses();
90
+ const suggestions = {};
91
+ for (const business of allBusinesses) {
92
+ if (!business.suggestion_data)
93
+ continue;
38
94
  const { data: suggestionData, error, success, } = suggestionDataSchema.safeParse(business.suggestion_data);
39
95
  if (!success) {
40
96
  console.error('Failed to parse suggestion data for business', {
41
97
  businessId: business.id,
42
98
  error,
43
99
  });
44
- throw new GraphQLError('Failed to parse suggestion data for business');
100
+ continue;
45
101
  }
102
+ if (business.id in allBusinessIds) {
103
+ return {
104
+ description: suggestionData.description,
105
+ tags: await Promise.all((suggestionData.tags ?? []).map(tag => UUID_REGEX.test(tag)
106
+ ? injector.get(TagsProvider).getTagByIDLoader.load(tag)
107
+ : injector.get(TagsProvider).getTagByNameLoader.load(tag))).then(tags => tags.filter(Boolean)),
108
+ };
109
+ }
110
+ if (!suggestionData.phrases)
111
+ continue;
112
+ for (const phrase of suggestionData.phrases) {
113
+ suggestions[phrase] = {
114
+ description: suggestionData.description,
115
+ tags: suggestionData.tags
116
+ ? await Promise.all(suggestionData.tags.map(tag => UUID_REGEX.test(tag)
117
+ ? injector.get(TagsProvider).getTagByIDLoader.load(tag)
118
+ : injector.get(TagsProvider).getTagByNameLoader.load(tag))).then(tags => tags.filter(Boolean))
119
+ : [],
120
+ };
121
+ }
122
+ }
123
+ const transactions = await injector
124
+ .get(TransactionsProvider)
125
+ .transactionsByChargeIDLoader.load(DbCharge.id);
126
+ const description = transactions.map(t => t.source_description).join(' ');
127
+ for (const [phrase, suggestion] of Object.entries(suggestions)) {
128
+ if (Array.isArray(phrase) && new RegExp(phrase.join('|')).test(description)) {
129
+ return suggestion;
130
+ }
131
+ if (description.includes(phrase)) {
132
+ return suggestion;
133
+ }
134
+ }
135
+ if (description.includes('ע\' העברת מט"ח') ||
136
+ (description.includes('העברת מט"ח') && Math.abs(chargeAmount) < 400) ||
137
+ (description.includes('מטח') && Math.abs(chargeAmount) < 400) ||
138
+ description.includes('F.C.COM') ||
139
+ description.includes('ע.מפעולות-ישיר') ||
140
+ description.includes('ריבית חובה') ||
141
+ description.includes('FEE')) {
142
+ const sourceTransaction = transactions.length === 0
143
+ ? 'Missing'
144
+ : transactions.length === 1
145
+ ? transactions[0].source_reference
146
+ : `['${transactions.map(t => t.source_reference).join("','")}']`;
46
147
  return {
47
- description: suggestionData.description,
48
- tags: await Promise.all((suggestionData.tags ?? []).map(tag => UUID_REGEX.test(tag)
49
- ? injector.get(TagsProvider).getTagByIDLoader.load(tag)
50
- : injector.get(TagsProvider).getTagByNameLoader.load(tag))).then(tags => tags.filter(Boolean)),
148
+ tags: await injector
149
+ .get(TagsProvider)
150
+ .getTagByNameLoader.load('financial')
151
+ .then(res => (res ? [res] : [])),
152
+ description: `Fees for source transaction=${sourceTransaction}`,
51
153
  };
52
154
  }
53
- }
54
- if (allBusinessIds.length > 1) {
55
- const isKrakenIncluded = krakenBusinessId && allBusinessIds.includes(krakenBusinessId);
56
- const isEtherscanIncluded = etherScanBusinessId && allBusinessIds.includes(etherScanBusinessId);
57
- const isEtanaIncluded = etanaBusinessId && allBusinessIds.includes(etanaBusinessId);
58
- const isPoalimIncluded = poalimBusinessId && allBusinessIds.includes(poalimBusinessId);
59
- if (isKrakenIncluded && isEtherscanIncluded) {
155
+ if (description.includes('דותן שמחה') || description.includes('שמחה דותן')) {
156
+ const current = new Date();
157
+ current.setMonth(current.getMonth() - 1);
158
+ const previousMonth = current.toLocaleString('default', {
159
+ month: '2-digit',
160
+ });
161
+ return {
162
+ description: `${previousMonth}/2022 Salary`,
163
+ tags: await injector
164
+ .get(TagsProvider)
165
+ .getTagByNameLoader.load('business')
166
+ .then(res => (res ? [res] : [])),
167
+ };
168
+ }
169
+ if (description.includes('גולדשטין אורי')) {
170
+ const current = new Date();
171
+ current.setMonth(current.getMonth() - 1);
172
+ const previousMonth = current.toLocaleString('default', {
173
+ month: '2-digit',
174
+ });
175
+ return {
176
+ description: `${previousMonth}/2022 Salary`,
177
+ tags: await injector
178
+ .get(TagsProvider)
179
+ .getTagByNameLoader.load('business')
180
+ .then(res => (res ? [res] : [])),
181
+ };
182
+ }
183
+ if (description.includes('גרדוש')) {
184
+ const current = new Date();
185
+ current.setMonth(current.getMonth() - 1);
186
+ const previousMonth = current.toLocaleString('default', {
187
+ month: '2-digit',
188
+ });
189
+ return {
190
+ description: `${previousMonth}/2022 Salary`,
191
+ tags: await injector
192
+ .get(TagsProvider)
193
+ .getTagByNameLoader.load('business')
194
+ .then(res => (res ? [res] : [])),
195
+ };
196
+ }
197
+ if (description.includes('תובל')) {
198
+ const current = new Date();
199
+ current.setMonth(current.getMonth() - 1);
200
+ const previousMonth = current.toLocaleString('default', {
201
+ month: '2-digit',
202
+ });
203
+ return {
204
+ description: `${previousMonth}/2022 Salary`,
205
+ tags: await injector
206
+ .get(TagsProvider)
207
+ .getTagByNameLoader.load('business')
208
+ .then(res => (res ? [res] : [])),
209
+ };
210
+ }
211
+ if (description.includes('מנורה מבטחים פנס')) {
212
+ const current = new Date();
213
+ current.setMonth(current.getMonth() - 1);
214
+ const previousMonth = current.toLocaleString('default', {
215
+ month: '2-digit',
216
+ });
217
+ return {
218
+ description: `Pension ${previousMonth}/2022`,
219
+ tags: await injector
220
+ .get(TagsProvider)
221
+ .getTagByNameLoader.load('business')
222
+ .then(res => (res ? [res] : [])),
223
+ };
224
+ }
225
+ if (description.includes('פניקס אקסלנס')) {
226
+ const current = new Date();
227
+ current.setMonth(current.getMonth() - 1);
228
+ const previousMonth = current.toLocaleString('default', {
229
+ month: '2-digit',
230
+ });
231
+ return {
232
+ description: `Training Fund ${previousMonth}/2022`,
233
+ tags: await injector
234
+ .get(TagsProvider)
235
+ .getTagByNameLoader.load('business')
236
+ .then(res => (res ? [res] : [])),
237
+ };
238
+ }
239
+ if (description.includes('מיטב דש גמל ופנס')) {
240
+ const current = new Date();
241
+ current.setMonth(current.getMonth() - 1);
242
+ const previousMonth = current.toLocaleString('default', {
243
+ month: '2-digit',
244
+ });
245
+ return {
246
+ description: `Pension ${previousMonth}/2022`,
247
+ tags: await injector
248
+ .get(TagsProvider)
249
+ .getTagByNameLoader.load('business')
250
+ .then(res => (res ? [res] : [])),
251
+ };
252
+ }
253
+ if (description.includes('מגדל מקפת')) {
254
+ const current = new Date();
255
+ current.setMonth(current.getMonth() - 1);
256
+ const previousMonth = current.toLocaleString('default', {
257
+ month: '2-digit',
258
+ });
259
+ return {
260
+ description: `Pension ${previousMonth}/2022`,
261
+ tags: await injector
262
+ .get(TagsProvider)
263
+ .getTagByNameLoader.load('business')
264
+ .then(res => (res ? [res] : [])),
265
+ };
266
+ }
267
+ if (description.includes('מגדל השתלמות')) {
268
+ const current = new Date();
269
+ current.setMonth(current.getMonth() - 1);
270
+ const previousMonth = current.toLocaleString('default', {
271
+ month: '2-digit',
272
+ });
273
+ return {
274
+ description: `Training Fund ${previousMonth}/2022`,
275
+ tags: await injector
276
+ .get(TagsProvider)
277
+ .getTagByNameLoader.load('business')
278
+ .then(res => (res ? [res] : [])),
279
+ };
280
+ }
281
+ if (description.includes('ביטוח לאומי')) {
282
+ const current = new Date();
283
+ current.setMonth(current.getMonth() - 1);
284
+ const previousMonth = current.toLocaleString('default', {
285
+ month: '2-digit',
286
+ });
287
+ return {
288
+ description: `Social Security Deductions for Salaries ${previousMonth}/2022`,
289
+ tags: await injector
290
+ .get(TagsProvider)
291
+ .getTagByNameLoader.load('business')
292
+ .then(res => (res ? [res] : [])),
293
+ };
294
+ }
295
+ if (description.includes('LANCE GLOBAL')) {
296
+ const current = new Date();
297
+ current.setMonth(current.getMonth() - 1);
298
+ const previousMonth = current.toLocaleString('default', { month: 'long' });
299
+ return {
300
+ description: `The Guild Enterprise Support - ${previousMonth} 2022`,
301
+ tags: await injector
302
+ .get(TagsProvider)
303
+ .getTagByNameLoader.load('business')
304
+ .then(res => (res ? [res] : [])),
305
+ };
306
+ }
307
+ if ((description.includes('העברת מט"ח') &&
308
+ (description.includes('fbv') || description.includes('fv'))) ||
309
+ description.includes('kamil kisiela')) {
310
+ const current = new Date();
311
+ current.setMonth(current.getMonth() - 1);
312
+ const previousMonth = current.toLocaleString('default', {
313
+ month: '2-digit',
314
+ });
315
+ return {
316
+ description: `Software Development and Consulting ${previousMonth}/23`,
317
+ tags: await injector
318
+ .get(TagsProvider)
319
+ .getTagByNameLoader.load('business')
320
+ .then(res => (res ? [res] : [])),
321
+ };
322
+ }
323
+ if (description.includes('slava')) {
324
+ const current = new Date();
325
+ current.setMonth(current.getMonth() - 1);
326
+ const previousMonth = current.toLocaleString('default', { month: '2-digit' });
327
+ return {
328
+ description: `Web Development Services ${previousMonth}/23`,
329
+ tags: await injector
330
+ .get(TagsProvider)
331
+ .getTagByNameLoader.load('business')
332
+ .then(res => (res ? [res] : [])),
333
+ };
334
+ }
335
+ if (description.includes('COURIER PLUS INC')) {
336
+ const current = new Date();
337
+ current.setMonth(current.getMonth() - 1);
338
+ const previousMonth = current.toLocaleString('default', { month: 'long' });
339
+ return {
340
+ description: `GraphQL Hive Enterprise License - ${previousMonth} 2023`,
341
+ tags: await injector
342
+ .get(TagsProvider)
343
+ .getTagByNameLoader.load('business')
344
+ .then(res => (res ? [res] : [])),
345
+ };
346
+ }
347
+ if (description.includes('GOBRANDS')) {
348
+ const current = new Date();
349
+ current.setMonth(current.getMonth() - 1);
350
+ const previousMonth = current.toLocaleString('default', { month: 'long' });
351
+ return {
352
+ description: `GraphQL Hive Enterprise License - ${previousMonth} 2023`,
353
+ tags: await injector
354
+ .get(TagsProvider)
355
+ .getTagByNameLoader.load('business')
356
+ .then(res => (res ? [res] : [])),
357
+ };
358
+ }
359
+ if (description.includes('MEDIC FIRST AI')) {
360
+ const current = new Date();
361
+ current.setMonth(current.getMonth() - 1);
362
+ const previousMonth = current.toLocaleString('default', { month: 'long' });
363
+ return {
364
+ description: `GraphQL Hive Enterprise License - ${previousMonth} 2023`,
365
+ tags: await injector
366
+ .get(TagsProvider)
367
+ .getTagByNameLoader.load('business')
368
+ .then(res => (res ? [res] : [])),
369
+ };
370
+ }
371
+ if (description.includes('מס הכנסה')) {
372
+ const flag = description.includes('מס הכנסה ני');
373
+ const current = new Date();
374
+ current.setMonth(current.getMonth() - 1);
375
+ const previousMonth = current.toLocaleString('default', {
376
+ month: '2-digit',
377
+ });
378
+ return {
379
+ tags: await injector
380
+ .get(TagsProvider)
381
+ .getTagByNameLoader.load('business')
382
+ .then(res => (res ? [res] : [])),
383
+ description: flag
384
+ ? `Tax for employees for ${previousMonth}/2022`
385
+ : `Advance Tax for ${previousMonth}/2022`,
386
+ };
387
+ }
388
+ if (description.includes('המכס ומעמ-גביי תשלום') || description.includes('CUSTOM + V.A.T')) {
389
+ const current = new Date();
390
+ current.setMonth(current.getMonth() - 1);
391
+ const previousMonth = current.toLocaleString('default', {
392
+ month: '2-digit',
393
+ });
394
+ return {
395
+ description: `VAT for ${previousMonth}/2022`,
396
+ tags: await injector
397
+ .get(TagsProvider)
398
+ .getTagByNameLoader.load('business')
399
+ .then(res => (res ? [res] : [])),
400
+ };
401
+ }
402
+ if (description.includes('חניון')) {
403
+ return {
404
+ description: 'Parking',
405
+ tags: await injector
406
+ .get(TagsProvider)
407
+ .getTagByNameLoader.load('transportation')
408
+ .then(res => (res ? [res] : [])),
409
+ };
410
+ }
411
+ if (description.includes('deel')) {
412
+ return {
413
+ description: 'Laurin Salary',
414
+ tags: await injector
415
+ .get(TagsProvider)
416
+ .getTagByNameLoader.load('business')
417
+ .then(res => (res ? [res] : [])),
418
+ };
419
+ }
420
+ if (description.includes('GITHUB')) {
421
+ const suggested = {
422
+ description: 'GitHub Actions',
423
+ tags: await injector
424
+ .get(TagsProvider)
425
+ .getTagByNameLoader.load('business')
426
+ .then(res => (res ? [res] : [])),
427
+ };
428
+ if (chargeAmount <= -2000) {
429
+ suggested.description = 'Monthly Sponsor for Benjie, Code-Hex, hayes';
430
+ }
431
+ else if (chargeAmount <= -1000) {
432
+ suggested.description = 'Monthly Sponsor for Andarist, warrenday';
433
+ }
434
+ else {
435
+ suggested.description = 'GitHub Actions';
436
+ }
437
+ return suggested;
438
+ }
439
+ if (chargeAmount === -4329) {
440
+ return {
441
+ description: 'Office rent',
442
+ tags: await injector
443
+ .get(TagsProvider)
444
+ .getTagByNameLoader.load('business')
445
+ .then(res => (res ? [res] : [])),
446
+ };
447
+ }
448
+ if (description.includes('APPLE COM BILL/ITUNES.COM')) {
449
+ const flag = chargeAmount === -109.9;
450
+ return {
451
+ taxCategory: 'אתר',
452
+ beneficiaaries: [], // NOTE: used to be ' '
453
+ description: flag ? 'LinkedIn' : 'Apple Services',
454
+ tags: await injector
455
+ .get(TagsProvider)
456
+ .getTagByNameLoader.load(flag ? 'business' : 'computer')
457
+ .then(res => (res ? [res] : [])),
458
+ };
459
+ }
460
+ if (description.includes('ע\' העברת מט"ח') ||
461
+ (description.includes('העברת מט"ח') && Math.abs(chargeAmount) < 400) ||
462
+ (description.includes('מטח') && Math.abs(chargeAmount) < 400) ||
463
+ description.includes('F.C.COM') ||
464
+ description.includes('ע.מפעולות-ישיר') ||
465
+ description.includes('ריבית חובה') ||
466
+ description.includes('FEE')) {
467
+ const description = transactions.length
468
+ ? `['${transactions.map(t => t.source_reference).join("','")}']`
469
+ : 'Missing';
470
+ //NOTE: multiple suggestions business
60
471
  return {
61
- description: 'Etherscan to Kraken transfer',
62
472
  tags: await injector
63
473
  .get(TagsProvider)
64
474
  .getTagByNameLoader.load('financial')
65
475
  .then(res => (res ? [res] : [])),
476
+ description,
66
477
  };
67
478
  }
68
- if (isKrakenIncluded && isEtanaIncluded) {
479
+ if (description.includes('ריבית זכות')) {
480
+ //NOTE: multiple suggestions business
69
481
  return {
70
- description: 'Kraken to Etana transfer',
482
+ description: 'Interest fees on Euro plus',
71
483
  tags: await injector
72
484
  .get(TagsProvider)
73
485
  .getTagByNameLoader.load('financial')
74
486
  .then(res => (res ? [res] : [])),
75
487
  };
76
488
  }
77
- if (isPoalimIncluded && isEtanaIncluded) {
489
+ if (description.includes('פועלים- דמי כרטיס')) {
490
+ //NOTE: multiple suggestions business
78
491
  return {
79
- description: 'Etana to Poalim transfer',
492
+ description: 'Bank creditcard fees',
80
493
  tags: await injector
81
494
  .get(TagsProvider)
82
495
  .getTagByNameLoader.load('financial')
83
496
  .then(res => (res ? [res] : [])),
84
497
  };
85
498
  }
86
- }
87
- const allBusinesses = await injector.get(BusinessesProvider).getAllBusinesses();
88
- const suggestions = {};
89
- for (const business of allBusinesses) {
90
- if (!business.suggestion_data)
91
- continue;
92
- const { data: suggestionData, error, success, } = suggestionDataSchema.safeParse(business.suggestion_data);
93
- if (!success) {
94
- console.error('Failed to parse suggestion data for business', {
95
- businessId: business.id,
96
- error,
97
- });
98
- continue;
499
+ if (description.includes('אריה קריסטל')) {
500
+ //NOTE: multiple suggestions business
501
+ return {
502
+ description: 'Water bill for 04-2022',
503
+ tags: await injector
504
+ .get(TagsProvider)
505
+ .getTagByNameLoader.load('house')
506
+ .then(res => (res ? [res] : [])),
507
+ };
99
508
  }
100
- if (business.id in allBusinessIds) {
509
+ if (description.includes('aleksandra')) {
510
+ const current = new Date();
511
+ current.setMonth(current.getMonth() - 1);
512
+ const previousMonth = current.toLocaleString('default', { month: '2-digit' });
101
513
  return {
102
- description: suggestionData.description,
103
- tags: await Promise.all((suggestionData.tags ?? []).map(tag => UUID_REGEX.test(tag)
104
- ? injector.get(TagsProvider).getTagByIDLoader.load(tag)
105
- : injector.get(TagsProvider).getTagByNameLoader.load(tag))).then(tags => tags.filter(Boolean)),
106
- };
107
- }
108
- if (!suggestionData.phrases)
109
- continue;
110
- for (const phrase of suggestionData.phrases) {
111
- suggestions[phrase] = {
112
- description: suggestionData.description,
113
- tags: suggestionData.tags
114
- ? await Promise.all(suggestionData.tags.map(tag => UUID_REGEX.test(tag)
115
- ? injector.get(TagsProvider).getTagByIDLoader.load(tag)
116
- : injector.get(TagsProvider).getTagByNameLoader.load(tag))).then(tags => tags.filter(Boolean))
117
- : [],
514
+ description: `Software Consulting Fees (${previousMonth}/2023)`,
515
+ tags: await injector
516
+ .get(TagsProvider)
517
+ .getTagByNameLoader.load('business')
518
+ .then(res => (res ? [res] : [])),
118
519
  };
119
520
  }
120
- }
121
- const transactions = await injector
122
- .get(TransactionsProvider)
123
- .transactionsByChargeIDLoader.load(DbCharge.id);
124
- const description = transactions.map(t => t.source_description).join(' ');
125
- for (const [phrase, suggestion] of Object.entries(suggestions)) {
126
- if (Array.isArray(phrase) && new RegExp(phrase.join('|')).test(description)) {
127
- return suggestion;
521
+ if (description.includes('denelop')) {
522
+ const current = new Date();
523
+ current.setMonth(current.getMonth() - 1);
524
+ const previousMonth = current.toLocaleString('default', { month: '2-digit' });
525
+ return {
526
+ description: `Software Development and Consulting ${previousMonth}/2023`,
527
+ tags: await injector
528
+ .get(TagsProvider)
529
+ .getTagByNameLoader.load('business')
530
+ .then(res => (res ? [res] : [])),
531
+ };
128
532
  }
129
- if (description.includes(phrase)) {
130
- return suggestion;
533
+ if (chargeAmount === -12_000) {
534
+ const current = new Date();
535
+ current.setMonth(current.getMonth() - 1);
536
+ const previousMonth = current.toLocaleString('default', { month: '2-digit' });
537
+ return {
538
+ description: `${previousMonth}/2022`,
539
+ tags: await injector
540
+ .get(TagsProvider)
541
+ .getTagByNameLoader.load('business')
542
+ .then(res => (res ? [res] : [])),
543
+ };
131
544
  }
545
+ if (chargeAmount === -600) {
546
+ return {
547
+ description: 'Matic Zavadlal - April 2021',
548
+ tags: await injector
549
+ .get(TagsProvider)
550
+ .getTagByNameLoader.load('business')
551
+ .then(res => (res ? [res] : [])),
552
+ };
553
+ }
554
+ return null;
132
555
  }
133
- if (description.includes('ע\' העברת מט"ח') ||
134
- (description.includes('העברת מט"ח') && Math.abs(chargeAmount) < 400) ||
135
- (description.includes('מטח') && Math.abs(chargeAmount) < 400) ||
136
- description.includes('F.C.COM') ||
137
- description.includes('ע.מפעולות-ישיר') ||
138
- description.includes('ריבית חובה') ||
139
- description.includes('FEE')) {
140
- const sourceTransaction = transactions.length === 0
141
- ? 'Missing'
142
- : transactions.length === 1
143
- ? transactions[0].source_reference
144
- : `['${transactions.map(t => t.source_reference).join("','")}']`;
145
- return {
146
- tags: await injector
147
- .get(TagsProvider)
148
- .getTagByNameLoader.load('financial')
149
- .then(res => (res ? [res] : [])),
150
- description: `Fees for source transaction=${sourceTransaction}`,
151
- };
152
- }
153
- if (description.includes('דותן שמחה') || description.includes('שמחה דותן')) {
154
- const current = new Date();
155
- current.setMonth(current.getMonth() - 1);
156
- const previousMonth = current.toLocaleString('default', {
157
- month: '2-digit',
158
- });
159
- return {
160
- description: `${previousMonth}/2022 Salary`,
161
- tags: await injector
162
- .get(TagsProvider)
163
- .getTagByNameLoader.load('business')
164
- .then(res => (res ? [res] : [])),
165
- };
166
- }
167
- if (description.includes('גולדשטין אורי')) {
168
- const current = new Date();
169
- current.setMonth(current.getMonth() - 1);
170
- const previousMonth = current.toLocaleString('default', {
171
- month: '2-digit',
172
- });
173
- return {
174
- description: `${previousMonth}/2022 Salary`,
175
- tags: await injector
176
- .get(TagsProvider)
177
- .getTagByNameLoader.load('business')
178
- .then(res => (res ? [res] : [])),
179
- };
180
- }
181
- if (description.includes('גרדוש')) {
182
- const current = new Date();
183
- current.setMonth(current.getMonth() - 1);
184
- const previousMonth = current.toLocaleString('default', {
185
- month: '2-digit',
186
- });
187
- return {
188
- description: `${previousMonth}/2022 Salary`,
189
- tags: await injector
190
- .get(TagsProvider)
191
- .getTagByNameLoader.load('business')
192
- .then(res => (res ? [res] : [])),
193
- };
194
- }
195
- if (description.includes('תובל')) {
196
- const current = new Date();
197
- current.setMonth(current.getMonth() - 1);
198
- const previousMonth = current.toLocaleString('default', {
199
- month: '2-digit',
200
- });
201
- return {
202
- description: `${previousMonth}/2022 Salary`,
203
- tags: await injector
204
- .get(TagsProvider)
205
- .getTagByNameLoader.load('business')
206
- .then(res => (res ? [res] : [])),
207
- };
208
- }
209
- if (description.includes('מנורה מבטחים פנס')) {
210
- const current = new Date();
211
- current.setMonth(current.getMonth() - 1);
212
- const previousMonth = current.toLocaleString('default', {
213
- month: '2-digit',
214
- });
215
- return {
216
- description: `Pension ${previousMonth}/2022`,
217
- tags: await injector
218
- .get(TagsProvider)
219
- .getTagByNameLoader.load('business')
220
- .then(res => (res ? [res] : [])),
221
- };
222
- }
223
- if (description.includes('פניקס אקסלנס')) {
224
- const current = new Date();
225
- current.setMonth(current.getMonth() - 1);
226
- const previousMonth = current.toLocaleString('default', {
227
- month: '2-digit',
228
- });
229
- return {
230
- description: `Training Fund ${previousMonth}/2022`,
231
- tags: await injector
232
- .get(TagsProvider)
233
- .getTagByNameLoader.load('business')
234
- .then(res => (res ? [res] : [])),
235
- };
236
- }
237
- if (description.includes('מיטב דש גמל ופנס')) {
238
- const current = new Date();
239
- current.setMonth(current.getMonth() - 1);
240
- const previousMonth = current.toLocaleString('default', {
241
- month: '2-digit',
242
- });
243
- return {
244
- description: `Pension ${previousMonth}/2022`,
245
- tags: await injector
246
- .get(TagsProvider)
247
- .getTagByNameLoader.load('business')
248
- .then(res => (res ? [res] : [])),
249
- };
250
- }
251
- if (description.includes('מגדל מקפת')) {
252
- const current = new Date();
253
- current.setMonth(current.getMonth() - 1);
254
- const previousMonth = current.toLocaleString('default', {
255
- month: '2-digit',
256
- });
257
- return {
258
- description: `Pension ${previousMonth}/2022`,
259
- tags: await injector
260
- .get(TagsProvider)
261
- .getTagByNameLoader.load('business')
262
- .then(res => (res ? [res] : [])),
263
- };
264
- }
265
- if (description.includes('מגדל השתלמות')) {
266
- const current = new Date();
267
- current.setMonth(current.getMonth() - 1);
268
- const previousMonth = current.toLocaleString('default', {
269
- month: '2-digit',
270
- });
271
- return {
272
- description: `Training Fund ${previousMonth}/2022`,
273
- tags: await injector
274
- .get(TagsProvider)
275
- .getTagByNameLoader.load('business')
276
- .then(res => (res ? [res] : [])),
277
- };
278
- }
279
- if (description.includes('ביטוח לאומי')) {
280
- const current = new Date();
281
- current.setMonth(current.getMonth() - 1);
282
- const previousMonth = current.toLocaleString('default', {
283
- month: '2-digit',
284
- });
285
- return {
286
- description: `Social Security Deductions for Salaries ${previousMonth}/2022`,
287
- tags: await injector
288
- .get(TagsProvider)
289
- .getTagByNameLoader.load('business')
290
- .then(res => (res ? [res] : [])),
291
- };
292
- }
293
- if (description.includes('LANCE GLOBAL')) {
294
- const current = new Date();
295
- current.setMonth(current.getMonth() - 1);
296
- const previousMonth = current.toLocaleString('default', { month: 'long' });
297
- return {
298
- description: `The Guild Enterprise Support - ${previousMonth} 2022`,
299
- tags: await injector
300
- .get(TagsProvider)
301
- .getTagByNameLoader.load('business')
302
- .then(res => (res ? [res] : [])),
303
- };
304
- }
305
- if ((description.includes('העברת מט"ח') &&
306
- (description.includes('fbv') || description.includes('fv'))) ||
307
- description.includes('kamil kisiela')) {
308
- const current = new Date();
309
- current.setMonth(current.getMonth() - 1);
310
- const previousMonth = current.toLocaleString('default', {
311
- month: '2-digit',
312
- });
313
- return {
314
- description: `Software Development and Consulting ${previousMonth}/23`,
315
- tags: await injector
316
- .get(TagsProvider)
317
- .getTagByNameLoader.load('business')
318
- .then(res => (res ? [res] : [])),
319
- };
320
- }
321
- if (description.includes('slava')) {
322
- const current = new Date();
323
- current.setMonth(current.getMonth() - 1);
324
- const previousMonth = current.toLocaleString('default', { month: '2-digit' });
325
- return {
326
- description: `Web Development Services ${previousMonth}/23`,
327
- tags: await injector
328
- .get(TagsProvider)
329
- .getTagByNameLoader.load('business')
330
- .then(res => (res ? [res] : [])),
331
- };
332
- }
333
- if (description.includes('COURIER PLUS INC')) {
334
- const current = new Date();
335
- current.setMonth(current.getMonth() - 1);
336
- const previousMonth = current.toLocaleString('default', { month: 'long' });
337
- return {
338
- description: `GraphQL Hive Enterprise License - ${previousMonth} 2023`,
339
- tags: await injector
340
- .get(TagsProvider)
341
- .getTagByNameLoader.load('business')
342
- .then(res => (res ? [res] : [])),
343
- };
344
- }
345
- if (description.includes('GOBRANDS')) {
346
- const current = new Date();
347
- current.setMonth(current.getMonth() - 1);
348
- const previousMonth = current.toLocaleString('default', { month: 'long' });
349
- return {
350
- description: `GraphQL Hive Enterprise License - ${previousMonth} 2023`,
351
- tags: await injector
352
- .get(TagsProvider)
353
- .getTagByNameLoader.load('business')
354
- .then(res => (res ? [res] : [])),
355
- };
356
- }
357
- if (description.includes('MEDIC FIRST AI')) {
358
- const current = new Date();
359
- current.setMonth(current.getMonth() - 1);
360
- const previousMonth = current.toLocaleString('default', { month: 'long' });
361
- return {
362
- description: `GraphQL Hive Enterprise License - ${previousMonth} 2023`,
363
- tags: await injector
364
- .get(TagsProvider)
365
- .getTagByNameLoader.load('business')
366
- .then(res => (res ? [res] : [])),
367
- };
368
- }
369
- if (description.includes('מס הכנסה')) {
370
- const flag = description.includes('מס הכנסה ני');
371
- const current = new Date();
372
- current.setMonth(current.getMonth() - 1);
373
- const previousMonth = current.toLocaleString('default', {
374
- month: '2-digit',
375
- });
376
- return {
377
- tags: await injector
378
- .get(TagsProvider)
379
- .getTagByNameLoader.load('business')
380
- .then(res => (res ? [res] : [])),
381
- description: flag
382
- ? `Tax for employees for ${previousMonth}/2022`
383
- : `Advance Tax for ${previousMonth}/2022`,
384
- };
385
- }
386
- if (description.includes('המכס ומעמ-גביי תשלום') || description.includes('CUSTOM + V.A.T')) {
387
- const current = new Date();
388
- current.setMonth(current.getMonth() - 1);
389
- const previousMonth = current.toLocaleString('default', {
390
- month: '2-digit',
391
- });
392
- return {
393
- description: `VAT for ${previousMonth}/2022`,
394
- tags: await injector
395
- .get(TagsProvider)
396
- .getTagByNameLoader.load('business')
397
- .then(res => (res ? [res] : [])),
398
- };
399
- }
400
- if (description.includes('חניון')) {
401
- return {
402
- description: 'Parking',
403
- tags: await injector
404
- .get(TagsProvider)
405
- .getTagByNameLoader.load('transportation')
406
- .then(res => (res ? [res] : [])),
407
- };
408
- }
409
- if (description.includes('deel')) {
410
- return {
411
- description: 'Laurin Salary',
412
- tags: await injector
413
- .get(TagsProvider)
414
- .getTagByNameLoader.load('business')
415
- .then(res => (res ? [res] : [])),
416
- };
417
- }
418
- if (description.includes('GITHUB')) {
419
- const suggested = {
420
- description: 'GitHub Actions',
421
- tags: await injector
422
- .get(TagsProvider)
423
- .getTagByNameLoader.load('business')
424
- .then(res => (res ? [res] : [])),
425
- };
426
- if (chargeAmount <= -2000) {
427
- suggested.description = 'Monthly Sponsor for Benjie, Code-Hex, hayes';
428
- }
429
- else if (chargeAmount <= -1000) {
430
- suggested.description = 'Monthly Sponsor for Andarist, warrenday';
431
- }
432
- else {
433
- suggested.description = 'GitHub Actions';
434
- }
435
- return suggested;
436
- }
437
- if (chargeAmount === -4329) {
438
- return {
439
- description: 'Office rent',
440
- tags: await injector
441
- .get(TagsProvider)
442
- .getTagByNameLoader.load('business')
443
- .then(res => (res ? [res] : [])),
444
- };
445
- }
446
- if (description.includes('APPLE COM BILL/ITUNES.COM')) {
447
- const flag = chargeAmount === -109.9;
448
- return {
449
- taxCategory: 'אתר',
450
- beneficiaaries: [], // NOTE: used to be ' '
451
- description: flag ? 'LinkedIn' : 'Apple Services',
452
- tags: await injector
453
- .get(TagsProvider)
454
- .getTagByNameLoader.load(flag ? 'business' : 'computer')
455
- .then(res => (res ? [res] : [])),
456
- };
457
- }
458
- if (description.includes('ע\' העברת מט"ח') ||
459
- (description.includes('העברת מט"ח') && Math.abs(chargeAmount) < 400) ||
460
- (description.includes('מטח') && Math.abs(chargeAmount) < 400) ||
461
- description.includes('F.C.COM') ||
462
- description.includes('ע.מפעולות-ישיר') ||
463
- description.includes('ריבית חובה') ||
464
- description.includes('FEE')) {
465
- const description = transactions.length
466
- ? `['${transactions.map(t => t.source_reference).join("','")}']`
467
- : 'Missing';
468
- //NOTE: multiple suggestions business
469
- return {
470
- tags: await injector
471
- .get(TagsProvider)
472
- .getTagByNameLoader.load('financial')
473
- .then(res => (res ? [res] : [])),
474
- description,
475
- };
476
- }
477
- if (description.includes('ריבית זכות')) {
478
- //NOTE: multiple suggestions business
479
- return {
480
- description: 'Interest fees on Euro plus',
481
- tags: await injector
482
- .get(TagsProvider)
483
- .getTagByNameLoader.load('financial')
484
- .then(res => (res ? [res] : [])),
485
- };
486
- }
487
- if (description.includes('פועלים- דמי כרטיס')) {
488
- //NOTE: multiple suggestions business
489
- return {
490
- description: 'Bank creditcard fees',
491
- tags: await injector
492
- .get(TagsProvider)
493
- .getTagByNameLoader.load('financial')
494
- .then(res => (res ? [res] : [])),
495
- };
496
- }
497
- if (description.includes('אריה קריסטל')) {
498
- //NOTE: multiple suggestions business
499
- return {
500
- description: 'Water bill for 04-2022',
501
- tags: await injector
502
- .get(TagsProvider)
503
- .getTagByNameLoader.load('house')
504
- .then(res => (res ? [res] : [])),
505
- };
506
- }
507
- if (description.includes('aleksandra')) {
508
- const current = new Date();
509
- current.setMonth(current.getMonth() - 1);
510
- const previousMonth = current.toLocaleString('default', { month: '2-digit' });
511
- return {
512
- description: `Software Consulting Fees (${previousMonth}/2023)`,
513
- tags: await injector
514
- .get(TagsProvider)
515
- .getTagByNameLoader.load('business')
516
- .then(res => (res ? [res] : [])),
517
- };
518
- }
519
- if (description.includes('denelop')) {
520
- const current = new Date();
521
- current.setMonth(current.getMonth() - 1);
522
- const previousMonth = current.toLocaleString('default', { month: '2-digit' });
523
- return {
524
- description: `Software Development and Consulting ${previousMonth}/2023`,
525
- tags: await injector
526
- .get(TagsProvider)
527
- .getTagByNameLoader.load('business')
528
- .then(res => (res ? [res] : [])),
529
- };
530
- }
531
- if (chargeAmount === -12_000) {
532
- const current = new Date();
533
- current.setMonth(current.getMonth() - 1);
534
- const previousMonth = current.toLocaleString('default', { month: '2-digit' });
535
- return {
536
- description: `${previousMonth}/2022`,
537
- tags: await injector
538
- .get(TagsProvider)
539
- .getTagByNameLoader.load('business')
540
- .then(res => (res ? [res] : [])),
541
- };
542
- }
543
- if (chargeAmount === -600) {
544
- return {
545
- description: 'Matic Zavadlal - April 2021',
546
- tags: await injector
547
- .get(TagsProvider)
548
- .getTagByNameLoader.load('business')
549
- .then(res => (res ? [res] : [])),
550
- };
556
+ catch (error) {
557
+ throw errorSimplifier('Unexpected error fetching missing info suggestions', error);
551
558
  }
552
- return null;
553
559
  };
554
560
  const commonChargeFields = {
555
561
  missingInfoSuggestions: missingInfoSuggestions,
@@ -560,63 +566,73 @@ export const chargeSuggestionsResolvers = {
560
566
  if (!chargeId?.trim()) {
561
567
  throw new GraphQLError('Charge ID is required');
562
568
  }
563
- const [mainCharge, { allBusinessIds, mainBusinessId }] = await Promise.all([
564
- injector
569
+ try {
570
+ const [mainCharge, { allBusinessIds, mainBusinessId }] = await Promise.all([
571
+ injector
572
+ .get(ChargesProvider)
573
+ .getChargeByIdLoader.load(chargeId)
574
+ .catch(e => {
575
+ console.error('Error fetching charge', { chargeId, error: e });
576
+ throw new GraphQLError('Error fetching charge');
577
+ }),
578
+ getChargeBusinesses(chargeId, injector),
579
+ ]);
580
+ if (!mainCharge) {
581
+ throw new GraphQLError(`Charge not found: ${chargeId}`);
582
+ }
583
+ const similarCharges = await injector
565
584
  .get(ChargesProvider)
566
- .getChargeByIdLoader.load(chargeId)
567
- .catch(e => {
568
- console.error('Error fetching charge', { chargeId, error: e });
569
- throw new GraphQLError('Error fetching charge');
570
- }),
571
- getChargeBusinesses(chargeId, injector),
572
- ]);
573
- if (!mainCharge) {
574
- throw new GraphQLError(`Charge not found: ${chargeId}`);
575
- }
576
- const similarCharges = await injector
577
- .get(ChargesProvider)
578
- .getSimilarCharges({
579
- businessId: mainBusinessId,
580
- businessArray: allBusinessIds,
581
- withMissingTags,
582
- withMissingDescription,
583
- tagsDifferentThan: tagsDifferentThan ? [...tagsDifferentThan] : undefined,
584
- descriptionDifferentThan,
585
- ownerId: mainCharge.owner_id,
586
- })
587
- .catch(e => {
588
- console.error('Error fetching similar charges:', {
589
- chargeId,
585
+ .getSimilarCharges({
590
586
  businessId: mainBusinessId,
591
587
  businessArray: allBusinessIds,
592
- error: e.message,
588
+ withMissingTags,
589
+ withMissingDescription,
590
+ tagsDifferentThan: tagsDifferentThan ? [...tagsDifferentThan] : undefined,
591
+ descriptionDifferentThan,
592
+ ownerId: mainCharge.owner_id,
593
+ })
594
+ .catch(e => {
595
+ console.error('Error fetching similar charges:', {
596
+ chargeId,
597
+ businessId: mainBusinessId,
598
+ businessArray: allBusinessIds,
599
+ error: e.message,
600
+ });
601
+ throw new GraphQLError('Error fetching similar charges');
593
602
  });
594
- throw new GraphQLError('Error fetching similar charges');
595
- });
596
- return similarCharges;
603
+ return similarCharges;
604
+ }
605
+ catch (error) {
606
+ throw errorSimplifier('Unexpected error fetching similar charges', error);
607
+ }
597
608
  },
598
609
  similarChargesByBusiness: async (_, { businessId, ownerId: ownerIdInput, tagsDifferentThan, descriptionDifferentThan }, { injector, adminContext }) => {
599
610
  if (!businessId?.trim()) {
600
611
  throw new GraphQLError('Business ID is required');
601
612
  }
602
- const ownerId = ownerIdInput?.trim() || adminContext.defaultAdminBusinessId;
603
- const similarCharges = await injector
604
- .get(ChargesProvider)
605
- .getSimilarCharges({
606
- businessId,
607
- tagsDifferentThan: tagsDifferentThan ? [...tagsDifferentThan] : undefined,
608
- descriptionDifferentThan,
609
- ownerId,
610
- })
611
- .catch(e => {
612
- console.error('Error fetching similar charges:', {
613
+ try {
614
+ const ownerId = ownerIdInput?.trim() || adminContext.defaultAdminBusinessId;
615
+ const similarCharges = await injector
616
+ .get(ChargesProvider)
617
+ .getSimilarCharges({
613
618
  businessId,
619
+ tagsDifferentThan: tagsDifferentThan ? [...tagsDifferentThan] : undefined,
620
+ descriptionDifferentThan,
614
621
  ownerId,
615
- error: e.message,
622
+ })
623
+ .catch(e => {
624
+ console.error('Error fetching similar charges:', {
625
+ businessId,
626
+ ownerId,
627
+ error: e.message,
628
+ });
629
+ throw new GraphQLError('Error fetching similar charges by business');
616
630
  });
617
- throw new GraphQLError('Error fetching similar charges by business');
618
- });
619
- return similarCharges;
631
+ return similarCharges;
632
+ }
633
+ catch (error) {
634
+ throw errorSimplifier('Unexpected error fetching similar charges by business', error);
635
+ }
620
636
  },
621
637
  },
622
638
  CommonCharge: commonChargeFields,