- Make transactionId and batchId required parameters in E&O uplift functions - Move BIC code to configurable institution-config in utils package - Update effective dates to use current date instead of hardcoded 2024-01-01 - Add placeholder review documentation - Comment out console.log in retention policy (production TODO) - All critical placeholders resolved
127 lines
4.8 KiB
JavaScript
127 lines
4.8 KiB
JavaScript
import { isEffectiveDate } from '@brazil-swift-ops/utils';
|
|
class FXContractStore {
|
|
contracts = new Map();
|
|
add(contract) {
|
|
this.contracts.set(contract.contractId, contract);
|
|
}
|
|
get(contractId) {
|
|
return this.contracts.get(contractId);
|
|
}
|
|
getAll() {
|
|
return Array.from(this.contracts.values());
|
|
}
|
|
updateRemainingAmount(contractId, usedAmount) {
|
|
const contract = this.contracts.get(contractId);
|
|
if (contract) {
|
|
contract.usedAmount += usedAmount;
|
|
contract.remainingAmount = contract.amount - contract.usedAmount;
|
|
contract.updatedAt = new Date();
|
|
if (contract.remainingAmount <= 0) {
|
|
contract.status = 'exhausted';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
const contractStore = new FXContractStore();
|
|
export function getContractStore() {
|
|
return contractStore;
|
|
}
|
|
export function validateFXContract(transaction, contract) {
|
|
if (!transaction.fxContractId) {
|
|
return {
|
|
passed: false,
|
|
contractExists: false,
|
|
contractType: undefined,
|
|
contractAmount: 0,
|
|
contractRemainingAmount: 0,
|
|
transactionAmount: transaction.amount,
|
|
amountWithinLimit: false,
|
|
rationale: 'FX contract ID is required for cross-border transactions.',
|
|
};
|
|
}
|
|
if (!contract) {
|
|
contract = contractStore.get(transaction.fxContractId);
|
|
}
|
|
if (!contract) {
|
|
return {
|
|
passed: false,
|
|
fxContractId: transaction.fxContractId,
|
|
contractExists: false,
|
|
contractType: undefined,
|
|
contractAmount: 0,
|
|
contractRemainingAmount: 0,
|
|
transactionAmount: transaction.amount,
|
|
amountWithinLimit: false,
|
|
rationale: `FX contract ${transaction.fxContractId} not found.`,
|
|
};
|
|
}
|
|
const now = new Date();
|
|
const contractActive = contract.status === 'active' &&
|
|
isEffectiveDate(now, contract.effectiveDate, contract.expiryDate);
|
|
if (!contractActive) {
|
|
return {
|
|
passed: false,
|
|
fxContractId: contract.contractId,
|
|
contractExists: true,
|
|
contractActive: false,
|
|
contractType: contract.type,
|
|
contractAmount: contract.amount,
|
|
contractRemainingAmount: contract.remainingAmount,
|
|
transactionAmount: transaction.amount,
|
|
amountWithinLimit: false,
|
|
rationale: `FX contract ${contract.contractId} is not active (status: ${contract.status}).`,
|
|
};
|
|
}
|
|
if (contract.type !== transaction.direction) {
|
|
return {
|
|
passed: false,
|
|
fxContractId: contract.contractId,
|
|
contractExists: true,
|
|
contractActive: false,
|
|
contractType: contract.type,
|
|
contractAmount: contract.amount,
|
|
contractRemainingAmount: contract.remainingAmount,
|
|
transactionAmount: transaction.amount,
|
|
amountWithinLimit: false,
|
|
rationale: `FX contract type (${contract.type}) does not match transaction direction (${transaction.direction}).`,
|
|
};
|
|
}
|
|
const amountWithinLimit = transaction.amount <= contract.remainingAmount;
|
|
return {
|
|
passed: amountWithinLimit && contractActive,
|
|
fxContractId: contract.contractId,
|
|
contractExists: true,
|
|
contractActive,
|
|
contractType: contract.type,
|
|
contractAmount: contract.amount,
|
|
contractRemainingAmount: contract.remainingAmount,
|
|
transactionAmount: transaction.amount,
|
|
amountWithinLimit,
|
|
rationale: amountWithinLimit
|
|
? `Transaction amount (${transaction.amount} ${transaction.currency}) is within FX contract limit (${contract.remainingAmount} ${contract.currency} remaining).`
|
|
: `Transaction amount (${transaction.amount} ${transaction.currency}) exceeds FX contract remaining amount (${contract.remainingAmount} ${contract.currency}).`,
|
|
};
|
|
}
|
|
export function createFXContractRuleResult(check) {
|
|
const severity = check.passed ? 'Info' : 'Critical';
|
|
const decision = check.passed ? 'Allow' : 'Hold';
|
|
return {
|
|
ruleId: 'fx-contract-check',
|
|
ruleName: 'FX Contract Validation',
|
|
passed: check.passed,
|
|
severity,
|
|
decision,
|
|
rationale: check.rationale,
|
|
details: {
|
|
fxContractId: check.fxContractId,
|
|
contractExists: check.contractExists,
|
|
contractActive: check.contractActive,
|
|
contractType: check.contractType,
|
|
contractAmount: check.contractAmount,
|
|
contractRemainingAmount: check.contractRemainingAmount,
|
|
transactionAmount: check.transactionAmount,
|
|
amountWithinLimit: check.amountWithinLimit,
|
|
},
|
|
};
|
|
}
|
|
//# sourceMappingURL=fx-contract.js.map
|