@accounter/server 0.0.8-alpha-20251102200443-d7162b8ce1dfc629b8b454df17dcec9ed005a052 → 0.0.8-alpha-20251102213150-c9d936f545d5351df0dc5326c2623266f1ad1f46
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/CHANGELOG.md +47 -7
- package/dist/green-invoice-graphql/src/mesh-artifacts/index.d.ts +1 -1
- package/dist/server/src/__generated__/types.d.ts +77 -0
- package/dist/server/src/__generated__/types.js.map +1 -1
- package/dist/server/src/modules/charges-matcher/__generated__/types.d.ts +68 -0
- package/dist/server/src/modules/charges-matcher/__generated__/types.js +7 -0
- package/dist/server/src/modules/charges-matcher/__generated__/types.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/amount-confidence.test.d.ts +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/amount-confidence.test.js +218 -0
- package/dist/server/src/modules/charges-matcher/__tests__/amount-confidence.test.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/auto-match-integration.test.d.ts +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/auto-match-integration.test.js +645 -0
- package/dist/server/src/modules/charges-matcher/__tests__/auto-match-integration.test.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/auto-match.test.d.ts +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/auto-match.test.js +530 -0
- package/dist/server/src/modules/charges-matcher/__tests__/auto-match.test.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/business-confidence.test.d.ts +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/business-confidence.test.js +143 -0
- package/dist/server/src/modules/charges-matcher/__tests__/business-confidence.test.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/candidate-filter.test.d.ts +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/candidate-filter.test.js +186 -0
- package/dist/server/src/modules/charges-matcher/__tests__/candidate-filter.test.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/charge-validator.test.d.ts +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/charge-validator.test.js +301 -0
- package/dist/server/src/modules/charges-matcher/__tests__/charge-validator.test.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/currency-confidence.test.d.ts +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/currency-confidence.test.js +127 -0
- package/dist/server/src/modules/charges-matcher/__tests__/currency-confidence.test.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/date-confidence.test.d.ts +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/date-confidence.test.js +246 -0
- package/dist/server/src/modules/charges-matcher/__tests__/date-confidence.test.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/document-aggregator.test.d.ts +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/document-aggregator.test.js +475 -0
- package/dist/server/src/modules/charges-matcher/__tests__/document-aggregator.test.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/document-amount.test.d.ts +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/document-amount.test.js +287 -0
- package/dist/server/src/modules/charges-matcher/__tests__/document-amount.test.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/document-business.test.d.ts +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/document-business.test.js +151 -0
- package/dist/server/src/modules/charges-matcher/__tests__/document-business.test.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/match-scorer.test.d.ts +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/match-scorer.test.js +550 -0
- package/dist/server/src/modules/charges-matcher/__tests__/match-scorer.test.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/overall-confidence.test.d.ts +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/overall-confidence.test.js +410 -0
- package/dist/server/src/modules/charges-matcher/__tests__/overall-confidence.test.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/single-match-integration.test.d.ts +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/single-match-integration.test.js +504 -0
- package/dist/server/src/modules/charges-matcher/__tests__/single-match-integration.test.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/single-match.test.d.ts +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/single-match.test.js +483 -0
- package/dist/server/src/modules/charges-matcher/__tests__/single-match.test.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/test-helpers.d.ts +46 -0
- package/dist/server/src/modules/charges-matcher/__tests__/test-helpers.js +143 -0
- package/dist/server/src/modules/charges-matcher/__tests__/test-helpers.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/test-infrastructure.spec.d.ts +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/test-infrastructure.spec.js +137 -0
- package/dist/server/src/modules/charges-matcher/__tests__/test-infrastructure.spec.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/transaction-aggregator.test.d.ts +1 -0
- package/dist/server/src/modules/charges-matcher/__tests__/transaction-aggregator.test.js +415 -0
- package/dist/server/src/modules/charges-matcher/__tests__/transaction-aggregator.test.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/helpers/amount-confidence.helper.d.ts +7 -0
- package/dist/server/src/modules/charges-matcher/helpers/amount-confidence.helper.js +70 -0
- package/dist/server/src/modules/charges-matcher/helpers/amount-confidence.helper.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/helpers/business-confidence.helper.d.ts +7 -0
- package/dist/server/src/modules/charges-matcher/helpers/business-confidence.helper.js +19 -0
- package/dist/server/src/modules/charges-matcher/helpers/business-confidence.helper.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/helpers/candidate-filter.helper.d.ts +24 -0
- package/dist/server/src/modules/charges-matcher/helpers/candidate-filter.helper.js +45 -0
- package/dist/server/src/modules/charges-matcher/helpers/candidate-filter.helper.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/helpers/charge-validator.helper.d.ts +33 -0
- package/dist/server/src/modules/charges-matcher/helpers/charge-validator.helper.js +65 -0
- package/dist/server/src/modules/charges-matcher/helpers/charge-validator.helper.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/helpers/currency-confidence.helper.d.ts +7 -0
- package/dist/server/src/modules/charges-matcher/helpers/currency-confidence.helper.js +18 -0
- package/dist/server/src/modules/charges-matcher/helpers/currency-confidence.helper.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/helpers/date-confidence.helper.d.ts +7 -0
- package/dist/server/src/modules/charges-matcher/helpers/date-confidence.helper.js +35 -0
- package/dist/server/src/modules/charges-matcher/helpers/date-confidence.helper.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/helpers/document-amount.helper.d.ts +49 -0
- package/dist/server/src/modules/charges-matcher/helpers/document-amount.helper.js +58 -0
- package/dist/server/src/modules/charges-matcher/helpers/document-amount.helper.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/helpers/document-business.helper.d.ts +13 -0
- package/dist/server/src/modules/charges-matcher/helpers/document-business.helper.js +37 -0
- package/dist/server/src/modules/charges-matcher/helpers/document-business.helper.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/helpers/overall-confidence.helper.d.ts +42 -0
- package/dist/server/src/modules/charges-matcher/helpers/overall-confidence.helper.js +77 -0
- package/dist/server/src/modules/charges-matcher/helpers/overall-confidence.helper.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/index.d.ts +3 -0
- package/dist/server/src/modules/charges-matcher/index.js +15 -0
- package/dist/server/src/modules/charges-matcher/index.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/providers/auto-match.provider.d.ts +48 -0
- package/dist/server/src/modules/charges-matcher/providers/auto-match.provider.js +133 -0
- package/dist/server/src/modules/charges-matcher/providers/auto-match.provider.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/providers/charges-matcher.provider.d.ts +38 -0
- package/dist/server/src/modules/charges-matcher/providers/charges-matcher.provider.js +248 -0
- package/dist/server/src/modules/charges-matcher/providers/charges-matcher.provider.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/providers/document-aggregator.d.ts +61 -0
- package/dist/server/src/modules/charges-matcher/providers/document-aggregator.js +153 -0
- package/dist/server/src/modules/charges-matcher/providers/document-aggregator.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/providers/match-scorer.provider.d.ts +25 -0
- package/dist/server/src/modules/charges-matcher/providers/match-scorer.provider.js +114 -0
- package/dist/server/src/modules/charges-matcher/providers/match-scorer.provider.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/providers/single-match.provider.d.ts +39 -0
- package/dist/server/src/modules/charges-matcher/providers/single-match.provider.js +189 -0
- package/dist/server/src/modules/charges-matcher/providers/single-match.provider.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/providers/transaction-aggregator.d.ts +54 -0
- package/dist/server/src/modules/charges-matcher/providers/transaction-aggregator.js +93 -0
- package/dist/server/src/modules/charges-matcher/providers/transaction-aggregator.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/resolvers/auto-match-charges.resolver.d.ts +2 -0
- package/dist/server/src/modules/charges-matcher/resolvers/auto-match-charges.resolver.js +22 -0
- package/dist/server/src/modules/charges-matcher/resolvers/auto-match-charges.resolver.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/resolvers/find-charge-matches.resolver.d.ts +2 -0
- package/dist/server/src/modules/charges-matcher/resolvers/find-charge-matches.resolver.js +24 -0
- package/dist/server/src/modules/charges-matcher/resolvers/find-charge-matches.resolver.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/resolvers/index.d.ts +2 -0
- package/dist/server/src/modules/charges-matcher/resolvers/index.js +11 -0
- package/dist/server/src/modules/charges-matcher/resolvers/index.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/typeDefs/charges-matcher.graphql.d.ts +2 -0
- package/dist/server/src/modules/charges-matcher/typeDefs/charges-matcher.graphql.js +47 -0
- package/dist/server/src/modules/charges-matcher/typeDefs/charges-matcher.graphql.js.map +1 -0
- package/dist/server/src/modules/charges-matcher/types.d.ts +179 -0
- package/dist/server/src/modules/charges-matcher/types.js +14 -0
- package/dist/server/src/modules/charges-matcher/types.js.map +1 -0
- package/dist/server/src/modules/documents/resolvers/document-suggestions.resolver.js +2 -2
- package/dist/server/src/modules/documents/resolvers/document-suggestions.resolver.js.map +1 -1
- package/dist/server/src/modules-app.js +2 -0
- package/dist/server/src/modules-app.js.map +1 -1
- package/dist/server/src/shared/types/index.d.ts +1 -1
- package/package.json +4 -4
- package/src/__generated__/types.ts +87 -0
- package/src/modules/charges-matcher/README.md +279 -0
- package/src/modules/charges-matcher/__generated__/types.ts +71 -0
- package/src/modules/charges-matcher/__tests__/amount-confidence.test.ts +260 -0
- package/src/modules/charges-matcher/__tests__/auto-match-integration.test.ts +714 -0
- package/src/modules/charges-matcher/__tests__/auto-match.test.ts +621 -0
- package/src/modules/charges-matcher/__tests__/business-confidence.test.ts +177 -0
- package/src/modules/charges-matcher/__tests__/candidate-filter.test.ts +238 -0
- package/src/modules/charges-matcher/__tests__/charge-validator.test.ts +374 -0
- package/src/modules/charges-matcher/__tests__/currency-confidence.test.ts +164 -0
- package/src/modules/charges-matcher/__tests__/date-confidence.test.ts +291 -0
- package/src/modules/charges-matcher/__tests__/document-aggregator.test.ts +614 -0
- package/src/modules/charges-matcher/__tests__/document-amount.test.ts +352 -0
- package/src/modules/charges-matcher/__tests__/document-business.test.ts +192 -0
- package/src/modules/charges-matcher/__tests__/match-scorer.test.ts +659 -0
- package/src/modules/charges-matcher/__tests__/overall-confidence.test.ts +502 -0
- package/src/modules/charges-matcher/__tests__/single-match-integration.test.ts +556 -0
- package/src/modules/charges-matcher/__tests__/single-match.test.ts +608 -0
- package/src/modules/charges-matcher/__tests__/test-helpers.ts +174 -0
- package/src/modules/charges-matcher/__tests__/test-infrastructure.spec.ts +177 -0
- package/src/modules/charges-matcher/__tests__/transaction-aggregator.test.ts +547 -0
- package/src/modules/charges-matcher/documentation/README.md +331 -0
- package/src/modules/charges-matcher/documentation/SPEC.md +1503 -0
- package/src/modules/charges-matcher/documentation/TODO.md +799 -0
- package/src/modules/charges-matcher/helpers/amount-confidence.helper.ts +88 -0
- package/src/modules/charges-matcher/helpers/business-confidence.helper.ts +23 -0
- package/src/modules/charges-matcher/helpers/candidate-filter.helper.ts +56 -0
- package/src/modules/charges-matcher/helpers/charge-validator.helper.ts +100 -0
- package/src/modules/charges-matcher/helpers/currency-confidence.helper.ts +22 -0
- package/src/modules/charges-matcher/helpers/date-confidence.helper.ts +41 -0
- package/src/modules/charges-matcher/helpers/document-amount.helper.ts +77 -0
- package/src/modules/charges-matcher/helpers/document-business.helper.ts +54 -0
- package/src/modules/charges-matcher/helpers/overall-confidence.helper.ts +90 -0
- package/src/modules/charges-matcher/index.ts +17 -0
- package/src/modules/charges-matcher/providers/auto-match.provider.ts +176 -0
- package/src/modules/charges-matcher/providers/charges-matcher.provider.ts +322 -0
- package/src/modules/charges-matcher/providers/document-aggregator.ts +211 -0
- package/src/modules/charges-matcher/providers/match-scorer.provider.ts +154 -0
- package/src/modules/charges-matcher/providers/single-match.provider.ts +252 -0
- package/src/modules/charges-matcher/providers/transaction-aggregator.ts +131 -0
- package/src/modules/charges-matcher/resolvers/auto-match-charges.resolver.ts +23 -0
- package/src/modules/charges-matcher/resolvers/find-charge-matches.resolver.ts +25 -0
- package/src/modules/charges-matcher/resolvers/index.ts +12 -0
- package/src/modules/charges-matcher/typeDefs/charges-matcher.graphql.ts +47 -0
- package/src/modules/charges-matcher/types.ts +200 -0
- package/src/modules/documents/resolvers/document-suggestions.resolver.ts +2 -2
- package/src/modules-app.ts +2 -0
- package/src/shared/types/index.ts +1 -1
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
calculateOverallConfidence,
|
|
4
|
+
type ConfidenceComponents,
|
|
5
|
+
} from '../helpers/overall-confidence.helper.js';
|
|
6
|
+
|
|
7
|
+
describe('Overall Confidence Calculator', () => {
|
|
8
|
+
describe('Perfect Matches', () => {
|
|
9
|
+
it('should return 1.0 when all components are 1.0', () => {
|
|
10
|
+
const components: ConfidenceComponents = {
|
|
11
|
+
amount: 1.0,
|
|
12
|
+
currency: 1.0,
|
|
13
|
+
business: 1.0,
|
|
14
|
+
date: 1.0,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
expect(calculateOverallConfidence(components)).toBe(1.0);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should return 1.0 when all components are exactly 1.0', () => {
|
|
21
|
+
const result = calculateOverallConfidence({
|
|
22
|
+
amount: 1.0,
|
|
23
|
+
currency: 1.0,
|
|
24
|
+
business: 1.0,
|
|
25
|
+
date: 1.0,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
expect(result).toBe(1.0);
|
|
29
|
+
expect(typeof result).toBe('number');
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('Zero Matches', () => {
|
|
34
|
+
it('should return 0.0 when all components are 0.0', () => {
|
|
35
|
+
const components: ConfidenceComponents = {
|
|
36
|
+
amount: 0.0,
|
|
37
|
+
currency: 0.0,
|
|
38
|
+
business: 0.0,
|
|
39
|
+
date: 0.0,
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
expect(calculateOverallConfidence(components)).toBe(0.0);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
describe('Weighted Formula Verification', () => {
|
|
47
|
+
it('should correctly apply amount weight (0.4)', () => {
|
|
48
|
+
// Only amount is 1.0, others are 0.0
|
|
49
|
+
const result = calculateOverallConfidence({
|
|
50
|
+
amount: 1.0,
|
|
51
|
+
currency: 0.0,
|
|
52
|
+
business: 0.0,
|
|
53
|
+
date: 0.0,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
expect(result).toBe(0.4);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should correctly apply currency weight (0.2)', () => {
|
|
60
|
+
// Only currency is 1.0, others are 0.0
|
|
61
|
+
const result = calculateOverallConfidence({
|
|
62
|
+
amount: 0.0,
|
|
63
|
+
currency: 1.0,
|
|
64
|
+
business: 0.0,
|
|
65
|
+
date: 0.0,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
expect(result).toBe(0.2);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('should correctly apply business weight (0.3)', () => {
|
|
72
|
+
// Only business is 1.0, others are 0.0
|
|
73
|
+
const result = calculateOverallConfidence({
|
|
74
|
+
amount: 0.0,
|
|
75
|
+
currency: 0.0,
|
|
76
|
+
business: 1.0,
|
|
77
|
+
date: 0.0,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
expect(result).toBe(0.3);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('should correctly apply date weight (0.1)', () => {
|
|
84
|
+
// Only date is 1.0, others are 0.0
|
|
85
|
+
const result = calculateOverallConfidence({
|
|
86
|
+
amount: 0.0,
|
|
87
|
+
currency: 0.0,
|
|
88
|
+
business: 0.0,
|
|
89
|
+
date: 1.0,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
expect(result).toBe(0.1);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('should verify weights sum to 1.0', () => {
|
|
96
|
+
// When all components are 1.0, result should be 1.0
|
|
97
|
+
// This verifies: 0.4 + 0.2 + 0.3 + 0.1 = 1.0
|
|
98
|
+
const result = calculateOverallConfidence({
|
|
99
|
+
amount: 1.0,
|
|
100
|
+
currency: 1.0,
|
|
101
|
+
business: 1.0,
|
|
102
|
+
date: 1.0,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
expect(result).toBe(1.0);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
describe('Mixed Confidence Scenarios', () => {
|
|
110
|
+
it('should handle typical good match (all high)', () => {
|
|
111
|
+
const result = calculateOverallConfidence({
|
|
112
|
+
amount: 0.9,
|
|
113
|
+
currency: 1.0,
|
|
114
|
+
business: 1.0,
|
|
115
|
+
date: 1.0,
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// (0.9 × 0.4) + (1.0 × 0.2) + (1.0 × 0.3) + (1.0 × 0.1) = 0.96
|
|
119
|
+
expect(result).toBe(0.96);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('should handle partial match (mixed scores)', () => {
|
|
123
|
+
const result = calculateOverallConfidence({
|
|
124
|
+
amount: 0.9,
|
|
125
|
+
currency: 1.0,
|
|
126
|
+
business: 0.5,
|
|
127
|
+
date: 0.8,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// (0.9 × 0.4) + (1.0 × 0.2) + (0.5 × 0.3) + (0.8 × 0.1)
|
|
131
|
+
// = 0.36 + 0.2 + 0.15 + 0.08 = 0.79
|
|
132
|
+
expect(result).toBe(0.79);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('should handle uncertain business with good other factors', () => {
|
|
136
|
+
const result = calculateOverallConfidence({
|
|
137
|
+
amount: 1.0,
|
|
138
|
+
currency: 1.0,
|
|
139
|
+
business: 0.5,
|
|
140
|
+
date: 1.0,
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// (1.0 × 0.4) + (1.0 × 0.2) + (0.5 × 0.3) + (1.0 × 0.1)
|
|
144
|
+
// = 0.4 + 0.2 + 0.15 + 0.1 = 0.85
|
|
145
|
+
expect(result).toBe(0.85);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('should handle missing currency with good match otherwise', () => {
|
|
149
|
+
const result = calculateOverallConfidence({
|
|
150
|
+
amount: 1.0,
|
|
151
|
+
currency: 0.2, // Missing currency penalty
|
|
152
|
+
business: 1.0,
|
|
153
|
+
date: 1.0,
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// (1.0 × 0.4) + (0.2 × 0.2) + (1.0 × 0.3) + (1.0 × 0.1)
|
|
157
|
+
// = 0.4 + 0.04 + 0.3 + 0.1 = 0.84
|
|
158
|
+
expect(result).toBe(0.84);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('should handle business mismatch with good amount/currency', () => {
|
|
162
|
+
const result = calculateOverallConfidence({
|
|
163
|
+
amount: 1.0,
|
|
164
|
+
currency: 1.0,
|
|
165
|
+
business: 0.2, // Mismatch
|
|
166
|
+
date: 1.0,
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// (1.0 × 0.4) + (1.0 × 0.2) + (0.2 × 0.3) + (1.0 × 0.1)
|
|
170
|
+
// = 0.4 + 0.2 + 0.06 + 0.1 = 0.76
|
|
171
|
+
expect(result).toBe(0.76);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('should handle old date with perfect other factors', () => {
|
|
175
|
+
const result = calculateOverallConfidence({
|
|
176
|
+
amount: 1.0,
|
|
177
|
+
currency: 1.0,
|
|
178
|
+
business: 1.0,
|
|
179
|
+
date: 0.0, // 30+ days apart
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// (1.0 × 0.4) + (1.0 × 0.2) + (1.0 × 0.3) + (0.0 × 0.1)
|
|
183
|
+
// = 0.4 + 0.2 + 0.3 + 0.0 = 0.9
|
|
184
|
+
expect(result).toBe(0.9);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
describe('Auto-Match Threshold Scenarios', () => {
|
|
189
|
+
it('should identify clear auto-match candidate (≥0.95)', () => {
|
|
190
|
+
const result = calculateOverallConfidence({
|
|
191
|
+
amount: 1.0,
|
|
192
|
+
currency: 1.0,
|
|
193
|
+
business: 1.0,
|
|
194
|
+
date: 0.5,
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// (1.0 × 0.4) + (1.0 × 0.2) + (1.0 × 0.3) + (0.5 × 0.1)
|
|
198
|
+
// = 0.4 + 0.2 + 0.3 + 0.05 = 0.95
|
|
199
|
+
expect(result).toBe(0.95);
|
|
200
|
+
expect(result).toBeGreaterThanOrEqual(0.95);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('should identify borderline case (just below threshold)', () => {
|
|
204
|
+
const result = calculateOverallConfidence({
|
|
205
|
+
amount: 0.9,
|
|
206
|
+
currency: 1.0,
|
|
207
|
+
business: 1.0,
|
|
208
|
+
date: 0.9,
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// (0.9 × 0.4) + (1.0 × 0.2) + (1.0 × 0.3) + (0.9 × 0.1)
|
|
212
|
+
// = 0.36 + 0.2 + 0.3 + 0.09 = 0.95
|
|
213
|
+
expect(result).toBe(0.95);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('should identify case just above threshold', () => {
|
|
217
|
+
const result = calculateOverallConfidence({
|
|
218
|
+
amount: 1.0,
|
|
219
|
+
currency: 1.0,
|
|
220
|
+
business: 1.0,
|
|
221
|
+
date: 0.6,
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
// (1.0 × 0.4) + (1.0 × 0.2) + (1.0 × 0.3) + (0.6 × 0.1)
|
|
225
|
+
// = 0.4 + 0.2 + 0.3 + 0.06 = 0.96
|
|
226
|
+
expect(result).toBe(0.96);
|
|
227
|
+
expect(result).toBeGreaterThan(0.95);
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
describe('Decimal Precision', () => {
|
|
232
|
+
it('should round to 2 decimal places', () => {
|
|
233
|
+
const result = calculateOverallConfidence({
|
|
234
|
+
amount: 0.333,
|
|
235
|
+
currency: 0.667,
|
|
236
|
+
business: 0.555,
|
|
237
|
+
date: 0.444,
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// (0.333 × 0.4) + (0.667 × 0.2) + (0.555 × 0.3) + (0.444 × 0.1)
|
|
241
|
+
// = 0.1332 + 0.1334 + 0.1665 + 0.0444 = 0.4775
|
|
242
|
+
expect(result).toBe(0.48);
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it('should handle rounding edge case (0.445 rounds to 0.45)', () => {
|
|
246
|
+
const result = calculateOverallConfidence({
|
|
247
|
+
amount: 0.5,
|
|
248
|
+
currency: 0.5,
|
|
249
|
+
business: 0.5,
|
|
250
|
+
date: 0.0,
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
// (0.5 × 0.4) + (0.5 × 0.2) + (0.5 × 0.3) + (0.0 × 0.1)
|
|
254
|
+
// = 0.2 + 0.1 + 0.15 + 0.0 = 0.45
|
|
255
|
+
expect(result).toBe(0.45);
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
it('should handle precise calculation without floating point errors', () => {
|
|
259
|
+
const result = calculateOverallConfidence({
|
|
260
|
+
amount: 0.1,
|
|
261
|
+
currency: 0.2,
|
|
262
|
+
business: 0.3,
|
|
263
|
+
date: 0.4,
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
// (0.1 × 0.4) + (0.2 × 0.2) + (0.3 × 0.3) + (0.4 × 0.1)
|
|
267
|
+
// = 0.04 + 0.04 + 0.09 + 0.04 = 0.21
|
|
268
|
+
expect(result).toBe(0.21);
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
describe('Edge Cases', () => {
|
|
273
|
+
it('should handle all components at 0.5', () => {
|
|
274
|
+
const result = calculateOverallConfidence({
|
|
275
|
+
amount: 0.5,
|
|
276
|
+
currency: 0.5,
|
|
277
|
+
business: 0.5,
|
|
278
|
+
date: 0.5,
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
// (0.5 × 0.4) + (0.5 × 0.2) + (0.5 × 0.3) + (0.5 × 0.1)
|
|
282
|
+
// = 0.2 + 0.1 + 0.15 + 0.05 = 0.5
|
|
283
|
+
expect(result).toBe(0.5);
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it('should handle very small non-zero values', () => {
|
|
287
|
+
const result = calculateOverallConfidence({
|
|
288
|
+
amount: 0.01,
|
|
289
|
+
currency: 0.01,
|
|
290
|
+
business: 0.01,
|
|
291
|
+
date: 0.01,
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
// (0.01 × 0.4) + (0.01 × 0.2) + (0.01 × 0.3) + (0.01 × 0.1)
|
|
295
|
+
// = 0.004 + 0.002 + 0.003 + 0.001 = 0.01
|
|
296
|
+
expect(result).toBe(0.01);
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
it('should handle values very close to 1.0', () => {
|
|
300
|
+
const result = calculateOverallConfidence({
|
|
301
|
+
amount: 0.99,
|
|
302
|
+
currency: 0.99,
|
|
303
|
+
business: 0.99,
|
|
304
|
+
date: 0.99,
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
// (0.99 × 0.4) + (0.99 × 0.2) + (0.99 × 0.3) + (0.99 × 0.1)
|
|
308
|
+
// = 0.396 + 0.198 + 0.297 + 0.099 = 0.99
|
|
309
|
+
expect(result).toBe(0.99);
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
describe('Validation - Missing Components', () => {
|
|
314
|
+
it('should throw error when amount is null', () => {
|
|
315
|
+
expect(() =>
|
|
316
|
+
calculateOverallConfidence({
|
|
317
|
+
amount: null as any,
|
|
318
|
+
currency: 1.0,
|
|
319
|
+
business: 1.0,
|
|
320
|
+
date: 1.0,
|
|
321
|
+
}),
|
|
322
|
+
).toThrow('Amount confidence is required');
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
it('should throw error when currency is null', () => {
|
|
326
|
+
expect(() =>
|
|
327
|
+
calculateOverallConfidence({
|
|
328
|
+
amount: 1.0,
|
|
329
|
+
currency: null as any,
|
|
330
|
+
business: 1.0,
|
|
331
|
+
date: 1.0,
|
|
332
|
+
}),
|
|
333
|
+
).toThrow('Currency confidence is required');
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
it('should throw error when business is null', () => {
|
|
337
|
+
expect(() =>
|
|
338
|
+
calculateOverallConfidence({
|
|
339
|
+
amount: 1.0,
|
|
340
|
+
currency: 1.0,
|
|
341
|
+
business: null as any,
|
|
342
|
+
date: 1.0,
|
|
343
|
+
}),
|
|
344
|
+
).toThrow('Business confidence is required');
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
it('should throw error when date is null', () => {
|
|
348
|
+
expect(() =>
|
|
349
|
+
calculateOverallConfidence({
|
|
350
|
+
amount: 1.0,
|
|
351
|
+
currency: 1.0,
|
|
352
|
+
business: 1.0,
|
|
353
|
+
date: null as any,
|
|
354
|
+
}),
|
|
355
|
+
).toThrow('Date confidence is required');
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
it('should throw error when amount is undefined', () => {
|
|
359
|
+
expect(() =>
|
|
360
|
+
calculateOverallConfidence({
|
|
361
|
+
amount: undefined as any,
|
|
362
|
+
currency: 1.0,
|
|
363
|
+
business: 1.0,
|
|
364
|
+
date: 1.0,
|
|
365
|
+
}),
|
|
366
|
+
).toThrow('Amount confidence is required');
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
it('should throw error when multiple components are null', () => {
|
|
370
|
+
expect(() =>
|
|
371
|
+
calculateOverallConfidence({
|
|
372
|
+
amount: null as any,
|
|
373
|
+
currency: null as any,
|
|
374
|
+
business: 1.0,
|
|
375
|
+
date: 1.0,
|
|
376
|
+
}),
|
|
377
|
+
).toThrow('Amount confidence is required');
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
describe('Validation - Out of Range', () => {
|
|
382
|
+
it('should throw error when amount is negative', () => {
|
|
383
|
+
expect(() =>
|
|
384
|
+
calculateOverallConfidence({
|
|
385
|
+
amount: -0.1,
|
|
386
|
+
currency: 1.0,
|
|
387
|
+
business: 1.0,
|
|
388
|
+
date: 1.0,
|
|
389
|
+
}),
|
|
390
|
+
).toThrow('Amount confidence must be between 0.0 and 1.0');
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
it('should throw error when amount exceeds 1.0', () => {
|
|
394
|
+
expect(() =>
|
|
395
|
+
calculateOverallConfidence({
|
|
396
|
+
amount: 1.1,
|
|
397
|
+
currency: 1.0,
|
|
398
|
+
business: 1.0,
|
|
399
|
+
date: 1.0,
|
|
400
|
+
}),
|
|
401
|
+
).toThrow('Amount confidence must be between 0.0 and 1.0');
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
it('should throw error when currency is negative', () => {
|
|
405
|
+
expect(() =>
|
|
406
|
+
calculateOverallConfidence({
|
|
407
|
+
amount: 1.0,
|
|
408
|
+
currency: -0.5,
|
|
409
|
+
business: 1.0,
|
|
410
|
+
date: 1.0,
|
|
411
|
+
}),
|
|
412
|
+
).toThrow('Currency confidence must be between 0.0 and 1.0');
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
it('should throw error when business exceeds 1.0', () => {
|
|
416
|
+
expect(() =>
|
|
417
|
+
calculateOverallConfidence({
|
|
418
|
+
amount: 1.0,
|
|
419
|
+
currency: 1.0,
|
|
420
|
+
business: 2.0,
|
|
421
|
+
date: 1.0,
|
|
422
|
+
}),
|
|
423
|
+
).toThrow('Business confidence must be between 0.0 and 1.0');
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
it('should throw error when date is negative', () => {
|
|
427
|
+
expect(() =>
|
|
428
|
+
calculateOverallConfidence({
|
|
429
|
+
amount: 1.0,
|
|
430
|
+
currency: 1.0,
|
|
431
|
+
business: 1.0,
|
|
432
|
+
date: -1.0,
|
|
433
|
+
}),
|
|
434
|
+
).toThrow('Date confidence must be between 0.0 and 1.0');
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
it('should throw error with correct component name', () => {
|
|
438
|
+
expect(() =>
|
|
439
|
+
calculateOverallConfidence({
|
|
440
|
+
amount: 1.0,
|
|
441
|
+
currency: 1.0,
|
|
442
|
+
business: 5.0,
|
|
443
|
+
date: 1.0,
|
|
444
|
+
}),
|
|
445
|
+
).toThrow(/Business confidence/);
|
|
446
|
+
});
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
describe('Real-World Scenarios', () => {
|
|
450
|
+
it('should handle typical invoice match', () => {
|
|
451
|
+
// Exact amount, currency, business match, 2 days apart
|
|
452
|
+
const result = calculateOverallConfidence({
|
|
453
|
+
amount: 1.0,
|
|
454
|
+
currency: 1.0,
|
|
455
|
+
business: 1.0,
|
|
456
|
+
date: 0.93, // ~2 days difference
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
// (1.0 × 0.4) + (1.0 × 0.2) + (1.0 × 0.3) + (0.93 × 0.1) = 0.993
|
|
460
|
+
expect(result).toBe(0.99);
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
it('should handle receipt with missing business', () => {
|
|
464
|
+
// Good amount/currency, no business ID, same day
|
|
465
|
+
const result = calculateOverallConfidence({
|
|
466
|
+
amount: 1.0,
|
|
467
|
+
currency: 1.0,
|
|
468
|
+
business: 0.5, // Unknown business
|
|
469
|
+
date: 1.0,
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
// (1.0 × 0.4) + (1.0 × 0.2) + (0.5 × 0.3) + (1.0 × 0.1) = 0.85
|
|
473
|
+
expect(result).toBe(0.85);
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
it('should handle cross-currency near match', () => {
|
|
477
|
+
// Good amount, no currency match, good business/date
|
|
478
|
+
const result = calculateOverallConfidence({
|
|
479
|
+
amount: 0.9,
|
|
480
|
+
currency: 0.0, // Different currency
|
|
481
|
+
business: 1.0,
|
|
482
|
+
date: 1.0,
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
// (0.9 × 0.4) + (0.0 × 0.2) + (1.0 × 0.3) + (1.0 × 0.1) = 0.76
|
|
486
|
+
expect(result).toBe(0.76);
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
it('should handle delayed receipt (15 days)', () => {
|
|
490
|
+
// Perfect match except date
|
|
491
|
+
const result = calculateOverallConfidence({
|
|
492
|
+
amount: 1.0,
|
|
493
|
+
currency: 1.0,
|
|
494
|
+
business: 1.0,
|
|
495
|
+
date: 0.5, // 15 days difference
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
// (1.0 × 0.4) + (1.0 × 0.2) + (1.0 × 0.3) + (0.5 × 0.1) = 0.95
|
|
499
|
+
expect(result).toBe(0.95);
|
|
500
|
+
});
|
|
501
|
+
});
|
|
502
|
+
});
|