[ 
https://issues.apache.org/jira/browse/FINERACT-167?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15322230#comment-15322230
 ] 

ASF GitHub Bot commented on FINERACT-167:
-----------------------------------------

Github user nazeer1100126 commented on a diff in the pull request:

    https://github.com/apache/incubator-fineract/pull/130#discussion_r66409263
  
    --- Diff: 
fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
 ---
    @@ -5972,4 +5986,204 @@ public BigDecimal 
getDerivedAmountForCharge(LoanCharge loanCharge) {
             return amount;
         }
     
    +    public LoanRepaymentScheduleInstallment 
fetchLoanForeclosureDetail(final LocalDate closureDate) {
    +        Money totalPrincipal = Money.of(getCurrency(), 
this.getSummary().getTotalPrincipalOutstanding());
    +        Money[] receivables = 
retriveIncomeOutstandingTillDate(closureDate);
    +        final List<LoanInterestRecalcualtionAdditionalDetails> 
compoundingDetails = null;
    +        return new LoanRepaymentScheduleInstallment(null, 0, 
LocalDate.now(), LocalDate.now(), totalPrincipal.getAmount(),
    +                receivables[0].getAmount(), receivables[1].getAmount(), 
receivables[2].getAmount(), false, compoundingDetails);
    +    }
    +
    +    public Money[] retriveIncomeOutstandingTillDate(final LocalDate 
paymentDate) {
    +        Money[] balances = new Money[3];
    +        final MonetaryCurrency currency = getCurrency();
    +        Money interest = Money.zero(currency);
    +        Money fee = Money.zero(currency);
    +        Money penalty = Money.zero(currency);
    +        boolean isArrearsPresent = false;
    +        for (final LoanRepaymentScheduleInstallment installment : 
this.repaymentScheduleInstallments) {
    +            if (installment.isNotFullyPaidOff()) {
    +                if (!isArrearsPresent || 
!installment.getDueDate().isAfter(paymentDate)) {
    +                    interest = 
interest.plus(installment.getInterestOutstanding(currency));
    +                    fee = 
fee.plus(installment.getFeeChargesOutstanding(currency));
    +                    penalty = 
penalty.plus(installment.getPenaltyChargesOutstanding(currency));
    +                    isArrearsPresent = true;
    +                } else if 
(installment.getFromDate().isBefore(paymentDate)) {
    +                    int totalPeriodDays = 
Days.daysBetween(installment.getFromDate(), installment.getDueDate()).getDays();
    +                    int tillDays = 
Days.daysBetween(installment.getFromDate(), paymentDate).getDays();
    +                    interest = 
interest.plus(calculateInterestForDays(totalPeriodDays, 
installment.getInterestOutstanding(currency)
    +                            .getAmount(), tillDays));
    +                    for (LoanCharge loanCharge : this.charges) {
    +                        if (loanCharge.isActive()
    +                                && 
loanCharge.isDueForCollectionFromAndUpToAndIncluding(installment.getFromDate(), 
paymentDate)) {
    +                            if (loanCharge.isPenaltyCharge()) {
    +                                penalty = 
penalty.plus(loanCharge.getAmountOutstanding(currency));
    +                            } else {
    +                                fee = 
fee.plus(loanCharge.getAmountOutstanding(currency));
    +                            }
    +                        }
    +                    }
    +                }
    +            }
    +        }
    +        balances[0] = interest;
    +        balances[1] = fee;
    +        balances[2] = penalty;
    +        return balances;
    +    }
    +
    +    private double calculateInterestForDays(int daysInPeriod, BigDecimal 
interest, int days) {
    +        if (interest.doubleValue() == 0) { return 0; }
    +        return ((interest.doubleValue()) / daysInPeriod) * days;
    +    }
    +
    +    public boolean canForecloseLoan() {
    +        boolean canForecloseLoan = false;
    +        if (isOpen()) {
    +            canForecloseLoan = true;
    +        }
    +        return canForecloseLoan;
    +    }
    +
    +    public Money[] getReceivableIncome(final LocalDate tillDate) {
    +        MonetaryCurrency currency = getCurrency();
    +        Money receivableInterest = Money.zero(currency);
    +        Money receivableFee = Money.zero(currency);
    +        Money receivablePenalty = Money.zero(currency);
    +        Money[] receivables = new Money[3];
    +        for (final LoanTransaction transaction : this.loanTransactions) {
    +            if (transaction.isNotReversed() && 
!transaction.isRepaymentAtDisbursement() && !transaction.isDisbursement()
    +                    && 
!transaction.getTransactionDate().isAfter(tillDate)) {
    +                if (transaction.isAccrual()) {
    +                    receivableInterest = 
receivableInterest.plus(transaction.getInterestPortion(currency));
    +                    receivableFee = 
receivableFee.plus(transaction.getFeeChargesPortion(currency));
    +                    receivablePenalty = 
receivablePenalty.plus(transaction.getPenaltyChargesPortion(currency));
    +                } else if (transaction.isRepayment() || 
transaction.isChargePayment()) {
    +                    receivableInterest = 
receivableInterest.minus(transaction.getInterestPortion(currency));
    +                    receivableFee = 
receivableFee.minus(transaction.getFeeChargesPortion(currency));
    +                    receivablePenalty = 
receivablePenalty.minus(transaction.getPenaltyChargesPortion(currency));
    +                }
    +            }
    +            if (receivableInterest.isLessThanZero()) {
    +                receivableInterest = receivableInterest.zero();
    +            }
    +            if (receivableFee.isLessThanZero()) {
    +                receivableFee = receivableFee.zero();
    +            }
    +            if (receivablePenalty.isLessThanZero()) {
    +                receivablePenalty = receivablePenalty.zero();
    +            }
    +        }
    +        receivables[0] = receivableInterest;
    +        receivables[1] = receivableFee;
    +        receivables[2] = receivablePenalty;
    +        return receivables;
    +    }
    +
    +    public void handleForeClosureTransactions(final List<LoanTransaction> 
repaymentTransaction,
    +            final LoanForeClosureDetailDTO foreClosureDetailDTO, final 
LoanLifecycleStateMachine loanLifecycleStateMachine) {
    +
    +        LoanEvent event = LoanEvent.LOAN_FORECLOSURE;
    +
    +        validateAccountStatus(event);
    +
    +        MonetaryCurrency currency = getCurrency();
    +
    +        final LoanRepaymentScheduleTransactionProcessor 
loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
    +                .determineProcessor(this.transactionProcessingStrategy);
    +
    +        
loanRepaymentScheduleTransactionProcessor.processTransactionsFromDerivedFields(repaymentTransaction,
 currency,
    +                this.repaymentScheduleInstallments, charges());
    +        this.loanTransactions.addAll(repaymentTransaction);
    +        this.loanSubStatus = LoanSubStatus.FORECLOSED.getValue();
    +        updateLoanSummaryDerivedFields();
    +        
doPostLoanTransactionChecks(foreClosureDetailDTO.getTransactionDate(), 
loanLifecycleStateMachine);
    +    }
    +
    +    public Money retrieveAccruedAmountAfterDate(final LocalDate tillDate) {
    +        Money totalAmountAccrued = Money.zero(getCurrency());
    +        Money actualAmountTobeAccrued = Money.zero(getCurrency());
    +        for (final LoanRepaymentScheduleInstallment installment : 
this.repaymentScheduleInstallments) {
    +            totalAmountAccrued = 
totalAmountAccrued.plus(installment.getInterestAccrued(getCurrency()));
    +
    +            if (tillDate.isAfter(installment.getFromDate()) && 
tillDate.isBefore(installment.getDueDate())) {
    +                int daysInPeriod = 
Days.daysBetween(installment.getFromDate(), installment.getDueDate()).getDays();
    +                int tillDays = Days.daysBetween(installment.getFromDate(), 
tillDate).getDays();
    +                double interest = calculateInterestForDays(daysInPeriod, 
installment.getInterestCharged(getCurrency()).getAmount(),
    +                        tillDays);
    +                actualAmountTobeAccrued = 
actualAmountTobeAccrued.plus(interest);
    +            } else if ((tillDate.isAfter(installment.getFromDate()) && 
tillDate.isEqual(installment.getDueDate()))
    +                    || (tillDate.isEqual(installment.getFromDate()) && 
tillDate.isEqual(installment.getDueDate()))
    +                    || (tillDate.isAfter(installment.getFromDate()) && 
tillDate.isAfter(installment.getDueDate()))) {
    +                actualAmountTobeAccrued = 
actualAmountTobeAccrued.plus(installment.getInterestAccrued(getCurrency()));
    +            }
    +        }
    +        Money accredAmountAfterDate = 
totalAmountAccrued.minus(actualAmountTobeAccrued);
    +        if (accredAmountAfterDate.isLessThanZero()) {
    +            accredAmountAfterDate = Money.zero(getCurrency());
    +        }
    +        return accredAmountAfterDate;
    +    }
    +
    +    public void validateForForeclosure(final LocalDate transactionDate) {
    +
    +        if (isInterestRecalculationEnabledForProduct()) {
    +            final String defaultUserMessage = "The loan with interest 
recalculation enabled cannot be foreclosed.";
    +            throw new 
LoanForeclosureException("loan.with.interest.recalculation.enabled.cannot.be.foreclosured",
 defaultUserMessage,
    +                    getId());
    +        }
    +
    +        LocalDate lastUserTransactionDate = getLastUserTransactionDate();
    +
    +        if (DateUtils.isDateInTheFuture(transactionDate)) {
    +            final String defaultUserMessage = "The transactionDate cannot 
be in the future.";
    +            throw new 
LoanForeclosureException("loan.foreclosure.transaction.date.is.in.future", 
defaultUserMessage, transactionDate);
    +        }
    +
    +        if (lastUserTransactionDate.isAfter(transactionDate)) {
    +            final String defaultUserMessage = "The transactionDate cannot 
be in the future.";
    +            throw new 
LoanForeclosureException("loan.foreclosure.transaction.date.cannot.before.the.last.transaction.date",
    +                    defaultUserMessage, transactionDate);
    +        }
    +    }
    +
    +    public void updateInstallmentsPostDate(LocalDate transactionDate) {
    +        List<LoanRepaymentScheduleInstallment> newInstallments = new 
ArrayList<>(this.repaymentScheduleInstallments);
    +        final MonetaryCurrency currency = getCurrency();
    +        Money totalPrincipal = Money.zero(currency);
    +        Money totalInterest = Money.zero(currency);
    +
    +        for (final LoanRepaymentScheduleInstallment installment : 
this.repaymentScheduleInstallments) {
    +            if (installment.getDueDate().isAfter(transactionDate)) {
    +                totalPrincipal = 
totalPrincipal.plus(installment.getPrincipalOutstanding(currency));
    +                totalInterest = 
totalInterest.plus(installment.getInterestOutstanding(currency));
    +                newInstallments.remove(installment);
    +            }
    +        }
    +
    +        LoanRepaymentScheduleInstallment newInstallment = new 
LoanRepaymentScheduleInstallment(null, newInstallments.size() + 1,
    +                newInstallments.get((newInstallments.size() - 
1)).getDueDate(), transactionDate, totalPrincipal.getAmount(),
    +                totalInterest.getAmount(), BigDecimal.ZERO, 
BigDecimal.ZERO, true, null);
    --- End diff --
    
    Here the interest should be till that foreclosure date and also you need to 
check charges till that date.


> Implementation of loan foreclosure functionality
> ------------------------------------------------
>
>                 Key: FINERACT-167
>                 URL: https://issues.apache.org/jira/browse/FINERACT-167
>             Project: Apache Fineract
>          Issue Type: New Feature
>          Components: Loan
>            Reporter: Vishwanath R
>            Assignee: Markus Geiss
>
> On foreclosure of the active loan application, the following things should 
> happen,
> 1) Repay total loan outstanding principal amount.
> 2) Repay total Interest amount (accrued and due) till Foreclosure date.
> 3) Repay total Fee, Charges or Penalties due, if any till Foreclosure date.
> 4) Accounting entries will be made as per product configuration for interest 
> and loan portfolio payments.
> 5) Future installment Interest, Fee, Charge, or Penalty, if any, is waived 
> off (there won’t be any accounting entries for these transactions).



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to