Repository: incubator-fineract Updated Branches: refs/heads/develop 882132739 -> 7fe50160c
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b9b345a5/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java index f6df4e4..51038d4 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java @@ -126,5 +126,8 @@ public interface LoanReadPlatformService { LoanTransactionData retrieveRefundByCashTemplate(Long loanId); Collection<InterestRatePeriodData> retrieveLoanInterestRatePeriodData(Long loanId); + Collection<Long> retrieveLoanIdsWithPendingIncomePostingTransactions(); + + LoanTransactionData retrieveLoanForeclosureTemplate(final Long loanId, final LocalDate transactionDate); } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b9b345a5/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java index f994d91..7283ca0 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java @@ -93,6 +93,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleIns import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository; import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus; +import org.apache.fineract.portfolio.loanaccount.domain.LoanSubStatus; import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariationType; import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction; import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository; @@ -592,6 +593,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { + " l.total_overpaid_derived as totalOverpaid," + " l.fixed_emi_amount as fixedEmiAmount," + " l.max_outstanding_loan_balance as outstandingLoanBalance," + + " l.loan_sub_status_id as loanSubStatusId," + " la.principal_overdue_derived as principalOverdue," + " la.interest_overdue_derived as interestOverdue," + " la.fee_charges_overdue_derived as feeChargesOverdue," @@ -783,6 +785,12 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { final Integer lifeCycleStatusId = JdbcSupport.getInteger(rs, "lifeCycleStatusId"); final LoanStatusEnumData status = LoanEnumerations.status(lifeCycleStatusId); + final Integer loanSubStatusId = JdbcSupport.getInteger(rs, "loanSubStatusId"); + EnumOptionData loanSubStatus = null; + if (loanSubStatusId != null) { + loanSubStatus = LoanSubStatus.loanSubStatus(loanSubStatusId); + } + // settings final LocalDate expectedFirstRepaymentOnDate = JdbcSupport.getLocalDate(rs, "expectedFirstRepaymentOnDate"); final LocalDate interestChargedFromDate = JdbcSupport.getLocalDate(rs, "interestChargedFromDate"); @@ -936,7 +944,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { loanProductCounter, multiDisburseLoan, canDefineInstallmentAmount, fixedEmiAmount, outstandingLoanBalance, inArrears, graceOnArrearsAgeing, isNPA, daysInMonthType, daysInYearType, isInterestRecalculationEnabled, interestRecalculationData, createStandingInstructionAtDisbursement, isvariableInstallmentsAllowed, minimumGap, - maximumGap); + maximumGap, loanSubStatus); } } @@ -2028,7 +2036,6 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { final LoanTransactionEnumData transactionType = LoanEnumerations.transactionType(LoanTransactionType.REFUND_FOR_ACTIVE_LOAN); final Collection<PaymentTypeData> paymentOptions = this.paymentTypeReadPlatformService.retrieveAllPaymentTypes(); - return new LoanTransactionData(null, null, null, transactionType, null, currencyData, earliestUnpaidInstallmentDate, retrieveTotalPaidInAdvance(loan.getId()).getPaidInAdvance(), null, null, null, null, null, null, paymentOptions, null, null, null, null, false); @@ -2100,4 +2107,35 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { return null; } } + + @Override + public LoanTransactionData retrieveLoanForeclosureTemplate(final Long loanId, final LocalDate transactionDate) { + this.context.authenticatedUser(); + + final Loan loan = this.loanRepository.findOne(loanId); + if (loan == null) { throw new LoanNotFoundException(loanId); } + loan.validateForForeclosure(transactionDate); + final MonetaryCurrency currency = loan.getCurrency(); + final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency); + + final CurrencyData currencyData = applicationCurrency.toData(); + + final LocalDate earliestUnpaidInstallmentDate = DateUtils.getLocalDateOfTenant(); + + final LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment = loan.fetchLoanForeclosureDetail(transactionDate); + BigDecimal unrecognizedIncomePortion = null; + final LoanTransactionEnumData transactionType = LoanEnumerations.transactionType(LoanTransactionType.REPAYMENT); + final Collection<PaymentTypeData> paymentTypeOptions = this.paymentTypeReadPlatformService.retrieveAllPaymentTypes(); + final BigDecimal outstandingLoanBalance = loanRepaymentScheduleInstallment.getPrincipalOutstanding(currency).getAmount(); + final Boolean isReversed = false; + + final Money outStandingAmount = loanRepaymentScheduleInstallment.getTotalOutstanding(currency); + + return new LoanTransactionData(null, null, null, transactionType, null, currencyData, earliestUnpaidInstallmentDate, + outStandingAmount.getAmount(), loanRepaymentScheduleInstallment.getPrincipalOutstanding(currency).getAmount(), + loanRepaymentScheduleInstallment.getInterestOutstanding(currency).getAmount(), loanRepaymentScheduleInstallment + .getFeeChargesOutstanding(currency).getAmount(), loanRepaymentScheduleInstallment.getPenaltyChargesOutstanding( + currency).getAmount(), null, unrecognizedIncomePortion, paymentTypeOptions, null, null, null, + outstandingLoanBalance, isReversed); + } } http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b9b345a5/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformService.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformService.java index 9189718..49a52fb 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformService.java @@ -104,6 +104,8 @@ public interface LoanWritePlatformService { void recalculateInterest(long loanId); - CommandProcessingResult undoLastLoanDisbursal(Long loanId, JsonCommand command); + CommandProcessingResult undoLastLoanDisbursal(Long loanId, JsonCommand command); + + CommandProcessingResult forecloseLoan(final Long loanId, JsonCommand command); } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b9b345a5/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index f897c3d..6e35e51 100755 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -137,6 +137,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleIns import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository; import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus; +import org.apache.fineract.portfolio.loanaccount.domain.LoanSubStatus; import org.apache.fineract.portfolio.loanaccount.domain.LoanSummaryWrapper; import org.apache.fineract.portfolio.loanaccount.domain.LoanTrancheDisbursementCharge; import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction; @@ -145,6 +146,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType; import org.apache.fineract.portfolio.loanaccount.exception.ExceedingTrancheCountException; import org.apache.fineract.portfolio.loanaccount.exception.InvalidPaidInAdvanceAmountException; import org.apache.fineract.portfolio.loanaccount.exception.LoanDisbursalException; +import org.apache.fineract.portfolio.loanaccount.exception.LoanForeclosureException; import org.apache.fineract.portfolio.loanaccount.exception.LoanMultiDisbursementException; import org.apache.fineract.portfolio.loanaccount.exception.LoanOfficerAssignmentException; import org.apache.fineract.portfolio.loanaccount.exception.LoanOfficerUnassignmentException; @@ -822,6 +824,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf this.loanEventApiJsonValidator.validateTransaction(command.json()); final Loan loan = this.loanAssembler.assembleFrom(loanId); + if(loan.status().isClosed() && loan.getLoanSubStatus().equals(LoanSubStatus.FORECLOSED.getValue())) { + final String defaultUserMessage = "The loan cannot reopend as it is foreclosed."; + throw new LoanForeclosureException("loan.cannot.be.reopened.as.it.is.foreclosured", defaultUserMessage, + loanId); + } checkClientOrGroupActive(loan); final LoanTransaction transactionToAdjust = this.loanTransactionRepository.findOne(transactionId); if (transactionToAdjust == null) { throw new LoanTransactionNotFoundException(transactionId); } @@ -2883,6 +2890,33 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf .build(); } + @Override + @Transactional + public CommandProcessingResult forecloseLoan(final Long loanId, final JsonCommand command) { + final String json = command.json(); + final JsonElement element = fromApiJsonHelper.parse(json); + final Loan loan = this.loanAssembler.assembleFrom(loanId); + final LocalDate transactionDate = this.fromApiJsonHelper.extractLocalDateNamed(LoanApiConstants.transactionDateParamName, element); + this.loanEventApiJsonValidator.validateLoanForeclosure(command.json()); + loan.validateForForeclosure(transactionDate); + final Map<String, Object> changes = new LinkedHashMap<>(); + changes.put("transactionDate", transactionDate); + + String noteText = this.fromApiJsonHelper.extractStringNamed(LoanApiConstants.noteParamName, element); + LoanRescheduleRequest loanRescheduleRequest = null; + this.loanScheduleHistoryWritePlatformService.createAndSaveLoanScheduleArchive(loan.getRepaymentScheduleInstallments(), + loan, loanRescheduleRequest); + loan.updateInstallmentsPostDate(transactionDate); + + final Map<String, Object> modifications = this.loanAccountDomainService.foreCloseLoan(loan, transactionDate, noteText); + changes.putAll(modifications); + + final CommandProcessingResultBuilder commandProcessingResultBuilder = new CommandProcessingResultBuilder(); + return commandProcessingResultBuilder.withLoanId(loanId) // + .with(changes) // + .build(); + } + private void validateIsMultiDisbursalLoanAndDisbursedMoreThanOneTranche(Loan loan) { if (!loan.isMultiDisburmentLoan()) { final String errorMessage = "loan.product.does.not.support.multiple.disbursals.cannot.undo.last.disbursal"; http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/b9b345a5/fineract-provider/src/main/resources/sql/migrations/core_db/V311__foreclosure_details.sql ---------------------------------------------------------------------- diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V311__foreclosure_details.sql b/fineract-provider/src/main/resources/sql/migrations/core_db/V311__foreclosure_details.sql new file mode 100644 index 0000000..63bfc29 --- /dev/null +++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V311__foreclosure_details.sql @@ -0,0 +1,7 @@ +INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES +('portfolio', 'FORECLOSURE_LOAN', 'LOAN', 'FORECLOSURE', 0), +('portfolio', 'FORECLOSURE_LOAN_CHECKER', 'LOAN', 'FORECLOSURE_CHECKER', 0); + + +ALTER TABLE `m_loan` + ADD COLUMN `loan_sub_status_id` SMALLINT(5) NULL DEFAULT NULL; \ No newline at end of file
