@dizzlkheinz/ynab-mcpb 0.18.4 → 0.19.0
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/CLAUDE.md +87 -8
- package/bin/ynab-mcp-server.cjs +2 -2
- package/bin/ynab-mcp-server.js +3 -3
- package/biome.json +39 -0
- package/dist/bundle/index.cjs +67 -67
- package/dist/index.d.ts +1 -1
- package/dist/index.js +27 -27
- package/dist/server/YNABMCPServer.d.ts +3 -4
- package/dist/server/YNABMCPServer.js +111 -116
- package/dist/server/budgetResolver.d.ts +6 -5
- package/dist/server/budgetResolver.js +46 -36
- package/dist/server/cacheKeys.js +6 -6
- package/dist/server/cacheManager.js +14 -11
- package/dist/server/completions.d.ts +2 -2
- package/dist/server/completions.js +20 -15
- package/dist/server/config.d.ts +10 -5
- package/dist/server/config.js +24 -7
- package/dist/server/deltaCache.d.ts +2 -2
- package/dist/server/deltaCache.js +22 -16
- package/dist/server/deltaCache.merge.d.ts +2 -2
- package/dist/server/diagnostics.d.ts +4 -4
- package/dist/server/diagnostics.js +38 -32
- package/dist/server/errorHandler.d.ts +5 -12
- package/dist/server/errorHandler.js +219 -217
- package/dist/server/prompts.d.ts +2 -2
- package/dist/server/prompts.js +45 -45
- package/dist/server/rateLimiter.js +4 -4
- package/dist/server/requestLogger.d.ts +1 -1
- package/dist/server/requestLogger.js +40 -35
- package/dist/server/resources.d.ts +3 -3
- package/dist/server/resources.js +55 -52
- package/dist/server/responseFormatter.js +6 -6
- package/dist/server/securityMiddleware.d.ts +2 -2
- package/dist/server/securityMiddleware.js +22 -20
- package/dist/server/serverKnowledgeStore.js +1 -1
- package/dist/server/toolRegistry.d.ts +3 -3
- package/dist/server/toolRegistry.js +47 -40
- package/dist/tools/__tests__/deltaTestUtils.d.ts +3 -3
- package/dist/tools/__tests__/deltaTestUtils.js +2 -2
- package/dist/tools/accountTools.d.ts +9 -8
- package/dist/tools/accountTools.js +47 -47
- package/dist/tools/adapters.d.ts +13 -8
- package/dist/tools/adapters.js +21 -11
- package/dist/tools/budgetTools.d.ts +8 -7
- package/dist/tools/budgetTools.js +22 -22
- package/dist/tools/categoryTools.d.ts +9 -8
- package/dist/tools/categoryTools.js +68 -59
- package/dist/tools/compareTransactions/formatter.d.ts +3 -3
- package/dist/tools/compareTransactions/formatter.js +9 -9
- package/dist/tools/compareTransactions/index.d.ts +6 -6
- package/dist/tools/compareTransactions/index.js +58 -43
- package/dist/tools/compareTransactions/matcher.d.ts +1 -1
- package/dist/tools/compareTransactions/matcher.js +28 -15
- package/dist/tools/compareTransactions/parser.d.ts +2 -2
- package/dist/tools/compareTransactions/parser.js +144 -138
- package/dist/tools/compareTransactions/types.d.ts +4 -4
- package/dist/tools/compareTransactions.d.ts +1 -1
- package/dist/tools/compareTransactions.js +1 -1
- package/dist/tools/deltaFetcher.d.ts +2 -2
- package/dist/tools/deltaFetcher.js +16 -15
- package/dist/tools/deltaSupport.d.ts +4 -4
- package/dist/tools/deltaSupport.js +35 -41
- package/dist/tools/exportTransactions.d.ts +5 -4
- package/dist/tools/exportTransactions.js +61 -59
- package/dist/tools/monthTools.d.ts +7 -6
- package/dist/tools/monthTools.js +31 -29
- package/dist/tools/payeeTools.d.ts +7 -6
- package/dist/tools/payeeTools.js +28 -28
- package/dist/tools/reconcileAdapter.d.ts +2 -2
- package/dist/tools/reconcileAdapter.js +19 -12
- package/dist/tools/reconciliation/analyzer.d.ts +4 -4
- package/dist/tools/reconciliation/analyzer.js +73 -59
- package/dist/tools/reconciliation/csvParser.d.ts +3 -3
- package/dist/tools/reconciliation/csvParser.js +128 -104
- package/dist/tools/reconciliation/executor.d.ts +4 -4
- package/dist/tools/reconciliation/executor.js +148 -109
- package/dist/tools/reconciliation/index.d.ts +10 -10
- package/dist/tools/reconciliation/index.js +96 -83
- package/dist/tools/reconciliation/matcher.d.ts +3 -3
- package/dist/tools/reconciliation/matcher.js +17 -16
- package/dist/tools/reconciliation/payeeNormalizer.js +19 -8
- package/dist/tools/reconciliation/recommendationEngine.d.ts +1 -1
- package/dist/tools/reconciliation/recommendationEngine.js +40 -40
- package/dist/tools/reconciliation/reportFormatter.d.ts +2 -2
- package/dist/tools/reconciliation/reportFormatter.js +59 -58
- package/dist/tools/reconciliation/signDetector.d.ts +1 -1
- package/dist/tools/reconciliation/types.d.ts +16 -16
- package/dist/tools/reconciliation/ynabAdapter.d.ts +2 -2
- package/dist/tools/schemas/common.d.ts +1 -1
- package/dist/tools/schemas/common.js +1 -1
- package/dist/tools/schemas/outputs/accountOutputs.d.ts +1 -1
- package/dist/tools/schemas/outputs/accountOutputs.js +24 -18
- package/dist/tools/schemas/outputs/budgetOutputs.d.ts +1 -1
- package/dist/tools/schemas/outputs/budgetOutputs.js +14 -11
- package/dist/tools/schemas/outputs/categoryOutputs.d.ts +1 -1
- package/dist/tools/schemas/outputs/categoryOutputs.js +49 -29
- package/dist/tools/schemas/outputs/comparisonOutputs.d.ts +1 -1
- package/dist/tools/schemas/outputs/comparisonOutputs.js +12 -12
- package/dist/tools/schemas/outputs/index.d.ts +14 -14
- package/dist/tools/schemas/outputs/index.js +14 -14
- package/dist/tools/schemas/outputs/monthOutputs.d.ts +1 -1
- package/dist/tools/schemas/outputs/monthOutputs.js +56 -41
- package/dist/tools/schemas/outputs/payeeOutputs.d.ts +1 -1
- package/dist/tools/schemas/outputs/payeeOutputs.js +10 -10
- package/dist/tools/schemas/outputs/reconciliationOutputs.d.ts +2 -2
- package/dist/tools/schemas/outputs/reconciliationOutputs.js +45 -45
- package/dist/tools/schemas/outputs/transactionMutationOutputs.d.ts +1 -1
- package/dist/tools/schemas/outputs/transactionMutationOutputs.js +28 -22
- package/dist/tools/schemas/outputs/transactionOutputs.d.ts +1 -1
- package/dist/tools/schemas/outputs/transactionOutputs.js +43 -35
- package/dist/tools/schemas/outputs/utilityOutputs.d.ts +1 -1
- package/dist/tools/schemas/outputs/utilityOutputs.js +5 -3
- package/dist/tools/schemas/shared/commonOutputs.d.ts +1 -1
- package/dist/tools/schemas/shared/commonOutputs.js +15 -9
- package/dist/tools/transactionReadTools.d.ts +11 -0
- package/dist/tools/transactionReadTools.js +202 -0
- package/dist/tools/transactionSchemas.d.ts +7 -7
- package/dist/tools/transactionSchemas.js +77 -57
- package/dist/tools/transactionTools.d.ts +6 -24
- package/dist/tools/transactionTools.js +7 -1499
- package/dist/tools/transactionUtils.d.ts +6 -6
- package/dist/tools/transactionUtils.js +78 -63
- package/dist/tools/transactionWriteTools.d.ts +20 -0
- package/dist/tools/transactionWriteTools.js +1342 -0
- package/dist/tools/utilityTools.d.ts +5 -4
- package/dist/tools/utilityTools.js +11 -11
- package/dist/types/index.d.ts +7 -7
- package/dist/types/index.js +6 -6
- package/dist/types/reconciliation.d.ts +1 -1
- package/dist/types/toolRegistration.d.ts +14 -12
- package/dist/utils/amountUtils.js +1 -1
- package/dist/utils/dateUtils.js +4 -4
- package/dist/utils/errors.d.ts +3 -3
- package/dist/utils/errors.js +4 -4
- package/dist/utils/money.d.ts +2 -2
- package/dist/utils/money.js +8 -8
- package/dist/utils/validationError.d.ts +1 -1
- package/dist/utils/validationError.js +1 -1
- package/docs/assets/examples/reconciliation-with-recommendations.json +66 -66
- package/docs/assets/schemas/reconciliation-v2.json +360 -336
- package/esbuild.config.mjs +53 -50
- package/meta.json +12548 -12548
- package/package.json +98 -111
- package/scripts/analyze-bundle.mjs +33 -30
- package/scripts/create-pr-description.js +169 -120
- package/scripts/run-all-tests.js +178 -169
- package/scripts/run-domain-integration-tests.js +28 -18
- package/scripts/run-generate-mcpb.js +19 -17
- package/scripts/run-throttled-integration-tests.js +92 -83
- package/scripts/test-delta-params.mjs +149 -120
- package/scripts/test-recommendations.ts +36 -32
- package/scripts/tmpTransaction.ts +80 -43
- package/scripts/validate-env.js +98 -91
- package/scripts/verify-build.js +78 -76
- package/src/__tests__/comprehensive.integration.test.ts +1281 -1154
- package/src/__tests__/performance.test.ts +723 -671
- package/src/__tests__/setup.ts +442 -395
- package/src/__tests__/smoke.e2e.test.ts +41 -39
- package/src/__tests__/testRunner.ts +314 -295
- package/src/__tests__/testUtils.ts +456 -364
- package/src/__tests__/tools/reconciliation/csvParser.integration.test.ts +109 -107
- package/src/__tests__/tools/reconciliation/real-world.integration.test.ts +41 -41
- package/src/index.ts +68 -59
- package/src/server/CLAUDE.md +480 -0
- package/src/server/YNABMCPServer.ts +821 -794
- package/src/server/__tests__/YNABMCPServer.integration.test.ts +929 -893
- package/src/server/__tests__/YNABMCPServer.test.ts +903 -899
- package/src/server/__tests__/budgetResolver.test.ts +466 -423
- package/src/server/__tests__/cacheManager.test.ts +891 -874
- package/src/server/__tests__/completions.integration.test.ts +115 -106
- package/src/server/__tests__/completions.test.ts +334 -313
- package/src/server/__tests__/config.test.ts +98 -86
- package/src/server/__tests__/deltaCache.merge.test.ts +774 -703
- package/src/server/__tests__/deltaCache.swr.test.ts +198 -153
- package/src/server/__tests__/deltaCache.test.ts +946 -759
- package/src/server/__tests__/diagnostics.test.ts +825 -792
- package/src/server/__tests__/errorHandler.integration.test.ts +512 -462
- package/src/server/__tests__/errorHandler.test.ts +402 -397
- package/src/server/__tests__/prompts.test.ts +424 -347
- package/src/server/__tests__/rateLimiter.test.ts +313 -309
- package/src/server/__tests__/requestLogger.test.ts +443 -403
- package/src/server/__tests__/resources.template.test.ts +196 -185
- package/src/server/__tests__/resources.test.ts +294 -288
- package/src/server/__tests__/security.integration.test.ts +487 -421
- package/src/server/__tests__/securityMiddleware.test.ts +519 -444
- package/src/server/__tests__/server-startup.integration.test.ts +509 -490
- package/src/server/__tests__/serverKnowledgeStore.test.ts +174 -173
- package/src/server/__tests__/toolRegistration.test.ts +239 -210
- package/src/server/__tests__/toolRegistry.test.ts +907 -845
- package/src/server/budgetResolver.ts +221 -181
- package/src/server/cacheKeys.ts +6 -6
- package/src/server/cacheManager.ts +498 -484
- package/src/server/completions.ts +267 -243
- package/src/server/config.ts +35 -14
- package/src/server/deltaCache.merge.ts +146 -128
- package/src/server/deltaCache.ts +352 -309
- package/src/server/diagnostics.ts +257 -242
- package/src/server/errorHandler.ts +747 -744
- package/src/server/prompts.ts +181 -176
- package/src/server/rateLimiter.ts +131 -129
- package/src/server/requestLogger.ts +350 -322
- package/src/server/resources.ts +442 -374
- package/src/server/responseFormatter.ts +41 -37
- package/src/server/securityMiddleware.ts +223 -205
- package/src/server/serverKnowledgeStore.ts +67 -67
- package/src/server/toolRegistry.ts +508 -474
- package/src/tools/CLAUDE.md +604 -0
- package/src/tools/__tests__/accountTools.delta.integration.test.ts +128 -111
- package/src/tools/__tests__/accountTools.integration.test.ts +129 -111
- package/src/tools/__tests__/accountTools.test.ts +685 -638
- package/src/tools/__tests__/adapters.test.ts +142 -108
- package/src/tools/__tests__/budgetTools.delta.integration.test.ts +73 -73
- package/src/tools/__tests__/budgetTools.integration.test.ts +132 -124
- package/src/tools/__tests__/budgetTools.test.ts +442 -413
- package/src/tools/__tests__/categoryTools.delta.integration.test.ts +76 -68
- package/src/tools/__tests__/categoryTools.integration.test.ts +314 -288
- package/src/tools/__tests__/categoryTools.test.ts +656 -625
- package/src/tools/__tests__/compareTransactions/formatter.test.ts +535 -462
- package/src/tools/__tests__/compareTransactions/index.test.ts +378 -358
- package/src/tools/__tests__/compareTransactions/matcher.test.ts +497 -398
- package/src/tools/__tests__/compareTransactions/parser.test.ts +765 -747
- package/src/tools/__tests__/compareTransactions.test.ts +352 -332
- package/src/tools/__tests__/compareTransactions.window.test.ts +150 -146
- package/src/tools/__tests__/deltaFetcher.scheduled.integration.test.ts +69 -65
- package/src/tools/__tests__/deltaFetcher.test.ts +325 -265
- package/src/tools/__tests__/deltaSupport.test.ts +211 -184
- package/src/tools/__tests__/deltaTestUtils.ts +37 -33
- package/src/tools/__tests__/exportTransactions.test.ts +205 -200
- package/src/tools/__tests__/monthTools.delta.integration.test.ts +68 -68
- package/src/tools/__tests__/monthTools.integration.test.ts +178 -166
- package/src/tools/__tests__/monthTools.test.ts +561 -512
- package/src/tools/__tests__/payeeTools.delta.integration.test.ts +68 -68
- package/src/tools/__tests__/payeeTools.integration.test.ts +158 -142
- package/src/tools/__tests__/payeeTools.test.ts +486 -434
- package/src/tools/__tests__/transactionSchemas.test.ts +1202 -1186
- package/src/tools/__tests__/transactionTools.integration.test.ts +875 -825
- package/src/tools/__tests__/transactionTools.test.ts +4923 -4366
- package/src/tools/__tests__/transactionUtils.test.ts +1004 -977
- package/src/tools/__tests__/utilityTools.integration.test.ts +32 -32
- package/src/tools/__tests__/utilityTools.test.ts +68 -58
- package/src/tools/accountTools.ts +293 -271
- package/src/tools/adapters.ts +120 -63
- package/src/tools/budgetTools.ts +121 -116
- package/src/tools/categoryTools.ts +379 -339
- package/src/tools/compareTransactions/formatter.ts +131 -119
- package/src/tools/compareTransactions/index.ts +249 -214
- package/src/tools/compareTransactions/matcher.ts +259 -209
- package/src/tools/compareTransactions/parser.ts +517 -487
- package/src/tools/compareTransactions/types.ts +38 -38
- package/src/tools/compareTransactions.ts +1 -1
- package/src/tools/deltaFetcher.ts +281 -260
- package/src/tools/deltaSupport.ts +264 -259
- package/src/tools/exportTransactions.ts +230 -218
- package/src/tools/monthTools.ts +180 -165
- package/src/tools/payeeTools.ts +152 -140
- package/src/tools/reconcileAdapter.ts +297 -252
- package/src/tools/reconciliation/CLAUDE.md +506 -0
- package/src/tools/reconciliation/__tests__/adapter.causes.test.ts +133 -124
- package/src/tools/reconciliation/__tests__/adapter.test.ts +249 -230
- package/src/tools/reconciliation/__tests__/analyzer.test.ts +408 -400
- package/src/tools/reconciliation/__tests__/csvParser.test.ts +71 -69
- package/src/tools/reconciliation/__tests__/executor.integration.test.ts +348 -323
- package/src/tools/reconciliation/__tests__/executor.progress.test.ts +503 -457
- package/src/tools/reconciliation/__tests__/executor.test.ts +898 -831
- package/src/tools/reconciliation/__tests__/matcher.test.ts +667 -663
- package/src/tools/reconciliation/__tests__/payeeNormalizer.test.ts +296 -276
- package/src/tools/reconciliation/__tests__/recommendationEngine.integration.test.ts +692 -624
- package/src/tools/reconciliation/__tests__/recommendationEngine.test.ts +1008 -989
- package/src/tools/reconciliation/__tests__/reconciliation.delta.integration.test.ts +187 -146
- package/src/tools/reconciliation/__tests__/reportFormatter.test.ts +583 -533
- package/src/tools/reconciliation/__tests__/scenarios/adapterCurrency.scenario.test.ts +75 -74
- package/src/tools/reconciliation/__tests__/scenarios/extremes.scenario.test.ts +70 -62
- package/src/tools/reconciliation/__tests__/scenarios/repeatAmount.scenario.test.ts +102 -88
- package/src/tools/reconciliation/__tests__/schemaUrl.test.ts +56 -55
- package/src/tools/reconciliation/__tests__/signDetector.test.ts +209 -206
- package/src/tools/reconciliation/__tests__/ynabAdapter.test.ts +66 -60
- package/src/tools/reconciliation/analyzer.ts +564 -504
- package/src/tools/reconciliation/csvParser.ts +656 -609
- package/src/tools/reconciliation/executor.ts +1290 -1128
- package/src/tools/reconciliation/index.ts +580 -528
- package/src/tools/reconciliation/matcher.ts +256 -240
- package/src/tools/reconciliation/payeeNormalizer.ts +92 -78
- package/src/tools/reconciliation/recommendationEngine.ts +357 -345
- package/src/tools/reconciliation/reportFormatter.ts +343 -307
- package/src/tools/reconciliation/signDetector.ts +89 -83
- package/src/tools/reconciliation/types.ts +164 -159
- package/src/tools/reconciliation/ynabAdapter.ts +17 -15
- package/src/tools/schemas/CLAUDE.md +546 -0
- package/src/tools/schemas/common.ts +1 -1
- package/src/tools/schemas/outputs/__tests__/accountOutputs.test.ts +410 -409
- package/src/tools/schemas/outputs/__tests__/budgetOutputs.test.ts +305 -299
- package/src/tools/schemas/outputs/__tests__/categoryOutputs.test.ts +431 -430
- package/src/tools/schemas/outputs/__tests__/comparisonOutputs.test.ts +510 -495
- package/src/tools/schemas/outputs/__tests__/dateValidation.test.ts +179 -153
- package/src/tools/schemas/outputs/__tests__/discrepancyDirection.test.ts +293 -254
- package/src/tools/schemas/outputs/__tests__/monthOutputs.test.ts +457 -457
- package/src/tools/schemas/outputs/__tests__/payeeOutputs.test.ts +362 -356
- package/src/tools/schemas/outputs/__tests__/reconciliationOutputs.test.ts +402 -399
- package/src/tools/schemas/outputs/__tests__/transactionMutationSchemas.test.ts +225 -211
- package/src/tools/schemas/outputs/__tests__/transactionOutputs.test.ts +457 -454
- package/src/tools/schemas/outputs/__tests__/utilityOutputs.test.ts +316 -315
- package/src/tools/schemas/outputs/accountOutputs.ts +40 -34
- package/src/tools/schemas/outputs/budgetOutputs.ts +24 -19
- package/src/tools/schemas/outputs/categoryOutputs.ts +76 -56
- package/src/tools/schemas/outputs/comparisonOutputs.ts +192 -169
- package/src/tools/schemas/outputs/index.ts +163 -163
- package/src/tools/schemas/outputs/monthOutputs.ts +95 -80
- package/src/tools/schemas/outputs/payeeOutputs.ts +18 -18
- package/src/tools/schemas/outputs/reconciliationOutputs.ts +386 -373
- package/src/tools/schemas/outputs/transactionMutationOutputs.ts +259 -231
- package/src/tools/schemas/outputs/transactionOutputs.ts +81 -71
- package/src/tools/schemas/outputs/utilityOutputs.ts +90 -84
- package/src/tools/schemas/shared/commonOutputs.ts +27 -19
- package/src/tools/toolCategories.ts +114 -114
- package/src/tools/transactionReadTools.ts +327 -0
- package/src/tools/transactionSchemas.ts +322 -291
- package/src/tools/transactionTools.ts +84 -2246
- package/src/tools/transactionUtils.ts +507 -422
- package/src/tools/transactionWriteTools.ts +2110 -0
- package/src/tools/utilityTools.ts +46 -41
- package/src/types/CLAUDE.md +477 -0
- package/src/types/__tests__/index.test.ts +51 -51
- package/src/types/index.ts +43 -39
- package/src/types/integration-tests.d.ts +26 -26
- package/src/types/reconciliation.ts +29 -29
- package/src/types/toolAnnotations.ts +30 -30
- package/src/types/toolRegistration.ts +43 -32
- package/src/utils/CLAUDE.md +508 -0
- package/src/utils/__tests__/dateUtils.test.ts +174 -168
- package/src/utils/__tests__/money.test.ts +193 -187
- package/src/utils/amountUtils.ts +5 -5
- package/src/utils/baseError.ts +5 -5
- package/src/utils/dateUtils.ts +29 -26
- package/src/utils/errors.ts +14 -14
- package/src/utils/money.ts +66 -52
- package/src/utils/validationError.ts +1 -1
- package/tsconfig.json +29 -29
- package/tsconfig.prod.json +16 -16
- package/vitest-reporters/split-json-reporter.ts +247 -204
- package/vitest.config.ts +99 -95
- package/.prettierignore +0 -10
- package/.prettierrc.json +0 -10
- package/eslint.config.js +0 -49
|
@@ -5,12 +5,15 @@
|
|
|
5
5
|
* bank amounts need to be inverted to match YNAB's sign convention.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type {
|
|
8
|
+
import type {
|
|
9
|
+
BankTransaction,
|
|
10
|
+
NormalizedYNABTransaction,
|
|
11
|
+
} from "../../types/reconciliation.js";
|
|
9
12
|
|
|
10
13
|
interface SignMatch {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
bankAmount: number;
|
|
15
|
+
ynabAmount: number;
|
|
16
|
+
oppositeSign: boolean;
|
|
14
17
|
}
|
|
15
18
|
|
|
16
19
|
/**
|
|
@@ -27,91 +30,94 @@ interface SignMatch {
|
|
|
27
30
|
* @returns true if bank amounts should be inverted, false otherwise
|
|
28
31
|
*/
|
|
29
32
|
export function detectSignInversion(
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
bankTransactions: BankTransaction[],
|
|
34
|
+
ynabTransactions: NormalizedYNABTransaction[],
|
|
32
35
|
): boolean {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
36
|
+
// Edge cases: empty lists
|
|
37
|
+
if (bankTransactions.length === 0 || ynabTransactions.length === 0) {
|
|
38
|
+
return false; // Conservative default: don't invert
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Sample up to 20 transactions for performance
|
|
42
|
+
const sampleSize = Math.min(20, bankTransactions.length);
|
|
43
|
+
const sample = bankTransactions.slice(0, sampleSize);
|
|
44
|
+
|
|
45
|
+
const matches: SignMatch[] = [];
|
|
46
|
+
|
|
47
|
+
// Try to find matches for each bank transaction
|
|
48
|
+
for (const bankTxn of sample) {
|
|
49
|
+
const match = findClosestMatch(bankTxn, ynabTransactions);
|
|
50
|
+
if (match) {
|
|
51
|
+
matches.push(match);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Need at least 1 match to make a determination
|
|
56
|
+
if (matches.length === 0) {
|
|
57
|
+
return false; // Conservative default: don't invert
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Count how many matches have opposite signs
|
|
61
|
+
const oppositeSignCount = matches.filter((m) => m.oppositeSign).length;
|
|
62
|
+
const oppositeSignRatio = oppositeSignCount / matches.length;
|
|
63
|
+
|
|
64
|
+
// If more than 50% have opposite signs, inversion is needed
|
|
65
|
+
return oppositeSignRatio > 0.5;
|
|
63
66
|
}
|
|
64
67
|
|
|
65
68
|
/**
|
|
66
69
|
* Find the closest matching YNAB transaction for a bank transaction
|
|
67
70
|
*/
|
|
68
71
|
function findClosestMatch(
|
|
69
|
-
|
|
70
|
-
|
|
72
|
+
bankTxn: BankTransaction,
|
|
73
|
+
ynabTransactions: NormalizedYNABTransaction[],
|
|
71
74
|
): SignMatch | null {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
75
|
+
const bankDate = new Date(bankTxn.date);
|
|
76
|
+
const bankAbsAmount = Math.abs(bankTxn.amount);
|
|
77
|
+
|
|
78
|
+
let bestMatch: SignMatch | null = null;
|
|
79
|
+
let bestScore = 0;
|
|
80
|
+
|
|
81
|
+
for (const ynabTxn of ynabTransactions) {
|
|
82
|
+
const ynabDate = new Date(ynabTxn.date);
|
|
83
|
+
const ynabAbsAmount = Math.abs(ynabTxn.amount);
|
|
84
|
+
|
|
85
|
+
// Check if amounts match (within tolerance)
|
|
86
|
+
const amountDiff = Math.abs(bankAbsAmount - ynabAbsAmount);
|
|
87
|
+
const amountTolerance = 100; // 10 cents in milliunits
|
|
88
|
+
if (amountDiff > amountTolerance) {
|
|
89
|
+
continue; // Amounts too different
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Check date proximity
|
|
93
|
+
const daysDiff =
|
|
94
|
+
Math.abs(bankDate.getTime() - ynabDate.getTime()) / (1000 * 60 * 60 * 24);
|
|
95
|
+
if (daysDiff > 7) {
|
|
96
|
+
continue; // Dates too far apart
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Calculate match score (closer = higher score)
|
|
100
|
+
const amountScore =
|
|
101
|
+
amountDiff === 0 ? 100 : Math.max(0, 100 - amountDiff / 10);
|
|
102
|
+
const dateScore = daysDiff === 0 ? 100 : Math.max(0, 100 - daysDiff * 10);
|
|
103
|
+
const score = amountScore * 0.7 + dateScore * 0.3;
|
|
104
|
+
|
|
105
|
+
if (score > bestScore) {
|
|
106
|
+
bestScore = score;
|
|
107
|
+
|
|
108
|
+
// Check if signs are opposite
|
|
109
|
+
const bankSign = Math.sign(bankTxn.amount);
|
|
110
|
+
const ynabSign = Math.sign(ynabTxn.amount);
|
|
111
|
+
const oppositeSign =
|
|
112
|
+
bankSign !== 0 && ynabSign !== 0 && bankSign !== ynabSign;
|
|
113
|
+
|
|
114
|
+
bestMatch = {
|
|
115
|
+
bankAmount: bankTxn.amount,
|
|
116
|
+
ynabAmount: ynabTxn.amount,
|
|
117
|
+
oppositeSign,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return bestMatch;
|
|
117
123
|
}
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
* All internal calculations use milliunits to avoid floating-point errors.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import type { MoneyValue } from '../../utils/money.js';
|
|
12
11
|
import type {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
} from
|
|
12
|
+
BankTransaction as CanonicalBankTransaction,
|
|
13
|
+
NormalizedYNABTransaction as CanonicalYNABTransaction,
|
|
14
|
+
} from "../../types/reconciliation.js";
|
|
15
|
+
import type { MoneyValue } from "../../utils/money.js";
|
|
16
16
|
|
|
17
17
|
// Re-export canonical types as the standard types
|
|
18
18
|
export type BankTransaction = CanonicalBankTransaction;
|
|
@@ -21,278 +21,283 @@ export type YNABTransaction = CanonicalYNABTransaction;
|
|
|
21
21
|
/**
|
|
22
22
|
* Matching confidence levels
|
|
23
23
|
*/
|
|
24
|
-
export type MatchConfidence =
|
|
24
|
+
export type MatchConfidence = "high" | "medium" | "low" | "none";
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* Match candidate with confidence score
|
|
28
28
|
*/
|
|
29
29
|
export interface MatchCandidate {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
ynab_transaction: YNABTransaction;
|
|
31
|
+
confidence: number;
|
|
32
|
+
match_reason: string;
|
|
33
|
+
explanation: string;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
37
|
* Transaction match result
|
|
38
38
|
*/
|
|
39
39
|
export interface TransactionMatch {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
40
|
+
bankTransaction: BankTransaction;
|
|
41
|
+
/** Best matched YNAB transaction (if any) */
|
|
42
|
+
ynabTransaction?: YNABTransaction;
|
|
43
|
+
/** Alternative candidates for suggested matches */
|
|
44
|
+
candidates?: MatchCandidate[];
|
|
45
|
+
/** Confidence level */
|
|
46
|
+
confidence: MatchConfidence;
|
|
47
|
+
/** Confidence score 0-100 */
|
|
48
|
+
confidenceScore: number;
|
|
49
|
+
/** Reason for the match */
|
|
50
|
+
matchReason: string;
|
|
51
|
+
/** Top confidence from candidates */
|
|
52
|
+
topConfidence?: number;
|
|
53
|
+
/** Action hint for user */
|
|
54
|
+
actionHint?: string;
|
|
55
|
+
/** Recommendation text */
|
|
56
|
+
recommendation?: string;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
/**
|
|
60
60
|
* Balance information with structured monetary values
|
|
61
61
|
*/
|
|
62
62
|
export interface BalanceInfo {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
63
|
+
current_cleared: MoneyValue;
|
|
64
|
+
current_uncleared: MoneyValue;
|
|
65
|
+
current_total: MoneyValue;
|
|
66
|
+
target_statement: MoneyValue;
|
|
67
|
+
discrepancy: MoneyValue;
|
|
68
|
+
on_track: boolean;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
/**
|
|
72
72
|
* Reconciliation summary statistics with structured monetary values
|
|
73
73
|
*/
|
|
74
74
|
export interface ReconciliationSummary {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
75
|
+
statement_date_range: string;
|
|
76
|
+
bank_transactions_count: number;
|
|
77
|
+
ynab_transactions_count: number;
|
|
78
|
+
/** YNAB transactions within the statement date range (used for matching) */
|
|
79
|
+
ynab_in_range_count: number;
|
|
80
|
+
/** YNAB transactions outside the statement date range (not compared) */
|
|
81
|
+
ynab_outside_range_count: number;
|
|
82
|
+
auto_matched: number;
|
|
83
|
+
suggested_matches: number;
|
|
84
|
+
unmatched_bank: number;
|
|
85
|
+
unmatched_ynab: number;
|
|
86
|
+
current_cleared_balance: MoneyValue;
|
|
87
|
+
target_statement_balance: MoneyValue;
|
|
88
|
+
discrepancy: MoneyValue;
|
|
89
|
+
discrepancy_explanation: string;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
/**
|
|
93
93
|
* Insight severity levels
|
|
94
94
|
*/
|
|
95
|
-
export type InsightSeverity =
|
|
95
|
+
export type InsightSeverity = "info" | "warning" | "critical";
|
|
96
96
|
|
|
97
97
|
/**
|
|
98
98
|
* Insight types for reconciliation analysis
|
|
99
99
|
*/
|
|
100
|
-
export type InsightKind =
|
|
100
|
+
export type InsightKind = "repeat_amount" | "near_match" | "anomaly";
|
|
101
101
|
|
|
102
102
|
/**
|
|
103
103
|
* Reconciliation insight - highlights important findings that help explain discrepancies
|
|
104
104
|
*/
|
|
105
105
|
export interface ReconciliationInsight {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
106
|
+
id: string;
|
|
107
|
+
type: InsightKind;
|
|
108
|
+
severity: InsightSeverity;
|
|
109
|
+
title: string;
|
|
110
|
+
description: string;
|
|
111
|
+
evidence?: Record<string, unknown>;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
/**
|
|
115
115
|
* Analysis phase result
|
|
116
116
|
*/
|
|
117
117
|
export interface ReconciliationAnalysis {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
118
|
+
success: true;
|
|
119
|
+
phase: "analysis";
|
|
120
|
+
summary: ReconciliationSummary;
|
|
121
|
+
auto_matches: TransactionMatch[];
|
|
122
|
+
suggested_matches: TransactionMatch[];
|
|
123
|
+
unmatched_bank: BankTransaction[];
|
|
124
|
+
unmatched_ynab: YNABTransaction[];
|
|
125
|
+
/** YNAB transactions outside the statement date range (not compared, expected) */
|
|
126
|
+
ynab_outside_date_range: YNABTransaction[];
|
|
127
|
+
balance_info: BalanceInfo;
|
|
128
|
+
next_steps: string[];
|
|
129
|
+
insights: ReconciliationInsight[];
|
|
130
|
+
recommendations?: ActionableRecommendation[];
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
/**
|
|
134
134
|
* Reconciliation action types
|
|
135
135
|
*/
|
|
136
|
-
export type ReconciliationActionType =
|
|
136
|
+
export type ReconciliationActionType =
|
|
137
|
+
| "match"
|
|
138
|
+
| "add"
|
|
139
|
+
| "unclear"
|
|
140
|
+
| "delete"
|
|
141
|
+
| "ignore";
|
|
137
142
|
|
|
138
143
|
/**
|
|
139
144
|
* Reconciliation action
|
|
140
145
|
*/
|
|
141
146
|
export interface ReconciliationAction {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
type: ReconciliationActionType;
|
|
148
|
+
bank_txn_id?: string;
|
|
149
|
+
ynab_txn_id?: string;
|
|
150
|
+
mark_cleared?: boolean;
|
|
151
|
+
create_as_cleared?: boolean;
|
|
152
|
+
reason?: string;
|
|
153
|
+
metadata?: Record<string, unknown>;
|
|
149
154
|
}
|
|
150
155
|
|
|
151
156
|
/**
|
|
152
157
|
* Matching algorithm configuration (V2)
|
|
153
158
|
*/
|
|
154
159
|
export interface MatchingConfig {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
+
weights: {
|
|
161
|
+
amount: number; // Recommended: 0.50
|
|
162
|
+
date: number; // Recommended: 0.15
|
|
163
|
+
payee: number; // Recommended: 0.35
|
|
164
|
+
};
|
|
160
165
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
166
|
+
// Tolerances (in MILLIUNITS for amount)
|
|
167
|
+
amountToleranceMilliunits: number; // Default: 10 (1 cent)
|
|
168
|
+
dateToleranceDays: number; // Default: 7
|
|
164
169
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
170
|
+
// Thresholds
|
|
171
|
+
autoMatchThreshold: number; // Default: 85
|
|
172
|
+
suggestedMatchThreshold: number; // Default: 60
|
|
173
|
+
minimumCandidateScore: number; // Default: 40
|
|
169
174
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
175
|
+
// Bonuses for perfect matches
|
|
176
|
+
exactAmountBonus: number; // Default: 10
|
|
177
|
+
exactDateBonus: number; // Default: 5
|
|
178
|
+
exactPayeeBonus: number; // Default: 10
|
|
174
179
|
}
|
|
175
180
|
|
|
176
181
|
/**
|
|
177
182
|
* Parsed CSV data from compareTransactions
|
|
178
183
|
*/
|
|
179
184
|
export interface ParsedCSVData {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
185
|
+
transactions: BankTransaction[];
|
|
186
|
+
format_detected: string;
|
|
187
|
+
delimiter: string;
|
|
188
|
+
total_rows: number;
|
|
189
|
+
valid_rows: number;
|
|
190
|
+
errors: string[];
|
|
186
191
|
}
|
|
187
192
|
|
|
188
193
|
/**
|
|
189
194
|
* Priority levels for actionable recommendations
|
|
190
195
|
*/
|
|
191
|
-
export type RecommendationPriority =
|
|
196
|
+
export type RecommendationPriority = "high" | "medium" | "low";
|
|
192
197
|
|
|
193
198
|
/**
|
|
194
199
|
* Base fields common to all recommendation types
|
|
195
200
|
*/
|
|
196
201
|
export interface BaseRecommendation {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
202
|
+
/** Unique identifier for this recommendation */
|
|
203
|
+
id: string;
|
|
204
|
+
/** Priority level for execution */
|
|
205
|
+
priority: RecommendationPriority;
|
|
206
|
+
/** Confidence score 0-1 (higher = more confident) */
|
|
207
|
+
confidence: number;
|
|
208
|
+
/** Human-readable message describing the recommendation */
|
|
209
|
+
message: string;
|
|
210
|
+
/** Explanation of why this recommendation was generated */
|
|
211
|
+
reason: string;
|
|
212
|
+
/** Estimated impact on reconciliation balance */
|
|
213
|
+
estimated_impact: MoneyValue;
|
|
214
|
+
/** YNAB account ID this recommendation applies to */
|
|
215
|
+
account_id: string;
|
|
216
|
+
/** Optional link to the insight that generated this recommendation */
|
|
217
|
+
source_insight_id?: string;
|
|
218
|
+
/** Additional metadata (version, timestamps, etc.) */
|
|
219
|
+
metadata?: Record<string, unknown>;
|
|
215
220
|
}
|
|
216
221
|
|
|
217
222
|
/**
|
|
218
223
|
* Recommendation to create a new YNAB transaction
|
|
219
224
|
*/
|
|
220
225
|
export interface CreateTransactionRecommendation extends BaseRecommendation {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
226
|
+
action_type: "create_transaction";
|
|
227
|
+
parameters: {
|
|
228
|
+
account_id: string;
|
|
229
|
+
date: string;
|
|
230
|
+
amount: number;
|
|
231
|
+
payee_name: string;
|
|
232
|
+
memo?: string;
|
|
233
|
+
cleared: "cleared" | "uncleared";
|
|
234
|
+
approved: boolean;
|
|
235
|
+
category_id?: string;
|
|
236
|
+
};
|
|
232
237
|
}
|
|
233
238
|
|
|
234
239
|
/**
|
|
235
240
|
* Recommendation to update a transaction's cleared status
|
|
236
241
|
*/
|
|
237
242
|
export interface UpdateClearedRecommendation extends BaseRecommendation {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
+
action_type: "update_cleared";
|
|
244
|
+
parameters: {
|
|
245
|
+
transaction_id: string;
|
|
246
|
+
cleared: "cleared" | "uncleared" | "reconciled";
|
|
247
|
+
};
|
|
243
248
|
}
|
|
244
249
|
|
|
245
250
|
/**
|
|
246
251
|
* Recommendation to review potential duplicate transactions
|
|
247
252
|
*/
|
|
248
253
|
export interface ReviewDuplicateRecommendation extends BaseRecommendation {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
254
|
+
action_type: "review_duplicate";
|
|
255
|
+
parameters: {
|
|
256
|
+
candidate_ids: string[];
|
|
257
|
+
bank_transaction?: BankTransaction;
|
|
258
|
+
suggested_match_id?: string;
|
|
259
|
+
};
|
|
255
260
|
}
|
|
256
261
|
|
|
257
262
|
/**
|
|
258
263
|
* Related transaction reference for manual review
|
|
259
264
|
*/
|
|
260
265
|
export interface RelatedTransaction {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
266
|
+
source: "bank" | "ynab";
|
|
267
|
+
id: string;
|
|
268
|
+
description: string;
|
|
264
269
|
}
|
|
265
270
|
|
|
266
271
|
/**
|
|
267
272
|
* Recommendation requiring manual investigation
|
|
268
273
|
*/
|
|
269
274
|
export interface ManualReviewRecommendation extends BaseRecommendation {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
+
action_type: "manual_review";
|
|
276
|
+
parameters: {
|
|
277
|
+
issue_type: "complex_match" | "large_discrepancy" | "unknown";
|
|
278
|
+
related_transactions?: RelatedTransaction[];
|
|
279
|
+
};
|
|
275
280
|
}
|
|
276
281
|
|
|
277
282
|
/**
|
|
278
283
|
* Union type of all possible recommendation types (discriminated by action_type)
|
|
279
284
|
*/
|
|
280
285
|
export type ActionableRecommendation =
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
286
|
+
| CreateTransactionRecommendation
|
|
287
|
+
| UpdateClearedRecommendation
|
|
288
|
+
| ReviewDuplicateRecommendation
|
|
289
|
+
| ManualReviewRecommendation;
|
|
285
290
|
|
|
286
291
|
/**
|
|
287
292
|
* Context passed to recommendation engine for generating recommendations
|
|
288
293
|
*/
|
|
289
294
|
export interface RecommendationContext {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
295
|
+
/** Account ID for the recommendations */
|
|
296
|
+
account_id: string;
|
|
297
|
+
/** Budget ID (reserved for future category suggestions) */
|
|
298
|
+
budget_id: string;
|
|
299
|
+
/** The reconciliation analysis results */
|
|
300
|
+
analysis: ReconciliationAnalysis;
|
|
301
|
+
/** Matching configuration used during analysis */
|
|
302
|
+
matching_config: MatchingConfig;
|
|
298
303
|
}
|