List of usage examples for org.joda.time LocalDate isAfter
public boolean isAfter(ReadablePartial partial)
From source file:com.gst.portfolio.loanaccount.service.LoanArrearsAgingServiceImpl.java
License:Apache License
private void createInsertStatements(List<String> insertStatement, Map<Long, List<LoanSchedulePeriodData>> scheduleDate, boolean isInsertStatement) { for (Map.Entry<Long, List<LoanSchedulePeriodData>> entry : scheduleDate.entrySet()) { final Long loanId = entry.getKey(); BigDecimal principalOverdue = BigDecimal.ZERO; BigDecimal interestOverdue = BigDecimal.ZERO; BigDecimal feeOverdue = BigDecimal.ZERO; BigDecimal penaltyOverdue = BigDecimal.ZERO; LocalDate overDueSince = LocalDate.now(); for (LoanSchedulePeriodData loanSchedulePeriodData : entry.getValue()) { if (!loanSchedulePeriodData.getComplete()) { principalOverdue = principalOverdue.add( loanSchedulePeriodData.principalDue().subtract(loanSchedulePeriodData.principalPaid())); interestOverdue = interestOverdue.add( loanSchedulePeriodData.interestDue().subtract(loanSchedulePeriodData.interestPaid())); feeOverdue = feeOverdue.add(loanSchedulePeriodData.feeChargesDue() .subtract(loanSchedulePeriodData.feeChargesPaid())); penaltyOverdue = penaltyOverdue.add(loanSchedulePeriodData.penaltyChargesDue() .subtract(loanSchedulePeriodData.penaltyChargesPaid())); if (overDueSince.isAfter(loanSchedulePeriodData.periodDueDate()) && loanSchedulePeriodData .principalDue().subtract(loanSchedulePeriodData.principalPaid()) .compareTo(BigDecimal.ZERO) == 1) { overDueSince = loanSchedulePeriodData.periodDueDate(); }/*from ww w. j a va 2 s.c om*/ } } if (principalOverdue.compareTo(BigDecimal.ZERO) == 1) { String sqlStatement = null; if (isInsertStatement) { sqlStatement = constructInsertStatement(loanId, principalOverdue, interestOverdue, feeOverdue, penaltyOverdue, overDueSince); } else { sqlStatement = constructUpdateStatement(loanId, principalOverdue, interestOverdue, feeOverdue, penaltyOverdue, overDueSince); } insertStatement.add(sqlStatement); } } }
From source file:com.gst.portfolio.loanaccount.service.LoanWritePlatformServiceJpaRepositoryImpl.java
License:Apache License
@Transactional @Override//from w w w . j a v a2s . co m public CommandProcessingResult addLoanCharge(final Long loanId, final JsonCommand command) { this.loanEventApiJsonValidator.validateAddLoanCharge(command.json()); final Loan loan = this.loanAssembler.assembleFrom(loanId); checkClientOrGroupActive(loan); List<LoanDisbursementDetails> loanDisburseDetails = loan.getDisbursementDetails(); final Long chargeDefinitionId = command.longValueOfParameterNamed("chargeId"); final Charge chargeDefinition = this.chargeRepository.findOneWithNotFoundDetection(chargeDefinitionId); if (loan.isDisbursed() && chargeDefinition.isDisbursementCharge()) { validateAddingNewChargeAllowed(loanDisburseDetails); // validates // whether any // pending // disbursements // are // available to // apply this // charge } final List<Long> existingTransactionIds = new ArrayList<>(loan.findExistingTransactionIds()); final List<Long> existingReversedTransactionIds = new ArrayList<>( loan.findExistingReversedTransactionIds()); boolean isAppliedOnBackDate = false; LoanCharge loanCharge = null; LocalDate recalculateFrom = loan.fetchInterestRecalculateFromDate(); if (chargeDefinition.isPercentageOfDisbursementAmount()) { LoanTrancheDisbursementCharge loanTrancheDisbursementCharge = null; for (LoanDisbursementDetails disbursementDetail : loanDisburseDetails) { if (disbursementDetail.actualDisbursementDate() == null) { loanCharge = LoanCharge.createNewWithoutLoan(chargeDefinition, disbursementDetail.principal(), null, null, null, disbursementDetail.expectedDisbursementDateAsLocalDate(), null, null); loanTrancheDisbursementCharge = new LoanTrancheDisbursementCharge(loanCharge, disbursementDetail); loanCharge.updateLoanTrancheDisbursementCharge(loanTrancheDisbursementCharge); this.businessEventNotifierService.notifyBusinessEventToBeExecuted( BUSINESS_EVENTS.LOAN_ADD_CHARGE, constructEntityMap(BUSINESS_ENTITY.LOAN_CHARGE, loanCharge)); validateAddLoanCharge(loan, chargeDefinition, loanCharge); addCharge(loan, chargeDefinition, loanCharge); isAppliedOnBackDate = true; if (recalculateFrom.isAfter(disbursementDetail.expectedDisbursementDateAsLocalDate())) { recalculateFrom = disbursementDetail.expectedDisbursementDateAsLocalDate(); } } } loan.addTrancheLoanCharge(chargeDefinition); } else { loanCharge = LoanCharge.createNewFromJson(loan, chargeDefinition, command); this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.LOAN_ADD_CHARGE, constructEntityMap(BUSINESS_ENTITY.LOAN_CHARGE, loanCharge)); validateAddLoanCharge(loan, chargeDefinition, loanCharge); isAppliedOnBackDate = addCharge(loan, chargeDefinition, loanCharge); if (loanCharge.getDueLocalDate() == null || recalculateFrom.isAfter(loanCharge.getDueLocalDate())) { isAppliedOnBackDate = true; recalculateFrom = loanCharge.getDueLocalDate(); } } boolean reprocessRequired = true; if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { if (isAppliedOnBackDate && loan.isFeeCompoundingEnabledForInterestRecalculation()) { runScheduleRecalculation(loan, recalculateFrom); reprocessRequired = false; } updateOriginalSchedule(loan); } if (reprocessRequired) { ChangedTransactionDetail changedTransactionDetail = loan.reprocessTransactions(); if (changedTransactionDetail != null) { for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail .getNewTransactionMappings().entrySet()) { this.loanTransactionRepository.save(mapEntry.getValue()); // update loan with references to the newly created // transactions loan.addLoanTransaction(mapEntry.getValue()); this.accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue()); } } saveLoanWithDataIntegrityViolationChecks(loan); } postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds); if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled() && isAppliedOnBackDate && loan.isFeeCompoundingEnabledForInterestRecalculation()) { this.loanAccountDomainService.recalculateAccruals(loan); } this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_ADD_CHARGE, constructEntityMap(BUSINESS_ENTITY.LOAN_CHARGE, loanCharge)); return new CommandProcessingResultBuilder() // .withCommandId(command.commandId()) // .withEntityId(loanCharge.getId()) // .withOfficeId(loan.getOfficeId()) // .withClientId(loan.getClientId()) // .withGroupId(loan.getGroupId()) // .withLoanId(loanId) // .build(); }
From source file:com.gst.portfolio.loanaccount.service.LoanWritePlatformServiceJpaRepositoryImpl.java
License:Apache License
@Override @Transactional//from w w w. ja va2 s. com public void applyOverdueChargesForLoan(final Long loanId, Collection<OverdueLoanScheduleData> overdueLoanScheduleDatas) { Loan loan = null; final List<Long> existingTransactionIds = new ArrayList<>(); final List<Long> existingReversedTransactionIds = new ArrayList<>(); boolean runInterestRecalculation = false; LocalDate recalculateFrom = DateUtils.getLocalDateOfTenant(); LocalDate lastChargeDate = null; for (final OverdueLoanScheduleData overdueInstallment : overdueLoanScheduleDatas) { final JsonElement parsedCommand = this.fromApiJsonHelper.parse(overdueInstallment.toString()); final JsonCommand command = JsonCommand.from(overdueInstallment.toString(), parsedCommand, this.fromApiJsonHelper, null, null, null, null, null, loanId, null, null, null, null); LoanOverdueDTO overdueDTO = applyChargeToOverdueLoanInstallment(loanId, overdueInstallment.getChargeId(), overdueInstallment.getPeriodNumber(), command, loan, existingTransactionIds, existingReversedTransactionIds); loan = overdueDTO.getLoan(); runInterestRecalculation = runInterestRecalculation || overdueDTO.isRunInterestRecalculation(); if (recalculateFrom.isAfter(overdueDTO.getRecalculateFrom())) { recalculateFrom = overdueDTO.getRecalculateFrom(); } if (lastChargeDate == null || overdueDTO.getLastChargeAppliedDate().isAfter(lastChargeDate)) { lastChargeDate = overdueDTO.getLastChargeAppliedDate(); } } if (loan != null) { boolean reprocessRequired = true; LocalDate recalculatedTill = loan.fetchInterestRecalculateFromDate(); if (recalculateFrom.isAfter(recalculatedTill)) { recalculateFrom = recalculatedTill; } if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) { if (runInterestRecalculation && loan.isFeeCompoundingEnabledForInterestRecalculation()) { runScheduleRecalculation(loan, recalculateFrom); reprocessRequired = false; } updateOriginalSchedule(loan); } if (reprocessRequired) { addInstallmentIfPenaltyAppliedAfterLastDueDate(loan, lastChargeDate); ChangedTransactionDetail changedTransactionDetail = loan.reprocessTransactions(); if (changedTransactionDetail != null) { for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail .getNewTransactionMappings().entrySet()) { this.loanTransactionRepository.save(mapEntry.getValue()); // update loan with references to the newly created // transactions loan.addLoanTransaction(mapEntry.getValue()); this.accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue()); } } saveLoanWithDataIntegrityViolationChecks(loan); } postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds); if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled() && runInterestRecalculation && loan.isFeeCompoundingEnabledForInterestRecalculation()) { this.loanAccountDomainService.recalculateAccruals(loan); } this.businessEventNotifierService.notifyBusinessEventWasExecuted( BUSINESS_EVENTS.LOAN_APPLY_OVERDUE_CHARGE, constructEntityMap(BUSINESS_ENTITY.LOAN, loan)); } }
From source file:com.gst.portfolio.loanaccount.service.LoanWritePlatformServiceJpaRepositoryImpl.java
License:Apache License
private void addInstallmentIfPenaltyAppliedAfterLastDueDate(Loan loan, LocalDate lastChargeDate) { if (lastChargeDate != null) { List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments(); LoanRepaymentScheduleInstallment lastInstallment = loan .fetchRepaymentScheduleInstallment(installments.size()); if (lastChargeDate.isAfter(lastInstallment.getDueDate())) { if (lastInstallment.isRecalculatedInterestComponent()) { installments.remove(lastInstallment); lastInstallment = loan.fetchRepaymentScheduleInstallment(installments.size()); }//from ww w. j a v a2 s .c o m boolean recalculatedInterestComponent = true; BigDecimal principal = BigDecimal.ZERO; BigDecimal interest = BigDecimal.ZERO; BigDecimal feeCharges = BigDecimal.ZERO; BigDecimal penaltyCharges = BigDecimal.ONE; final Set<LoanInterestRecalcualtionAdditionalDetails> compoundingDetails = null; LoanRepaymentScheduleInstallment newEntry = new LoanRepaymentScheduleInstallment(loan, installments.size() + 1, lastInstallment.getDueDate(), lastChargeDate, principal, interest, feeCharges, penaltyCharges, recalculatedInterestComponent, compoundingDetails); installments.add(newEntry); loan.addLoanRepaymentScheduleInstallment(newEntry); } } }
From source file:com.gst.portfolio.savings.domain.DepositAccountTermAndPreClosure.java
License:Apache License
public boolean isAfterExpectedFirstDepositDate(final LocalDate compareDate) { boolean isAfterExpectedFirstDepositDate = false; if (this.expectedFirstDepositOnDate != null) { isAfterExpectedFirstDepositDate = compareDate.isAfter(getExpectedFirstDepositOnDate()); }//from w w w . j a v a 2 s. c o m return isAfterExpectedFirstDepositDate; }
From source file:com.gst.portfolio.savings.domain.FixedDepositAccount.java
License:Apache License
public void prematureClosure(final AppUser currentUser, final JsonCommand command, final LocalDate tenantsTodayDate, final Map<String, Object> actualChanges) { final List<ApiParameterError> dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource(FIXED_DEPOSIT_ACCOUNT_RESOURCE_NAME + DepositsApiConstants.preMatureCloseAction); final SavingsAccountStatusType currentStatus = SavingsAccountStatusType.fromInt(this.status); if (!SavingsAccountStatusType.ACTIVE.hasStateOf(currentStatus)) { baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("not.in.active.state"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }/*from w ww. j a v a2 s.c om*/ } final Locale locale = command.extractLocale(); final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale); final LocalDate closedDate = command .localDateValueOfParameterNamed(SavingsApiConstants.closedOnDateParamName); if (closedDate.isBefore(getActivationLocalDate())) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.after.activation.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } if (isAccountLocked(closedDate)) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.after.lockin.period"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } if (closedDate.isAfter(maturityDate())) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.before.maturity.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } if (closedDate.isAfter(tenantsTodayDate)) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("cannot.be.a.future.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } final List<SavingsAccountTransaction> savingsAccountTransactions = retreiveListOfTransactions(); if (savingsAccountTransactions.size() > 0) { final SavingsAccountTransaction accountTransaction = savingsAccountTransactions .get(savingsAccountTransactions.size() - 1); if (accountTransaction.isAfter(closedDate)) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.after.last.transaction.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } } validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_CLOSE_ACCOUNT, closedDate); this.status = SavingsAccountStatusType.PRE_MATURE_CLOSURE.getValue(); final Integer onAccountClosureId = command.integerValueOfParameterNamed(onAccountClosureIdParamName); final DepositAccountOnClosureType onClosureType = DepositAccountOnClosureType.fromInt(onAccountClosureId); this.accountTermAndPreClosure.updateOnAccountClosureStatus(onClosureType); /* * // withdraw deposit amount before closing the account final Money * transactionAmountMoney = Money.of(this.currency, * this.getAccountBalance()); final SavingsAccountTransaction withdraw = * SavingsAccountTransaction.withdrawal(this, office(), paymentDetail, * closedDate, transactionAmountMoney, new Date()); * this.transactions.add(withdraw); */ actualChanges.put(SavingsApiConstants.statusParamName, SavingsEnumerations.status(this.status)); actualChanges.put(SavingsApiConstants.localeParamName, command.locale()); actualChanges.put(SavingsApiConstants.dateFormatParamName, command.dateFormat()); actualChanges.put(SavingsApiConstants.closedOnDateParamName, closedDate.toString(fmt)); this.rejectedOnDate = null; this.rejectedBy = null; this.withdrawnOnDate = null; this.withdrawnBy = null; this.closedOnDate = closedDate.toDate(); this.closedBy = currentUser; this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions); }
From source file:com.gst.portfolio.savings.domain.FixedDepositAccount.java
License:Apache License
public void close(final AppUser currentUser, final JsonCommand command, final LocalDate tenantsTodayDate, final Map<String, Object> actualChanges) { final List<ApiParameterError> dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource(FIXED_DEPOSIT_ACCOUNT_RESOURCE_NAME + SavingsApiConstants.closeAction); final SavingsAccountStatusType currentStatus = SavingsAccountStatusType.fromInt(this.status); if (!SavingsAccountStatusType.MATURED.hasStateOf(currentStatus)) { baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("not.in.matured.state"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }/* w ww . j a v a 2s . c o m*/ } final Locale locale = command.extractLocale(); final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale); final LocalDate closedDate = command .localDateValueOfParameterNamed(SavingsApiConstants.closedOnDateParamName); if (closedDate.isBefore(getActivationLocalDate())) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.after.activation.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } if (closedDate.isBefore(maturityDate())) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.after.account.maturity.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } if (closedDate.isAfter(tenantsTodayDate)) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("cannot.be.a.future.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } final List<SavingsAccountTransaction> savingsAccountTransactions = retreiveListOfTransactions(); if (savingsAccountTransactions.size() > 0) { final SavingsAccountTransaction accountTransaction = savingsAccountTransactions .get(savingsAccountTransactions.size() - 1); if (accountTransaction.isAfter(closedDate)) { baseDataValidator.reset().parameter(SavingsApiConstants.closedOnDateParamName).value(closedDate) .failWithCode("must.be.after.last.transaction.date"); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } } validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_CLOSE_ACCOUNT, closedDate); this.status = SavingsAccountStatusType.CLOSED.getValue(); final Integer onAccountClosureId = command.integerValueOfParameterNamed(onAccountClosureIdParamName); final DepositAccountOnClosureType onClosureType = DepositAccountOnClosureType.fromInt(onAccountClosureId); this.accountTermAndPreClosure.updateOnAccountClosureStatus(onClosureType); // // withdraw deposit amount before closing the account // final Money transactionAmountMoney = Money.of(this.currency, // this.getAccountBalance()); // final SavingsAccountTransaction withdraw = // SavingsAccountTransaction.withdrawal(this, office(), paymentDetail, // closedDate, // transactionAmountMoney, new Date()); // this.transactions.add(withdraw); actualChanges.put(SavingsApiConstants.statusParamName, SavingsEnumerations.status(this.status)); actualChanges.put(SavingsApiConstants.localeParamName, command.locale()); actualChanges.put(SavingsApiConstants.dateFormatParamName, command.dateFormat()); actualChanges.put(SavingsApiConstants.closedOnDateParamName, closedDate.toString(fmt)); this.rejectedOnDate = null; this.rejectedBy = null; this.withdrawnOnDate = null; this.withdrawnBy = null; this.closedOnDate = closedDate.toDate(); this.closedBy = currentUser; // this.summary.updateSummary(this.currency, // this.savingsAccountTransactionSummaryWrapper, this.transactions); }
From source file:com.gst.portfolio.savings.domain.FixedDepositAccount.java
License:Apache License
public void postMaturityInterest(final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth) { final LocalDate interestPostingUpToDate = maturityDate(); final MathContext mc = MathContext.DECIMAL64; final boolean isInterestTransfer = false; final LocalDate postInterestOnDate = null; final List<PostingPeriod> postingPeriods = calculateInterestUsing(mc, interestPostingUpToDate, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth, postInterestOnDate);/*from w ww .j a va 2 s . c o m*/ Money interestPostedToDate = Money.zero(this.currency); boolean recalucateDailyBalanceDetails = false; for (final PostingPeriod interestPostingPeriod : postingPeriods) { LocalDate interestPostingTransactionDate = interestPostingPeriod.dateOfPostingTransaction(); interestPostingTransactionDate = interestPostingTransactionDate.isAfter(interestPostingUpToDate) ? interestPostingUpToDate : interestPostingTransactionDate; final Money interestEarnedToBePostedForPeriod = interestPostingPeriod.getInterestEarned(); interestPostedToDate = interestPostedToDate.plus(interestEarnedToBePostedForPeriod); final SavingsAccountTransaction postingTransaction = findInterestPostingTransactionFor( interestPostingTransactionDate); if (postingTransaction == null) { final SavingsAccountTransaction newPostingTransaction = SavingsAccountTransaction.interestPosting( this, office(), interestPostingTransactionDate, interestEarnedToBePostedForPeriod, interestPostingPeriod.isUserPosting()); this.transactions.add(newPostingTransaction); recalucateDailyBalanceDetails = true; } else { final boolean correctionRequired = postingTransaction .hasNotAmount(interestEarnedToBePostedForPeriod); if (correctionRequired) { postingTransaction.reverse(); final SavingsAccountTransaction newPostingTransaction = SavingsAccountTransaction .interestPosting(this, office(), interestPostingTransactionDate, interestEarnedToBePostedForPeriod, interestPostingPeriod.isUserPosting()); this.transactions.add(newPostingTransaction); recalucateDailyBalanceDetails = true; } } } recalucateDailyBalanceDetails = applyWithholdTaxForDepositAccounts(interestPostingUpToDate, recalucateDailyBalanceDetails); if (recalucateDailyBalanceDetails) { // update existing transactions so derived balance fields are // correct. recalculateDailyBalances(Money.zero(this.currency), interestPostingUpToDate); } this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions); }
From source file:com.gst.portfolio.savings.domain.interest.EndOfDayBalance.java
License:Apache License
/** * @param compoundingPeriodInterval//from w w w.ja va 2 s . c om * @param upToInterestCalculationDate * : For calculating maturity details in advance * upToInterestCalculationDate will be maturity date else it will * be DateUtils.getLocalDateOfTenant(). * @return */ public EndOfDayBalance upTo(final LocalDateInterval compoundingPeriodInterval, final LocalDate upToInterestCalculationDate) { Money startingBalance = this.openingBalance; LocalDate balanceStartDate = this.date; LocalDate oldBalanceEndDate = this.date.plusDays(this.numberOfDays - 1); int daysOfBalance = this.numberOfDays; if (this.date.isBefore(compoundingPeriodInterval.startDate())) { balanceStartDate = compoundingPeriodInterval.startDate(); startingBalance = this.endOfDayBalance; final LocalDateInterval balancePeriodInterval = LocalDateInterval.create(balanceStartDate, oldBalanceEndDate); daysOfBalance = balancePeriodInterval.daysInPeriodInclusiveOfEndDate(); } LocalDate balanceEndDate = balanceStartDate.plusDays(daysOfBalance - 1); if (balanceEndDate.isAfter(compoundingPeriodInterval.endDate())) { balanceEndDate = compoundingPeriodInterval.endDate(); final LocalDateInterval balancePeriodInterval = LocalDateInterval.create(balanceStartDate, balanceEndDate); daysOfBalance = balancePeriodInterval.daysInPeriodInclusiveOfEndDate(); } if (balanceEndDate.isAfter(upToInterestCalculationDate)) { balanceEndDate = upToInterestCalculationDate; final LocalDateInterval balancePeriodInterval = LocalDateInterval.create(balanceStartDate, balanceEndDate); daysOfBalance = balancePeriodInterval.daysInPeriodInclusiveOfEndDate(); } return new EndOfDayBalance(balanceStartDate, startingBalance, this.endOfDayBalance, daysOfBalance); }
From source file:com.gst.portfolio.savings.domain.interest.PostingPeriod.java
License:Apache License
public static PostingPeriod createFrom(final LocalDateInterval periodInterval, final Money periodStartingBalance, final List<SavingsAccountTransaction> orderedListOfTransactions, final MonetaryCurrency currency, final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType, final SavingsInterestCalculationType interestCalculationType, final BigDecimal interestRateAsFraction, final long daysInYear, final LocalDate upToInterestCalculationDate, Collection<Long> interestPostTransactions, boolean isInterestTransfer, final Money minBalanceForInterestCalculation, final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final BigDecimal overdraftInterestRateAsFraction, final Money minOverdraftForInterestCalculation, boolean isUserPosting) { final List<EndOfDayBalance> accountEndOfDayBalances = new ArrayList<>(); boolean interestTransfered = false; Money openingDayBalance = periodStartingBalance; Money closeOfDayBalance = openingDayBalance; for (final SavingsAccountTransaction transaction : orderedListOfTransactions) { if (transaction.fallsWithin(periodInterval)) { // the balance of the transaction falls entirely within this // period so no need to do any cropping/bounding final EndOfDayBalance endOfDayBalance = transaction.toEndOfDayBalance(openingDayBalance); accountEndOfDayBalances.add(endOfDayBalance); openingDayBalance = endOfDayBalance.closingBalance(); } else if (transaction.spansAnyPortionOf(periodInterval)) { final EndOfDayBalance endOfDayBalance = transaction.toEndOfDayBalanceBoundedBy(openingDayBalance, periodInterval);// w w w . j a v a2 s.c o m accountEndOfDayBalances.add(endOfDayBalance); closeOfDayBalance = endOfDayBalance.closingBalance(); openingDayBalance = closeOfDayBalance; } // this check is to make sure to add interest if withdrawal is // happened for already if (transaction.occursOn(periodInterval.endDate().plusDays(1))) { if (transaction.getId() == null) { interestTransfered = isInterestTransfer; } else if (interestPostTransactions.contains(transaction.getId())) { interestTransfered = true; } } } if (accountEndOfDayBalances.isEmpty()) { LocalDate balanceStartDate = periodInterval.startDate(); LocalDate balanceEndDate = periodInterval.endDate(); Integer numberOfDaysOfBalance = periodInterval.daysInPeriodInclusiveOfEndDate(); if (balanceEndDate.isAfter(upToInterestCalculationDate)) { balanceEndDate = upToInterestCalculationDate; final LocalDateInterval spanOfBalance = LocalDateInterval.create(balanceStartDate, balanceEndDate); numberOfDaysOfBalance = spanOfBalance.daysInPeriodInclusiveOfEndDate(); } final EndOfDayBalance endOfDayBalance = EndOfDayBalance.from(balanceStartDate, openingDayBalance, closeOfDayBalance, numberOfDaysOfBalance); accountEndOfDayBalances.add(endOfDayBalance); closeOfDayBalance = endOfDayBalance.closingBalance(); openingDayBalance = closeOfDayBalance; } final List<CompoundingPeriod> compoundingPeriods = compoundingPeriodsInPostingPeriod(periodInterval, interestCompoundingPeriodType, accountEndOfDayBalances, upToInterestCalculationDate); return new PostingPeriod(periodInterval, currency, periodStartingBalance, openingDayBalance, interestCompoundingPeriodType, interestCalculationType, interestRateAsFraction, daysInYear, compoundingPeriods, interestTransfered, minBalanceForInterestCalculation, isSavingsInterestPostingAtCurrentPeriodEnd, overdraftInterestRateAsFraction, minOverdraftForInterestCalculation, isUserPosting); }