cboddeposit-60-accrual.spp
cboddeposit/accrual/cboddeposit-60-accrual.spp
Download original file · Bank deposit source contents
1domain cboddeposit;23Role DepositAccrualPlan {4int endDate;5int normalDays;6int overdraftDays;7BigDecimal(25, 2) normalIncrement;8BigDecimal(25, 2) agreementIncrement;9int principalDays;10int interestDays;11BigDecimal(25, 2) overdraftIncrement;12BigDecimal(25, 2) overdraftInterestIncrement;13}1415atomic check checkAccrualPolicy(DepositAccount, DepositInterestPolicy) {16require(17DepositInterestPolicy.normalUnit > 0 && DepositInterestPolicy.overdraftUnit > 0,18"INVALID_ACCRUAL_UNIT"19);20require(DepositAccount.overdraftPrincipal >= 0, "E1155");21}2223atomic calculate prepareAccrualDates(DepositAccrualState, BusinessDay, BankDate start, BankDate end) {24start.encoded = DepositAccrualState.lastProductDate;25end.encoded = BusinessDay.date;26}2728atomic calculate prepareNormalAccrualPeriod(DepositAccount, DepositInterestPolicy, InterestPeriod) {29InterestPeriod.amount = 0;30if (DepositInterestPolicy.normalEnabled) {31InterestPeriod.amount = DepositAccount.interestBase;32}33InterestPeriod.unit = DepositInterestPolicy.normalUnit;34}3536// CSAPRD4 uses ACT days for overdraft independently of the normal interest calendar.3738atomic calculate calculateAccrual(39DepositAccount,40DepositInterestPolicy,41InterestPeriod,42InterestProduct,43BankDate start,44BankDate end,45DepositAccrualPlan46) {47DepositAccrualPlan.endDate = end.encoded;48DepositAccrualPlan.normalDays = InterestPeriod.days;49DepositAccrualPlan.overdraftDays = end.epochDay - start.epochDay;50DepositAccrualPlan.normalIncrement = InterestProduct.product;51DepositAccrualPlan.overdraftIncrement = roundDown(52DepositAccount.overdraftPrincipal / DepositInterestPolicy.overdraftUnit,53054) * DepositInterestPolicy.overdraftUnit * DepositAccrualPlan.overdraftDays;55DepositAccrualPlan.overdraftInterestIncrement = roundDown(56(DepositAccount.overdraftInterest57+ DepositAccount.collectionInterest)58/ DepositInterestPolicy.overdraftUnit,59060) * DepositInterestPolicy.overdraftUnit * DepositAccrualPlan.overdraftDays;61}6263atomic calculate accumulateAccrual(DepositAccrualState, DepositAccrualPlan) {64DepositAccrualState.lastProductDate = DepositAccrualPlan.endDate;65DepositAccrualState.normalProduct += DepositAccrualPlan.normalIncrement;66DepositAccrualState.overdraftProduct += DepositAccrualPlan.overdraftIncrement;67DepositAccrualState.overdraftInterestProduct += DepositAccrualPlan.overdraftInterestIncrement;68DepositAccrualState.actualProduct = DepositAccrualState.normalProduct69- DepositAccrualState.overdraftProduct;70DepositAccrualState.overdraftDays += DepositAccrualPlan.principalDays;71DepositAccrualState.overdraftInterestDays += DepositAccrualPlan.interestDays;72DepositAccrualState.agreementProduct += DepositAccrualPlan.agreementIncrement;73}7475atomic check checkAccrualDates(76DepositAccrualState,77BusinessDay,78InterestCalendar,79AgreementTerm,80AgreementBand[]81) {82require(83isGregorianDate(DepositAccrualState.lastProductDate) && isGregorianDate(BusinessDay.date),84"EE374"85);86require(DepositAccrualState.lastProductDate <= BusinessDay.date, "E1175");87require(88InterestCalendar.convention == "ACT"89|| InterestCalendar.convention == "360365"90|| InterestCalendar.convention == "360360",91"EEC28"92);93require(AgreementTerm.effectiveDate == 0 || isGregorianDate(AgreementTerm.effectiveDate), "EE374");94require(AgreementTerm.cancelDate == 0 || isGregorianDate(AgreementTerm.cancelDate), "EE374");95int expected = 5;96for (AgreementBand band : AgreementBand[]) {97require(band.slot == expected && band.threshold >= 0, "INVALID_AGREEMENT_BANDS");98expected--;99}100require(expected == 0, "INVALID_AGREEMENT_BANDS");101}102103// All local mathematical intermediate participants are created in a calculation atom.104105atomic calculate calculateDepositAccrual(106DepositAccount,107BusinessDay,108DepositAccrualState,109DepositInterestPolicy,110InterestCalendar,111AgreementTerm,112AgreementPolicy,113AgreementBand[],114DepositAccrualPlan115) {116BankDate start = new BankDate();117BankDate end = new BankDate();118BankDate clippedStart = new BankDate();119BankDate clippedEnd = new BankDate();120InterestPeriod normal = new InterestPeriod();121InterestPeriod overlap = new InterestPeriod();122InterestProduct normalProduct = new InterestProduct();123AgreementProduct products = new AgreementProduct();124prepareAccrualDates(DepositAccrualState, BusinessDay, start, end);125decodeBankDate(start);126decodeBankDate(end);127prepareNormalAccrualPeriod(DepositAccount, DepositInterestPolicy, normal);128calculateBankDays(start, end, InterestCalendar, normal);129AgreementPolicy.enabled = DepositInterestPolicy.normalEnabled && AgreementPolicy.enabled;130prepareAgreementWindow(131start,132end,133AgreementTerm,134clippedStart,135clippedEnd,136normal,137overlap,138AgreementPolicy139);140decodeBankDate(clippedStart);141decodeBankDate(clippedEnd);142calculateBankDays(clippedStart, clippedEnd, InterestCalendar, overlap);143calculateAgreementProduct(normal, overlap, AgreementPolicy, AgreementBand[], products);144calculateInterestProduct(normal, normalProduct);145calculateAccrual(146DepositAccount,147DepositInterestPolicy,148normal,149normalProduct,150start,151end,152DepositAccrualPlan153);154DepositAccrualPlan.normalIncrement = products.normalProduct;155DepositAccrualPlan.agreementIncrement = products.bandProduct;156DepositAccrualPlan.principalDays = 0;157DepositAccrualPlan.interestDays = 0;158if (DepositAccount.overdraftPrincipal > 0) {159DepositAccrualPlan.principalDays = DepositAccrualPlan.overdraftDays;160}161if (DepositAccount.overdraftInterest > 0) {162DepositAccrualPlan.interestDays = DepositAccrualPlan.overdraftDays;163}164}