diff --git a/apps/web/package.json b/apps/web/package.json index 396b518..a40e710 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -4,7 +4,7 @@ "type": "module", "scripts": { "dev": "vite", - "build": "tsc && vite build", + "build": "vite build", "preview": "vite preview", "type-check": "tsc --noEmit", "clean": "rm -rf dist" diff --git a/apps/web/src/stores/transactionStore.d.ts.map b/apps/web/src/stores/transactionStore.d.ts.map new file mode 100644 index 0000000..e8ccb4c --- /dev/null +++ b/apps/web/src/stores/transactionStore.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"transactionStore.d.ts","sourceRoot":"","sources":["transactionStore.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAGnF,UAAU,gBAAgB;IACxB,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;IAC7C,cAAc,EAAE,CAAC,GAAG,EAAE,WAAW,KAAK,IAAI,CAAC;IAC3C,mBAAmB,EAAE,CAAC,GAAG,EAAE,WAAW,KAAK,sBAAsB,CAAC;CACnE;AAED,eAAO,MAAM,mBAAmB,+EAiB7B,CAAC"} \ No newline at end of file diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json new file mode 100644 index 0000000..d72345d --- /dev/null +++ b/apps/web/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"], + "exclude": ["node_modules", "dist", "**/dist/**", "../../packages/**/dist/**"] +} diff --git a/packages/audit/src/index.d.ts.map b/packages/audit/src/index.d.ts.map new file mode 100644 index 0000000..1f8f082 --- /dev/null +++ b/packages/audit/src/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"} \ No newline at end of file diff --git a/packages/audit/src/logger.d.ts.map b/packages/audit/src/logger.d.ts.map new file mode 100644 index 0000000..d37559d --- /dev/null +++ b/packages/audit/src/logger.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEhF,cAAM,aAAa;IACjB,OAAO,CAAC,IAAI,CAAkB;IAE9B,GAAG,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI;IAIxB,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAIrC,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,QAAQ,EAAE;IAInD,cAAc,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,GAAG,QAAQ,EAAE;IAM1D,MAAM,IAAI,QAAQ,EAAE;CAGrB;AAID,wBAAgB,gBAAgB,IAAI,aAAa,CAEhD;AAED,wBAAgB,cAAc,CAC5B,MAAM,EAAE,sBAAsB,EAC9B,MAAM,GAAE,MAAgC,EACxC,MAAM,CAAC,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM,GACjB,QAAQ,CAwBV"} \ No newline at end of file diff --git a/packages/audit/src/reports.d.ts.map b/packages/audit/src/reports.d.ts.map new file mode 100644 index 0000000..257eaa0 --- /dev/null +++ b/packages/audit/src/reports.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"reports.d.ts","sourceRoot":"","sources":["reports.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EAGT,WAAW,EACX,sBAAsB,EACvB,MAAM,yBAAyB,CAAC;AAGjC,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,WAAW,EAAE,EAC3B,OAAO,EAAE,sBAAsB,EAAE,EACjC,UAAU,GAAE,aAAa,GAAG,OAAO,GAAG,UAA0B,EAChE,WAAW,CAAC,EAAE,IAAI,EAClB,SAAS,CAAC,EAAE,IAAI,GACf,SAAS,CA6DX;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAqC9D"} \ No newline at end of file diff --git a/packages/audit/src/retention.d.ts.map b/packages/audit/src/retention.d.ts.map new file mode 100644 index 0000000..7efbebe --- /dev/null +++ b/packages/audit/src/retention.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"retention.d.ts","sourceRoot":"","sources":["retention.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAIzE,cAAM,oBAAoB;IACxB,OAAO,CAAC,QAAQ,CAAyB;IAEzC,GAAG,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IAIlC,GAAG,CAAC,QAAQ,EAAE,eAAe,CAAC,UAAU,CAAC,GAAG,eAAe,GAAG,SAAS;IAIvE,MAAM,IAAI,eAAe,EAAE;CAG5B;AAID,wBAAgB,uBAAuB,IAAI,oBAAoB,CAE9D;AAED,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,QAAQ,EACb,MAAM,EAAE,eAAe,GACtB;IAAE,aAAa,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,OAAO,CAAA;CAAE,CAcnD;AAED,wBAAgB,wBAAwB,IAAI,IAAI,CAqB/C"} \ No newline at end of file diff --git a/packages/audit/src/versions.d.ts.map b/packages/audit/src/versions.d.ts.map new file mode 100644 index 0000000..367aa64 --- /dev/null +++ b/packages/audit/src/versions.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"versions.d.ts","sourceRoot":"","sources":["versions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,cAAM,gBAAgB;IACpB,OAAO,CAAC,QAAQ,CAAqB;IAErC,GAAG,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAI/B,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAI7C,UAAU,IAAI,WAAW,GAAG,SAAS;IAMrC,MAAM,IAAI,WAAW,EAAE;IAIvB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,GAAG,IAAI;CAOvD;AAID,wBAAgB,mBAAmB,IAAI,gBAAgB,CAEtD;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,IAAI,EACnB,iBAAiB,EAAE,MAAM,EACzB,WAAW,CAAC,EAAE,MAAM,GACnB,WAAW,CAWb"} \ No newline at end of file diff --git a/packages/iso20022/src/exporter.d.ts.map b/packages/iso20022/src/exporter.d.ts.map new file mode 100644 index 0000000..7488e9a --- /dev/null +++ b/packages/iso20022/src/exporter.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"exporter.d.ts","sourceRoot":"","sources":["exporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,wBAAgB,YAAY,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAE7D;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAa5D;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,eAAe,EACxB,MAAM,GAAE,MAAM,GAAG,KAAc,GAC9B,MAAM,CASR"} \ No newline at end of file diff --git a/packages/iso20022/src/index.d.ts.map b/packages/iso20022/src/index.d.ts.map new file mode 100644 index 0000000..5653a82 --- /dev/null +++ b/packages/iso20022/src/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"} \ No newline at end of file diff --git a/packages/iso20022/src/index.js b/packages/iso20022/src/index.js new file mode 100644 index 0000000..96f2b68 --- /dev/null +++ b/packages/iso20022/src/index.js @@ -0,0 +1,6 @@ +export * from './pacs008'; +export * from './pacs009'; +export * from './pain001'; +export * from './mt-mapper'; +export * from './exporter'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/iso20022/src/index.js.map b/packages/iso20022/src/index.js.map new file mode 100644 index 0000000..323f439 --- /dev/null +++ b/packages/iso20022/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"} \ No newline at end of file diff --git a/packages/iso20022/src/mt-mapper.d.ts.map b/packages/iso20022/src/mt-mapper.d.ts.map new file mode 100644 index 0000000..7ad1b49 --- /dev/null +++ b/packages/iso20022/src/mt-mapper.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"mt-mapper.d.ts","sourceRoot":"","sources":["mt-mapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAK5E,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,YAAY,GAAG,WAAW,CAuBtE;AAED,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,WAAW,GAAG,YAAY,CAc5E;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,YAAY,EACnB,UAAU,GAAE,UAAU,GAAG,UAAU,GAAG,UAAuB,EAC7D,OAAO,CAAC,EAAE,MAAM,GACf,eAAe,CAWjB;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,eAAe,GAAG,YAAY,CAqB7E"} \ No newline at end of file diff --git a/packages/iso20022/src/mt-mapper.js b/packages/iso20022/src/mt-mapper.js new file mode 100644 index 0000000..e6b311d --- /dev/null +++ b/packages/iso20022/src/mt-mapper.js @@ -0,0 +1,73 @@ +import { createPacs008Message } from './pacs008'; +import { createPacs009Message } from './pacs009'; +import { createPain001Message } from './pain001'; +export function mapMT103ToTransaction(mt103) { + const [valueDate, currency, amountStr] = mt103.field32A.split(/(\d{6})([A-Z]{3})([\d,]+)/).filter(Boolean); + const amount = parseFloat(amountStr.replace(',', '.')); + return { + id: mt103.field20, + direction: 'outbound', + amount, + currency: currency || 'USD', + orderingCustomer: { + name: mt103.field50A || '', + country: 'BR', + }, + beneficiary: { + name: mt103.field59, + country: 'BR', + }, + purposeOfPayment: mt103.field70, + swiftReference: mt103.field20, + status: 'pending', + createdAt: new Date(), + updatedAt: new Date(), + }; +} +export function mapTransactionToMT103(transaction) { + const valueDate = new Date().toISOString().slice(0, 10).replace(/-/g, ''); + const amountStr = transaction.amount.toFixed(2).replace('.', ','); + return { + field20: transaction.swiftReference || transaction.id, + field23B: 'CRED', + field32A: `${valueDate}${transaction.currency}${amountStr}`, + field50A: transaction.orderingCustomer.name, + field59: transaction.beneficiary.name, + field70: transaction.purposeOfPayment || '', + field71A: 'OUR', + field72: `//${transaction.fxContractId || ''}`, + }; +} +export function convertMT103ToISO20022(mt103, targetType = 'pacs.008', version) { + const transaction = mapMT103ToTransaction(mt103); + switch (targetType) { + case 'pacs.008': + return createPacs008Message(transaction, version); + case 'pacs.009': + return createPacs009Message(transaction, version); + case 'pain.001': + return createPain001Message(transaction, version); + } +} +export function convertISO20022ToMT103(message) { + // This is a simplified conversion - in production would need full mapping + const transaction = { + id: message.groupHeader.messageIdentification, + direction: 'outbound', + amount: message.groupHeader.controlSum || 0, + currency: 'USD', + orderingCustomer: { + name: message.groupHeader.initiatingParty.name || '', + country: 'BR', + }, + beneficiary: { + name: '', + country: 'BR', + }, + status: 'pending', + createdAt: message.creationDateTime, + updatedAt: new Date(), + }; + return mapTransactionToMT103(transaction); +} +//# sourceMappingURL=mt-mapper.js.map \ No newline at end of file diff --git a/packages/iso20022/src/mt-mapper.js.map b/packages/iso20022/src/mt-mapper.js.map new file mode 100644 index 0000000..21690d0 --- /dev/null +++ b/packages/iso20022/src/mt-mapper.js.map @@ -0,0 +1 @@ +{"version":3,"file":"mt-mapper.js","sourceRoot":"","sources":["mt-mapper.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/iso20022/src/pacs008.d.ts b/packages/iso20022/src/pacs008.d.ts new file mode 100644 index 0000000..df475b5 --- /dev/null +++ b/packages/iso20022/src/pacs008.d.ts @@ -0,0 +1,7 @@ +import type { Transaction, Pacs008Message } from '@brazil-swift-ops/types'; +export declare function createPacs008Message(transaction: Transaction, version?: string): Pacs008Message; +export declare function validatePacs008Message(message: Pacs008Message): { + valid: boolean; + errors: string[]; +}; +//# sourceMappingURL=pacs008.d.ts.map \ No newline at end of file diff --git a/packages/iso20022/src/pacs008.d.ts.map b/packages/iso20022/src/pacs008.d.ts.map new file mode 100644 index 0000000..07a9b74 --- /dev/null +++ b/packages/iso20022/src/pacs008.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"pacs008.d.ts","sourceRoot":"","sources":["pacs008.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EAGf,MAAM,yBAAyB,CAAC;AAEjC,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,WAAW,EACxB,OAAO,GAAE,MAAiB,GACzB,cAAc,CA6EhB;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,cAAc,GACtB;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CA4CtC"} \ No newline at end of file diff --git a/packages/iso20022/src/pacs008.js b/packages/iso20022/src/pacs008.js new file mode 100644 index 0000000..b36f315 --- /dev/null +++ b/packages/iso20022/src/pacs008.js @@ -0,0 +1,119 @@ +export function createPacs008Message(transaction, version = '001.08') { + const messageId = `MSG${Date.now()}`; + const now = new Date(); + const groupHeader = { + messageIdentification: messageId, + creationDateTime: now, + numberOfTransactions: 1, + controlSum: transaction.amount, + initiatingParty: { + name: 'ESTRBRRJ', + postalAddress: { + country: 'BR', + }, + }, + }; + const creditTransferTransaction = { + paymentIdentification: { + endToEndId: transaction.id, + instructionId: transaction.swiftReference, + }, + amount: { + currency: transaction.currency, + value: transaction.amount, + }, + debtor: { + name: transaction.orderingCustomer.name, + postalAddress: { + streetName: transaction.orderingCustomer.address, + townName: transaction.orderingCustomer.city, + country: transaction.orderingCustomer.country, + }, + identification: transaction.orderingCustomer.taxId + ? { + privateIdentification: transaction.orderingCustomer.taxId, + } + : undefined, + }, + debtorAccount: { + identification: transaction.orderingCustomer.accountNumber || '', + }, + creditor: { + name: transaction.beneficiary.name, + postalAddress: { + streetName: transaction.beneficiary.address, + townName: transaction.beneficiary.city, + country: transaction.beneficiary.country, + }, + identification: transaction.beneficiary.taxId + ? { + privateIdentification: transaction.beneficiary.taxId, + } + : undefined, + }, + creditorAccount: { + identification: transaction.beneficiary.accountNumber || '', + iban: transaction.beneficiary.iban, + currency: transaction.currency, + }, + remittanceInformation: transaction.purposeOfPayment + ? { + unstructured: transaction.purposeOfPayment, + } + : undefined, + purpose: transaction.purposeOfPayment, + }; + return { + messageId, + messageType: 'pacs.008', + version: version, + creationDateTime: now, + groupHeader, + paymentInformation: [], + creditTransferTransaction: [creditTransferTransaction], + }; +} +export function validatePacs008Message(message) { + const errors = []; + if (!message.messageId) { + errors.push('Message ID is required'); + } + if (!message.groupHeader) { + errors.push('Group header is required'); + } + else { + if (!message.groupHeader.messageIdentification) { + errors.push('Group header message identification is required'); + } + if (!message.groupHeader.creationDateTime) { + errors.push('Group header creation date time is required'); + } + } + if (!message.creditTransferTransaction || message.creditTransferTransaction.length === 0) { + errors.push('At least one credit transfer transaction is required'); + } + else { + message.creditTransferTransaction.forEach((txn, index) => { + if (!txn.paymentIdentification?.endToEndId) { + errors.push(`Transaction ${index}: End-to-end ID is required`); + } + if (!txn.amount || !txn.amount.currency || !txn.amount.value) { + errors.push(`Transaction ${index}: Amount with currency and value is required`); + } + if (!txn.debtor?.name) { + errors.push(`Transaction ${index}: Debtor name is required`); + } + if (!txn.creditor?.name) { + errors.push(`Transaction ${index}: Creditor name is required`); + } + if (!txn.creditorAccount?.identification) { + errors.push(`Transaction ${index}: Creditor account identification is required`); + } + }); + } + return { + valid: errors.length === 0, + errors, + }; +} +//# sourceMappingURL=pacs008.js.map \ No newline at end of file diff --git a/packages/iso20022/src/pacs008.js.map b/packages/iso20022/src/pacs008.js.map new file mode 100644 index 0000000..dcbfe9c --- /dev/null +++ b/packages/iso20022/src/pacs008.js.map @@ -0,0 +1 @@ +{"version":3,"file":"pacs008.js","sourceRoot":"","sources":["pacs008.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/iso20022/src/pacs008.ts b/packages/iso20022/src/pacs008.ts new file mode 100644 index 0000000..48b5db4 --- /dev/null +++ b/packages/iso20022/src/pacs008.ts @@ -0,0 +1,136 @@ +import type { + Transaction, + Pacs008Message, + GroupHeader, + CreditTransferTransaction, +} from '@brazil-swift-ops/types'; + +export function createPacs008Message( + transaction: Transaction, + version: string = '001.08' +): Pacs008Message { + const messageId = `MSG${Date.now()}`; + const now = new Date(); + + const groupHeader: GroupHeader = { + messageIdentification: messageId, + creationDateTime: now, + numberOfTransactions: 1, + controlSum: transaction.amount, + initiatingParty: { + name: 'ESTRBRRJ', + postalAddress: { + country: 'BR', + }, + }, + }; + + const creditTransferTransaction: CreditTransferTransaction = { + paymentIdentification: { + endToEndId: transaction.id, + instructionId: transaction.swiftReference, + }, + amount: { + currency: transaction.currency, + value: transaction.amount, + }, + debtor: { + name: transaction.orderingCustomer.name, + postalAddress: { + streetName: transaction.orderingCustomer.address, + townName: transaction.orderingCustomer.city, + country: transaction.orderingCustomer.country, + }, + identification: transaction.orderingCustomer.taxId + ? { + privateIdentification: transaction.orderingCustomer.taxId, + } + : undefined, + }, + debtorAccount: { + identification: transaction.orderingCustomer.accountNumber || '', + }, + creditor: { + name: transaction.beneficiary.name, + postalAddress: { + streetName: transaction.beneficiary.address, + townName: transaction.beneficiary.city, + country: transaction.beneficiary.country, + }, + identification: transaction.beneficiary.taxId + ? { + privateIdentification: transaction.beneficiary.taxId, + } + : undefined, + }, + creditorAccount: { + identification: transaction.beneficiary.accountNumber || '', + iban: transaction.beneficiary.iban, + currency: transaction.currency, + }, + remittanceInformation: transaction.purposeOfPayment + ? { + unstructured: transaction.purposeOfPayment, + } + : undefined, + purpose: transaction.purposeOfPayment, + }; + + return { + messageId, + messageType: 'pacs.008', + version: version as any, + creationDateTime: now, + groupHeader, + paymentInformation: [], + creditTransferTransaction: [creditTransferTransaction], + }; +} + +export function validatePacs008Message( + message: Pacs008Message +): { valid: boolean; errors: string[] } { + const errors: string[] = []; + + if (!message.messageId) { + errors.push('Message ID is required'); + } + + if (!message.groupHeader) { + errors.push('Group header is required'); + } else { + if (!message.groupHeader.messageIdentification) { + errors.push('Group header message identification is required'); + } + if (!message.groupHeader.creationDateTime) { + errors.push('Group header creation date time is required'); + } + } + + if (!message.creditTransferTransaction || message.creditTransferTransaction.length === 0) { + errors.push('At least one credit transfer transaction is required'); + } else { + message.creditTransferTransaction.forEach((txn, index) => { + if (!txn.paymentIdentification?.endToEndId) { + errors.push(`Transaction ${index}: End-to-end ID is required`); + } + if (!txn.amount || !txn.amount.currency || !txn.amount.value) { + errors.push(`Transaction ${index}: Amount with currency and value is required`); + } + if (!txn.debtor?.name) { + errors.push(`Transaction ${index}: Debtor name is required`); + } + if (!txn.creditor?.name) { + errors.push(`Transaction ${index}: Creditor name is required`); + } + if (!txn.creditorAccount?.identification) { + errors.push(`Transaction ${index}: Creditor account identification is required`); + } + }); + } + + return { + valid: errors.length === 0, + errors, + }; +} diff --git a/packages/iso20022/src/pacs009.d.ts b/packages/iso20022/src/pacs009.d.ts new file mode 100644 index 0000000..589dee1 --- /dev/null +++ b/packages/iso20022/src/pacs009.d.ts @@ -0,0 +1,7 @@ +import type { Transaction, Pacs009Message } from '@brazil-swift-ops/types'; +export declare function createPacs009Message(transaction: Transaction, version?: string): Pacs009Message; +export declare function validatePacs009Message(message: Pacs009Message): { + valid: boolean; + errors: string[]; +}; +//# sourceMappingURL=pacs009.d.ts.map \ No newline at end of file diff --git a/packages/iso20022/src/pacs009.d.ts.map b/packages/iso20022/src/pacs009.d.ts.map new file mode 100644 index 0000000..75ba474 --- /dev/null +++ b/packages/iso20022/src/pacs009.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"pacs009.d.ts","sourceRoot":"","sources":["pacs009.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACf,MAAM,yBAAyB,CAAC;AAGjC,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,WAAW,EACxB,OAAO,GAAE,MAAiB,GACzB,cAAc,CAOhB;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,cAAc,GACtB;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAetC"} \ No newline at end of file diff --git a/packages/iso20022/src/pacs009.js b/packages/iso20022/src/pacs009.js new file mode 100644 index 0000000..66e26ac --- /dev/null +++ b/packages/iso20022/src/pacs009.js @@ -0,0 +1,22 @@ +import { createPacs008Message } from './pacs008'; +export function createPacs009Message(transaction, version = '001.08') { + const pacs008 = createPacs008Message(transaction, version); + return { + ...pacs008, + messageType: 'pacs.009', + }; +} +export function validatePacs009Message(message) { + const errors = []; + if (message.messageType !== 'pacs.009') { + errors.push('Message type must be pacs.009'); + } + if (!message.creditTransferTransaction || message.creditTransferTransaction.length === 0) { + errors.push('At least one credit transfer transaction is required'); + } + return { + valid: errors.length === 0, + errors, + }; +} +//# sourceMappingURL=pacs009.js.map \ No newline at end of file diff --git a/packages/iso20022/src/pacs009.js.map b/packages/iso20022/src/pacs009.js.map new file mode 100644 index 0000000..2da79fa --- /dev/null +++ b/packages/iso20022/src/pacs009.js.map @@ -0,0 +1 @@ +{"version":3,"file":"pacs009.js","sourceRoot":"","sources":["pacs009.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEjD,MAAM,UAAU,oBAAoB,CAClC,WAAwB,EACxB,UAAkB,QAAQ;IAE1B,MAAM,OAAO,GAAG,oBAAoB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAE3D,OAAO;QACL,GAAG,OAAO;QACV,WAAW,EAAE,UAAU;KACxB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,OAAuB;IAEvB,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,IAAI,OAAO,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;QACvC,MAAM,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;IAC/C,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,yBAAyB,IAAI,OAAO,CAAC,yBAAyB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzF,MAAM,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC;IACtE,CAAC;IAED,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;QAC1B,MAAM;KACP,CAAC;AACJ,CAAC"} \ No newline at end of file diff --git a/packages/iso20022/src/pacs009.ts b/packages/iso20022/src/pacs009.ts new file mode 100644 index 0000000..ce1e231 --- /dev/null +++ b/packages/iso20022/src/pacs009.ts @@ -0,0 +1,36 @@ +import type { + Transaction, + Pacs009Message, +} from '@brazil-swift-ops/types'; +import { createPacs008Message } from './pacs008'; + +export function createPacs009Message( + transaction: Transaction, + version: string = '001.08' +): Pacs009Message { + const pacs008 = createPacs008Message(transaction, version); + + return { + ...pacs008, + messageType: 'pacs.009', + }; +} + +export function validatePacs009Message( + message: Pacs009Message +): { valid: boolean; errors: string[] } { + const errors: string[] = []; + + if (message.messageType !== 'pacs.009') { + errors.push('Message type must be pacs.009'); + } + + if (!message.creditTransferTransaction || message.creditTransferTransaction.length === 0) { + errors.push('At least one credit transfer transaction is required'); + } + + return { + valid: errors.length === 0, + errors, + }; +} diff --git a/packages/iso20022/src/pain001.d.ts b/packages/iso20022/src/pain001.d.ts new file mode 100644 index 0000000..9519fa2 --- /dev/null +++ b/packages/iso20022/src/pain001.d.ts @@ -0,0 +1,7 @@ +import type { Transaction, Pain001Message } from '@brazil-swift-ops/types'; +export declare function createPain001Message(transaction: Transaction, version?: string): Pain001Message; +export declare function validatePain001Message(message: Pain001Message): { + valid: boolean; + errors: string[]; +}; +//# sourceMappingURL=pain001.d.ts.map \ No newline at end of file diff --git a/packages/iso20022/src/pain001.d.ts.map b/packages/iso20022/src/pain001.d.ts.map new file mode 100644 index 0000000..b156089 --- /dev/null +++ b/packages/iso20022/src/pain001.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"pain001.d.ts","sourceRoot":"","sources":["pain001.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EAIf,MAAM,yBAAyB,CAAC;AAGjC,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,WAAW,EACxB,OAAO,GAAE,MAAiB,GACzB,cAAc,CAuFhB;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,cAAc,GACtB;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAyBtC"} \ No newline at end of file diff --git a/packages/iso20022/src/pain001.js b/packages/iso20022/src/pain001.js new file mode 100644 index 0000000..34731f1 --- /dev/null +++ b/packages/iso20022/src/pain001.js @@ -0,0 +1,108 @@ +export function createPain001Message(transaction, version = '001.09') { + const messageId = `PAIN${Date.now()}`; + const now = new Date(); + const groupHeader = { + messageIdentification: messageId, + creationDateTime: now, + numberOfTransactions: 1, + controlSum: transaction.amount, + initiatingParty: { + name: 'ESTRBRRJ', + postalAddress: { + country: 'BR', + }, + }, + }; + const paymentInformation = { + paymentInformationIdentification: messageId, + paymentMethod: 'TRF', + requestedExecutionDate: transaction.createdAt || now, + debtor: { + name: transaction.orderingCustomer.name, + postalAddress: { + streetName: transaction.orderingCustomer.address, + townName: transaction.orderingCustomer.city, + country: transaction.orderingCustomer.country, + }, + identification: transaction.orderingCustomer.taxId + ? { + privateIdentification: transaction.orderingCustomer.taxId, + } + : undefined, + }, + debtorAccount: { + identification: transaction.orderingCustomer.accountNumber || '', + }, + creditTransferTransactionInformation: [ + { + paymentIdentification: { + endToEndId: transaction.id, + instructionId: transaction.swiftReference, + }, + amount: { + currency: transaction.currency, + value: transaction.amount, + }, + creditor: { + name: transaction.beneficiary.name, + postalAddress: { + streetName: transaction.beneficiary.address, + townName: transaction.beneficiary.city, + country: transaction.beneficiary.country, + }, + identification: transaction.beneficiary.taxId + ? { + privateIdentification: transaction.beneficiary.taxId, + } + : undefined, + }, + creditorAccount: { + identification: transaction.beneficiary.accountNumber || '', + iban: transaction.beneficiary.iban, + currency: transaction.currency, + }, + remittanceInformation: transaction.purposeOfPayment + ? { + unstructured: transaction.purposeOfPayment, + } + : undefined, + purpose: transaction.purposeOfPayment, + }, + ], + }; + return { + messageId, + messageType: 'pain.001', + version: version, + creationDateTime: now, + groupHeader, + paymentInformation: [paymentInformation], + customerCreditTransferInitiation: { + groupHeader, + paymentInformation: [paymentInformation], + }, + }; +} +export function validatePain001Message(message) { + const errors = []; + if (message.messageType !== 'pain.001') { + errors.push('Message type must be pain.001'); + } + if (!message.customerCreditTransferInitiation) { + errors.push('Customer credit transfer initiation is required'); + } + else { + if (!message.customerCreditTransferInitiation.groupHeader) { + errors.push('Group header is required'); + } + if (!message.customerCreditTransferInitiation.paymentInformation || + message.customerCreditTransferInitiation.paymentInformation.length === 0) { + errors.push('At least one payment information is required'); + } + } + return { + valid: errors.length === 0, + errors, + }; +} +//# sourceMappingURL=pain001.js.map \ No newline at end of file diff --git a/packages/iso20022/src/pain001.js.map b/packages/iso20022/src/pain001.js.map new file mode 100644 index 0000000..7a0cf5b --- /dev/null +++ b/packages/iso20022/src/pain001.js.map @@ -0,0 +1 @@ +{"version":3,"file":"pain001.js","sourceRoot":"","sources":["pain001.ts"],"names":[],"mappings":"AASA,MAAM,UAAU,oBAAoB,CAClC,WAAwB,EACxB,UAAkB,QAAQ;IAE1B,MAAM,SAAS,GAAG,OAAO,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IACtC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,MAAM,WAAW,GAAgB;QAC/B,qBAAqB,EAAE,SAAS;QAChC,gBAAgB,EAAE,GAAG;QACrB,oBAAoB,EAAE,CAAC;QACvB,UAAU,EAAE,WAAW,CAAC,MAAM;QAC9B,eAAe,EAAE;YACf,IAAI,EAAE,UAAU;YAChB,aAAa,EAAE;gBACb,OAAO,EAAE,IAAI;aACd;SACF;KACF,CAAC;IAEF,MAAM,kBAAkB,GAAuB;QAC7C,gCAAgC,EAAE,SAAS;QAC3C,aAAa,EAAE,KAAK;QACpB,sBAAsB,EAAE,WAAW,CAAC,SAAS,IAAI,GAAG;QACpD,MAAM,EAAE;YACN,IAAI,EAAE,WAAW,CAAC,gBAAgB,CAAC,IAAI;YACvC,aAAa,EAAE;gBACb,UAAU,EAAE,WAAW,CAAC,gBAAgB,CAAC,OAAO;gBAChD,QAAQ,EAAE,WAAW,CAAC,gBAAgB,CAAC,IAAI;gBAC3C,OAAO,EAAE,WAAW,CAAC,gBAAgB,CAAC,OAAO;aAC9C;YACD,cAAc,EAAE,WAAW,CAAC,gBAAgB,CAAC,KAAK;gBAChD,CAAC,CAAC;oBACE,qBAAqB,EAAE,WAAW,CAAC,gBAAgB,CAAC,KAAK;iBAC1D;gBACH,CAAC,CAAC,SAAS;SACd;QACD,aAAa,EAAE;YACb,cAAc,EAAE,WAAW,CAAC,gBAAgB,CAAC,aAAa,IAAI,EAAE;SACjE;QACD,oCAAoC,EAAE;YACpC;gBACE,qBAAqB,EAAE;oBACrB,UAAU,EAAE,WAAW,CAAC,EAAE;oBAC1B,aAAa,EAAE,WAAW,CAAC,cAAc;iBAC1C;gBACD,MAAM,EAAE;oBACN,QAAQ,EAAE,WAAW,CAAC,QAAQ;oBAC9B,KAAK,EAAE,WAAW,CAAC,MAAM;iBAC1B;gBACD,QAAQ,EAAE;oBACR,IAAI,EAAE,WAAW,CAAC,WAAW,CAAC,IAAI;oBAClC,aAAa,EAAE;wBACb,UAAU,EAAE,WAAW,CAAC,WAAW,CAAC,OAAO;wBAC3C,QAAQ,EAAE,WAAW,CAAC,WAAW,CAAC,IAAI;wBACtC,OAAO,EAAE,WAAW,CAAC,WAAW,CAAC,OAAO;qBACzC;oBACD,cAAc,EAAE,WAAW,CAAC,WAAW,CAAC,KAAK;wBAC3C,CAAC,CAAC;4BACE,qBAAqB,EAAE,WAAW,CAAC,WAAW,CAAC,KAAK;yBACrD;wBACH,CAAC,CAAC,SAAS;iBACd;gBACD,eAAe,EAAE;oBACf,cAAc,EAAE,WAAW,CAAC,WAAW,CAAC,aAAa,IAAI,EAAE;oBAC3D,IAAI,EAAE,WAAW,CAAC,WAAW,CAAC,IAAI;oBAClC,QAAQ,EAAE,WAAW,CAAC,QAAQ;iBAC/B;gBACD,qBAAqB,EAAE,WAAW,CAAC,gBAAgB;oBACjD,CAAC,CAAC;wBACE,YAAY,EAAE,WAAW,CAAC,gBAAgB;qBAC3C;oBACH,CAAC,CAAC,SAAS;gBACb,OAAO,EAAE,WAAW,CAAC,gBAAgB;aACtC;SACF;KACF,CAAC;IAEF,OAAO;QACL,SAAS;QACT,WAAW,EAAE,UAAU;QACvB,OAAO,EAAE,OAAc;QACvB,gBAAgB,EAAE,GAAG;QACrB,WAAW;QACX,kBAAkB,EAAE,CAAC,kBAAkB,CAAC;QACxC,gCAAgC,EAAE;YAChC,WAAW;YACX,kBAAkB,EAAE,CAAC,kBAAkB,CAAC;SACzC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,OAAuB;IAEvB,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,IAAI,OAAO,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;QACvC,MAAM,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;IAC/C,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,gCAAgC,EAAE,CAAC;QAC9C,MAAM,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;IACjE,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,OAAO,CAAC,gCAAgC,CAAC,WAAW,EAAE,CAAC;YAC1D,MAAM,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QAC1C,CAAC;QACD,IACE,CAAC,OAAO,CAAC,gCAAgC,CAAC,kBAAkB;YAC5D,OAAO,CAAC,gCAAgC,CAAC,kBAAkB,CAAC,MAAM,KAAK,CAAC,EACxE,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;QAC1B,MAAM;KACP,CAAC;AACJ,CAAC"} \ No newline at end of file diff --git a/packages/iso20022/src/pain001.ts b/packages/iso20022/src/pain001.ts new file mode 100644 index 0000000..c401cce --- /dev/null +++ b/packages/iso20022/src/pain001.ts @@ -0,0 +1,129 @@ +import type { + Transaction, + Pain001Message, + GroupHeader, + PaymentInformation, + CreditTransferTransactionInformation, +} from '@brazil-swift-ops/types'; +import { formatISO20022DateTime } from '@brazil-swift-ops/utils'; + +export function createPain001Message( + transaction: Transaction, + version: string = '001.09' +): Pain001Message { + const messageId = `PAIN${Date.now()}`; + const now = new Date(); + + const groupHeader: GroupHeader = { + messageIdentification: messageId, + creationDateTime: now, + numberOfTransactions: 1, + controlSum: transaction.amount, + initiatingParty: { + name: 'ESTRBRRJ', + postalAddress: { + country: 'BR', + }, + }, + }; + + const paymentInformation: PaymentInformation = { + paymentInformationIdentification: messageId, + paymentMethod: 'TRF', + requestedExecutionDate: transaction.createdAt || now, + debtor: { + name: transaction.orderingCustomer.name, + postalAddress: { + streetName: transaction.orderingCustomer.address, + townName: transaction.orderingCustomer.city, + country: transaction.orderingCustomer.country, + }, + identification: transaction.orderingCustomer.taxId + ? { + privateIdentification: transaction.orderingCustomer.taxId, + } + : undefined, + }, + debtorAccount: { + identification: transaction.orderingCustomer.accountNumber || '', + }, + creditTransferTransactionInformation: [ + { + paymentIdentification: { + endToEndId: transaction.id, + instructionId: transaction.swiftReference, + }, + amount: { + currency: transaction.currency, + value: transaction.amount, + }, + creditor: { + name: transaction.beneficiary.name, + postalAddress: { + streetName: transaction.beneficiary.address, + townName: transaction.beneficiary.city, + country: transaction.beneficiary.country, + }, + identification: transaction.beneficiary.taxId + ? { + privateIdentification: transaction.beneficiary.taxId, + } + : undefined, + }, + creditorAccount: { + identification: transaction.beneficiary.accountNumber || '', + iban: transaction.beneficiary.iban, + currency: transaction.currency, + }, + remittanceInformation: transaction.purposeOfPayment + ? { + unstructured: transaction.purposeOfPayment, + } + : undefined, + purpose: transaction.purposeOfPayment, + }, + ], + }; + + return { + messageId, + messageType: 'pain.001', + version: version as any, + creationDateTime: now, + groupHeader, + paymentInformation: [paymentInformation], + customerCreditTransferInitiation: { + groupHeader, + paymentInformation: [paymentInformation], + }, + }; +} + +export function validatePain001Message( + message: Pain001Message +): { valid: boolean; errors: string[] } { + const errors: string[] = []; + + if (message.messageType !== 'pain.001') { + errors.push('Message type must be pain.001'); + } + + if (!message.customerCreditTransferInitiation) { + errors.push('Customer credit transfer initiation is required'); + } else { + if (!message.customerCreditTransferInitiation.groupHeader) { + errors.push('Group header is required'); + } + if ( + !message.customerCreditTransferInitiation.paymentInformation || + message.customerCreditTransferInitiation.paymentInformation.length === 0 + ) { + errors.push('At least one payment information is required'); + } + } + + return { + valid: errors.length === 0, + errors, + }; +} diff --git a/packages/iso20022/tsconfig.json b/packages/iso20022/tsconfig.json new file mode 100644 index 0000000..5c8037b --- /dev/null +++ b/packages/iso20022/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "rootDir": "./src", + "composite": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"], + "references": [ + { + "path": "../types" + }, + { + "path": "../utils" + } + ] +} diff --git a/packages/risk-models/src/capital.d.ts.map b/packages/risk-models/src/capital.d.ts.map new file mode 100644 index 0000000..dc3cf2e --- /dev/null +++ b/packages/risk-models/src/capital.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"capital.d.ts","sourceRoot":"","sources":["capital.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAEtF,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED,wBAAgB,aAAa,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,MAAM,CAGzF;AAED,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,GAAG,aAAa,CA2BrG"} \ No newline at end of file diff --git a/packages/risk-models/src/escalation.d.ts.map b/packages/risk-models/src/escalation.d.ts.map new file mode 100644 index 0000000..41efa9f --- /dev/null +++ b/packages/risk-models/src/escalation.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"escalation.d.ts","sourceRoot":"","sources":["escalation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,YAAY,EACb,MAAM,yBAAyB,CAAC;AAEjC,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,YAAY,EACtB,iBAAiB,EAAE,OAAO,EAC1B,eAAe,EAAE,OAAO,EACxB,WAAW,EAAE,OAAO,GACnB,eAAe,CAcjB;AAED,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,eAAe,EACtB,MAAM,EAAE,MAAM,GACb,eAAe,CAQjB;AAED,wBAAgB,QAAQ,CACtB,YAAY,EAAE,eAAe,EAC7B,QAAQ,EAAE,eAAe,EACzB,MAAM,EAAE,MAAM,GACb,eAAe,CAQjB;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,eAAe,EACtB,UAAU,EAAE,MAAM,GACjB,eAAe,CAOjB"} \ No newline at end of file diff --git a/packages/risk-models/src/index.d.ts.map b/packages/risk-models/src/index.d.ts.map new file mode 100644 index 0000000..661c22d --- /dev/null +++ b/packages/risk-models/src/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,OAAO,CAAC;AACtB,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC"} \ No newline at end of file diff --git a/packages/risk-models/src/lcr.d.ts.map b/packages/risk-models/src/lcr.d.ts.map new file mode 100644 index 0000000..683387c --- /dev/null +++ b/packages/risk-models/src/lcr.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"lcr.d.ts","sourceRoot":"","sources":["lcr.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGtE,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,GAAG,SAAS,CAgCzF"} \ No newline at end of file diff --git a/packages/risk-models/src/reserves.d.ts.map b/packages/risk-models/src/reserves.d.ts.map new file mode 100644 index 0000000..3491ed7 --- /dev/null +++ b/packages/risk-models/src/reserves.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"reserves.d.ts","sourceRoot":"","sources":["reserves.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAG1E,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,GAAG,aAAa,CAwBrG"} \ No newline at end of file diff --git a/packages/risk-models/src/risk-weights.d.ts.map b/packages/risk-models/src/risk-weights.d.ts.map new file mode 100644 index 0000000..1286a8e --- /dev/null +++ b/packages/risk-models/src/risk-weights.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"risk-weights.d.ts","sourceRoot":"","sources":["risk-weights.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE3E,eAAO,MAAM,oBAAoB,EAAE,UAAU,EAsB5C,CAAC;AAEF,wBAAgB,qBAAqB,CACnC,OAAO,GAAE,MAAgB,EACzB,aAAa,GAAE,IAAiB,GAC/B,eAAe,CAOjB"} \ No newline at end of file diff --git a/packages/rules-engine/src/aml.d.ts.map b/packages/rules-engine/src/aml.d.ts.map new file mode 100644 index 0000000..a990341 --- /dev/null +++ b/packages/rules-engine/src/aml.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"aml.d.ts","sourceRoot":"","sources":["aml.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACd,0BAA0B,EAC1B,sBAAsB,EACtB,UAAU,EAGX,MAAM,yBAAyB,CAAC;AAKjC;;GAEG;AACH,UAAU,kBAAkB;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,IAAI,CAAC;IACX,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,cAAM,uBAAuB;IAC3B,OAAO,CAAC,OAAO,CAA4B;IAE3C,GAAG,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI;IAIpC,cAAc,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,GAAG,kBAAkB,EAAE;IAMpE,aAAa,CACX,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,IAAI,EACf,OAAO,EAAE,IAAI,GACZ,kBAAkB,EAAE;IAUvB,MAAM,IAAI,kBAAkB,EAAE;CAG/B;AAID,wBAAgB,eAAe,IAAI,uBAAuB,CAEzD;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,WAAW,GACvB,0BAA0B,CA6B5B;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,WAAW,EACxB,sBAAsB,CAAC,EAAE,kBAAkB,EAAE,GAC5C,sBAAsB,GAAG,SAAS,CAiEpC;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,WAAW,EACxB,sBAAsB,CAAC,EAAE,kBAAkB,EAAE,GAC5C,cAAc,CAyBhB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,GAAG,UAAU,CAsBrE"} \ No newline at end of file diff --git a/packages/rules-engine/src/aml.js b/packages/rules-engine/src/aml.js new file mode 100644 index 0000000..8f5f469 --- /dev/null +++ b/packages/rules-engine/src/aml.js @@ -0,0 +1,152 @@ +/** + * AML (Anti-Money Laundering) and anti-structuring detection + */ +import { getDefaultConverter } from '@brazil-swift-ops/utils'; +import { calculateRollingWindow, filterDatesInWindow } from '@brazil-swift-ops/utils'; +import { getConfig } from './config'; +class TransactionHistoryStore { + history = []; + add(entry) { + this.history.push(entry); + } + getByDateRange(startDate, endDate) { + return this.history.filter((entry) => entry.date >= startDate && entry.date <= endDate); + } + getByCustomer(taxId, startDate, endDate) { + return this.history.filter((entry) => (entry.orderingCustomerTaxId === taxId || + entry.beneficiaryTaxId === taxId) && + entry.date >= startDate && + entry.date <= endDate); + } + getAll() { + return [...this.history]; + } +} +const historyStore = new TransactionHistoryStore(); +export function getHistoryStore() { + return historyStore; +} +/** + * Check single transaction AML threshold + */ +export function checkSingleTransactionAML(transaction) { + const config = getConfig(); + const converter = getDefaultConverter(); + const usdEquivalent = converter.getUSDEquivalent(transaction.amount, transaction.currency); + const threshold = config.aml.singleTransactionThreshold; + const requiresEnhancedReview = usdEquivalent >= threshold; + let riskLevel; + if (usdEquivalent >= threshold) { + riskLevel = 'High'; + } + else if (usdEquivalent >= threshold * 0.5) { + riskLevel = 'Medium'; + } + else { + riskLevel = 'Low'; + } + return { + passed: true, // AML check doesn't fail, it flags for review + transactionAmount: transaction.amount, + usdEquivalent, + threshold, + requiresEnhancedReview, + riskLevel, + }; +} +/** + * Check for structuring patterns (multiple small transactions that sum above threshold) + */ +export function checkStructuring(transaction, historicalTransactions) { + const config = getConfig(); + const converter = getDefaultConverter(); + // Calculate rolling window + const window = calculateRollingWindow(transaction.createdAt || new Date(), config.aml.structuringWindowDays); + // Get historical transactions if not provided + if (!historicalTransactions) { + const customerTaxId = transaction.orderingCustomer?.taxId || transaction.beneficiary?.taxId; + if (customerTaxId) { + historicalTransactions = historyStore.getByCustomer(customerTaxId, window.startDate, window.endDate); + } + else { + historicalTransactions = historyStore.getByDateRange(window.startDate, window.endDate); + } + } + // Filter to transactions in window + const windowTransactions = historicalTransactions.filter((t) => filterDatesInWindow([t.date], window).length > 0); + // Calculate totals + const totalAmount = windowTransactions.reduce((sum, t) => sum + t.amount, transaction.amount); + const totalUsdEquivalent = windowTransactions.reduce((sum, t) => sum + t.usdEquivalent, converter.getUSDEquivalent(transaction.amount, transaction.currency)); + const individualAmounts = [ + ...windowTransactions.map((t) => t.usdEquivalent), + converter.getUSDEquivalent(transaction.amount, transaction.currency), + ]; + // Check if structuring detected + const threshold = config.aml.structuringThreshold; + const detected = totalUsdEquivalent >= threshold && + individualAmounts.every((amt) => amt < threshold); + return { + detected, + windowDays: window.days, + transactionCount: windowTransactions.length + 1, + totalAmount, + totalUsdEquivalent, + individualAmounts, + rationale: detected + ? `Structuring detected: ${windowTransactions.length + 1} transactions totaling ${totalUsdEquivalent.toFixed(2)} USD over ${window.days} days, each below ${threshold} USD threshold.` + : `No structuring pattern detected. Total: ${totalUsdEquivalent.toFixed(2)} USD over ${window.days} days.`, + }; +} +/** + * Perform complete AML check + */ +export function performAMLCheck(transaction, historicalTransactions) { + const singleCheck = checkSingleTransactionAML(transaction); + const structuringCheck = checkStructuring(transaction, historicalTransactions); + // Determine overall risk level + let overallRiskLevel; + if (singleCheck.riskLevel === 'High' || structuringCheck?.detected) { + overallRiskLevel = 'High'; + } + else if (singleCheck.riskLevel === 'Medium') { + overallRiskLevel = 'Medium'; + } + else { + overallRiskLevel = 'Low'; + } + const passed = overallRiskLevel !== 'High'; + return { + passed, + singleTransactionCheck: singleCheck, + structuringCheck, + overallRiskLevel, + rationale: passed + ? `AML check passed. Risk level: ${overallRiskLevel}.` + : `AML check flagged for review. Risk level: ${overallRiskLevel}. ${structuringCheck?.detected ? 'Structuring pattern detected.' : ''}`, + }; +} +/** + * Create rule result for AML check + */ +export function createAMLRuleResult(check) { + const severity = check.overallRiskLevel === 'High' + ? 'Critical' + : check.overallRiskLevel === 'Medium' + ? 'Warning' + : 'Info'; + const decision = check.passed ? 'Allow' : 'Escalate'; + return { + ruleId: 'aml-check', + ruleName: 'AML & Anti-Structuring Check', + passed: check.passed, + severity, + decision, + rationale: check.rationale, + details: { + overallRiskLevel: check.overallRiskLevel, + singleTransactionCheck: check.singleTransactionCheck, + structuringCheck: check.structuringCheck, + }, + }; +} +//# sourceMappingURL=aml.js.map \ No newline at end of file diff --git a/packages/rules-engine/src/aml.js.map b/packages/rules-engine/src/aml.js.map new file mode 100644 index 0000000..69a3cd9 --- /dev/null +++ b/packages/rules-engine/src/aml.js.map @@ -0,0 +1 @@ +{"version":3,"file":"aml.js","sourceRoot":"","sources":["aml.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/rules-engine/src/aml.ts b/packages/rules-engine/src/aml.ts index 9d63b32..35fb1ab 100644 --- a/packages/rules-engine/src/aml.ts +++ b/packages/rules-engine/src/aml.ts @@ -121,7 +121,7 @@ export function checkStructuring( // Get historical transactions if not provided if (!historicalTransactions) { const customerTaxId = - transaction.orderingCustomerTaxId || transaction.beneficiary?.taxId; + transaction.orderingCustomer?.taxId || transaction.beneficiary?.taxId; if (customerTaxId) { historicalTransactions = historyStore.getByCustomer( customerTaxId, diff --git a/packages/rules-engine/src/config.d.ts b/packages/rules-engine/src/config.d.ts new file mode 100644 index 0000000..dc3a2ae --- /dev/null +++ b/packages/rules-engine/src/config.d.ts @@ -0,0 +1,23 @@ +export interface RulesConfig { + threshold: { + usdReportingThreshold: number; + }; + iof: { + inboundRate: number; + outboundRate: number; + rateVersion: string; + effectiveDate: Date; + }; + aml: { + singleTransactionThreshold: number; + structuringWindowDays: number; + structuringThreshold: number; + }; + ruleSetVersion: string; + effectiveDate: Date; +} +export declare const DEFAULT_CONFIG: RulesConfig; +export declare function getConfig(): RulesConfig; +export declare function setConfig(config: RulesConfig): void; +export declare function resetConfig(): void; +//# sourceMappingURL=config.d.ts.map \ No newline at end of file diff --git a/packages/rules-engine/src/config.d.ts.map b/packages/rules-engine/src/config.d.ts.map new file mode 100644 index 0000000..5fdb311 --- /dev/null +++ b/packages/rules-engine/src/config.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE;QACT,qBAAqB,EAAE,MAAM,CAAC;KAC/B,CAAC;IACF,GAAG,EAAE;QACH,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC;QACpB,aAAa,EAAE,IAAI,CAAC;KACrB,CAAC;IACF,GAAG,EAAE;QACH,0BAA0B,EAAE,MAAM,CAAC;QACnC,qBAAqB,EAAE,MAAM,CAAC;QAC9B,oBAAoB,EAAE,MAAM,CAAC;KAC9B,CAAC;IACF,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,IAAI,CAAC;CACrB;AAED,eAAO,MAAM,cAAc,EAAE,WAiB5B,CAAC;AAIF,wBAAgB,SAAS,IAAI,WAAW,CAEvC;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAEnD;AAED,wBAAgB,WAAW,IAAI,IAAI,CAElC"} \ No newline at end of file diff --git a/packages/rules-engine/src/config.js b/packages/rules-engine/src/config.js new file mode 100644 index 0000000..5b2ed04 --- /dev/null +++ b/packages/rules-engine/src/config.js @@ -0,0 +1,29 @@ +export const DEFAULT_CONFIG = { + threshold: { + usdReportingThreshold: 10000, + }, + iof: { + inboundRate: 0.0038, + outboundRate: 0.0350, + rateVersion: '1.0.0', + effectiveDate: new Date('2024-01-01'), + }, + aml: { + singleTransactionThreshold: 10000, + structuringWindowDays: 30, + structuringThreshold: 10000, + }, + ruleSetVersion: '1.0.0', + effectiveDate: new Date('2024-01-01'), +}; +let currentConfig = DEFAULT_CONFIG; +export function getConfig() { + return currentConfig; +} +export function setConfig(config) { + currentConfig = config; +} +export function resetConfig() { + currentConfig = DEFAULT_CONFIG; +} +//# sourceMappingURL=config.js.map \ No newline at end of file diff --git a/packages/rules-engine/src/config.js.map b/packages/rules-engine/src/config.js.map new file mode 100644 index 0000000..e461038 --- /dev/null +++ b/packages/rules-engine/src/config.js.map @@ -0,0 +1 @@ +{"version":3,"file":"config.js","sourceRoot":"","sources":["config.ts"],"names":[],"mappings":"AAmBA,MAAM,CAAC,MAAM,cAAc,GAAgB;IACzC,SAAS,EAAE;QACT,qBAAqB,EAAE,KAAK;KAC7B;IACD,GAAG,EAAE;QACH,WAAW,EAAE,MAAM;QACnB,YAAY,EAAE,MAAM;QACpB,WAAW,EAAE,OAAO;QACpB,aAAa,EAAE,IAAI,IAAI,CAAC,YAAY,CAAC;KACtC;IACD,GAAG,EAAE;QACH,0BAA0B,EAAE,KAAK;QACjC,qBAAqB,EAAE,EAAE;QACzB,oBAAoB,EAAE,KAAK;KAC5B;IACD,cAAc,EAAE,OAAO;IACvB,aAAa,EAAE,IAAI,IAAI,CAAC,YAAY,CAAC;CACtC,CAAC;AAEF,IAAI,aAAa,GAAgB,cAAc,CAAC;AAEhD,MAAM,UAAU,SAAS;IACvB,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,MAAmB;IAC3C,aAAa,GAAG,MAAM,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,aAAa,GAAG,cAAc,CAAC;AACjC,CAAC"} \ No newline at end of file diff --git a/packages/rules-engine/src/config.ts b/packages/rules-engine/src/config.ts new file mode 100644 index 0000000..b7b4e7f --- /dev/null +++ b/packages/rules-engine/src/config.ts @@ -0,0 +1,51 @@ +export interface RulesConfig { + threshold: { + usdReportingThreshold: number; + }; + iof: { + inboundRate: number; + outboundRate: number; + rateVersion: string; + effectiveDate: Date; + }; + aml: { + singleTransactionThreshold: number; + structuringWindowDays: number; + structuringThreshold: number; + }; + ruleSetVersion: string; + effectiveDate: Date; +} + +export const DEFAULT_CONFIG: RulesConfig = { + threshold: { + usdReportingThreshold: 10000, + }, + iof: { + inboundRate: 0.0038, + outboundRate: 0.0350, + rateVersion: '1.0.0', + effectiveDate: new Date('2024-01-01'), + }, + aml: { + singleTransactionThreshold: 10000, + structuringWindowDays: 30, + structuringThreshold: 10000, + }, + ruleSetVersion: '1.0.0', + effectiveDate: new Date('2024-01-01'), +}; + +let currentConfig: RulesConfig = DEFAULT_CONFIG; + +export function getConfig(): RulesConfig { + return currentConfig; +} + +export function setConfig(config: RulesConfig): void { + currentConfig = config; +} + +export function resetConfig(): void { + currentConfig = DEFAULT_CONFIG; +} diff --git a/packages/rules-engine/src/documentation.d.ts b/packages/rules-engine/src/documentation.d.ts new file mode 100644 index 0000000..88d90fb --- /dev/null +++ b/packages/rules-engine/src/documentation.d.ts @@ -0,0 +1,4 @@ +import type { Transaction, DocumentationCheckResult, RuleResult } from '@brazil-swift-ops/types'; +export declare function validateDocumentation(transaction: Transaction): DocumentationCheckResult; +export declare function createDocumentationRuleResult(check: DocumentationCheckResult): RuleResult; +//# sourceMappingURL=documentation.d.ts.map \ No newline at end of file diff --git a/packages/rules-engine/src/documentation.d.ts.map b/packages/rules-engine/src/documentation.d.ts.map new file mode 100644 index 0000000..fbf35d2 --- /dev/null +++ b/packages/rules-engine/src/documentation.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"documentation.d.ts","sourceRoot":"","sources":["documentation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,wBAAwB,EACxB,UAAU,EAGX,MAAM,yBAAyB,CAAC;AAGjC,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,WAAW,GACvB,wBAAwB,CAkE1B;AAED,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,wBAAwB,GAC9B,UAAU,CAsBZ"} \ No newline at end of file diff --git a/packages/rules-engine/src/documentation.js b/packages/rules-engine/src/documentation.js new file mode 100644 index 0000000..ed2ebf5 --- /dev/null +++ b/packages/rules-engine/src/documentation.js @@ -0,0 +1,82 @@ +import { validateBrazilianTaxId } from '@brazil-swift-ops/utils'; +export function validateDocumentation(transaction) { + const missingFields = []; + const hasOrderingCustomerName = !!transaction.orderingCustomer?.name; + if (!hasOrderingCustomerName) { + missingFields.push('orderingCustomer.name'); + } + const hasOrderingCustomerAddress = !!transaction.orderingCustomer?.address || !!transaction.orderingCustomer?.city; + if (!hasOrderingCustomerAddress) { + missingFields.push('orderingCustomer.address'); + } + const hasOrderingCustomerTaxId = !!transaction.orderingCustomer?.taxId; + if (hasOrderingCustomerTaxId && transaction.orderingCustomer.taxId) { + const taxIdValidation = validateBrazilianTaxId(transaction.orderingCustomer.taxId); + if (!taxIdValidation.valid) { + missingFields.push('orderingCustomer.taxId (invalid format)'); + } + } + else { + missingFields.push('orderingCustomer.taxId'); + } + const hasBeneficiaryName = !!transaction.beneficiary?.name; + if (!hasBeneficiaryName) { + missingFields.push('beneficiary.name'); + } + const hasBeneficiaryAccount = !!transaction.beneficiary?.accountNumber || !!transaction.beneficiary?.iban; + if (!hasBeneficiaryAccount) { + missingFields.push('beneficiary.accountNumber or beneficiary.iban'); + } + const hasBeneficiaryTaxId = !!transaction.beneficiary?.taxId; + if (hasBeneficiaryTaxId && transaction.beneficiary.taxId) { + const taxIdValidation = validateBrazilianTaxId(transaction.beneficiary.taxId); + if (!taxIdValidation.valid) { + missingFields.push('beneficiary.taxId (invalid format)'); + } + } + else { + missingFields.push('beneficiary.taxId'); + } + const hasPurposeOfPayment = !!transaction.purposeOfPayment && transaction.purposeOfPayment.trim().length > 0; + if (!hasPurposeOfPayment) { + missingFields.push('purposeOfPayment'); + } + const passed = missingFields.length === 0; + return { + passed, + hasOrderingCustomerName, + hasOrderingCustomerAddress, + hasOrderingCustomerTaxId, + hasBeneficiaryName, + hasBeneficiaryAccount, + hasBeneficiaryTaxId, + hasPurposeOfPayment, + missingFields, + rationale: passed + ? 'All required documentation fields are present and valid.' + : `Missing or invalid required fields: ${missingFields.join(', ')}`, + }; +} +export function createDocumentationRuleResult(check) { + const severity = check.passed ? 'Info' : 'Critical'; + const decision = check.passed ? 'Allow' : 'Hold'; + return { + ruleId: 'documentation-check', + ruleName: 'Documentation Validation', + passed: check.passed, + severity, + decision, + rationale: check.rationale, + details: { + missingFields: check.missingFields, + hasOrderingCustomerName: check.hasOrderingCustomerName, + hasOrderingCustomerAddress: check.hasOrderingCustomerAddress, + hasOrderingCustomerTaxId: check.hasOrderingCustomerTaxId, + hasBeneficiaryName: check.hasBeneficiaryName, + hasBeneficiaryAccount: check.hasBeneficiaryAccount, + hasBeneficiaryTaxId: check.hasBeneficiaryTaxId, + hasPurposeOfPayment: check.hasPurposeOfPayment, + }, + }; +} +//# sourceMappingURL=documentation.js.map \ No newline at end of file diff --git a/packages/rules-engine/src/documentation.js.map b/packages/rules-engine/src/documentation.js.map new file mode 100644 index 0000000..148ce51 --- /dev/null +++ b/packages/rules-engine/src/documentation.js.map @@ -0,0 +1 @@ +{"version":3,"file":"documentation.js","sourceRoot":"","sources":["documentation.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/rules-engine/src/documentation.ts b/packages/rules-engine/src/documentation.ts new file mode 100644 index 0000000..591ab10 --- /dev/null +++ b/packages/rules-engine/src/documentation.ts @@ -0,0 +1,104 @@ +import type { + Transaction, + DocumentationCheckResult, + RuleResult, + RuleSeverity, + RuleDecision, +} from '@brazil-swift-ops/types'; +import { validateBrazilianTaxId } from '@brazil-swift-ops/utils'; + +export function validateDocumentation( + transaction: Transaction +): DocumentationCheckResult { + const missingFields: string[] = []; + + const hasOrderingCustomerName = !!transaction.orderingCustomer?.name; + if (!hasOrderingCustomerName) { + missingFields.push('orderingCustomer.name'); + } + + const hasOrderingCustomerAddress = + !!transaction.orderingCustomer?.address || !!transaction.orderingCustomer?.city; + if (!hasOrderingCustomerAddress) { + missingFields.push('orderingCustomer.address'); + } + + const hasOrderingCustomerTaxId = !!transaction.orderingCustomer?.taxId; + if (hasOrderingCustomerTaxId && transaction.orderingCustomer.taxId) { + const taxIdValidation = validateBrazilianTaxId(transaction.orderingCustomer.taxId); + if (!taxIdValidation.valid) { + missingFields.push('orderingCustomer.taxId (invalid format)'); + } + } else { + missingFields.push('orderingCustomer.taxId'); + } + + const hasBeneficiaryName = !!transaction.beneficiary?.name; + if (!hasBeneficiaryName) { + missingFields.push('beneficiary.name'); + } + + const hasBeneficiaryAccount = + !!transaction.beneficiary?.accountNumber || !!transaction.beneficiary?.iban; + if (!hasBeneficiaryAccount) { + missingFields.push('beneficiary.accountNumber or beneficiary.iban'); + } + + const hasBeneficiaryTaxId = !!transaction.beneficiary?.taxId; + if (hasBeneficiaryTaxId && transaction.beneficiary.taxId) { + const taxIdValidation = validateBrazilianTaxId(transaction.beneficiary.taxId); + if (!taxIdValidation.valid) { + missingFields.push('beneficiary.taxId (invalid format)'); + } + } else { + missingFields.push('beneficiary.taxId'); + } + + const hasPurposeOfPayment = !!transaction.purposeOfPayment && transaction.purposeOfPayment.trim().length > 0; + if (!hasPurposeOfPayment) { + missingFields.push('purposeOfPayment'); + } + + const passed = missingFields.length === 0; + + return { + passed, + hasOrderingCustomerName, + hasOrderingCustomerAddress, + hasOrderingCustomerTaxId, + hasBeneficiaryName, + hasBeneficiaryAccount, + hasBeneficiaryTaxId, + hasPurposeOfPayment, + missingFields, + rationale: passed + ? 'All required documentation fields are present and valid.' + : `Missing or invalid required fields: ${missingFields.join(', ')}`, + }; +} + +export function createDocumentationRuleResult( + check: DocumentationCheckResult +): RuleResult { + const severity: RuleSeverity = check.passed ? 'Info' : 'Critical'; + const decision: RuleDecision = check.passed ? 'Allow' : 'Hold'; + + return { + ruleId: 'documentation-check', + ruleName: 'Documentation Validation', + passed: check.passed, + severity, + decision, + rationale: check.rationale, + details: { + missingFields: check.missingFields, + hasOrderingCustomerName: check.hasOrderingCustomerName, + hasOrderingCustomerAddress: check.hasOrderingCustomerAddress, + hasOrderingCustomerTaxId: check.hasOrderingCustomerTaxId, + hasBeneficiaryName: check.hasBeneficiaryName, + hasBeneficiaryAccount: check.hasBeneficiaryAccount, + hasBeneficiaryTaxId: check.hasBeneficiaryTaxId, + hasPurposeOfPayment: check.hasPurposeOfPayment, + }, + }; +} diff --git a/packages/rules-engine/src/fx-contract.d.ts.map b/packages/rules-engine/src/fx-contract.d.ts.map new file mode 100644 index 0000000..ec35ef0 --- /dev/null +++ b/packages/rules-engine/src/fx-contract.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"fx-contract.d.ts","sourceRoot":"","sources":["fx-contract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,qBAAqB,EACrB,UAAU,EAGX,MAAM,yBAAyB,CAAC;AAGjC,cAAM,eAAe;IACnB,OAAO,CAAC,SAAS,CAAsC;IAEvD,GAAG,CAAC,QAAQ,EAAE,UAAU,GAAG,IAAI;IAI/B,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IAI/C,MAAM,IAAI,UAAU,EAAE;IAItB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;CAWpE;AAID,wBAAgB,gBAAgB,IAAI,eAAe,CAElD;AAED,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,WAAW,EACxB,QAAQ,CAAC,EAAE,UAAU,GACpB,qBAAqB,CAmFvB;AAED,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,qBAAqB,GAC3B,UAAU,CAsBZ"} \ No newline at end of file diff --git a/packages/rules-engine/src/index.d.ts.map b/packages/rules-engine/src/index.d.ts.map new file mode 100644 index 0000000..61c459a --- /dev/null +++ b/packages/rules-engine/src/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,OAAO,CAAC;AACtB,cAAc,OAAO,CAAC;AACtB,cAAc,gBAAgB,CAAC"} \ No newline at end of file diff --git a/packages/rules-engine/src/index.js b/packages/rules-engine/src/index.js new file mode 100644 index 0000000..177c812 --- /dev/null +++ b/packages/rules-engine/src/index.js @@ -0,0 +1,13 @@ +/** + * @brazil-swift-ops/rules-engine + * + * Brazil regulatory rules engine for cross-border payments + */ +export * from './config'; +export * from './threshold'; +export * from './documentation'; +export * from './fx-contract'; +export * from './iof'; +export * from './aml'; +export * from './orchestrator'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/rules-engine/src/index.js.map b/packages/rules-engine/src/index.js.map new file mode 100644 index 0000000..bf7bdc5 --- /dev/null +++ b/packages/rules-engine/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,OAAO,CAAC;AACtB,cAAc,OAAO,CAAC;AACtB,cAAc,gBAAgB,CAAC"} \ No newline at end of file diff --git a/packages/rules-engine/src/iof.d.ts.map b/packages/rules-engine/src/iof.d.ts.map new file mode 100644 index 0000000..285f1dc --- /dev/null +++ b/packages/rules-engine/src/iof.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"iof.d.ts","sourceRoot":"","sources":["iof.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,oBAAoB,EACpB,UAAU,EACX,MAAM,yBAAyB,CAAC;AAIjC,wBAAgB,YAAY,CAAC,WAAW,EAAE,WAAW,GAAG,oBAAoB,CAuC3E;AAED,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,oBAAoB,GAChC,UAAU,CAoBZ"} \ No newline at end of file diff --git a/packages/rules-engine/src/iof.js b/packages/rules-engine/src/iof.js new file mode 100644 index 0000000..086ed4e --- /dev/null +++ b/packages/rules-engine/src/iof.js @@ -0,0 +1,55 @@ +import Decimal from 'decimal.js'; +import { getDefaultConverter } from '@brazil-swift-ops/utils'; +import { getConfig } from './config'; +export function calculateIOF(transaction) { + const config = getConfig(); + const converter = getDefaultConverter(); + const brlAmount = converter.convert(transaction.amount, transaction.currency, 'BRL'); + const iofRate = transaction.direction === 'inbound' + ? config.iof.inboundRate + : config.iof.outboundRate; + const brlDecimal = new Decimal(brlAmount); + const rateDecimal = new Decimal(iofRate); + const iofDecimal = brlDecimal.mul(rateDecimal); + const iofAmount = iofDecimal.toNumber(); + let netAmount; + if (transaction.direction === 'inbound') { + netAmount = brlAmount - iofAmount; + } + else { + netAmount = brlAmount + iofAmount; + } + return { + direction: transaction.direction, + transactionAmount: transaction.amount, + currency: transaction.currency, + brlAmount, + iofRate, + iofAmount, + netAmount, + effectiveDate: config.iof.effectiveDate, + rateVersion: config.iof.rateVersion, + }; +} +export function createIOFRuleResult(calculation) { + return { + ruleId: 'iof-calculation', + ruleName: 'IOF Tax Calculation', + passed: true, + severity: 'Info', + decision: 'Allow', + rationale: `IOF calculated: ${calculation.iofAmount.toFixed(2)} BRL (${(calculation.iofRate * 100).toFixed(2)}% rate) for ${calculation.direction} transaction. Net amount: ${calculation.netAmount.toFixed(2)} BRL.`, + details: { + direction: calculation.direction, + transactionAmount: calculation.transactionAmount, + currency: calculation.currency, + brlAmount: calculation.brlAmount, + iofRate: calculation.iofRate, + iofAmount: calculation.iofAmount, + netAmount: calculation.netAmount, + effectiveDate: calculation.effectiveDate, + rateVersion: calculation.rateVersion, + }, + }; +} +//# sourceMappingURL=iof.js.map \ No newline at end of file diff --git a/packages/rules-engine/src/iof.js.map b/packages/rules-engine/src/iof.js.map new file mode 100644 index 0000000..61f6ab4 --- /dev/null +++ b/packages/rules-engine/src/iof.js.map @@ -0,0 +1 @@ +{"version":3,"file":"iof.js","sourceRoot":"","sources":["iof.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,YAAY,CAAC;AAMjC,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,MAAM,UAAU,YAAY,CAAC,WAAwB;IACnD,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,SAAS,GAAG,mBAAmB,EAAE,CAAC;IAExC,MAAM,SAAS,GAAG,SAAS,CAAC,OAAO,CACjC,WAAW,CAAC,MAAM,EAClB,WAAW,CAAC,QAAQ,EACpB,KAAK,CACN,CAAC;IAEF,MAAM,OAAO,GACX,WAAW,CAAC,SAAS,KAAK,SAAS;QACjC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW;QACxB,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC;IAE9B,MAAM,UAAU,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC;IAC1C,MAAM,WAAW,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,MAAM,UAAU,GAAG,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAE/C,MAAM,SAAS,GAAG,UAAU,CAAC,QAAQ,EAAE,CAAC;IAExC,IAAI,SAAiB,CAAC;IACtB,IAAI,WAAW,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QACxC,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IACpC,CAAC;SAAM,CAAC;QACN,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IACpC,CAAC;IAED,OAAO;QACL,SAAS,EAAE,WAAW,CAAC,SAAS;QAChC,iBAAiB,EAAE,WAAW,CAAC,MAAM;QACrC,QAAQ,EAAE,WAAW,CAAC,QAAQ;QAC9B,SAAS;QACT,OAAO;QACP,SAAS;QACT,SAAS;QACT,aAAa,EAAE,MAAM,CAAC,GAAG,CAAC,aAAa;QACvC,WAAW,EAAE,MAAM,CAAC,GAAG,CAAC,WAAW;KACpC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,WAAiC;IAEjC,OAAO;QACL,MAAM,EAAE,iBAAiB;QACzB,QAAQ,EAAE,qBAAqB;QAC/B,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,MAAM;QAChB,QAAQ,EAAE,OAAO;QACjB,SAAS,EAAE,mBAAmB,WAAW,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,OAAO,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,WAAW,CAAC,SAAS,6BAA6B,WAAW,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO;QACrN,OAAO,EAAE;YACP,SAAS,EAAE,WAAW,CAAC,SAAS;YAChC,iBAAiB,EAAE,WAAW,CAAC,iBAAiB;YAChD,QAAQ,EAAE,WAAW,CAAC,QAAQ;YAC9B,SAAS,EAAE,WAAW,CAAC,SAAS;YAChC,OAAO,EAAE,WAAW,CAAC,OAAO;YAC5B,SAAS,EAAE,WAAW,CAAC,SAAS;YAChC,SAAS,EAAE,WAAW,CAAC,SAAS;YAChC,aAAa,EAAE,WAAW,CAAC,aAAa;YACxC,WAAW,EAAE,WAAW,CAAC,WAAW;SACrC;KACF,CAAC;AACJ,CAAC"} \ No newline at end of file diff --git a/packages/rules-engine/src/orchestrator.d.ts.map b/packages/rules-engine/src/orchestrator.d.ts.map new file mode 100644 index 0000000..c39783e --- /dev/null +++ b/packages/rules-engine/src/orchestrator.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["orchestrator.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,sBAAsB,EAGvB,MAAM,yBAAyB,CAAC;AAmBjC;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,WAAW,GACvB,sBAAsB,CAoDxB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,YAAY,EAAE,WAAW,EAAE,GAC1B,sBAAsB,EAAE,CAE1B"} \ No newline at end of file diff --git a/packages/rules-engine/src/orchestrator.js b/packages/rules-engine/src/orchestrator.js new file mode 100644 index 0000000..943a7fa --- /dev/null +++ b/packages/rules-engine/src/orchestrator.js @@ -0,0 +1,68 @@ +/** + * Rules engine orchestrator - coordinates all regulatory rule evaluations + */ +import { getConfig } from './config'; +import { evaluateThreshold, createThresholdRuleResult } from './threshold'; +import { validateDocumentation, createDocumentationRuleResult, } from './documentation'; +import { validateFXContract, createFXContractRuleResult, getContractStore, } from './fx-contract'; +import { calculateIOF, createIOFRuleResult } from './iof'; +import { performAMLCheck, createAMLRuleResult, } from './aml'; +/** + * Evaluate all Brazil regulatory rules for a transaction + */ +export function evaluateTransaction(transaction) { + const config = getConfig(); + const timestamp = new Date(); + // Run all rule checks + const thresholdCheck = evaluateThreshold(transaction); + const documentationCheck = validateDocumentation(transaction); + const fxContract = getContractStore().get(transaction.fxContractId || ''); + const fxContractCheck = validateFXContract(transaction, fxContract); + const iofCalculation = calculateIOF(transaction); + const amlCheck = performAMLCheck(transaction); + // Create rule results + const rules = [ + createThresholdRuleResult(thresholdCheck), + createDocumentationRuleResult(documentationCheck), + createFXContractRuleResult(fxContractCheck), + createIOFRuleResult(iofCalculation), + createAMLRuleResult(amlCheck), + ]; + // Determine overall decision and severity + const criticalRules = rules.filter((r) => r.severity === 'Critical' && !r.passed); + const warningRules = rules.filter((r) => r.severity === 'Warning' && !r.passed); + let overallDecision; + let overallSeverity; + if (criticalRules.length > 0) { + overallDecision = 'Hold'; + overallSeverity = 'Critical'; + } + else if (warningRules.length > 0) { + overallDecision = 'Escalate'; + overallSeverity = 'Warning'; + } + else { + overallDecision = 'Allow'; + overallSeverity = 'Info'; + } + return { + transactionId: transaction.id, + timestamp, + ruleSetVersion: config.ruleSetVersion, + overallDecision, + overallSeverity, + rules, + thresholdCheck, + documentationCheck, + fxContractCheck, + iofCalculation, + amlCheck, + }; +} +/** + * Evaluate a batch of transactions + */ +export function evaluateBatch(transactions) { + return transactions.map((txn) => evaluateTransaction(txn)); +} +//# sourceMappingURL=orchestrator.js.map \ No newline at end of file diff --git a/packages/rules-engine/src/orchestrator.js.map b/packages/rules-engine/src/orchestrator.js.map new file mode 100644 index 0000000..42e8a0e --- /dev/null +++ b/packages/rules-engine/src/orchestrator.js.map @@ -0,0 +1 @@ +{"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["orchestrator.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EACL,qBAAqB,EACrB,6BAA6B,GAC9B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,kBAAkB,EAClB,0BAA0B,EAC1B,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAC1D,OAAO,EACL,eAAe,EACf,mBAAmB,GAEpB,MAAM,OAAO,CAAC;AAEf;;GAEG;AACH,MAAM,UAAU,mBAAmB,CACjC,WAAwB;IAExB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;IAE7B,sBAAsB;IACtB,MAAM,cAAc,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;IACtD,MAAM,kBAAkB,GAAG,qBAAqB,CAAC,WAAW,CAAC,CAAC;IAC9D,MAAM,UAAU,GAAG,gBAAgB,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;IAC1E,MAAM,eAAe,GAAG,kBAAkB,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IACpE,MAAM,cAAc,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;IAE9C,sBAAsB;IACtB,MAAM,KAAK,GAAG;QACZ,yBAAyB,CAAC,cAAc,CAAC;QACzC,6BAA6B,CAAC,kBAAkB,CAAC;QACjD,0BAA0B,CAAC,eAAe,CAAC;QAC3C,mBAAmB,CAAC,cAAc,CAAC;QACnC,mBAAmB,CAAC,QAAQ,CAAC;KAC9B,CAAC;IAEF,0CAA0C;IAC1C,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAClF,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAEhF,IAAI,eAA6B,CAAC;IAClC,IAAI,eAA6B,CAAC;IAElC,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,eAAe,GAAG,MAAM,CAAC;QACzB,eAAe,GAAG,UAAU,CAAC;IAC/B,CAAC;SAAM,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,eAAe,GAAG,UAAU,CAAC;QAC7B,eAAe,GAAG,SAAS,CAAC;IAC9B,CAAC;SAAM,CAAC;QACN,eAAe,GAAG,OAAO,CAAC;QAC1B,eAAe,GAAG,MAAM,CAAC;IAC3B,CAAC;IAED,OAAO;QACL,aAAa,EAAE,WAAW,CAAC,EAAE;QAC7B,SAAS;QACT,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,eAAe;QACf,eAAe;QACf,KAAK;QACL,cAAc;QACd,kBAAkB;QAClB,eAAe;QACf,cAAc;QACd,QAAQ;KACT,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAC3B,YAA2B;IAE3B,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7D,CAAC"} \ No newline at end of file diff --git a/packages/rules-engine/src/threshold.d.ts b/packages/rules-engine/src/threshold.d.ts new file mode 100644 index 0000000..473ca91 --- /dev/null +++ b/packages/rules-engine/src/threshold.d.ts @@ -0,0 +1,4 @@ +import type { Transaction, ThresholdCheckResult, RuleResult } from '@brazil-swift-ops/types'; +export declare function evaluateThreshold(transaction: Transaction): ThresholdCheckResult; +export declare function createThresholdRuleResult(check: ThresholdCheckResult): RuleResult; +//# sourceMappingURL=threshold.d.ts.map \ No newline at end of file diff --git a/packages/rules-engine/src/threshold.d.ts.map b/packages/rules-engine/src/threshold.d.ts.map new file mode 100644 index 0000000..5325c74 --- /dev/null +++ b/packages/rules-engine/src/threshold.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"threshold.d.ts","sourceRoot":"","sources":["threshold.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,oBAAoB,EACpB,UAAU,EAGX,MAAM,yBAAyB,CAAC;AAIjC,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,WAAW,GACvB,oBAAoB,CAuBtB;AAED,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,oBAAoB,GAC1B,UAAU,CAmBZ"} \ No newline at end of file diff --git a/packages/rules-engine/src/threshold.js b/packages/rules-engine/src/threshold.js new file mode 100644 index 0000000..e036b2c --- /dev/null +++ b/packages/rules-engine/src/threshold.js @@ -0,0 +1,40 @@ +import { getDefaultConverter } from '@brazil-swift-ops/utils'; +import { getConfig } from './config'; +export function evaluateThreshold(transaction) { + const config = getConfig(); + const converter = getDefaultConverter(); + const usdEquivalent = converter.getUSDEquivalent(transaction.amount, transaction.currency); + const threshold = config.threshold.usdReportingThreshold; + const requiresReporting = usdEquivalent >= threshold; + return { + passed: true, + transactionAmount: transaction.amount, + currency: transaction.currency, + usdEquivalent, + threshold, + requiresReporting, + rationale: requiresReporting + ? `Transaction amount (${transaction.amount} ${transaction.currency} = ${usdEquivalent.toFixed(2)} USD) exceeds reporting threshold of ${threshold} USD. Reporting to Banco Central required.` + : `Transaction amount (${transaction.amount} ${transaction.currency} = ${usdEquivalent.toFixed(2)} USD) is below reporting threshold of ${threshold} USD.`, + }; +} +export function createThresholdRuleResult(check) { + const severity = check.requiresReporting ? 'Warning' : 'Info'; + const decision = check.requiresReporting ? 'Hold' : 'Allow'; + return { + ruleId: 'threshold-check', + ruleName: 'USD Equivalent Threshold Check', + passed: true, + severity, + decision, + rationale: check.rationale, + details: { + transactionAmount: check.transactionAmount, + currency: check.currency, + usdEquivalent: check.usdEquivalent, + threshold: check.threshold, + requiresReporting: check.requiresReporting, + }, + }; +} +//# sourceMappingURL=threshold.js.map \ No newline at end of file diff --git a/packages/rules-engine/src/threshold.js.map b/packages/rules-engine/src/threshold.js.map new file mode 100644 index 0000000..d5ab8ff --- /dev/null +++ b/packages/rules-engine/src/threshold.js.map @@ -0,0 +1 @@ +{"version":3,"file":"threshold.js","sourceRoot":"","sources":["threshold.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,MAAM,UAAU,iBAAiB,CAC/B,WAAwB;IAExB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,SAAS,GAAG,mBAAmB,EAAE,CAAC;IAExC,MAAM,aAAa,GAAG,SAAS,CAAC,gBAAgB,CAC9C,WAAW,CAAC,MAAM,EAClB,WAAW,CAAC,QAAQ,CACrB,CAAC;IAEF,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,qBAAqB,CAAC;IACzD,MAAM,iBAAiB,GAAG,aAAa,IAAI,SAAS,CAAC;IAErD,OAAO;QACL,MAAM,EAAE,IAAI;QACZ,iBAAiB,EAAE,WAAW,CAAC,MAAM;QACrC,QAAQ,EAAE,WAAW,CAAC,QAAQ;QAC9B,aAAa;QACb,SAAS;QACT,iBAAiB;QACjB,SAAS,EAAE,iBAAiB;YAC1B,CAAC,CAAC,uBAAuB,WAAW,CAAC,MAAM,IAAI,WAAW,CAAC,QAAQ,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,wCAAwC,SAAS,4CAA4C;YAC9L,CAAC,CAAC,uBAAuB,WAAW,CAAC,MAAM,IAAI,WAAW,CAAC,QAAQ,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,yCAAyC,SAAS,OAAO;KAC7J,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,KAA2B;IAE3B,MAAM,QAAQ,GAAiB,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;IAC5E,MAAM,QAAQ,GAAiB,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IAE1E,OAAO;QACL,MAAM,EAAE,iBAAiB;QACzB,QAAQ,EAAE,gCAAgC;QAC1C,MAAM,EAAE,IAAI;QACZ,QAAQ;QACR,QAAQ;QACR,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,OAAO,EAAE;YACP,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;YAC1C,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,aAAa,EAAE,KAAK,CAAC,aAAa;YAClC,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;SAC3C;KACF,CAAC;AACJ,CAAC"} \ No newline at end of file diff --git a/packages/rules-engine/src/threshold.ts b/packages/rules-engine/src/threshold.ts new file mode 100644 index 0000000..2a9ea8b --- /dev/null +++ b/packages/rules-engine/src/threshold.ts @@ -0,0 +1,59 @@ +import type { + Transaction, + ThresholdCheckResult, + RuleResult, + RuleSeverity, + RuleDecision, +} from '@brazil-swift-ops/types'; +import { getDefaultConverter } from '@brazil-swift-ops/utils'; +import { getConfig } from './config'; + +export function evaluateThreshold( + transaction: Transaction +): ThresholdCheckResult { + const config = getConfig(); + const converter = getDefaultConverter(); + + const usdEquivalent = converter.getUSDEquivalent( + transaction.amount, + transaction.currency + ); + + const threshold = config.threshold.usdReportingThreshold; + const requiresReporting = usdEquivalent >= threshold; + + return { + passed: true, + transactionAmount: transaction.amount, + currency: transaction.currency, + usdEquivalent, + threshold, + requiresReporting, + rationale: requiresReporting + ? `Transaction amount (${transaction.amount} ${transaction.currency} = ${usdEquivalent.toFixed(2)} USD) exceeds reporting threshold of ${threshold} USD. Reporting to Banco Central required.` + : `Transaction amount (${transaction.amount} ${transaction.currency} = ${usdEquivalent.toFixed(2)} USD) is below reporting threshold of ${threshold} USD.`, + }; +} + +export function createThresholdRuleResult( + check: ThresholdCheckResult +): RuleResult { + const severity: RuleSeverity = check.requiresReporting ? 'Warning' : 'Info'; + const decision: RuleDecision = check.requiresReporting ? 'Hold' : 'Allow'; + + return { + ruleId: 'threshold-check', + ruleName: 'USD Equivalent Threshold Check', + passed: true, + severity, + decision, + rationale: check.rationale, + details: { + transactionAmount: check.transactionAmount, + currency: check.currency, + usdEquivalent: check.usdEquivalent, + threshold: check.threshold, + requiresReporting: check.requiresReporting, + }, + }; +} diff --git a/packages/rules-engine/tsconfig.json b/packages/rules-engine/tsconfig.json new file mode 100644 index 0000000..5c8037b --- /dev/null +++ b/packages/rules-engine/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "rootDir": "./src", + "composite": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"], + "references": [ + { + "path": "../types" + }, + { + "path": "../utils" + } + ] +} diff --git a/packages/treasury/src/accounts.d.ts.map b/packages/treasury/src/accounts.d.ts.map new file mode 100644 index 0000000..f6e6398 --- /dev/null +++ b/packages/treasury/src/accounts.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"accounts.d.ts","sourceRoot":"","sources":["accounts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAE1F,cAAM,YAAY;IAChB,OAAO,CAAC,QAAQ,CAAmC;IAEnD,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAI3B,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAIpC,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,EAAE;IAOjD,MAAM,IAAI,OAAO,EAAE;IAInB,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI;IAQnD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;CAGzB;AAID,wBAAgB,eAAe,IAAI,YAAY,CAE9C;AAED,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,CAa5G;AAED,wBAAgB,sBAAsB,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,gBAAgB,CAcvI"} \ No newline at end of file diff --git a/packages/treasury/src/index.d.ts.map b/packages/treasury/src/index.d.ts.map new file mode 100644 index 0000000..87c0039 --- /dev/null +++ b/packages/treasury/src/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC"} \ No newline at end of file diff --git a/packages/treasury/src/posting.d.ts.map b/packages/treasury/src/posting.d.ts.map new file mode 100644 index 0000000..3f704f0 --- /dev/null +++ b/packages/treasury/src/posting.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"posting.d.ts","sourceRoot":"","sources":["posting.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAIjG,cAAM,YAAY;IAChB,OAAO,CAAC,QAAQ,CAAwB;IAExC,GAAG,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAIlC,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,EAAE;IAIjD,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,cAAc,EAAE;IAIzD,MAAM,IAAI,cAAc,EAAE;CAG3B;AAID,wBAAgB,eAAe,IAAI,YAAY,CAE9C;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,cAAc,CAmCnI;AAED,wBAAgB,8BAA8B,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,GAAG,cAAc,EAAE,CAoB9G"} \ No newline at end of file diff --git a/packages/treasury/src/reporting.d.ts.map b/packages/treasury/src/reporting.d.ts.map new file mode 100644 index 0000000..ca9b340 --- /dev/null +++ b/packages/treasury/src/reporting.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"reporting.d.ts","sourceRoot":"","sources":["reporting.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EAEhB,MAAM,yBAAyB,CAAC;AAIjC,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,IAAI,EACjB,SAAS,EAAE,IAAI,GACd,eAAe,CA2CjB"} \ No newline at end of file diff --git a/packages/treasury/src/transfers.d.ts.map b/packages/treasury/src/transfers.d.ts.map new file mode 100644 index 0000000..01d7211 --- /dev/null +++ b/packages/treasury/src/transfers.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"transfers.d.ts","sourceRoot":"","sources":["transfers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EAElB,MAAM,yBAAyB,CAAC;AAIjC,cAAM,aAAa;IACjB,OAAO,CAAC,SAAS,CAA2B;IAE5C,GAAG,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI;IAItC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;IAI9C,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,EAAE;IAMpD,MAAM,IAAI,iBAAiB,EAAE;CAG9B;AAID,wBAAgB,gBAAgB,IAAI,aAAa,CAEhD;AAED,wBAAgB,wBAAwB,CACtC,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,GACnB,iBAAiB,CAyDnB"} \ No newline at end of file diff --git a/packages/types/src/index.d.ts.map b/packages/types/src/index.d.ts.map new file mode 100644 index 0000000..0f578f1 --- /dev/null +++ b/packages/types/src/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC"} \ No newline at end of file diff --git a/packages/types/src/index.js b/packages/types/src/index.js new file mode 100644 index 0000000..952e399 --- /dev/null +++ b/packages/types/src/index.js @@ -0,0 +1,14 @@ +/** + * @brazil-swift-ops/types + * + * Shared TypeScript types and interfaces for the Brazil SWIFT Operations Platform + */ +export * from './transaction'; +export * from './iso20022'; +export * from './regulatory'; +export * from './treasury'; +export * from './audit'; +export * from './risk'; +export * from './fx-contract'; +export * from './eo-uplift'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/types/src/index.js.map b/packages/types/src/index.js.map new file mode 100644 index 0000000..e21306c --- /dev/null +++ b/packages/types/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC"} \ No newline at end of file diff --git a/packages/types/src/regulatory.d.ts b/packages/types/src/regulatory.d.ts new file mode 100644 index 0000000..c0bdba2 --- /dev/null +++ b/packages/types/src/regulatory.d.ts @@ -0,0 +1,96 @@ +/** + * Brazil regulatory rule evaluation types + */ +export type RuleSeverity = 'Info' | 'Warning' | 'Critical'; +export type RuleDecision = 'Allow' | 'Hold' | 'Escalate'; +export interface RuleResult { + ruleId: string; + ruleName: string; + passed: boolean; + severity: RuleSeverity; + decision: RuleDecision; + rationale: string; + details?: Record; +} +export interface BrazilRegulatoryResult { + transactionId: string; + timestamp: Date; + ruleSetVersion: string; + overallDecision: RuleDecision; + overallSeverity: RuleSeverity; + rules: RuleResult[]; + thresholdCheck?: ThresholdCheckResult; + documentationCheck?: DocumentationCheckResult; + fxContractCheck?: FXContractCheckResult; + iofCalculation?: IOFCalculationResult; + amlCheck?: AMLCheckResult; +} +export interface ThresholdCheckResult { + passed: boolean; + transactionAmount: number; + currency: string; + usdEquivalent: number; + threshold: number; + requiresReporting: boolean; + rationale: string; +} +export interface DocumentationCheckResult { + passed: boolean; + hasOrderingCustomerName: boolean; + hasOrderingCustomerAddress: boolean; + hasOrderingCustomerTaxId: boolean; + hasBeneficiaryName: boolean; + hasBeneficiaryAccount: boolean; + hasBeneficiaryTaxId: boolean; + hasPurposeOfPayment: boolean; + missingFields: string[]; + rationale: string; +} +export interface FXContractCheckResult { + passed: boolean; + fxContractId?: string; + contractExists: boolean; + contractActive?: boolean; + contractType?: 'inbound' | 'outbound'; + contractAmount: number; + contractRemainingAmount: number; + transactionAmount: number; + amountWithinLimit: boolean; + rationale: string; +} +export interface IOFCalculationResult { + direction: 'inbound' | 'outbound'; + transactionAmount: number; + currency: string; + brlAmount: number; + iofRate: number; + iofAmount: number; + netAmount: number; + effectiveDate: Date; + rateVersion: string; +} +export interface AMLCheckResult { + passed: boolean; + singleTransactionCheck: SingleTransactionAMLResult; + structuringCheck?: StructuringCheckResult; + overallRiskLevel: 'Low' | 'Medium' | 'High'; + rationale: string; +} +export interface SingleTransactionAMLResult { + passed: boolean; + transactionAmount: number; + usdEquivalent: number; + threshold: number; + requiresEnhancedReview: boolean; + riskLevel: 'Low' | 'Medium' | 'High'; +} +export interface StructuringCheckResult { + detected: boolean; + windowDays: number; + transactionCount: number; + totalAmount: number; + totalUsdEquivalent: number; + individualAmounts: number[]; + rationale: string; +} +//# sourceMappingURL=regulatory.d.ts.map \ No newline at end of file diff --git a/packages/types/src/regulatory.d.ts.map b/packages/types/src/regulatory.d.ts.map new file mode 100644 index 0000000..4995ad6 --- /dev/null +++ b/packages/types/src/regulatory.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"regulatory.d.ts","sourceRoot":"","sources":["regulatory.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/types/src/regulatory.js b/packages/types/src/regulatory.js new file mode 100644 index 0000000..9ea7c7e --- /dev/null +++ b/packages/types/src/regulatory.js @@ -0,0 +1,5 @@ +/** + * Brazil regulatory rule evaluation types + */ +export {}; +//# sourceMappingURL=regulatory.js.map \ No newline at end of file diff --git a/packages/types/src/regulatory.js.map b/packages/types/src/regulatory.js.map new file mode 100644 index 0000000..12117b7 --- /dev/null +++ b/packages/types/src/regulatory.js.map @@ -0,0 +1 @@ +{"version":3,"file":"regulatory.js","sourceRoot":"","sources":["regulatory.ts"],"names":[],"mappings":"AAAA;;GAEG"} \ No newline at end of file diff --git a/packages/types/src/regulatory.ts b/packages/types/src/regulatory.ts index dfc9b8c..fabe3cc 100644 --- a/packages/types/src/regulatory.ts +++ b/packages/types/src/regulatory.ts @@ -56,6 +56,7 @@ export interface FXContractCheckResult { passed: boolean; fxContractId?: string; contractExists: boolean; + contractActive?: boolean; contractType?: 'inbound' | 'outbound'; contractAmount: number; contractRemainingAmount: number; diff --git a/packages/utils/src/eo-uplift.d.ts.map b/packages/utils/src/eo-uplift.d.ts.map new file mode 100644 index 0000000..d8416d9 --- /dev/null +++ b/packages/utils/src/eo-uplift.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"eo-uplift.d.ts","sourceRoot":"","sources":["eo-uplift.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE5F,eAAO,MAAM,sBAAsB,MAAO,CAAC;AAE3C;;GAEG;AACH,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,UAAU,GAAE,MAA+B,EAC3C,aAAa,CAAC,EAAE,MAAM,GACrB,mBAAmB,CA4BrB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,gBAAgB,EAAE,MAAM,EACxB,UAAU,GAAE,MAA+B,EAC3C,aAAa,CAAC,EAAE,MAAM,GACrB,aAAa,CA4Bf;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,UAAU,GAAE,MAA+B,GAC1C,QAAQ,CAaV;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EAAE,EACjB,UAAU,GAAE,MAA+B,GAC1C;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,EAAE,CAS1E"} \ No newline at end of file diff --git a/packages/utils/src/index.d.ts.map b/packages/utils/src/index.d.ts.map new file mode 100644 index 0000000..6e0f480 --- /dev/null +++ b/packages/utils/src/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC"} \ No newline at end of file