@accounter/server 0.0.8-alpha-20251102200443-d7162b8ce1dfc629b8b454df17dcec9ed005a052 → 0.0.8-alpha-20251103003648-f6467c8cb9c739ec4439c260bccc7325f6a761ae
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 +7 -7
- 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/green-invoice/helpers/contract-to-draft.helper.js +1 -1
- package/dist/server/src/modules/green-invoice/helpers/contract-to-draft.helper.js.map +1 -1
- package/dist/server/src/modules/green-invoice/helpers/green-invoice.helper.d.ts +1 -1
- package/dist/server/src/modules/green-invoice/helpers/green-invoice.helper.js +1 -1
- package/dist/server/src/modules/green-invoice/helpers/green-invoice.helper.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/green-invoice/helpers/contract-to-draft.helper.ts +1 -1
- package/src/modules/green-invoice/helpers/green-invoice.helper.ts +1 -1
- package/src/modules-app.ts +2 -0
- package/src/shared/types/index.ts +1 -1
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Document, Transaction } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Represents a charge with its associated transactions and documents
|
|
4
|
+
*/
|
|
5
|
+
interface Charge {
|
|
6
|
+
id: string;
|
|
7
|
+
owner_id: string | null;
|
|
8
|
+
transactions?: Transaction[];
|
|
9
|
+
documents?: Document[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Validate a charge is properly formed for matching
|
|
13
|
+
* @throws Error with descriptive message if invalid
|
|
14
|
+
*/
|
|
15
|
+
export declare function validateChargeForMatching(charge: Charge): void;
|
|
16
|
+
/**
|
|
17
|
+
* Check if charge is matched (has both transactions and accounting documents)
|
|
18
|
+
*/
|
|
19
|
+
export declare function isChargeMatched(charge: Charge): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Check if charge has only transactions (no accounting documents)
|
|
22
|
+
*/
|
|
23
|
+
export declare function hasOnlyTransactions(charge: Charge): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Check if charge has only accounting documents (no transactions)
|
|
26
|
+
*/
|
|
27
|
+
export declare function hasOnlyDocuments(charge: Charge): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Validate that a charge is unmatched (for matching operations)
|
|
30
|
+
* @throws Error if charge is already matched
|
|
31
|
+
*/
|
|
32
|
+
export declare function validateChargeIsUnmatched(charge: Charge): void;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Accounting document types that count toward matched/unmatched status
|
|
3
|
+
*/
|
|
4
|
+
const ACCOUNTING_DOC_TYPES = [
|
|
5
|
+
'INVOICE',
|
|
6
|
+
'CREDIT_INVOICE',
|
|
7
|
+
'RECEIPT',
|
|
8
|
+
'INVOICE_RECEIPT',
|
|
9
|
+
];
|
|
10
|
+
/**
|
|
11
|
+
* Validate a charge is properly formed for matching
|
|
12
|
+
* @throws Error with descriptive message if invalid
|
|
13
|
+
*/
|
|
14
|
+
export function validateChargeForMatching(charge) {
|
|
15
|
+
if (!charge) {
|
|
16
|
+
throw new Error('Charge is required');
|
|
17
|
+
}
|
|
18
|
+
if (!charge.id) {
|
|
19
|
+
throw new Error('Charge must have an ID');
|
|
20
|
+
}
|
|
21
|
+
if (!charge.owner_id) {
|
|
22
|
+
throw new Error(`Charge ${charge.id} must have an owner_id`);
|
|
23
|
+
}
|
|
24
|
+
// Check if charge has data
|
|
25
|
+
const hasTransactions = charge.transactions && charge.transactions.length > 0;
|
|
26
|
+
const hasDocuments = charge.documents && charge.documents.length > 0;
|
|
27
|
+
if (!hasTransactions && !hasDocuments) {
|
|
28
|
+
throw new Error(`Charge ${charge.id} has no transactions or documents - cannot be matched`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Check if charge is matched (has both transactions and accounting documents)
|
|
33
|
+
*/
|
|
34
|
+
export function isChargeMatched(charge) {
|
|
35
|
+
const hasTransactions = charge.transactions && charge.transactions.length > 0;
|
|
36
|
+
const hasAccountingDocs = charge.documents?.some(doc => ACCOUNTING_DOC_TYPES.includes(doc.type));
|
|
37
|
+
return !!hasTransactions && !!hasAccountingDocs;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Check if charge has only transactions (no accounting documents)
|
|
41
|
+
*/
|
|
42
|
+
export function hasOnlyTransactions(charge) {
|
|
43
|
+
const hasTransactions = charge.transactions && charge.transactions.length > 0;
|
|
44
|
+
const hasAccountingDocs = charge.documents?.some(doc => ACCOUNTING_DOC_TYPES.includes(doc.type));
|
|
45
|
+
return !!hasTransactions && !hasAccountingDocs;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Check if charge has only accounting documents (no transactions)
|
|
49
|
+
*/
|
|
50
|
+
export function hasOnlyDocuments(charge) {
|
|
51
|
+
const hasTransactions = charge.transactions && charge.transactions.length > 0;
|
|
52
|
+
const hasAccountingDocs = charge.documents?.some(doc => ACCOUNTING_DOC_TYPES.includes(doc.type));
|
|
53
|
+
return !hasTransactions && !!hasAccountingDocs;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Validate that a charge is unmatched (for matching operations)
|
|
57
|
+
* @throws Error if charge is already matched
|
|
58
|
+
*/
|
|
59
|
+
export function validateChargeIsUnmatched(charge) {
|
|
60
|
+
validateChargeForMatching(charge);
|
|
61
|
+
if (isChargeMatched(charge)) {
|
|
62
|
+
throw new Error(`Charge ${charge.id} is already matched (has both transactions and accounting documents)`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=charge-validator.helper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"charge-validator.helper.js","sourceRoot":"","sources":["../../../../../../src/modules/charges-matcher/helpers/charge-validator.helper.ts"],"names":[],"mappings":"AAYA;;GAEG;AACH,MAAM,oBAAoB,GAAmB;IAC3C,SAAS;IACT,gBAAgB;IAChB,SAAS;IACT,iBAAiB;CAClB,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CAAC,MAAc;IACtD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACxC,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC5C,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,UAAU,MAAM,CAAC,EAAE,wBAAwB,CAAC,CAAC;IAC/D,CAAC;IAED,2BAA2B;IAC3B,MAAM,eAAe,GAAG,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;IAC9E,MAAM,YAAY,GAAG,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;IAErE,IAAI,CAAC,eAAe,IAAI,CAAC,YAAY,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,UAAU,MAAM,CAAC,EAAE,uDAAuD,CAAC,CAAC;IAC9F,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,MAAM,eAAe,GAAG,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;IAE9E,MAAM,iBAAiB,GAAG,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CACrD,oBAAoB,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAoB,CAAC,CACxD,CAAC;IAEF,OAAO,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC,iBAAiB,CAAC;AAClD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,MAAM,eAAe,GAAG,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;IAE9E,MAAM,iBAAiB,GAAG,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CACrD,oBAAoB,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAoB,CAAC,CACxD,CAAC;IAEF,OAAO,CAAC,CAAC,eAAe,IAAI,CAAC,iBAAiB,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,MAAM,eAAe,GAAG,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;IAE9E,MAAM,iBAAiB,GAAG,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CACrD,oBAAoB,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAoB,CAAC,CACxD,CAAC;IAEF,OAAO,CAAC,eAAe,IAAI,CAAC,CAAC,iBAAiB,CAAC;AACjD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CAAC,MAAc;IACtD,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAElC,IAAI,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CACb,UAAU,MAAM,CAAC,EAAE,sEAAsE,CAC1F,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calculate confidence score based on currency match
|
|
3
|
+
* @param transactionCurrency - Currency code from transaction
|
|
4
|
+
* @param documentCurrency - Currency code from document
|
|
5
|
+
* @returns 1.0 if same, 0.2 if one/both missing, 0.0 if different
|
|
6
|
+
*/
|
|
7
|
+
export declare function calculateCurrencyConfidence(transactionCurrency: string | null | undefined, documentCurrency: string | null | undefined): number;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calculate confidence score based on currency match
|
|
3
|
+
* @param transactionCurrency - Currency code from transaction
|
|
4
|
+
* @param documentCurrency - Currency code from document
|
|
5
|
+
* @returns 1.0 if same, 0.2 if one/both missing, 0.0 if different
|
|
6
|
+
*/
|
|
7
|
+
export function calculateCurrencyConfidence(transactionCurrency, documentCurrency) {
|
|
8
|
+
// Handle null/undefined/empty cases
|
|
9
|
+
if (!transactionCurrency || !documentCurrency) {
|
|
10
|
+
return 0.2;
|
|
11
|
+
}
|
|
12
|
+
// Case-insensitive comparison
|
|
13
|
+
if (transactionCurrency.toUpperCase() === documentCurrency.toUpperCase()) {
|
|
14
|
+
return 1.0;
|
|
15
|
+
}
|
|
16
|
+
return 0.0;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=currency-confidence.helper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"currency-confidence.helper.js","sourceRoot":"","sources":["../../../../../../src/modules/charges-matcher/helpers/currency-confidence.helper.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,2BAA2B,CACzC,mBAA8C,EAC9C,gBAA2C;IAE3C,oCAAoC;IACpC,IAAI,CAAC,mBAAmB,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC9C,OAAO,GAAG,CAAC;IACb,CAAC;IAED,8BAA8B;IAC9B,IAAI,mBAAmB,CAAC,WAAW,EAAE,KAAK,gBAAgB,CAAC,WAAW,EAAE,EAAE,CAAC;QACzE,OAAO,GAAG,CAAC;IACb,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calculate confidence score based on date proximity
|
|
3
|
+
* @param date1 - First date
|
|
4
|
+
* @param date2 - Second date
|
|
5
|
+
* @returns Confidence score from 0.0 (30+ days) to 1.0 (same day)
|
|
6
|
+
*/
|
|
7
|
+
export declare function calculateDateConfidence(date1: Date, date2: Date): number;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calculate the absolute difference in days between two dates
|
|
3
|
+
* Ignores time components by comparing only the date parts
|
|
4
|
+
* @param date1 - First date
|
|
5
|
+
* @param date2 - Second date
|
|
6
|
+
* @returns Absolute difference in days
|
|
7
|
+
*/
|
|
8
|
+
function calculateDaysDifference(date1, date2) {
|
|
9
|
+
// Create new dates with time set to midnight to ignore time components
|
|
10
|
+
const d1 = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate());
|
|
11
|
+
const d2 = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());
|
|
12
|
+
// Calculate difference in milliseconds
|
|
13
|
+
const diffMs = Math.abs(d1.getTime() - d2.getTime());
|
|
14
|
+
// Convert to days
|
|
15
|
+
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|
16
|
+
return diffDays;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Calculate confidence score based on date proximity
|
|
20
|
+
* @param date1 - First date
|
|
21
|
+
* @param date2 - Second date
|
|
22
|
+
* @returns Confidence score from 0.0 (30+ days) to 1.0 (same day)
|
|
23
|
+
*/
|
|
24
|
+
export function calculateDateConfidence(date1, date2) {
|
|
25
|
+
const daysDiff = calculateDaysDifference(date1, date2);
|
|
26
|
+
// 30 or more days: return 0.0
|
|
27
|
+
if (daysDiff >= 30) {
|
|
28
|
+
return 0.0;
|
|
29
|
+
}
|
|
30
|
+
// Linear degradation: 1.0 - (days_diff / 30)
|
|
31
|
+
const confidence = 1.0 - daysDiff / 30;
|
|
32
|
+
// Round to 2 decimal places
|
|
33
|
+
return Math.round(confidence * 100) / 100;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=date-confidence.helper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date-confidence.helper.js","sourceRoot":"","sources":["../../../../../../src/modules/charges-matcher/helpers/date-confidence.helper.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,SAAS,uBAAuB,CAAC,KAAW,EAAE,KAAW;IACvD,uEAAuE;IACvE,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,KAAK,CAAC,QAAQ,EAAE,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IAC5E,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,KAAK,CAAC,QAAQ,EAAE,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IAE5E,uCAAuC;IACvC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;IAErD,kBAAkB;IAClB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;IAE5D,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAW,EAAE,KAAW;IAC9D,MAAM,QAAQ,GAAG,uBAAuB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAEvD,8BAA8B;IAC9B,IAAI,QAAQ,IAAI,EAAE,EAAE,CAAC;QACnB,OAAO,GAAG,CAAC;IACb,CAAC;IAED,6CAA6C;IAC7C,MAAM,UAAU,GAAG,GAAG,GAAG,QAAQ,GAAG,EAAE,CAAC;IAEvC,4BAA4B;IAC5B,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Document Amount Normalization
|
|
3
|
+
*
|
|
4
|
+
* Normalizes document amounts for comparison with transaction amounts.
|
|
5
|
+
* Per specification (section 4.3.1):
|
|
6
|
+
* 1. Start with absolute value of total_amount
|
|
7
|
+
* 2. If business is creditor: negate
|
|
8
|
+
* 3. If document type is CREDIT_INVOICE: negate
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Document types from database schema
|
|
12
|
+
*/
|
|
13
|
+
export type DocumentType = 'CREDIT_INVOICE' | 'INVOICE' | 'INVOICE_RECEIPT' | 'OTHER' | 'PROFORMA' | 'RECEIPT' | 'UNPROCESSED';
|
|
14
|
+
/**
|
|
15
|
+
* Normalize document amount for comparison with transaction amount
|
|
16
|
+
*
|
|
17
|
+
* Per specification:
|
|
18
|
+
* - Start with absolute value of total_amount
|
|
19
|
+
* - If business is creditor (debtor is user): negate
|
|
20
|
+
* - If document type is CREDIT_INVOICE: negate
|
|
21
|
+
*
|
|
22
|
+
* Examples:
|
|
23
|
+
* - INVOICE, business debtor (creditor is user): |100| = 100
|
|
24
|
+
* - INVOICE, business creditor (debtor is user): |100| * -1 = -100
|
|
25
|
+
* - CREDIT_INVOICE, business debtor: |100| * -1 = -100
|
|
26
|
+
* - CREDIT_INVOICE, business creditor: |100| * -1 * -1 = 100 (double negation)
|
|
27
|
+
*
|
|
28
|
+
* @param totalAmount - Raw total_amount from document (can be positive or negative)
|
|
29
|
+
* @param isBusinessCreditor - Whether the business is the creditor (from business extraction)
|
|
30
|
+
* @param documentType - Type of document
|
|
31
|
+
* @returns Normalized amount (signed) for comparison with transaction amount
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* // Regular invoice where user is creditor (business owes user)
|
|
35
|
+
* normalizeDocumentAmount(100, false, 'INVOICE') // Returns 100
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* // Regular invoice where user is debtor (user owes business)
|
|
39
|
+
* normalizeDocumentAmount(100, true, 'INVOICE') // Returns -100
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* // Credit invoice where user is creditor (user owes business a refund)
|
|
43
|
+
* normalizeDocumentAmount(100, false, 'CREDIT_INVOICE') // Returns -100
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* // Credit invoice where user is debtor (business owes user a refund)
|
|
47
|
+
* normalizeDocumentAmount(100, true, 'CREDIT_INVOICE') // Returns 100 (double negation)
|
|
48
|
+
*/
|
|
49
|
+
export declare function normalizeDocumentAmount(totalAmount: number, isBusinessCreditor: boolean, documentType: DocumentType): number;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Document Amount Normalization
|
|
3
|
+
*
|
|
4
|
+
* Normalizes document amounts for comparison with transaction amounts.
|
|
5
|
+
* Per specification (section 4.3.1):
|
|
6
|
+
* 1. Start with absolute value of total_amount
|
|
7
|
+
* 2. If business is creditor: negate
|
|
8
|
+
* 3. If document type is CREDIT_INVOICE: negate
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Normalize document amount for comparison with transaction amount
|
|
12
|
+
*
|
|
13
|
+
* Per specification:
|
|
14
|
+
* - Start with absolute value of total_amount
|
|
15
|
+
* - If business is creditor (debtor is user): negate
|
|
16
|
+
* - If document type is CREDIT_INVOICE: negate
|
|
17
|
+
*
|
|
18
|
+
* Examples:
|
|
19
|
+
* - INVOICE, business debtor (creditor is user): |100| = 100
|
|
20
|
+
* - INVOICE, business creditor (debtor is user): |100| * -1 = -100
|
|
21
|
+
* - CREDIT_INVOICE, business debtor: |100| * -1 = -100
|
|
22
|
+
* - CREDIT_INVOICE, business creditor: |100| * -1 * -1 = 100 (double negation)
|
|
23
|
+
*
|
|
24
|
+
* @param totalAmount - Raw total_amount from document (can be positive or negative)
|
|
25
|
+
* @param isBusinessCreditor - Whether the business is the creditor (from business extraction)
|
|
26
|
+
* @param documentType - Type of document
|
|
27
|
+
* @returns Normalized amount (signed) for comparison with transaction amount
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* // Regular invoice where user is creditor (business owes user)
|
|
31
|
+
* normalizeDocumentAmount(100, false, 'INVOICE') // Returns 100
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* // Regular invoice where user is debtor (user owes business)
|
|
35
|
+
* normalizeDocumentAmount(100, true, 'INVOICE') // Returns -100
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* // Credit invoice where user is creditor (user owes business a refund)
|
|
39
|
+
* normalizeDocumentAmount(100, false, 'CREDIT_INVOICE') // Returns -100
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* // Credit invoice where user is debtor (business owes user a refund)
|
|
43
|
+
* normalizeDocumentAmount(100, true, 'CREDIT_INVOICE') // Returns 100 (double negation)
|
|
44
|
+
*/
|
|
45
|
+
export function normalizeDocumentAmount(totalAmount, isBusinessCreditor, documentType) {
|
|
46
|
+
// Step 1: Start with absolute value
|
|
47
|
+
let normalizedAmount = Math.abs(totalAmount);
|
|
48
|
+
// Step 2: If business is creditor (debtor is user), negate
|
|
49
|
+
if (isBusinessCreditor) {
|
|
50
|
+
normalizedAmount = -normalizedAmount;
|
|
51
|
+
}
|
|
52
|
+
// Step 3: If document type is CREDIT_INVOICE, negate
|
|
53
|
+
if (documentType === 'CREDIT_INVOICE') {
|
|
54
|
+
normalizedAmount = -normalizedAmount;
|
|
55
|
+
}
|
|
56
|
+
return normalizedAmount;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=document-amount.helper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document-amount.helper.js","sourceRoot":"","sources":["../../../../../../src/modules/charges-matcher/helpers/document-amount.helper.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAcH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,UAAU,uBAAuB,CACrC,WAAmB,EACnB,kBAA2B,EAC3B,YAA0B;IAE1B,oCAAoC;IACpC,IAAI,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAE7C,2DAA2D;IAC3D,IAAI,kBAAkB,EAAE,CAAC;QACvB,gBAAgB,GAAG,CAAC,gBAAgB,CAAC;IACvC,CAAC;IAED,qDAAqD;IACrD,IAAI,YAAY,KAAK,gBAAgB,EAAE,CAAC;QACtC,gBAAgB,GAAG,CAAC,gBAAgB,CAAC;IACvC,CAAC;IAED,OAAO,gBAAgB,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface DocumentBusinessInfo {
|
|
2
|
+
businessId: string | null;
|
|
3
|
+
isBusinessCreditor: boolean;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Extract business information from a document
|
|
7
|
+
* @param creditorId - Document's creditor_id
|
|
8
|
+
* @param debtorId - Document's debtor_id
|
|
9
|
+
* @param adminBusinessId - Current user's ID
|
|
10
|
+
* @returns Business ID and whether business is the creditor
|
|
11
|
+
* @throws Error if both or neither IDs match adminBusinessId
|
|
12
|
+
*/
|
|
13
|
+
export declare function extractDocumentBusiness(creditorId: string | null, debtorId: string | null, adminBusinessId: string): DocumentBusinessInfo;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract business information from a document
|
|
3
|
+
* @param creditorId - Document's creditor_id
|
|
4
|
+
* @param debtorId - Document's debtor_id
|
|
5
|
+
* @param adminBusinessId - Current user's ID
|
|
6
|
+
* @returns Business ID and whether business is the creditor
|
|
7
|
+
* @throws Error if both or neither IDs match adminBusinessId
|
|
8
|
+
*/
|
|
9
|
+
export function extractDocumentBusiness(creditorId, debtorId, adminBusinessId) {
|
|
10
|
+
// Check if both are null
|
|
11
|
+
if (creditorId === null && debtorId === null) {
|
|
12
|
+
throw new Error('Document has both creditor_id and debtor_id as null - invalid document state');
|
|
13
|
+
}
|
|
14
|
+
const isCreditorUser = creditorId === adminBusinessId;
|
|
15
|
+
const isDebtorUser = debtorId === adminBusinessId;
|
|
16
|
+
// Both sides are user
|
|
17
|
+
if (isCreditorUser && isDebtorUser) {
|
|
18
|
+
throw new Error('Document has both creditor_id and debtor_id equal to user ID - invalid document state');
|
|
19
|
+
}
|
|
20
|
+
// Neither side is user
|
|
21
|
+
if (!isCreditorUser && !isDebtorUser) {
|
|
22
|
+
throw new Error('Document has neither creditor_id nor debtor_id equal to user ID - document does not belong to user');
|
|
23
|
+
}
|
|
24
|
+
// User is debtor, business is creditor (or creditor is null)
|
|
25
|
+
if (isDebtorUser) {
|
|
26
|
+
return {
|
|
27
|
+
businessId: creditorId,
|
|
28
|
+
isBusinessCreditor: true,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
// User is creditor, business is debtor (or debtor is null)
|
|
32
|
+
return {
|
|
33
|
+
businessId: debtorId,
|
|
34
|
+
isBusinessCreditor: false,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=document-business.helper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document-business.helper.js","sourceRoot":"","sources":["../../../../../../src/modules/charges-matcher/helpers/document-business.helper.ts"],"names":[],"mappings":"AAKA;;;;;;;GAOG;AACH,MAAM,UAAU,uBAAuB,CACrC,UAAyB,EACzB,QAAuB,EACvB,eAAuB;IAEvB,yBAAyB;IACzB,IAAI,UAAU,KAAK,IAAI,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,8EAA8E,CAAC,CAAC;IAClG,CAAC;IAED,MAAM,cAAc,GAAG,UAAU,KAAK,eAAe,CAAC;IACtD,MAAM,YAAY,GAAG,QAAQ,KAAK,eAAe,CAAC;IAElD,sBAAsB;IACtB,IAAI,cAAc,IAAI,YAAY,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,uFAAuF,CACxF,CAAC;IACJ,CAAC;IAED,uBAAuB;IACvB,IAAI,CAAC,cAAc,IAAI,CAAC,YAAY,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CACb,oGAAoG,CACrG,CAAC;IACJ,CAAC;IAED,6DAA6D;IAC7D,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO;YACL,UAAU,EAAE,UAAU;YACtB,kBAAkB,EAAE,IAAI;SACzB,CAAC;IACJ,CAAC;IAED,2DAA2D;IAC3D,OAAO;QACL,UAAU,EAAE,QAAQ;QACpB,kBAAkB,EAAE,KAAK;KAC1B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Overall Confidence Calculator
|
|
3
|
+
*
|
|
4
|
+
* Combines individual confidence scores (amount, currency, business, date)
|
|
5
|
+
* into a single weighted overall confidence score.
|
|
6
|
+
*
|
|
7
|
+
* Formula: (amount × 0.4) + (currency × 0.2) + (business × 0.3) + (date × 0.1)
|
|
8
|
+
*/
|
|
9
|
+
export interface ConfidenceComponents {
|
|
10
|
+
amount: number;
|
|
11
|
+
currency: number;
|
|
12
|
+
business: number;
|
|
13
|
+
date: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Calculate overall confidence score from individual components
|
|
17
|
+
*
|
|
18
|
+
* @param components - Individual confidence scores (each 0.0 to 1.0)
|
|
19
|
+
* @returns Weighted overall confidence score (0.0 to 1.0, rounded to 2 decimals)
|
|
20
|
+
*
|
|
21
|
+
* @throws {Error} If any component is null or undefined
|
|
22
|
+
* @throws {Error} If any component is outside the valid range [0.0, 1.0]
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* // Perfect match
|
|
26
|
+
* calculateOverallConfidence({
|
|
27
|
+
* amount: 1.0,
|
|
28
|
+
* currency: 1.0,
|
|
29
|
+
* business: 1.0,
|
|
30
|
+
* date: 1.0
|
|
31
|
+
* }) // Returns 1.0
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* // Mixed confidence
|
|
35
|
+
* calculateOverallConfidence({
|
|
36
|
+
* amount: 0.9,
|
|
37
|
+
* currency: 1.0,
|
|
38
|
+
* business: 0.5,
|
|
39
|
+
* date: 0.8
|
|
40
|
+
* }) // Returns 0.79
|
|
41
|
+
*/
|
|
42
|
+
export declare function calculateOverallConfidence(components: ConfidenceComponents): number;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Overall Confidence Calculator
|
|
3
|
+
*
|
|
4
|
+
* Combines individual confidence scores (amount, currency, business, date)
|
|
5
|
+
* into a single weighted overall confidence score.
|
|
6
|
+
*
|
|
7
|
+
* Formula: (amount × 0.4) + (currency × 0.2) + (business × 0.3) + (date × 0.1)
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Weights for each confidence component
|
|
11
|
+
*/
|
|
12
|
+
const CONFIDENCE_WEIGHTS = {
|
|
13
|
+
amount: 0.4,
|
|
14
|
+
currency: 0.2,
|
|
15
|
+
business: 0.3,
|
|
16
|
+
date: 0.1,
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Calculate overall confidence score from individual components
|
|
20
|
+
*
|
|
21
|
+
* @param components - Individual confidence scores (each 0.0 to 1.0)
|
|
22
|
+
* @returns Weighted overall confidence score (0.0 to 1.0, rounded to 2 decimals)
|
|
23
|
+
*
|
|
24
|
+
* @throws {Error} If any component is null or undefined
|
|
25
|
+
* @throws {Error} If any component is outside the valid range [0.0, 1.0]
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* // Perfect match
|
|
29
|
+
* calculateOverallConfidence({
|
|
30
|
+
* amount: 1.0,
|
|
31
|
+
* currency: 1.0,
|
|
32
|
+
* business: 1.0,
|
|
33
|
+
* date: 1.0
|
|
34
|
+
* }) // Returns 1.0
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* // Mixed confidence
|
|
38
|
+
* calculateOverallConfidence({
|
|
39
|
+
* amount: 0.9,
|
|
40
|
+
* currency: 1.0,
|
|
41
|
+
* business: 0.5,
|
|
42
|
+
* date: 0.8
|
|
43
|
+
* }) // Returns 0.79
|
|
44
|
+
*/
|
|
45
|
+
export function calculateOverallConfidence(components) {
|
|
46
|
+
// Validate all components are present
|
|
47
|
+
if (components.amount == null) {
|
|
48
|
+
throw new Error('Amount confidence is required');
|
|
49
|
+
}
|
|
50
|
+
if (components.currency == null) {
|
|
51
|
+
throw new Error('Currency confidence is required');
|
|
52
|
+
}
|
|
53
|
+
if (components.business == null) {
|
|
54
|
+
throw new Error('Business confidence is required');
|
|
55
|
+
}
|
|
56
|
+
if (components.date == null) {
|
|
57
|
+
throw new Error('Date confidence is required');
|
|
58
|
+
}
|
|
59
|
+
// Validate all components are in valid range
|
|
60
|
+
const validateRange = (value, name) => {
|
|
61
|
+
if (value < 0.0 || value > 1.0) {
|
|
62
|
+
throw new Error(`${name} confidence must be between 0.0 and 1.0, got ${value}`);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
validateRange(components.amount, 'Amount');
|
|
66
|
+
validateRange(components.currency, 'Currency');
|
|
67
|
+
validateRange(components.business, 'Business');
|
|
68
|
+
validateRange(components.date, 'Date');
|
|
69
|
+
// Calculate weighted sum
|
|
70
|
+
const weightedSum = components.amount * CONFIDENCE_WEIGHTS.amount +
|
|
71
|
+
components.currency * CONFIDENCE_WEIGHTS.currency +
|
|
72
|
+
components.business * CONFIDENCE_WEIGHTS.business +
|
|
73
|
+
components.date * CONFIDENCE_WEIGHTS.date;
|
|
74
|
+
// Round to 2 decimal places
|
|
75
|
+
return Math.round(weightedSum * 100) / 100;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=overall-confidence.helper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overall-confidence.helper.js","sourceRoot":"","sources":["../../../../../../src/modules/charges-matcher/helpers/overall-confidence.helper.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AASH;;GAEG;AACH,MAAM,kBAAkB,GAAG;IACzB,MAAM,EAAE,GAAG;IACX,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;IACb,IAAI,EAAE,GAAG;CACD,CAAC;AAEX;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,0BAA0B,CAAC,UAAgC;IACzE,sCAAsC;IACtC,IAAI,UAAU,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IACD,IAAI,UAAU,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACrD,CAAC;IACD,IAAI,UAAU,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACrD,CAAC;IACD,IAAI,UAAU,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IAED,6CAA6C;IAC7C,MAAM,aAAa,GAAG,CAAC,KAAa,EAAE,IAAY,EAAQ,EAAE;QAC1D,IAAI,KAAK,GAAG,GAAG,IAAI,KAAK,GAAG,GAAG,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,gDAAgD,KAAK,EAAE,CAAC,CAAC;QAClF,CAAC;IACH,CAAC,CAAC;IAEF,aAAa,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC3C,aAAa,CAAC,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC/C,aAAa,CAAC,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC/C,aAAa,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAEvC,yBAAyB;IACzB,MAAM,WAAW,GACf,UAAU,CAAC,MAAM,GAAG,kBAAkB,CAAC,MAAM;QAC7C,UAAU,CAAC,QAAQ,GAAG,kBAAkB,CAAC,QAAQ;QACjD,UAAU,CAAC,QAAQ,GAAG,kBAAkB,CAAC,QAAQ;QACjD,UAAU,CAAC,IAAI,GAAG,kBAAkB,CAAC,IAAI,CAAC;IAE5C,4BAA4B;IAC5B,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import chargesMatcherTypeDefs from './typeDefs/charges-matcher.graphql.js';
|
|
2
|
+
import { createModule } from 'graphql-modules';
|
|
3
|
+
import { ChargesMatcherProvider } from './providers/charges-matcher.provider.js';
|
|
4
|
+
import { chargesMatcherResolvers } from './resolvers/index.js';
|
|
5
|
+
const __dirname = new URL('.', import.meta.url).pathname;
|
|
6
|
+
export const chargesMatcherModule = createModule({
|
|
7
|
+
id: 'charges-matcher',
|
|
8
|
+
dirname: __dirname,
|
|
9
|
+
typeDefs: [chargesMatcherTypeDefs],
|
|
10
|
+
resolvers: [chargesMatcherResolvers],
|
|
11
|
+
providers: [ChargesMatcherProvider],
|
|
12
|
+
});
|
|
13
|
+
export { ChargesMatcherProvider } from './providers/charges-matcher.provider.js';
|
|
14
|
+
export * as ChargesMatcherTypes from './types.js';
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/modules/charges-matcher/index.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AACjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAE/D,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;AAEzD,MAAM,CAAC,MAAM,oBAAoB,GAAG,YAAY,CAAC;IAC/C,EAAE,EAAE,iBAAiB;IACrB,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,CAAC,sBAAsB,CAAC;IAClC,SAAS,EAAE,CAAC,uBAAuB,CAAC;IACpC,SAAS,EAAE,CAAC,sBAAsB,CAAC;CACpC,CAAC,CAAC;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AACjF,OAAO,KAAK,mBAAmB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-Match Provider
|
|
3
|
+
*
|
|
4
|
+
* Implements the core auto-match logic for processing all unmatched charges
|
|
5
|
+
* and automatically merging charges with high-confidence matches (≥0.95).
|
|
6
|
+
*/
|
|
7
|
+
import type { ChargeWithData } from '../types.js';
|
|
8
|
+
import { type MatchResult } from './single-match.provider.js';
|
|
9
|
+
/**
|
|
10
|
+
* Result of processing a single charge for auto-matching
|
|
11
|
+
*/
|
|
12
|
+
export interface ProcessChargeResult {
|
|
13
|
+
/** Match result if a valid match was found, null otherwise */
|
|
14
|
+
match: MatchResult | null;
|
|
15
|
+
/** Status of the processing */
|
|
16
|
+
status: 'matched' | 'skipped' | 'no-match';
|
|
17
|
+
/** Reason for the status (useful for debugging/logging) */
|
|
18
|
+
reason?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Process a single unmatched charge and find best match
|
|
22
|
+
*
|
|
23
|
+
* This function uses findMatches() from single-match provider with NO date window
|
|
24
|
+
* restriction, then filters for high-confidence matches (≥0.95 threshold).
|
|
25
|
+
*
|
|
26
|
+
* @param sourceCharge - Unmatched charge to process (must have only transactions OR only documents)
|
|
27
|
+
* @param allCandidates - All candidate charges to search (complementary type to source)
|
|
28
|
+
* @param userId - Current user ID for business extraction
|
|
29
|
+
* @returns Processing result with match status
|
|
30
|
+
*
|
|
31
|
+
* @throws Error if sourceCharge is already matched (has both transactions and documents)
|
|
32
|
+
* @throws Error if sourceCharge has no transactions or documents
|
|
33
|
+
* @throws Error if any validation fails (propagated from findMatches)
|
|
34
|
+
*/
|
|
35
|
+
export declare function processChargeForAutoMatch(sourceCharge: ChargeWithData, allCandidates: ChargeWithData[], userId: string): ProcessChargeResult;
|
|
36
|
+
/**
|
|
37
|
+
* Determine merge direction for two charges
|
|
38
|
+
*
|
|
39
|
+
* The merge direction follows these rules:
|
|
40
|
+
* 1. If one charge is matched (has both transactions and documents), keep the matched one
|
|
41
|
+
* 2. If both are unmatched, keep the one with transactions (transaction charge is the "anchor")
|
|
42
|
+
* 3. If neither has transactions, keep the first one (arbitrary but consistent)
|
|
43
|
+
*
|
|
44
|
+
* @param charge1 - First charge
|
|
45
|
+
* @param charge2 - Second charge
|
|
46
|
+
* @returns [source, target] tuple where source will be merged INTO target (source is deleted)
|
|
47
|
+
*/
|
|
48
|
+
export declare function determineMergeDirection(charge1: ChargeWithData, charge2: ChargeWithData): [ChargeWithData, ChargeWithData];
|