List of usage examples for org.joda.time LocalDate now
public static LocalDate now()
ISOChronology
in the default time zone. From source file:net.jrkatz.minero.data.BudgetPeriodProvider.java
License:Open Source License
@NonNull public BudgetPeriod getCurrentBudgetPeriod(@NonNull final ProviderContext context, final long budgetId) throws ProviderException { BudgetPeriod budgetPeriod = getLatestBudgetPeriod(context, budgetId); //if this budgetPeriod is too old it may be necessary to create a new one or _several_ //new ones.//from w w w . jav a 2s . c o m final LocalDate now = LocalDate.now(); if (budgetPeriod == null) { final Budget budget = context.getBudgetProvider().getBudget(context, budgetId); final PeriodDefinition periodDefinition = budget.getPeriodDefinition(); final Period period = periodDefinition.periodForDate(now); budgetPeriod = createBudgetPeriod(context, budgetId, budget.getDistribution(), period); } else if (!now.isBefore(budgetPeriod.getPeriod().getEnd())) { final BudgetProvider bp = context.getBudgetProvider(); final Budget budget = bp.getBudget(context, budgetId); final PeriodDefinition periodDefinition = budget.getPeriodDefinition(); do { //add savings from previous period bp.setBudgetRunningTotal(context, budgetId, budgetPeriod.getRemaining()); //make subsequent period final Period nextPeriod = periodDefinition.periodForDate(budgetPeriod.getPeriod().getEnd()); budgetPeriod = createBudgetPeriod(context, budgetId, budget.getDistribution(), nextPeriod); } while (!now.isBefore(budgetPeriod.getPeriod().getEnd())); } return budgetPeriod; }
From source file:org.alfresco.repo.web.scripts.solr.StatsGet.java
License:Open Source License
/** * Parses ISO8601 formatted Date Strings. * @param start If start is null then defaults to 1 month * @param end If end is null then it defaults to now(); *//*from w w w. ja va2 s . co m*/ public static Pair<LocalDate, LocalDate> getStartAndEndDates(String start, String end) { if (start == null) return null; LocalDate startDate = LocalDate.parse(start); LocalDate endDate = end != null ? LocalDate.parse(end) : LocalDate.now(); return new Pair<LocalDate, LocalDate>(startDate, endDate); }
From source file:org.apache.fineract.accounting.closure.bookoffincomeandexpense.service.CalculateIncomeAndExpenseBookingImpl.java
License:Apache License
private IncomeAndExpenseBookingData bookOffIncomeAndExpense( final List<IncomeAndExpenseJournalEntryData> incomeAndExpenseJournalEntryDataList, final GLClosureCommand closureData, final boolean preview, final GLAccount glAccount, final Office office) { /* All running balances has to be calculated before booking off income and expense account */ boolean isRunningBalanceCalculated = true; for (final IncomeAndExpenseJournalEntryData incomeAndExpenseData : incomeAndExpenseJournalEntryDataList) { if (!incomeAndExpenseData.isRunningBalanceCalculated()) { throw new RunningBalanceNotCalculatedException(incomeAndExpenseData.getOfficeId()); }/*from w w w . j a v a2s . com*/ } BigDecimal debits = BigDecimal.ZERO; BigDecimal credits = BigDecimal.ZERO; final List<SingleDebitOrCreditEntry> debitsJournalEntry = new ArrayList<>(); final List<SingleDebitOrCreditEntry> creditsJournalEntry = new ArrayList<>(); for (final IncomeAndExpenseJournalEntryData incomeAndExpense : incomeAndExpenseJournalEntryDataList) { if (incomeAndExpense.isIncomeAccountType()) { if (incomeAndExpense.getOfficeRunningBalance().signum() == 1) { debits = debits.add(incomeAndExpense.getOfficeRunningBalance()); debitsJournalEntry.add(new SingleDebitOrCreditEntry(incomeAndExpense.getAccountId(), incomeAndExpense.getGlAccountName(), incomeAndExpense.getOfficeRunningBalance(), null)); } else { credits = credits.add(incomeAndExpense.getOfficeRunningBalance().abs()); creditsJournalEntry.add(new SingleDebitOrCreditEntry(incomeAndExpense.getAccountId(), incomeAndExpense.getGlAccountName(), incomeAndExpense.getOfficeRunningBalance().abs(), null)); ; } } if (incomeAndExpense.isExpenseAccountType()) { if (incomeAndExpense.getOfficeRunningBalance().signum() == 1) { credits = credits.add(incomeAndExpense.getOfficeRunningBalance()); creditsJournalEntry.add(new SingleDebitOrCreditEntry(incomeAndExpense.getAccountId(), incomeAndExpense.getGlAccountName(), incomeAndExpense.getOfficeRunningBalance().abs(), null)); ; } else { debits = debits.add(incomeAndExpense.getOfficeRunningBalance().abs()); debitsJournalEntry.add(new SingleDebitOrCreditEntry(incomeAndExpense.getAccountId(), incomeAndExpense.getGlAccountName(), incomeAndExpense.getOfficeRunningBalance().abs(), null)); } } } final LocalDate today = DateUtils.getLocalDateOfTenant(); final int compare = debits.compareTo(credits); BigDecimal difference = BigDecimal.ZERO; JournalEntry journalEntry = null; if (compare == 1) { /* book with target gl id on the credit side */ difference = debits.subtract(credits); SingleDebitOrCreditEntry targetBooking = new SingleDebitOrCreditEntry( closureData.getEquityGlAccountId(), glAccount.getName(), difference, null); creditsJournalEntry.add(targetBooking); journalEntry = new JournalEntry(office.getId(), today.toString(), closureData.getComments(), creditsJournalEntry, debitsJournalEntry, null, false, closureData.getCurrencyCode(), office.getName()); } else if (compare == -1) { /* book with target gl id on the debit side*/ difference = credits.subtract(debits); SingleDebitOrCreditEntry targetBooking = new SingleDebitOrCreditEntry( closureData.getEquityGlAccountId(), glAccount.getName(), difference, null); debitsJournalEntry.add(targetBooking); journalEntry = new JournalEntry(office.getId(), today.toString(), closureData.getComments(), creditsJournalEntry, debitsJournalEntry, null, false, closureData.getCurrencyCode(), office.getName()); } else if (compare == 0) { //throw new RunningBalanceZeroException(office.getName()); } final LocalDate localDate = LocalDate.now(); final List<JournalEntry> journalEntries = new ArrayList<>(); if (journalEntry != null) { journalEntries.add(journalEntry); } return new IncomeAndExpenseBookingData(localDate, closureData.getComments(), journalEntries); }
From source file:org.apache.fineract.infrastructure.scheduledemail.domain.EmailMessage.java
License:Apache License
private EmailMessage(final Group group, final Client client, final Staff staff, final EmailCampaign emailCampaign, final EmailMessageStatusType statusType, final String emailSubject, final String message, final String emailAddress, final String campaignName) { this.group = group; this.client = client; this.staff = staff; this.emailCampaign = emailCampaign; this.statusType = statusType.getValue(); this.emailAddress = emailAddress; this.emailSubject = emailSubject; this.message = message; this.campaignName = campaignName; this.submittedOnDate = LocalDate.now().toDate(); }
From source file:org.apache.fineract.portfolio.client.command.ClientIdentifierCommand.java
License:Apache License
public void validateForCreate() { final List<ApiParameterError> dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource("clientIdentifier"); baseDataValidator.reset().parameter("documentTypeId").value(this.documentTypeId).notNull() .integerGreaterThanZero();//from ww w .ja v a 2s . c o m baseDataValidator.reset().parameter("documentKey").value(this.documentKey).notBlank(); baseDataValidator.reset().parameter("validity").value(this.validity) .validateDateAfter(LocalDate.now().plusMonths(1)).ignoreIfNull(); baseDataValidator.reset().parameter("isLifeTime").value(this.isLifeTime).ignoreIfNull(); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors); } }
From source file:org.apache.fineract.portfolio.group.service.GroupingTypesWritePlatformServiceJpaRepositoryImpl.java
License:Apache License
@Override public CommandProcessingResult assignGroupOrCenterStaff(final Long groupId, final JsonCommand command) { this.context.authenticatedUser(); final Map<String, Object> actualChanges = new LinkedHashMap<>(5); this.fromApiJsonDeserializer.validateForAssignStaff(command.json()); final Group groupForUpdate = this.groupRepository.findOneWithNotFoundDetection(groupId); Staff staff = null;//from www . j a v a 2s . co m final Long staffId = command.longValueOfParameterNamed(GroupingTypesApiConstants.staffIdParamName); final boolean inheritStaffForClientAccounts = command .booleanPrimitiveValueOfParameterNamed(GroupingTypesApiConstants.inheritStaffForClientAccounts); staff = this.staffRepository.findByOfficeHierarchyWithNotFoundDetection(staffId, groupForUpdate.getOffice().getHierarchy()); groupForUpdate.updateStaff(staff); if (inheritStaffForClientAccounts) { LocalDate loanOfficerReassignmentDate = LocalDate.now(); /* * update loan officer for client and update loan officer for * clients loans and savings */ Set<Client> clients = groupForUpdate.getClientMembers(); if (clients != null) { for (Client client : clients) { client.updateStaff(staff); if (this.loanRepository.doNonClosedLoanAccountsExistForClient(client.getId())) { for (final Loan loan : this.loanRepository.findLoanByClientId(client.getId())) { if (loan.isDisbursed() && !loan.isClosed()) { loan.reassignLoanOfficer(staff, loanOfficerReassignmentDate); } } } if (this.savingsAccountRepository.doNonClosedSavingAccountsExistForClient(client.getId())) { for (final SavingsAccount savingsAccount : this.savingsAccountRepository .findSavingAccountByClientId(client.getId())) { if (!savingsAccount.isClosed()) { savingsAccount.reassignSavingsOfficer(staff, loanOfficerReassignmentDate); } } } } } } this.groupRepository.saveAndFlush(groupForUpdate); actualChanges.put(GroupingTypesApiConstants.staffIdParamName, staffId); return new CommandProcessingResultBuilder() // .withOfficeId(groupForUpdate.officeId()) // .withEntityId(groupForUpdate.getId()) // .withGroupId(groupId) // .with(actualChanges) // .build(); }
From source file:org.apache.fineract.portfolio.loanaccount.domain.Loan.java
License:Apache License
public LoanTransaction waiveLoanCharge(final LoanCharge loanCharge, final LoanLifecycleStateMachine loanLifecycleStateMachine, final Map<String, Object> changes, final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds, final Integer loanInstallmentNumber, final ScheduleGeneratorDTO scheduleGeneratorDTO, final Money accruedCharge, final AppUser currentUser) { validateLoanIsNotClosed(loanCharge); final Money amountWaived = loanCharge.waive(loanCurrency(), loanInstallmentNumber); changes.put("amount", amountWaived.getAmount()); Money unrecognizedIncome = amountWaived.zero(); Money chargeComponent = amountWaived; if (isPeriodicAccrualAccountingEnabledOnLoanProduct()) { Money receivableCharge = Money.zero(getCurrency()); if (loanInstallmentNumber != null) { receivableCharge = accruedCharge.minus( loanCharge.getInstallmentLoanCharge(loanInstallmentNumber).getAmountPaid(getCurrency())); } else {// w w w. j av a2 s.c o m receivableCharge = accruedCharge.minus(loanCharge.getAmountPaid(getCurrency())); } if (receivableCharge.isLessThanZero()) { receivableCharge = amountWaived.zero(); } if (amountWaived.isGreaterThan(receivableCharge)) { chargeComponent = receivableCharge; unrecognizedIncome = amountWaived.minus(receivableCharge); } } Money feeChargesWaived = chargeComponent; Money penaltyChargesWaived = Money.zero(loanCurrency()); if (loanCharge.isPenaltyCharge()) { penaltyChargesWaived = chargeComponent; feeChargesWaived = Money.zero(loanCurrency()); } LocalDate transactionDate = getDisbursementDate(); if (loanCharge.isSpecifiedDueDate()) { transactionDate = loanCharge.getDueLocalDate(); } scheduleGeneratorDTO.setRecalculateFrom(transactionDate); updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement()); existingTransactionIds.addAll(findExistingTransactionIds()); existingReversedTransactionIds.addAll(findExistingReversedTransactionIds()); final LoanTransaction waiveLoanChargeTransaction = LoanTransaction.waiveLoanCharge(this, getOffice(), amountWaived, transactionDate, feeChargesWaived, penaltyChargesWaived, unrecognizedIncome, DateUtils.getLocalDateTimeOfTenant(), currentUser); final LoanChargePaidBy loanChargePaidBy = new LoanChargePaidBy(waiveLoanChargeTransaction, loanCharge, waiveLoanChargeTransaction.getAmount(getCurrency()).getAmount(), loanInstallmentNumber); waiveLoanChargeTransaction.getLoanChargesPaid().add(loanChargePaidBy); this.loanTransactions.add(waiveLoanChargeTransaction); if (this.repaymentScheduleDetail().isInterestRecalculationEnabled() && (loanCharge.getDueLocalDate() == null || LocalDate.now().isAfter(loanCharge.getDueLocalDate()))) { regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO, currentUser); } // Waive of charges whose due date falls after latest 'repayment' // transaction dont require entire loan schedule to be reprocessed. final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory .determineProcessor(this.transactionProcessingStrategy); if (!loanCharge.isDueAtDisbursement() && loanCharge.isPaidOrPartiallyPaid(loanCurrency())) { /**** * TODO Vishwas Currently we do not allow waiving fully paid loan * charge and waiving partially paid loan charges only waives the * remaining amount. * * Consider removing this block of code or logically completing it * for the future by getting the list of affected Transactions ***/ final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement(); loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement, getCurrency(), this.repaymentScheduleInstallments, charges()); } else { // reprocess loan schedule based on charge been waived. final LoanRepaymentScheduleProcessingWrapper wrapper = new LoanRepaymentScheduleProcessingWrapper(); wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, charges()); } updateLoanSummaryDerivedFields(); doPostLoanTransactionChecks(waiveLoanChargeTransaction.getTransactionDate(), loanLifecycleStateMachine); return waiveLoanChargeTransaction; }
From source file:org.apache.fineract.portfolio.loanaccount.domain.Loan.java
License:Apache License
private BigDecimal calculateOverdueAmountPercentageAppliedTo(final LoanCharge loanCharge, final int penaltyWaitPeriod) { LoanRepaymentScheduleInstallment installment = loanCharge.getOverdueInstallmentCharge().getInstallment(); LocalDate graceDate = LocalDate.now().minusDays(penaltyWaitPeriod); Money amount = Money.zero(getCurrency()); if (graceDate.isAfter(installment.getDueDate())) { amount = calculateOverdueAmountPercentageAppliedTo(installment, loanCharge.getChargeCalculation()); if (!amount.isGreaterThanZero()) { loanCharge.setActive(false); }/*from w ww . ja va 2 s. c o m*/ } else { loanCharge.setActive(false); } return amount.getAmount(); }
From source file:org.apache.fineract.portfolio.loanaccount.domain.Loan.java
License:Apache License
public ChangedTransactionDetail disburse(final AppUser currentUser, final JsonCommand command, final Map<String, Object> actualChanges, final ScheduleGeneratorDTO scheduleGeneratorDTO) { final LoanStatus statusEnum = this.loanLifecycleStateMachine.transition(LoanEvent.LOAN_DISBURSED, LoanStatus.fromInt(this.loanStatus)); final LocalDate actualDisbursementDate = command.localDateValueOfParameterNamed("actualDisbursementDate"); this.loanStatus = statusEnum.getValue(); actualChanges.put("status", LoanEnumerations.status(this.loanStatus)); this.disbursedBy = currentUser; updateLoanScheduleDependentDerivedFields(); actualChanges.put("locale", command.locale()); actualChanges.put("dateFormat", command.dateFormat()); actualChanges.put("actualDisbursementDate", command.stringValueOfParameterNamed("actualDisbursementDate")); HolidayDetailDTO holidayDetailDTO = scheduleGeneratorDTO.getHolidayDetailDTO(); // validate if disbursement date is a holiday or a non-working day validateDisbursementDateIsOnNonWorkingDay(holidayDetailDTO.getWorkingDays(), holidayDetailDTO.isAllowTransactionsOnNonWorkingDay()); validateDisbursementDateIsOnHoliday(holidayDetailDTO.isAllowTransactionsOnHoliday(), holidayDetailDTO.getHolidays()); if (this.repaymentScheduleDetail().isInterestRecalculationEnabled() && (fetchRepaymentScheduleInstallment(1).getDueDate().isBefore(LocalDate.now()) || isDisbursementMissed())) { regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO, currentUser); }/*w w w . ja va 2s.com*/ updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement()); updateLoanRepaymentPeriodsDerivedFields(actualDisbursementDate); LocalDateTime createdDate = DateUtils.getLocalDateTimeOfTenant(); handleDisbursementTransaction(actualDisbursementDate, createdDate, currentUser); updateLoanSummaryDerivedFields(); final Money interestApplied = Money.of(getCurrency(), this.summary.getTotalInterestCharged()); /** * Add an interest applied transaction of the interest is accrued * upfront (Up front accrual), no accounting or cash based accounting is * selected **/ if (isNoneOrCashOrUpfrontAccrualAccountingEnabledOnLoanProduct()) { final LoanTransaction interestAppliedTransaction = LoanTransaction.accrueInterest(getOffice(), this, interestApplied, actualDisbursementDate, createdDate, currentUser); this.loanTransactions.add(interestAppliedTransaction); } return reprocessTransactionForDisbursement(); }
From source file:org.apache.fineract.portfolio.loanaccount.domain.Loan.java
License:Apache License
private ChangedTransactionDetail handleRepaymentOrRecoveryOrWaiverTransaction( final LoanTransaction loanTransaction, final LoanLifecycleStateMachine loanLifecycleStateMachine, final LoanTransaction adjustedTransaction, final ScheduleGeneratorDTO scheduleGeneratorDTO, final AppUser currentUser) { ChangedTransactionDetail changedTransactionDetail = null; LoanStatus statusEnum = null;/* w w w . jav a2s .co m*/ LocalDate recalculateFrom = loanTransaction.getTransactionDate(); if (adjustedTransaction != null && adjustedTransaction.getTransactionDate().isBefore(recalculateFrom)) { recalculateFrom = adjustedTransaction.getTransactionDate(); } if (loanTransaction.isRecoveryRepayment()) { statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_RECOVERY_PAYMENT, LoanStatus.fromInt(this.loanStatus)); } else { statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_REPAYMENT_OR_WAIVER, LoanStatus.fromInt(this.loanStatus)); } this.loanStatus = statusEnum.getValue(); loanTransaction.updateLoan(this); final boolean isTransactionChronologicallyLatest = isChronologicallyLatestRepaymentOrWaiver(loanTransaction, this.loanTransactions); if (loanTransaction.isNotZero(loanCurrency())) { this.loanTransactions.add(loanTransaction); } if (loanTransaction.isNotRepayment() && loanTransaction.isNotWaiver() && loanTransaction.isNotRecoveryRepayment()) { final String errorMessage = "A transaction of type repayment or recovery repayment or waiver was expected but not received."; throw new InvalidLoanTransactionTypeException("transaction", "is.not.a.repayment.or.waiver.or.recovery.transaction", errorMessage); } final LocalDate loanTransactionDate = loanTransaction.getTransactionDate(); if (loanTransactionDate.isBefore(getDisbursementDate())) { final String errorMessage = "The transaction date cannot be before the loan disbursement date: " + getApprovedOnDate().toString(); throw new InvalidLoanStateTransitionException("transaction", "cannot.be.before.disbursement.date", errorMessage, loanTransactionDate, getDisbursementDate()); } if (loanTransactionDate.isAfter(DateUtils.getLocalDateOfTenant())) { final String errorMessage = "The transaction date cannot be in the future."; throw new InvalidLoanStateTransitionException("transaction", "cannot.be.a.future.date", errorMessage, loanTransactionDate); } if (loanTransaction.isInterestWaiver()) { Money totalInterestOutstandingOnLoan = getTotalInterestOutstandingOnLoan(); if (adjustedTransaction != null) { totalInterestOutstandingOnLoan = totalInterestOutstandingOnLoan .plus(adjustedTransaction.getAmount(loanCurrency())); } if (loanTransaction.getAmount(loanCurrency()).isGreaterThan(totalInterestOutstandingOnLoan)) { final String errorMessage = "The amount of interest to waive cannot be greater than total interest outstanding on loan."; throw new InvalidLoanStateTransitionException("waive.interest", "amount.exceeds.total.outstanding.interest", errorMessage, loanTransaction.getAmount(loanCurrency()), totalInterestOutstandingOnLoan.getAmount()); } } if (this.loanProduct.isMultiDisburseLoan() && adjustedTransaction == null) { BigDecimal totalDisbursed = getDisbursedAmount(); if (totalDisbursed.compareTo(this.summary.getTotalPrincipalRepaid()) < 0) { final String errorMessage = "The transaction cannot be done before the loan disbursement: " + getApprovedOnDate().toString(); throw new InvalidLoanStateTransitionException("transaction", "cannot.be.done.before.disbursement", errorMessage); } } final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory .determineProcessor(this.transactionProcessingStrategy); final LoanRepaymentScheduleInstallment currentInstallment = fetchLoanRepaymentScheduleInstallment( loanTransaction.getTransactionDate()); boolean reprocess = true; if (isTransactionChronologicallyLatest && adjustedTransaction == null && loanTransaction.getTransactionDate().isEqual(LocalDate.now()) && currentInstallment != null && currentInstallment.getTotalOutstanding(getCurrency()) .isEqualTo(loanTransaction.getAmount(getCurrency()))) { reprocess = false; } if (isTransactionChronologicallyLatest && adjustedTransaction == null && (!reprocess || !this.repaymentScheduleDetail().isInterestRecalculationEnabled())) { loanRepaymentScheduleTransactionProcessor.handleTransaction(loanTransaction, getCurrency(), this.repaymentScheduleInstallments, charges()); reprocess = false; if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) { if (currentInstallment == null || currentInstallment.isNotFullyPaidOff()) { reprocess = true; } else { final LoanRepaymentScheduleInstallment nextInstallment = fetchRepaymentScheduleInstallment( currentInstallment.getInstallmentNumber() + 1); if (nextInstallment != null && nextInstallment.getTotalPaidInAdvance(getCurrency()).isGreaterThanZero()) { reprocess = true; } } } } if (reprocess) { if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) { regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO, currentUser); } final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement(); changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.handleTransaction( getDisbursementDate(), allNonContraTransactionsPostDisbursement, getCurrency(), this.repaymentScheduleInstallments, charges()); for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail .getNewTransactionMappings().entrySet()) { mapEntry.getValue().updateLoan(this); } /*** * Commented since throwing exception if external id present for one * of the transactions. for this need to save the reversed * transactions first and then new transactions. */ this.loanTransactions.addAll(changedTransactionDetail.getNewTransactionMappings().values()); } updateLoanSummaryDerivedFields(); /** * FIXME: Vishwas, skipping post loan transaction checks for Loan * recoveries **/ if (loanTransaction.isNotRecoveryRepayment()) { doPostLoanTransactionChecks(loanTransaction.getTransactionDate(), loanLifecycleStateMachine); } if (this.loanProduct.isMultiDisburseLoan()) { BigDecimal totalDisbursed = getDisbursedAmount(); if (totalDisbursed.compareTo(this.summary.getTotalPrincipalRepaid()) < 0 && this.repaymentScheduleDetail().getPrincipal().minus(totalDisbursed).isGreaterThanZero()) { final String errorMessage = "The transaction cannot be done before the loan disbursement: " + getApprovedOnDate().toString(); throw new InvalidLoanStateTransitionException("transaction", "cannot.be.done.before.disbursement", errorMessage); } } if (changedTransactionDetail != null) { this.loanTransactions.removeAll(changedTransactionDetail.getNewTransactionMappings().values()); } return changedTransactionDetail; }