You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by "ruchiD (via GitHub)" <gi...@apache.org> on 2023/10/18 15:54:06 UTC

[PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

ruchiD opened a new pull request, #3515:
URL: https://github.com/apache/fineract/pull/3515

   ## Description
   Changes for calculating and persisting installment level delinquency data.
   
   Describe the changes made and why they were made.
   
   Ignore if these details are present on the associated [Apache Fineract JIRA ticket](https://github.com/apache/fineract/pull/1284).
   
   
   ## Checklist
   
   Please make sure these boxes are checked before submitting your pull request - thanks!
   
   - [ ] Write the commit message as per https://github.com/apache/fineract/#pull-requests
   
   - [ ] Acknowledge that we will not review PRs that are not passing the build _("green")_ - it is your responsibility to get a proposed PR to pass the build, not primarily the project's maintainers.
   
   - [ ] Create/update unit or integration tests for verifying the changes made.
   
   - [ ] Follow coding conventions at https://cwiki.apache.org/confluence/display/FINERACT/Coding+Conventions.
   
   - [ ] Add required Swagger annotation and update API documentation at fineract-provider/src/main/resources/static/legacy-docs/apiLive.htm with details of any API changes
   
   - [ ] Submission is not a "code dump".  (Large changes can be made "in repository" via a branch.  Ask on the developer mailing list for guidance, if required.)
   
   FYI our guidelines for code reviews are at https://cwiki.apache.org/confluence/display/FINERACT/Code+Review+Guide.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "ruchiD (via GitHub)" <gi...@apache.org>.
ruchiD commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1365227599


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java:
##########
@@ -160,6 +164,9 @@ public CommandProcessingResult applyDelinquencyTagToLoan(Long loanId, JsonComman
         if (delinquencyBucket != null) {
             final CollectionData collectionData = loanDelinquencyDomainService.getOverdueCollectionData(loan);
             changes = lookUpDelinquencyRange(loan, delinquencyBucket, collectionData.getDelinquentDays());
+            if (loan.isEnableInstallmentLevelDelinquency()) {

Review Comment:
   When Loan level delinquency gets calculated it calculates overdueSince date till oldest overdue installment or chargeback date for first non due installment if exists and does not calculates for rest of them. so we need to calculate for all installments separately.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "ruchiD (via GitHub)" <gi...@apache.org>.
ruchiD commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1373536569


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java:
##########
@@ -160,6 +164,9 @@ public CommandProcessingResult applyDelinquencyTagToLoan(Long loanId, JsonComman
         if (delinquencyBucket != null) {
             final CollectionData collectionData = loanDelinquencyDomainService.getOverdueCollectionData(loan);
             changes = lookUpDelinquencyRange(loan, delinquencyBucket, collectionData.getDelinquentDays());
+            if (loan.isEnableInstallmentLevelDelinquency()) {

Review Comment:
   Loan and installment delinquency calculation logic merged.



##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java:
##########
@@ -382,4 +395,95 @@ public int compare(DelinquencyRange o1, DelinquencyRange o2) {
         return ranges;
     }
 
+    private void applyDelinquencyDetailsForLoanInstallments(Loan loan, DelinquencyBucket delinquencyBucket) {
+        for (LoanRepaymentScheduleInstallment installment : loan.getRepaymentScheduleInstallments()) {
+            CollectionData installmentDelinquencyData = loanDelinquencyDomainService.getInstallmentOverdueCollectionData(loan, installment);
+            setInstallmentDelinquencyDetails(loan, installment, delinquencyBucket, installmentDelinquencyData);
+        }
+    }
+
+    private void setInstallmentDelinquencyDetails(Loan loan, LoanRepaymentScheduleInstallment installment,
+            DelinquencyBucket delinquencyBucket, CollectionData installmentDelinquencyData) {
+        Long delinquencyRangeIdForInstallment = getInstallmentDelinquencyRange(delinquencyBucket,
+                installmentDelinquencyData.getDelinquentDays());
+        setDelinquencyDetailsForInstallment(loan, installment, installmentDelinquencyData, delinquencyRangeIdForInstallment);
+    }
+
+    private Long getInstallmentDelinquencyRange(DelinquencyBucket delinquencyBucket, Long overDueDays) {
+        Long delinquencyRangeId = null;
+        if (overDueDays > 0) {
+            // Sort the ranges based on the minAgeDays
+            final List<DelinquencyRange> ranges = sortDelinquencyRangesByMinAge(delinquencyBucket.getRanges());
+            for (final DelinquencyRange delinquencyRange : ranges) {
+                if (delinquencyRange.getMaximumAgeDays() == null) { // Last Range in the Bucket
+                    if (delinquencyRange.getMinimumAgeDays() <= overDueDays) {
+                        delinquencyRangeId = delinquencyRange.getId();
+                        break;
+                    }
+                } else {
+                    if (delinquencyRange.getMinimumAgeDays() <= overDueDays && delinquencyRange.getMaximumAgeDays() >= overDueDays) {
+                        delinquencyRangeId = delinquencyRange.getId();
+                        break;
+                    }
+                }
+            }
+
+        }
+        return delinquencyRangeId;
+    }
+
+    private void setDelinquencyDetailsForInstallment(Loan loan, LoanRepaymentScheduleInstallment installment,
+            CollectionData installmentDelinquencyData, Long delinquencyRangeIdForInstallment) {
+        List<LoanInstallmentDelinquencyTag> installmentDelinquencyTags = new ArrayList<>();
+        LocalDate delinquencyCalculationDate = DateUtils.getBusinessLocalDate();
+
+        Optional<LoanInstallmentDelinquencyTag> currentInstallmentDelinquencyTag = loanInstallmentDelinquencyTagRepository
+                .findByLoanAndInstallment(loan, installment);
+        LoanInstallmentDelinquencyTag previousInstallmentDelinquencyTag = null;
+        if (currentInstallmentDelinquencyTag.isPresent()) {
+            previousInstallmentDelinquencyTag = currentInstallmentDelinquencyTag.get();
+        }
+
+        if (delinquencyRangeIdForInstallment == null) {
+            // if currentInstallmentDelinquencyTag exists and range is null, installment is out of delinquency, delete
+            // delinquency details
+            if (previousInstallmentDelinquencyTag != null) {
+                loanInstallmentDelinquencyTagRepository.delete(previousInstallmentDelinquencyTag);
+            }
+        } else {
+            DelinquencyRange delinquencyRange = repositoryRange.getReferenceById(delinquencyRangeIdForInstallment);
+            LoanInstallmentDelinquencyTag installmentDelinquency = null;
+            if (previousInstallmentDelinquencyTag != null) {
+                if (!previousInstallmentDelinquencyTag.getDelinquencyRange().getId().equals(delinquencyRangeIdForInstallment)) {
+                    // if current delinquency range exists and there is range change, delete previous delinquency
+                    // details and add new range details
+                    installmentDelinquency = new LoanInstallmentDelinquencyTag(delinquencyRange, loan, installment,
+                            delinquencyCalculationDate, null, previousInstallmentDelinquencyTag.getFirstOverdueDate(),
+                            installmentDelinquencyData.getDelinquentAmount());
+                    loanInstallmentDelinquencyTagRepository.delete(previousInstallmentDelinquencyTag);
+                }
+            } else {
+                // add new range, first time delinquent
+                installmentDelinquency = new LoanInstallmentDelinquencyTag(delinquencyRange, loan, installment, delinquencyCalculationDate,
+                        null, installmentDelinquencyData.getDelinquentDate(), installmentDelinquencyData.getDelinquentAmount());
+            }
+
+            if (installmentDelinquency != null) {
+                installmentDelinquencyTags.add(installmentDelinquency);
+            }
+
+        }
+
+        if (installmentDelinquencyTags.size() > 0) {
+            loanInstallmentDelinquencyTagRepository.saveAllAndFlush(installmentDelinquencyTags);
+        }
+
+    }
+
+    private void cleanLoanInstallmentsDelinquencyTags(Loan loan) {
+        List<LoanInstallmentDelinquencyTag> installmentDelinquencyTags = loanInstallmentDelinquencyTagRepository.findByLoan(loan);

Review Comment:
   done



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1371855324


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanInstallmentDelinquencyTagRemovalServiceImpl.java:
##########
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.loanaccount.service;
+
+import java.util.List;
+import lombok.RequiredArgsConstructor;
+import org.apache.fineract.portfolio.delinquency.domain.LoanInstallmentDelinquencyTag;
+import org.apache.fineract.portfolio.delinquency.domain.LoanInstallmentDelinquencyTagRepository;
+import org.springframework.stereotype.Component;
+
+@RequiredArgsConstructor
+@Component
+public class LoanInstallmentDelinquencyTagRemovalServiceImpl implements LoanInstallmentDelinquencyTagRemovalService {
+
+    private final LoanInstallmentDelinquencyTagRepository loanInstallmentDelinquencyTagRepository;
+
+    @Override
+    public void removeDelinquencyTagsForNonExistingInstallments(Long loanId) {

Review Comment:
   i am not fully sure why we need this:
   - Either you are deleting all of the tags and recalculate all of them and store
   or
   - You are removing which is not delinquent anymore / not existing (when you calculated the new entries, you have all the information to remove the "old" ones)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1371856100


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountConfiguration.java:
##########
@@ -239,7 +241,8 @@ public LoanApplicationWritePlatformService loanApplicationWritePlatformService(P
                 configurationDomainService, loanScheduleAssembler, loanUtilService, calendarReadPlatformService,
                 entityDatatableChecksWritePlatformService, globalConfigurationRepository, entityMappingRepository,
                 fineractEntityRelationRepository, loanProductReadPlatformService, rateAssembler, glimAccountInfoWritePlatformService,
-                glimRepository, loanRepository, gsimReadPlatformService, defaultLoanLifecycleStateMachine);
+                glimRepository, loanRepository, gsimReadPlatformService, defaultLoanLifecycleStateMachine,
+                loanInstallmentDelinquencyTagRemovalService);

Review Comment:
   Please undo this. There must be a different place and way to handle it!



##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountConfiguration.java:
##########
@@ -413,7 +417,7 @@ public LoanWritePlatformService loanWritePlatformService(PlatformSecurityContext
                 cashierTransactionDataValidator, glimRepository, loanRepository, repaymentWithPostDatedChecksAssembler,
                 postDatedChecksRepository, loanDisbursementDetailsRepository, loanRepaymentScheduleInstallmentRepository,
                 defaultLoanLifecycleStateMachine, loanAccountLockService, externalIdFactory, replayedTransactionBusinessEventService,
-                loanAccrualTransactionBusinessEventService, errorHandler);
+                loanAccrualTransactionBusinessEventService, errorHandler, loanInstallmentDelinquencyTagRemovalService);

Review Comment:
   Please undo this. There must be a different place and way to handle it!



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "ruchiD (via GitHub)" <gi...@apache.org>.
ruchiD commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1373539828


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java:
##########
@@ -382,4 +408,96 @@ public int compare(DelinquencyRange o1, DelinquencyRange o2) {
         return ranges;
     }
 
+    private void applyDelinquencyDetailsForLoanInstallments(final Loan loan, final DelinquencyBucket delinquencyBucket,
+            final Map<Long, CollectionData> installmentsCollectionData) {
+        for (Map.Entry<Long, CollectionData> installmentCollectionData : installmentsCollectionData.entrySet()) {
+            Optional<LoanRepaymentScheduleInstallment> installment = loan.getRepaymentScheduleInstallments().stream()
+                    .filter(instalment -> instalment.getId().equals(installmentCollectionData.getKey())).findFirst();
+            if (installment.isPresent()) {
+                setInstallmentDelinquencyDetails(loan, installment.get(), delinquencyBucket, installmentCollectionData.getValue());
+            }
+        }
+    }
+
+    private void setInstallmentDelinquencyDetails(final Loan loan, final LoanRepaymentScheduleInstallment installment,
+            final DelinquencyBucket delinquencyBucket, final CollectionData installmentDelinquencyData) {
+        DelinquencyRange delinquencyRangeForInstallment = getInstallmentDelinquencyRange(delinquencyBucket,
+                installmentDelinquencyData.getDelinquentDays());
+        setDelinquencyDetailsForInstallment(loan, installment, installmentDelinquencyData, delinquencyRangeForInstallment);
+    }
+
+    private DelinquencyRange getInstallmentDelinquencyRange(final DelinquencyBucket delinquencyBucket, Long overDueDays) {
+        DelinquencyRange delinquencyRangeForInstallment = null;
+        if (overDueDays > 0) {
+            // Sort the ranges based on the minAgeDays
+            final List<DelinquencyRange> ranges = sortDelinquencyRangesByMinAge(delinquencyBucket.getRanges());
+            for (final DelinquencyRange delinquencyRange : ranges) {
+                if (delinquencyRange.getMaximumAgeDays() == null) { // Last Range in the Bucket
+                    if (delinquencyRange.getMinimumAgeDays() <= overDueDays) {
+                        delinquencyRangeForInstallment = delinquencyRange;
+                        break;
+                    }
+                } else {
+                    if (delinquencyRange.getMinimumAgeDays() <= overDueDays && delinquencyRange.getMaximumAgeDays() >= overDueDays) {
+                        delinquencyRangeForInstallment = delinquencyRange;
+                        break;
+                    }
+                }
+            }
+
+        }
+        return delinquencyRangeForInstallment;
+    }
+
+    private void setDelinquencyDetailsForInstallment(final Loan loan, final LoanRepaymentScheduleInstallment installment,
+            CollectionData installmentDelinquencyData, final DelinquencyRange delinquencyRangeForInstallment) {
+        List<LoanInstallmentDelinquencyTag> installmentDelinquencyTags = new ArrayList<>();
+        LocalDate delinquencyCalculationDate = DateUtils.getBusinessLocalDate();
+
+        Optional<LoanInstallmentDelinquencyTag> currentInstallmentDelinquencyTag = loanInstallmentDelinquencyTagRepository
+                .findByLoanAndInstallment(loan, installment);
+        LoanInstallmentDelinquencyTag previousInstallmentDelinquencyTag = null;
+        if (currentInstallmentDelinquencyTag.isPresent()) {
+            previousInstallmentDelinquencyTag = currentInstallmentDelinquencyTag.get();
+        }
+
+        if (delinquencyRangeForInstallment == null) {
+            // if currentInstallmentDelinquencyTag exists and range is null, installment is out of delinquency, delete

Review Comment:
   Previous delinquency tag needed for range change  and out of delinquency events.



##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java:
##########
@@ -382,4 +408,96 @@ public int compare(DelinquencyRange o1, DelinquencyRange o2) {
         return ranges;
     }
 
+    private void applyDelinquencyDetailsForLoanInstallments(final Loan loan, final DelinquencyBucket delinquencyBucket,
+            final Map<Long, CollectionData> installmentsCollectionData) {
+        for (Map.Entry<Long, CollectionData> installmentCollectionData : installmentsCollectionData.entrySet()) {
+            Optional<LoanRepaymentScheduleInstallment> installment = loan.getRepaymentScheduleInstallments().stream()
+                    .filter(instalment -> instalment.getId().equals(installmentCollectionData.getKey())).findFirst();
+            if (installment.isPresent()) {
+                setInstallmentDelinquencyDetails(loan, installment.get(), delinquencyBucket, installmentCollectionData.getValue());
+            }
+        }
+    }
+
+    private void setInstallmentDelinquencyDetails(final Loan loan, final LoanRepaymentScheduleInstallment installment,
+            final DelinquencyBucket delinquencyBucket, final CollectionData installmentDelinquencyData) {
+        DelinquencyRange delinquencyRangeForInstallment = getInstallmentDelinquencyRange(delinquencyBucket,
+                installmentDelinquencyData.getDelinquentDays());
+        setDelinquencyDetailsForInstallment(loan, installment, installmentDelinquencyData, delinquencyRangeForInstallment);
+    }
+
+    private DelinquencyRange getInstallmentDelinquencyRange(final DelinquencyBucket delinquencyBucket, Long overDueDays) {
+        DelinquencyRange delinquencyRangeForInstallment = null;
+        if (overDueDays > 0) {
+            // Sort the ranges based on the minAgeDays
+            final List<DelinquencyRange> ranges = sortDelinquencyRangesByMinAge(delinquencyBucket.getRanges());
+            for (final DelinquencyRange delinquencyRange : ranges) {
+                if (delinquencyRange.getMaximumAgeDays() == null) { // Last Range in the Bucket
+                    if (delinquencyRange.getMinimumAgeDays() <= overDueDays) {
+                        delinquencyRangeForInstallment = delinquencyRange;
+                        break;
+                    }
+                } else {
+                    if (delinquencyRange.getMinimumAgeDays() <= overDueDays && delinquencyRange.getMaximumAgeDays() >= overDueDays) {
+                        delinquencyRangeForInstallment = delinquencyRange;
+                        break;
+                    }
+                }
+            }
+
+        }
+        return delinquencyRangeForInstallment;
+    }
+
+    private void setDelinquencyDetailsForInstallment(final Loan loan, final LoanRepaymentScheduleInstallment installment,
+            CollectionData installmentDelinquencyData, final DelinquencyRange delinquencyRangeForInstallment) {
+        List<LoanInstallmentDelinquencyTag> installmentDelinquencyTags = new ArrayList<>();
+        LocalDate delinquencyCalculationDate = DateUtils.getBusinessLocalDate();
+
+        Optional<LoanInstallmentDelinquencyTag> currentInstallmentDelinquencyTag = loanInstallmentDelinquencyTagRepository
+                .findByLoanAndInstallment(loan, installment);
+        LoanInstallmentDelinquencyTag previousInstallmentDelinquencyTag = null;
+        if (currentInstallmentDelinquencyTag.isPresent()) {
+            previousInstallmentDelinquencyTag = currentInstallmentDelinquencyTag.get();
+        }
+
+        if (delinquencyRangeForInstallment == null) {
+            // if currentInstallmentDelinquencyTag exists and range is null, installment is out of delinquency, delete
+            // delinquency details
+            if (previousInstallmentDelinquencyTag != null) {
+                loanInstallmentDelinquencyTagRepository.delete(previousInstallmentDelinquencyTag);
+            }
+        } else {
+            LoanInstallmentDelinquencyTag installmentDelinquency = null;
+            if (previousInstallmentDelinquencyTag != null) {
+                if (!previousInstallmentDelinquencyTag.getDelinquencyRange().getId().equals(delinquencyRangeForInstallment.getId())) {
+                    // if current delinquency range exists and there is range change, delete previous delinquency
+                    // details and add new range details
+                    installmentDelinquency = new LoanInstallmentDelinquencyTag(delinquencyRangeForInstallment, loan, installment,
+                            delinquencyCalculationDate, null, previousInstallmentDelinquencyTag.getFirstOverdueDate(),
+                            installmentDelinquencyData.getDelinquentAmount());
+                    loanInstallmentDelinquencyTagRepository.delete(previousInstallmentDelinquencyTag);

Review Comment:
   Previous delinquency tag needed for range change and out of delinquency events.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1371846842


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/LoanDelinquencyDomainServiceImpl.java:
##########
@@ -61,60 +59,90 @@ public CollectionData getOverdueCollectionData(final Loan loan) {
                     outstandingAmount = outstandingAmount.add(installment.getTotalOutstanding(loanCurrency).getAmount());
                     if (!oldestOverdueInstallment) {
                         log.debug("Oldest installment {} {}", installment.getInstallmentNumber(), installment.getDueDate());
+                        CollectionData overDueInstallmentDelinquentData = calculateDelinquencyDataForOverdueInstallment(loan, installment);
+                        overdueSinceDate = overDueInstallmentDelinquentData.getDelinquentDate();
                         oldestOverdueInstallment = true;
-                        overdueSinceDate = installment.getDueDate();
                         overdueSinceDateWasSet = true;
-
-                        amountAvailable = installment.getTotalPaid(loanCurrency).getAmount();
-
-                        boolean isLatestInstallment = Objects.equals(installment.getId(), latestInstallment.getId());
-                        for (LoanTransaction loanTransaction : chargebackTransactions) {
-                            boolean isLoanTransactionIsOnOrAfterInstallmentFromDate = loanTransaction.getTransactionDate().isEqual(
-                                    installment.getFromDate()) || loanTransaction.getTransactionDate().isAfter(installment.getFromDate());
-                            boolean isLoanTransactionIsBeforeNotLastInstallmentDueDate = !isLatestInstallment
-                                    && loanTransaction.getTransactionDate().isBefore(installment.getDueDate());
-                            boolean isLoanTransactionIsOnOrBeforeLastInstallmentDueDate = isLatestInstallment
-                                    && (loanTransaction.getTransactionDate().isEqual(installment.getDueDate())
-                                            || loanTransaction.getTransactionDate().isBefore(installment.getDueDate()));
-                            if (isLoanTransactionIsOnOrAfterInstallmentFromDate && (isLoanTransactionIsBeforeNotLastInstallmentDueDate
-                                    || isLoanTransactionIsOnOrBeforeLastInstallmentDueDate)) {
-                                amountAvailable = amountAvailable.subtract(loanTransaction.getAmount());
-                                if (amountAvailable.compareTo(BigDecimal.ZERO) < 0) {
-                                    overdueSinceDate = loanTransaction.getTransactionDate();
-                                    break;
-                                }
-                            }
-                        }
                     }
                 } else if (!firstNotYetDueInstallment) {
                     log.debug("Loan Id: {} with installment {} due date {}", loan.getId(), installment.getInstallmentNumber(),
                             installment.getDueDate());
                     firstNotYetDueInstallment = true;
-                    amountAvailable = installment.getTotalPaid(loanCurrency).getAmount();
-                    log.debug("Amount available {}", amountAvailable);
-                    for (LoanTransaction loanTransaction : chargebackTransactions) {
-                        boolean isLoanTransactionIsOnOrAfterInstallmentFromDate = loanTransaction.getTransactionDate().isEqual(
-                                installment.getFromDate()) || loanTransaction.getTransactionDate().isAfter(installment.getFromDate());
-                        boolean isLoanTransactionIsBeforeInstallmentDueDate = loanTransaction.getTransactionDate()
-                                .isBefore(installment.getDueDate());
-                        boolean isLoanTransactionIsBeforeBusinessDate = loanTransaction.getTransactionDate().isBefore(businessDate);
-                        if (isLoanTransactionIsOnOrAfterInstallmentFromDate && isLoanTransactionIsBeforeInstallmentDueDate
-                                && isLoanTransactionIsBeforeBusinessDate) {
-                            log.debug("Loan CB Transaction: {} {} {}", loanTransaction.getId(), loanTransaction.getTransactionDate(),
-                                    loanTransaction.getAmount());
-                            amountAvailable = amountAvailable.subtract(loanTransaction.getAmount());
-                            if (amountAvailable.compareTo(BigDecimal.ZERO) < 0 && !overdueSinceDateWasSet) {
-                                overdueSinceDate = loanTransaction.getTransactionDate();
-                                overdueSinceDateWasSet = true;
-                            }
-                        }

Review Comment:
   It is hard to see what got changed. Can you please explain the changes in a couple sentences?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "ruchiD (via GitHub)" <gi...@apache.org>.
ruchiD commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1373538322


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java:
##########
@@ -382,4 +408,96 @@ public int compare(DelinquencyRange o1, DelinquencyRange o2) {
         return ranges;
     }
 
+    private void applyDelinquencyDetailsForLoanInstallments(final Loan loan, final DelinquencyBucket delinquencyBucket,
+            final Map<Long, CollectionData> installmentsCollectionData) {
+        for (Map.Entry<Long, CollectionData> installmentCollectionData : installmentsCollectionData.entrySet()) {
+            Optional<LoanRepaymentScheduleInstallment> installment = loan.getRepaymentScheduleInstallments().stream()
+                    .filter(instalment -> instalment.getId().equals(installmentCollectionData.getKey())).findFirst();
+            if (installment.isPresent()) {
+                setInstallmentDelinquencyDetails(loan, installment.get(), delinquencyBucket, installmentCollectionData.getValue());
+            }
+        }
+    }
+
+    private void setInstallmentDelinquencyDetails(final Loan loan, final LoanRepaymentScheduleInstallment installment,
+            final DelinquencyBucket delinquencyBucket, final CollectionData installmentDelinquencyData) {
+        DelinquencyRange delinquencyRangeForInstallment = getInstallmentDelinquencyRange(delinquencyBucket,
+                installmentDelinquencyData.getDelinquentDays());
+        setDelinquencyDetailsForInstallment(loan, installment, installmentDelinquencyData, delinquencyRangeForInstallment);
+    }
+
+    private DelinquencyRange getInstallmentDelinquencyRange(final DelinquencyBucket delinquencyBucket, Long overDueDays) {
+        DelinquencyRange delinquencyRangeForInstallment = null;
+        if (overDueDays > 0) {
+            // Sort the ranges based on the minAgeDays
+            final List<DelinquencyRange> ranges = sortDelinquencyRangesByMinAge(delinquencyBucket.getRanges());
+            for (final DelinquencyRange delinquencyRange : ranges) {
+                if (delinquencyRange.getMaximumAgeDays() == null) { // Last Range in the Bucket
+                    if (delinquencyRange.getMinimumAgeDays() <= overDueDays) {
+                        delinquencyRangeForInstallment = delinquencyRange;
+                        break;
+                    }
+                } else {
+                    if (delinquencyRange.getMinimumAgeDays() <= overDueDays && delinquencyRange.getMaximumAgeDays() >= overDueDays) {
+                        delinquencyRangeForInstallment = delinquencyRange;
+                        break;
+                    }
+                }
+            }
+
+        }
+        return delinquencyRangeForInstallment;
+    }
+
+    private void setDelinquencyDetailsForInstallment(final Loan loan, final LoanRepaymentScheduleInstallment installment,
+            CollectionData installmentDelinquencyData, final DelinquencyRange delinquencyRangeForInstallment) {
+        List<LoanInstallmentDelinquencyTag> installmentDelinquencyTags = new ArrayList<>();
+        LocalDate delinquencyCalculationDate = DateUtils.getBusinessLocalDate();
+
+        Optional<LoanInstallmentDelinquencyTag> currentInstallmentDelinquencyTag = loanInstallmentDelinquencyTagRepository

Review Comment:
   done



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1371808991


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyReadPlatformServiceImpl.java:
##########
@@ -126,4 +133,18 @@ public CollectionData calculateLoanCollectionData(final Long loanId) {
         return collectionData;
     }
 
+    @Override
+    public Collection<LoanInstallmentDelinquencyTagData> retrieveLoanInstallmentsCurrentDelinquencyTag(Long loanId) {
+
+        List<LoanInstallmentDelinquencyTagData> loanInstallmentsDelinquencyData = new ArrayList<>();
+        List<LoanInstallmentDelinquencyTag> loanInstallmentsCurrentDelinquency = repositoryLoanInstallmentDelinquencyTag
+                .findByLoanId(loanId);
+        for (LoanInstallmentDelinquencyTag installmentDelinquencyTag : loanInstallmentsCurrentDelinquency) {

Review Comment:
   Still loading the loan for no reason. Please fetch the required `loanInstallmentsDelinquencyData` via the repository using JPA projections:
   
   https://www.baeldung.com/spring-data-jpa-projections



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1371844171


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java:
##########
@@ -382,4 +408,96 @@ public int compare(DelinquencyRange o1, DelinquencyRange o2) {
         return ranges;
     }
 
+    private void applyDelinquencyDetailsForLoanInstallments(final Loan loan, final DelinquencyBucket delinquencyBucket,
+            final Map<Long, CollectionData> installmentsCollectionData) {
+        for (Map.Entry<Long, CollectionData> installmentCollectionData : installmentsCollectionData.entrySet()) {
+            Optional<LoanRepaymentScheduleInstallment> installment = loan.getRepaymentScheduleInstallments().stream()
+                    .filter(instalment -> instalment.getId().equals(installmentCollectionData.getKey())).findFirst();
+            if (installment.isPresent()) {
+                setInstallmentDelinquencyDetails(loan, installment.get(), delinquencyBucket, installmentCollectionData.getValue());
+            }
+        }
+    }
+
+    private void setInstallmentDelinquencyDetails(final Loan loan, final LoanRepaymentScheduleInstallment installment,
+            final DelinquencyBucket delinquencyBucket, final CollectionData installmentDelinquencyData) {
+        DelinquencyRange delinquencyRangeForInstallment = getInstallmentDelinquencyRange(delinquencyBucket,
+                installmentDelinquencyData.getDelinquentDays());
+        setDelinquencyDetailsForInstallment(loan, installment, installmentDelinquencyData, delinquencyRangeForInstallment);
+    }
+
+    private DelinquencyRange getInstallmentDelinquencyRange(final DelinquencyBucket delinquencyBucket, Long overDueDays) {
+        DelinquencyRange delinquencyRangeForInstallment = null;
+        if (overDueDays > 0) {
+            // Sort the ranges based on the minAgeDays
+            final List<DelinquencyRange> ranges = sortDelinquencyRangesByMinAge(delinquencyBucket.getRanges());
+            for (final DelinquencyRange delinquencyRange : ranges) {
+                if (delinquencyRange.getMaximumAgeDays() == null) { // Last Range in the Bucket
+                    if (delinquencyRange.getMinimumAgeDays() <= overDueDays) {
+                        delinquencyRangeForInstallment = delinquencyRange;
+                        break;
+                    }
+                } else {
+                    if (delinquencyRange.getMinimumAgeDays() <= overDueDays && delinquencyRange.getMaximumAgeDays() >= overDueDays) {
+                        delinquencyRangeForInstallment = delinquencyRange;
+                        break;
+                    }
+                }
+            }
+
+        }
+        return delinquencyRangeForInstallment;
+    }
+
+    private void setDelinquencyDetailsForInstallment(final Loan loan, final LoanRepaymentScheduleInstallment installment,
+            CollectionData installmentDelinquencyData, final DelinquencyRange delinquencyRangeForInstallment) {
+        List<LoanInstallmentDelinquencyTag> installmentDelinquencyTags = new ArrayList<>();
+        LocalDate delinquencyCalculationDate = DateUtils.getBusinessLocalDate();
+
+        Optional<LoanInstallmentDelinquencyTag> currentInstallmentDelinquencyTag = loanInstallmentDelinquencyTagRepository
+                .findByLoanAndInstallment(loan, installment);
+        LoanInstallmentDelinquencyTag previousInstallmentDelinquencyTag = null;
+        if (currentInstallmentDelinquencyTag.isPresent()) {
+            previousInstallmentDelinquencyTag = currentInstallmentDelinquencyTag.get();
+        }
+
+        if (delinquencyRangeForInstallment == null) {
+            // if currentInstallmentDelinquencyTag exists and range is null, installment is out of delinquency, delete
+            // delinquency details
+            if (previousInstallmentDelinquencyTag != null) {
+                loanInstallmentDelinquencyTagRepository.delete(previousInstallmentDelinquencyTag);
+            }
+        } else {
+            LoanInstallmentDelinquencyTag installmentDelinquency = null;
+            if (previousInstallmentDelinquencyTag != null) {
+                if (!previousInstallmentDelinquencyTag.getDelinquencyRange().getId().equals(delinquencyRangeForInstallment.getId())) {
+                    // if current delinquency range exists and there is range change, delete previous delinquency
+                    // details and add new range details
+                    installmentDelinquency = new LoanInstallmentDelinquencyTag(delinquencyRangeForInstallment, loan, installment,
+                            delinquencyCalculationDate, null, previousInstallmentDelinquencyTag.getFirstOverdueDate(),
+                            installmentDelinquencyData.getDelinquentAmount());
+                    loanInstallmentDelinquencyTagRepository.delete(previousInstallmentDelinquencyTag);

Review Comment:
   same here



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1365265378


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java:
##########
@@ -160,6 +164,9 @@ public CommandProcessingResult applyDelinquencyTagToLoan(Long loanId, JsonComman
         if (delinquencyBucket != null) {
             final CollectionData collectionData = loanDelinquencyDomainService.getOverdueCollectionData(loan);
             changes = lookUpDelinquencyRange(loan, delinquencyBucket, collectionData.getDelinquentDays());
+            if (loan.isEnableInstallmentLevelDelinquency()) {

Review Comment:
   i was just wondering when we are calculating the loan delinquency and we are going through on the installments one by one,  we can calculate the delinquency for installment as well. What do you think?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1371856188


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountConfiguration.java:
##########
@@ -413,7 +417,7 @@ public LoanWritePlatformService loanWritePlatformService(PlatformSecurityContext
                 cashierTransactionDataValidator, glimRepository, loanRepository, repaymentWithPostDatedChecksAssembler,
                 postDatedChecksRepository, loanDisbursementDetailsRepository, loanRepaymentScheduleInstallmentRepository,
                 defaultLoanLifecycleStateMachine, loanAccountLockService, externalIdFactory, replayedTransactionBusinessEventService,
-                loanAccrualTransactionBusinessEventService, errorHandler);
+                loanAccrualTransactionBusinessEventService, errorHandler, loanInstallmentDelinquencyTagRemovalService);

Review Comment:
   Please undo this. There must be a different place and way to handle it!



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "ruchiD (via GitHub)" <gi...@apache.org>.
ruchiD commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1365227599


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java:
##########
@@ -160,6 +164,9 @@ public CommandProcessingResult applyDelinquencyTagToLoan(Long loanId, JsonComman
         if (delinquencyBucket != null) {
             final CollectionData collectionData = loanDelinquencyDomainService.getOverdueCollectionData(loan);
             changes = lookUpDelinquencyRange(loan, delinquencyBucket, collectionData.getDelinquentDays());
+            if (loan.isEnableInstallmentLevelDelinquency()) {

Review Comment:
   When Loan level delinquency gets calculated it calculates till oldest overdue installment or chargeback date for first non due installment if exists and does not calculates for rest of them. so we need to calculate for all installments separately.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "ruchiD (via GitHub)" <gi...@apache.org>.
ruchiD commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1373535942


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyReadPlatformServiceImpl.java:
##########
@@ -126,4 +134,20 @@ public CollectionData calculateLoanCollectionData(final Long loanId) {
         return collectionData;
     }
 
+    @Override
+    public Collection<LoanInstallmentDelinquencyTagData> retrieveLoanInstallmentsCurrentDelinquencyTag(Long loanId) {

Review Comment:
   done. Retrieving only DelinquencyRange and OutstandingAmount for installments as required by Api.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1371843360


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java:
##########
@@ -382,4 +408,96 @@ public int compare(DelinquencyRange o1, DelinquencyRange o2) {
         return ranges;
     }
 
+    private void applyDelinquencyDetailsForLoanInstallments(final Loan loan, final DelinquencyBucket delinquencyBucket,
+            final Map<Long, CollectionData> installmentsCollectionData) {
+        for (Map.Entry<Long, CollectionData> installmentCollectionData : installmentsCollectionData.entrySet()) {
+            Optional<LoanRepaymentScheduleInstallment> installment = loan.getRepaymentScheduleInstallments().stream()
+                    .filter(instalment -> instalment.getId().equals(installmentCollectionData.getKey())).findFirst();
+            if (installment.isPresent()) {
+                setInstallmentDelinquencyDetails(loan, installment.get(), delinquencyBucket, installmentCollectionData.getValue());
+            }
+        }
+    }
+
+    private void setInstallmentDelinquencyDetails(final Loan loan, final LoanRepaymentScheduleInstallment installment,
+            final DelinquencyBucket delinquencyBucket, final CollectionData installmentDelinquencyData) {
+        DelinquencyRange delinquencyRangeForInstallment = getInstallmentDelinquencyRange(delinquencyBucket,
+                installmentDelinquencyData.getDelinquentDays());
+        setDelinquencyDetailsForInstallment(loan, installment, installmentDelinquencyData, delinquencyRangeForInstallment);
+    }
+
+    private DelinquencyRange getInstallmentDelinquencyRange(final DelinquencyBucket delinquencyBucket, Long overDueDays) {
+        DelinquencyRange delinquencyRangeForInstallment = null;
+        if (overDueDays > 0) {
+            // Sort the ranges based on the minAgeDays
+            final List<DelinquencyRange> ranges = sortDelinquencyRangesByMinAge(delinquencyBucket.getRanges());
+            for (final DelinquencyRange delinquencyRange : ranges) {
+                if (delinquencyRange.getMaximumAgeDays() == null) { // Last Range in the Bucket
+                    if (delinquencyRange.getMinimumAgeDays() <= overDueDays) {
+                        delinquencyRangeForInstallment = delinquencyRange;
+                        break;
+                    }
+                } else {
+                    if (delinquencyRange.getMinimumAgeDays() <= overDueDays && delinquencyRange.getMaximumAgeDays() >= overDueDays) {
+                        delinquencyRangeForInstallment = delinquencyRange;
+                        break;
+                    }
+                }
+            }
+
+        }
+        return delinquencyRangeForInstallment;
+    }
+
+    private void setDelinquencyDetailsForInstallment(final Loan loan, final LoanRepaymentScheduleInstallment installment,
+            CollectionData installmentDelinquencyData, final DelinquencyRange delinquencyRangeForInstallment) {
+        List<LoanInstallmentDelinquencyTag> installmentDelinquencyTags = new ArrayList<>();
+        LocalDate delinquencyCalculationDate = DateUtils.getBusinessLocalDate();
+
+        Optional<LoanInstallmentDelinquencyTag> currentInstallmentDelinquencyTag = loanInstallmentDelinquencyTagRepository
+                .findByLoanAndInstallment(loan, installment);
+        LoanInstallmentDelinquencyTag previousInstallmentDelinquencyTag = null;
+        if (currentInstallmentDelinquencyTag.isPresent()) {
+            previousInstallmentDelinquencyTag = currentInstallmentDelinquencyTag.get();
+        }
+
+        if (delinquencyRangeForInstallment == null) {
+            // if currentInstallmentDelinquencyTag exists and range is null, installment is out of delinquency, delete

Review Comment:
   You dont need to fetch the tag to decide here whether it need to be deleted or not. You can immediately delete it if the range is null. no?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1364194571


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/data/LoanInstallmentDelinquencyTagHistoryData.java:
##########
@@ -0,0 +1,41 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.delinquency.data;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+@ToString
+@AllArgsConstructor
+@Getter
+@Setter
+public class LoanInstallmentDelinquencyTagHistoryData {

Review Comment:
   Since we would not keep this entries, rather regenerate them, please remove the "History" from everywhere



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "ruchiD (via GitHub)" <gi...@apache.org>.
ruchiD commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1373541200


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanInstallmentDelinquencyTagRemovalServiceImpl.java:
##########
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.loanaccount.service;
+
+import java.util.List;
+import lombok.RequiredArgsConstructor;
+import org.apache.fineract.portfolio.delinquency.domain.LoanInstallmentDelinquencyTag;
+import org.apache.fineract.portfolio.delinquency.domain.LoanInstallmentDelinquencyTagRepository;
+import org.springframework.stereotype.Component;
+
+@RequiredArgsConstructor
+@Component
+public class LoanInstallmentDelinquencyTagRemovalServiceImpl implements LoanInstallmentDelinquencyTagRemovalService {
+
+    private final LoanInstallmentDelinquencyTagRepository loanInstallmentDelinquencyTagRepository;
+
+    @Override
+    public void removeDelinquencyTagsForNonExistingInstallments(Long loanId) {

Review Comment:
   Moved this logic to delinquency calculation service.



##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java:
##########
@@ -635,6 +636,9 @@ private Loan saveAndFlushLoanWithDataIntegrityViolationChecks(final Loan loan) {
          */
         try {
             loanRepaymentScheduleInstallmentRepository.saveAll(loan.getRepaymentScheduleInstallments());
+            if (loan.isEnableInstallmentLevelDelinquency()) {

Review Comment:
   done



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy merged PR #3515:
URL: https://github.com/apache/fineract/pull/3515


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1371833854


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java:
##########
@@ -382,4 +408,96 @@ public int compare(DelinquencyRange o1, DelinquencyRange o2) {
         return ranges;
     }
 
+    private void applyDelinquencyDetailsForLoanInstallments(final Loan loan, final DelinquencyBucket delinquencyBucket,
+            final Map<Long, CollectionData> installmentsCollectionData) {
+        for (Map.Entry<Long, CollectionData> installmentCollectionData : installmentsCollectionData.entrySet()) {
+            Optional<LoanRepaymentScheduleInstallment> installment = loan.getRepaymentScheduleInstallments().stream()

Review Comment:
   This can be optimised a little bit:
   Iterate through the installments of the loan and get by id from the installmentCollectionData the entry. If there is none, go next.
   
   This way you only iterate through on the installments only once.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1371855838


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java:
##########
@@ -635,6 +636,9 @@ private Loan saveAndFlushLoanWithDataIntegrityViolationChecks(final Loan loan) {
          */
         try {
             loanRepaymentScheduleInstallmentRepository.saveAll(loan.getRepaymentScheduleInstallments());
+            if (loan.isEnableInstallmentLevelDelinquency()) {

Review Comment:
   Please undo this. There must be a different place and way to handle it!



##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountConfiguration.java:
##########
@@ -239,7 +241,8 @@ public LoanApplicationWritePlatformService loanApplicationWritePlatformService(P
                 configurationDomainService, loanScheduleAssembler, loanUtilService, calendarReadPlatformService,
                 entityDatatableChecksWritePlatformService, globalConfigurationRepository, entityMappingRepository,
                 fineractEntityRelationRepository, loanProductReadPlatformService, rateAssembler, glimAccountInfoWritePlatformService,
-                glimRepository, loanRepository, gsimReadPlatformService, defaultLoanLifecycleStateMachine);
+                glimRepository, loanRepository, gsimReadPlatformService, defaultLoanLifecycleStateMachine,
+                loanInstallmentDelinquencyTagRemovalService);

Review Comment:
   Please undo this. There must be a different place and way to handle it!



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1365154052


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyReadPlatformServiceImpl.java:
##########
@@ -126,4 +134,20 @@ public CollectionData calculateLoanCollectionData(final Long loanId) {
         return collectionData;
     }
 
+    @Override
+    public Collection<LoanInstallmentDelinquencyTagData> retrieveLoanInstallmentsCurrentDelinquencyTag(Long loanId) {

Review Comment:
   Please rewrite this to not load the loan (even if you fetch only a reference, then moment you are fetching one of its field, its fetches the full loan) and fetch one by one the installments and its delinquency tags, please do it in one shot:
   - Write a query that fetches them via the delinquency repository
   
   You might wanna consider using: https://www.baeldung.com/spring-data-jpa-projections



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "ruchiD (via GitHub)" <gi...@apache.org>.
ruchiD commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1364964070


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/domain/LoanInstallmentDelinquencyTagHistory.java:
##########
@@ -0,0 +1,80 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.delinquency.domain;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import jakarta.persistence.Version;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
+import org.apache.fineract.portfolio.loanaccount.domain.Loan;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@Entity
+@Table(name = "m_loan_installment_delinquency_tag_history")
+public class LoanInstallmentDelinquencyTagHistory extends AbstractAuditableWithUTCDateTimeCustom {
+
+    @ManyToOne
+    @JoinColumn(name = "delinquency_range_id", nullable = false)
+    private DelinquencyRange delinquencyRange;
+
+    @ManyToOne
+    @JoinColumn(name = "loan_id", nullable = false)
+    private Loan loan;
+
+    @ManyToOne
+    @JoinColumn(name = "installment_id", nullable = false)
+    private LoanRepaymentScheduleInstallment installment;
+
+    @Column(name = "addedon_date", nullable = false)
+    private LocalDate addedOnDate;
+
+    @Column(name = "liftedon_date", nullable = true)
+    private LocalDate liftedOnDate;
+
+    @Column(name = "first_overdue_date", nullable = false)
+    private LocalDate firstOverdueDate;

Review Comment:
   As i understood it, firstOverdueDate is the date when installment became delinquent for the first time. It can be installment due date or chargeback transaction date ,which we get after delinquency calculation. I am storing it when the record is getting created for the first time and if delinquency range changes i copy it from previous record and save it in new one.
   This column was defined as requirement in db ticket and this ticket as well.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1371808991


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyReadPlatformServiceImpl.java:
##########
@@ -126,4 +133,18 @@ public CollectionData calculateLoanCollectionData(final Long loanId) {
         return collectionData;
     }
 
+    @Override
+    public Collection<LoanInstallmentDelinquencyTagData> retrieveLoanInstallmentsCurrentDelinquencyTag(Long loanId) {
+
+        List<LoanInstallmentDelinquencyTagData> loanInstallmentsDelinquencyData = new ArrayList<>();
+        List<LoanInstallmentDelinquencyTag> loanInstallmentsCurrentDelinquency = repositoryLoanInstallmentDelinquencyTag
+                .findByLoanId(loanId);
+        for (LoanInstallmentDelinquencyTag installmentDelinquencyTag : loanInstallmentsCurrentDelinquency) {

Review Comment:
   Still loading the loan for no reason (by fetching LoanInstallmentDelinquencyTag you are fetching the loan as well hence the @ManyToOne relation is by default using eager fetching).
   
    Please fetch the required `loanInstallmentsDelinquencyData` (LoanInstallmentDelinquencyTagData) via the repository using JPA projections:
   
   https://www.baeldung.com/spring-data-jpa-projections



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "ruchiD (via GitHub)" <gi...@apache.org>.
ruchiD commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1373537187


##########
fineract-loan/src/main/resources/db/changelog/tenant/module/loan/parts/1009_refactor_loan_Installment_delinquency_tag.xml:
##########
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                   xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
+    <changeSet author="fineract" id="1">
+        <dropForeignKeyConstraint baseTableName="m_loan_installment_delinquency_tag_history" constraintName="FK_m_delinquency_installment_tags_range" />

Review Comment:
   done. dropped FK for installment only



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1371849429


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/LoanDelinquencyDomainServiceImpl.java:
##########
@@ -139,8 +167,114 @@ public CollectionData getOverdueCollectionData(final Loan loan) {
         if (delinquentDays > 0) {
             collectionData.setDelinquentDays(delinquentDays);
         }
+        return new LoanDelinquencyData(collectionData, loanInstallmentsCollectionData);
+    }
 
-        log.debug("Result: {}", collectionData.toString());
+    private CollectionData getInstallmentOverdueCollectionData(final Loan loan, final LoanRepaymentScheduleInstallment installment) {

Review Comment:
   There are a lot of new code, but i am not really see why?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1371840166


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java:
##########
@@ -382,4 +408,96 @@ public int compare(DelinquencyRange o1, DelinquencyRange o2) {
         return ranges;
     }
 
+    private void applyDelinquencyDetailsForLoanInstallments(final Loan loan, final DelinquencyBucket delinquencyBucket,
+            final Map<Long, CollectionData> installmentsCollectionData) {
+        for (Map.Entry<Long, CollectionData> installmentCollectionData : installmentsCollectionData.entrySet()) {
+            Optional<LoanRepaymentScheduleInstallment> installment = loan.getRepaymentScheduleInstallments().stream()
+                    .filter(instalment -> instalment.getId().equals(installmentCollectionData.getKey())).findFirst();
+            if (installment.isPresent()) {
+                setInstallmentDelinquencyDetails(loan, installment.get(), delinquencyBucket, installmentCollectionData.getValue());
+            }
+        }
+    }
+
+    private void setInstallmentDelinquencyDetails(final Loan loan, final LoanRepaymentScheduleInstallment installment,
+            final DelinquencyBucket delinquencyBucket, final CollectionData installmentDelinquencyData) {
+        DelinquencyRange delinquencyRangeForInstallment = getInstallmentDelinquencyRange(delinquencyBucket,
+                installmentDelinquencyData.getDelinquentDays());
+        setDelinquencyDetailsForInstallment(loan, installment, installmentDelinquencyData, delinquencyRangeForInstallment);
+    }
+
+    private DelinquencyRange getInstallmentDelinquencyRange(final DelinquencyBucket delinquencyBucket, Long overDueDays) {
+        DelinquencyRange delinquencyRangeForInstallment = null;
+        if (overDueDays > 0) {
+            // Sort the ranges based on the minAgeDays
+            final List<DelinquencyRange> ranges = sortDelinquencyRangesByMinAge(delinquencyBucket.getRanges());
+            for (final DelinquencyRange delinquencyRange : ranges) {
+                if (delinquencyRange.getMaximumAgeDays() == null) { // Last Range in the Bucket
+                    if (delinquencyRange.getMinimumAgeDays() <= overDueDays) {
+                        delinquencyRangeForInstallment = delinquencyRange;
+                        break;
+                    }
+                } else {
+                    if (delinquencyRange.getMinimumAgeDays() <= overDueDays && delinquencyRange.getMaximumAgeDays() >= overDueDays) {
+                        delinquencyRangeForInstallment = delinquencyRange;
+                        break;
+                    }
+                }
+            }
+
+        }
+        return delinquencyRangeForInstallment;
+    }
+
+    private void setDelinquencyDetailsForInstallment(final Loan loan, final LoanRepaymentScheduleInstallment installment,
+            CollectionData installmentDelinquencyData, final DelinquencyRange delinquencyRangeForInstallment) {
+        List<LoanInstallmentDelinquencyTag> installmentDelinquencyTags = new ArrayList<>();
+        LocalDate delinquencyCalculationDate = DateUtils.getBusinessLocalDate();
+
+        Optional<LoanInstallmentDelinquencyTag> currentInstallmentDelinquencyTag = loanInstallmentDelinquencyTagRepository

Review Comment:
   `currentInstallmentDelinquencyTag` is kind of meaningles... please review this logic again



##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java:
##########
@@ -382,4 +408,96 @@ public int compare(DelinquencyRange o1, DelinquencyRange o2) {
         return ranges;
     }
 
+    private void applyDelinquencyDetailsForLoanInstallments(final Loan loan, final DelinquencyBucket delinquencyBucket,
+            final Map<Long, CollectionData> installmentsCollectionData) {
+        for (Map.Entry<Long, CollectionData> installmentCollectionData : installmentsCollectionData.entrySet()) {
+            Optional<LoanRepaymentScheduleInstallment> installment = loan.getRepaymentScheduleInstallments().stream()
+                    .filter(instalment -> instalment.getId().equals(installmentCollectionData.getKey())).findFirst();
+            if (installment.isPresent()) {
+                setInstallmentDelinquencyDetails(loan, installment.get(), delinquencyBucket, installmentCollectionData.getValue());
+            }
+        }
+    }
+
+    private void setInstallmentDelinquencyDetails(final Loan loan, final LoanRepaymentScheduleInstallment installment,
+            final DelinquencyBucket delinquencyBucket, final CollectionData installmentDelinquencyData) {
+        DelinquencyRange delinquencyRangeForInstallment = getInstallmentDelinquencyRange(delinquencyBucket,
+                installmentDelinquencyData.getDelinquentDays());
+        setDelinquencyDetailsForInstallment(loan, installment, installmentDelinquencyData, delinquencyRangeForInstallment);
+    }
+
+    private DelinquencyRange getInstallmentDelinquencyRange(final DelinquencyBucket delinquencyBucket, Long overDueDays) {
+        DelinquencyRange delinquencyRangeForInstallment = null;
+        if (overDueDays > 0) {
+            // Sort the ranges based on the minAgeDays
+            final List<DelinquencyRange> ranges = sortDelinquencyRangesByMinAge(delinquencyBucket.getRanges());
+            for (final DelinquencyRange delinquencyRange : ranges) {
+                if (delinquencyRange.getMaximumAgeDays() == null) { // Last Range in the Bucket
+                    if (delinquencyRange.getMinimumAgeDays() <= overDueDays) {
+                        delinquencyRangeForInstallment = delinquencyRange;
+                        break;
+                    }
+                } else {
+                    if (delinquencyRange.getMinimumAgeDays() <= overDueDays && delinquencyRange.getMaximumAgeDays() >= overDueDays) {
+                        delinquencyRangeForInstallment = delinquencyRange;
+                        break;
+                    }
+                }
+            }
+
+        }
+        return delinquencyRangeForInstallment;
+    }
+
+    private void setDelinquencyDetailsForInstallment(final Loan loan, final LoanRepaymentScheduleInstallment installment,
+            CollectionData installmentDelinquencyData, final DelinquencyRange delinquencyRangeForInstallment) {
+        List<LoanInstallmentDelinquencyTag> installmentDelinquencyTags = new ArrayList<>();
+        LocalDate delinquencyCalculationDate = DateUtils.getBusinessLocalDate();
+
+        Optional<LoanInstallmentDelinquencyTag> currentInstallmentDelinquencyTag = loanInstallmentDelinquencyTagRepository

Review Comment:
   `currentInstallmentDelinquencyTag` is kind of meaningless... please review this logic again



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "ruchiD (via GitHub)" <gi...@apache.org>.
ruchiD commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1373347809


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/LoanDelinquencyDomainServiceImpl.java:
##########
@@ -139,8 +167,114 @@ public CollectionData getOverdueCollectionData(final Loan loan) {
         if (delinquentDays > 0) {
             collectionData.setDelinquentDays(delinquentDays);
         }
+        return new LoanDelinquencyData(collectionData, loanInstallmentsCollectionData);
+    }
 
-        log.debug("Result: {}", collectionData.toString());
+    private CollectionData getInstallmentOverdueCollectionData(final Loan loan, final LoanRepaymentScheduleInstallment installment) {

Review Comment:
   Merged logic of calculation loan and installments delinquency into one method -> getLoanDelinquencyData,
   
   In this method iterating to all loan installments and calculating delinquency for each installment in ->getInstallmentOverdueCollectionData 
   
   If installment is not paid 
   
   checking that
   [1] If installment is overdue calculating delinquent data with considering any chargeback transactions  in -> calculateDelinquencyDataForOverdueInstallment method
   [2[ If installment is not overdue calculating delinquent data if there is chargeback transaction before installment due date and current business date in ->calculateDelinquencyDataForNonOverdueInstallment method
   
   If installment is paid setting delinquent days as 0. 
   
   Adding installments delinquency calculation to final calculation data if configured.
   
   For calculating loan delinquency taking overdueSince date for oldest overdue installment or first non due installment with chargeback transaction which is before installment due date and current business date.
   
   
   getLoanDelinquencyData returns LoanDelinquencyData which has loanCollectionData and map of installment Collection Data.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "ruchiD (via GitHub)" <gi...@apache.org>.
ruchiD commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1373539828


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java:
##########
@@ -382,4 +408,96 @@ public int compare(DelinquencyRange o1, DelinquencyRange o2) {
         return ranges;
     }
 
+    private void applyDelinquencyDetailsForLoanInstallments(final Loan loan, final DelinquencyBucket delinquencyBucket,
+            final Map<Long, CollectionData> installmentsCollectionData) {
+        for (Map.Entry<Long, CollectionData> installmentCollectionData : installmentsCollectionData.entrySet()) {
+            Optional<LoanRepaymentScheduleInstallment> installment = loan.getRepaymentScheduleInstallments().stream()
+                    .filter(instalment -> instalment.getId().equals(installmentCollectionData.getKey())).findFirst();
+            if (installment.isPresent()) {
+                setInstallmentDelinquencyDetails(loan, installment.get(), delinquencyBucket, installmentCollectionData.getValue());
+            }
+        }
+    }
+
+    private void setInstallmentDelinquencyDetails(final Loan loan, final LoanRepaymentScheduleInstallment installment,
+            final DelinquencyBucket delinquencyBucket, final CollectionData installmentDelinquencyData) {
+        DelinquencyRange delinquencyRangeForInstallment = getInstallmentDelinquencyRange(delinquencyBucket,
+                installmentDelinquencyData.getDelinquentDays());
+        setDelinquencyDetailsForInstallment(loan, installment, installmentDelinquencyData, delinquencyRangeForInstallment);
+    }
+
+    private DelinquencyRange getInstallmentDelinquencyRange(final DelinquencyBucket delinquencyBucket, Long overDueDays) {
+        DelinquencyRange delinquencyRangeForInstallment = null;
+        if (overDueDays > 0) {
+            // Sort the ranges based on the minAgeDays
+            final List<DelinquencyRange> ranges = sortDelinquencyRangesByMinAge(delinquencyBucket.getRanges());
+            for (final DelinquencyRange delinquencyRange : ranges) {
+                if (delinquencyRange.getMaximumAgeDays() == null) { // Last Range in the Bucket
+                    if (delinquencyRange.getMinimumAgeDays() <= overDueDays) {
+                        delinquencyRangeForInstallment = delinquencyRange;
+                        break;
+                    }
+                } else {
+                    if (delinquencyRange.getMinimumAgeDays() <= overDueDays && delinquencyRange.getMaximumAgeDays() >= overDueDays) {
+                        delinquencyRangeForInstallment = delinquencyRange;
+                        break;
+                    }
+                }
+            }
+
+        }
+        return delinquencyRangeForInstallment;
+    }
+
+    private void setDelinquencyDetailsForInstallment(final Loan loan, final LoanRepaymentScheduleInstallment installment,
+            CollectionData installmentDelinquencyData, final DelinquencyRange delinquencyRangeForInstallment) {
+        List<LoanInstallmentDelinquencyTag> installmentDelinquencyTags = new ArrayList<>();
+        LocalDate delinquencyCalculationDate = DateUtils.getBusinessLocalDate();
+
+        Optional<LoanInstallmentDelinquencyTag> currentInstallmentDelinquencyTag = loanInstallmentDelinquencyTagRepository
+                .findByLoanAndInstallment(loan, installment);
+        LoanInstallmentDelinquencyTag previousInstallmentDelinquencyTag = null;
+        if (currentInstallmentDelinquencyTag.isPresent()) {
+            previousInstallmentDelinquencyTag = currentInstallmentDelinquencyTag.get();
+        }
+
+        if (delinquencyRangeForInstallment == null) {
+            // if currentInstallmentDelinquencyTag exists and range is null, installment is out of delinquency, delete

Review Comment:
   Previous delinquency tag needs for range change  and out of delinquency events.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1371803746


##########
fineract-loan/src/main/resources/db/changelog/tenant/module/loan/parts/1009_refactor_loan_Installment_delinquency_tag.xml:
##########
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                   xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
+    <changeSet author="fineract" id="1">
+        <dropForeignKeyConstraint baseTableName="m_loan_installment_delinquency_tag_history" constraintName="FK_m_delinquency_installment_tags_range" />

Review Comment:
   Why to drop the FK for the loan? and for the range?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "ruchiD (via GitHub)" <gi...@apache.org>.
ruchiD commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1365123897


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/data/LoanInstallmentDelinquencyTagHistoryData.java:
##########
@@ -0,0 +1,41 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.delinquency.data;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+@ToString
+@AllArgsConstructor
+@Getter
+@Setter
+public class LoanInstallmentDelinquencyTagHistoryData {

Review Comment:
   done.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1365154052


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyReadPlatformServiceImpl.java:
##########
@@ -126,4 +134,20 @@ public CollectionData calculateLoanCollectionData(final Long loanId) {
         return collectionData;
     }
 
+    @Override
+    public Collection<LoanInstallmentDelinquencyTagData> retrieveLoanInstallmentsCurrentDelinquencyTag(Long loanId) {

Review Comment:
   Please rewrite this to not load the loan (even if you fetch only a reference, then moment you are fetching one of its field, its fetches the full loan) and fetch one by one the installments and its delinquency tags, please do it in one shot:
   - Write a query that fetches them in the delinquency repository



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1365165429


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java:
##########
@@ -160,6 +164,9 @@ public CommandProcessingResult applyDelinquencyTagToLoan(Long loanId, JsonComman
         if (delinquencyBucket != null) {
             final CollectionData collectionData = loanDelinquencyDomainService.getOverdueCollectionData(loan);
             changes = lookUpDelinquencyRange(loan, delinquencyBucket, collectionData.getDelinquentDays());
+            if (loan.isEnableInstallmentLevelDelinquency()) {

Review Comment:
   When the loan delinquency gets calculated, the installment level delinquency can be also calculated. Would you consider to do merge them together?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1371808991


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyReadPlatformServiceImpl.java:
##########
@@ -126,4 +133,18 @@ public CollectionData calculateLoanCollectionData(final Long loanId) {
         return collectionData;
     }
 
+    @Override
+    public Collection<LoanInstallmentDelinquencyTagData> retrieveLoanInstallmentsCurrentDelinquencyTag(Long loanId) {
+
+        List<LoanInstallmentDelinquencyTagData> loanInstallmentsDelinquencyData = new ArrayList<>();
+        List<LoanInstallmentDelinquencyTag> loanInstallmentsCurrentDelinquency = repositoryLoanInstallmentDelinquencyTag
+                .findByLoanId(loanId);
+        for (LoanInstallmentDelinquencyTag installmentDelinquencyTag : loanInstallmentsCurrentDelinquency) {

Review Comment:
   Still loading the loan for no reason (by fetching LoanInstallmentDelinquencyTag you are fetching the loan as well hence the ManyToOne relation is by default using eager fetching).
   
    Please fetch the required `loanInstallmentsDelinquencyData` (LoanInstallmentDelinquencyTagData) via the repository using JPA projections:
   
   https://www.baeldung.com/spring-data-jpa-projections



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1365167099


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java:
##########
@@ -382,4 +395,95 @@ public int compare(DelinquencyRange o1, DelinquencyRange o2) {
         return ranges;
     }
 
+    private void applyDelinquencyDetailsForLoanInstallments(Loan loan, DelinquencyBucket delinquencyBucket) {
+        for (LoanRepaymentScheduleInstallment installment : loan.getRepaymentScheduleInstallments()) {
+            CollectionData installmentDelinquencyData = loanDelinquencyDomainService.getInstallmentOverdueCollectionData(loan, installment);
+            setInstallmentDelinquencyDetails(loan, installment, delinquencyBucket, installmentDelinquencyData);
+        }
+    }
+
+    private void setInstallmentDelinquencyDetails(Loan loan, LoanRepaymentScheduleInstallment installment,
+            DelinquencyBucket delinquencyBucket, CollectionData installmentDelinquencyData) {
+        Long delinquencyRangeIdForInstallment = getInstallmentDelinquencyRange(delinquencyBucket,
+                installmentDelinquencyData.getDelinquentDays());
+        setDelinquencyDetailsForInstallment(loan, installment, installmentDelinquencyData, delinquencyRangeIdForInstallment);
+    }
+
+    private Long getInstallmentDelinquencyRange(DelinquencyBucket delinquencyBucket, Long overDueDays) {
+        Long delinquencyRangeId = null;
+        if (overDueDays > 0) {
+            // Sort the ranges based on the minAgeDays
+            final List<DelinquencyRange> ranges = sortDelinquencyRangesByMinAge(delinquencyBucket.getRanges());
+            for (final DelinquencyRange delinquencyRange : ranges) {
+                if (delinquencyRange.getMaximumAgeDays() == null) { // Last Range in the Bucket
+                    if (delinquencyRange.getMinimumAgeDays() <= overDueDays) {
+                        delinquencyRangeId = delinquencyRange.getId();
+                        break;
+                    }
+                } else {
+                    if (delinquencyRange.getMinimumAgeDays() <= overDueDays && delinquencyRange.getMaximumAgeDays() >= overDueDays) {
+                        delinquencyRangeId = delinquencyRange.getId();
+                        break;
+                    }
+                }
+            }
+
+        }
+        return delinquencyRangeId;
+    }
+
+    private void setDelinquencyDetailsForInstallment(Loan loan, LoanRepaymentScheduleInstallment installment,
+            CollectionData installmentDelinquencyData, Long delinquencyRangeIdForInstallment) {
+        List<LoanInstallmentDelinquencyTag> installmentDelinquencyTags = new ArrayList<>();
+        LocalDate delinquencyCalculationDate = DateUtils.getBusinessLocalDate();
+
+        Optional<LoanInstallmentDelinquencyTag> currentInstallmentDelinquencyTag = loanInstallmentDelinquencyTagRepository
+                .findByLoanAndInstallment(loan, installment);
+        LoanInstallmentDelinquencyTag previousInstallmentDelinquencyTag = null;
+        if (currentInstallmentDelinquencyTag.isPresent()) {
+            previousInstallmentDelinquencyTag = currentInstallmentDelinquencyTag.get();
+        }
+
+        if (delinquencyRangeIdForInstallment == null) {
+            // if currentInstallmentDelinquencyTag exists and range is null, installment is out of delinquency, delete
+            // delinquency details
+            if (previousInstallmentDelinquencyTag != null) {
+                loanInstallmentDelinquencyTagRepository.delete(previousInstallmentDelinquencyTag);
+            }
+        } else {
+            DelinquencyRange delinquencyRange = repositoryRange.getReferenceById(delinquencyRangeIdForInstallment);
+            LoanInstallmentDelinquencyTag installmentDelinquency = null;
+            if (previousInstallmentDelinquencyTag != null) {
+                if (!previousInstallmentDelinquencyTag.getDelinquencyRange().getId().equals(delinquencyRangeIdForInstallment)) {
+                    // if current delinquency range exists and there is range change, delete previous delinquency
+                    // details and add new range details
+                    installmentDelinquency = new LoanInstallmentDelinquencyTag(delinquencyRange, loan, installment,
+                            delinquencyCalculationDate, null, previousInstallmentDelinquencyTag.getFirstOverdueDate(),
+                            installmentDelinquencyData.getDelinquentAmount());
+                    loanInstallmentDelinquencyTagRepository.delete(previousInstallmentDelinquencyTag);
+                }
+            } else {
+                // add new range, first time delinquent
+                installmentDelinquency = new LoanInstallmentDelinquencyTag(delinquencyRange, loan, installment, delinquencyCalculationDate,
+                        null, installmentDelinquencyData.getDelinquentDate(), installmentDelinquencyData.getDelinquentAmount());
+            }
+
+            if (installmentDelinquency != null) {
+                installmentDelinquencyTags.add(installmentDelinquency);
+            }
+
+        }
+
+        if (installmentDelinquencyTags.size() > 0) {
+            loanInstallmentDelinquencyTagRepository.saveAllAndFlush(installmentDelinquencyTags);
+        }
+
+    }
+
+    private void cleanLoanInstallmentsDelinquencyTags(Loan loan) {
+        List<LoanInstallmentDelinquencyTag> installmentDelinquencyTags = loanInstallmentDelinquencyTagRepository.findByLoan(loan);

Review Comment:
   We dont need to fetch the delinquency tags to be deleted. Please write a query which deletes all tags based on the loan.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1364197253


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/domain/LoanInstallmentDelinquencyTagHistory.java:
##########
@@ -0,0 +1,80 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.delinquency.domain;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import jakarta.persistence.Version;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
+import org.apache.fineract.portfolio.loanaccount.domain.Loan;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@Entity
+@Table(name = "m_loan_installment_delinquency_tag_history")
+public class LoanInstallmentDelinquencyTagHistory extends AbstractAuditableWithUTCDateTimeCustom {
+
+    @ManyToOne
+    @JoinColumn(name = "delinquency_range_id", nullable = false)
+    private DelinquencyRange delinquencyRange;
+
+    @ManyToOne
+    @JoinColumn(name = "loan_id", nullable = false)
+    private Loan loan;
+
+    @ManyToOne
+    @JoinColumn(name = "installment_id", nullable = false)
+    private LoanRepaymentScheduleInstallment installment;
+
+    @Column(name = "addedon_date", nullable = false)
+    private LocalDate addedOnDate;
+
+    @Column(name = "liftedon_date", nullable = true)
+    private LocalDate liftedOnDate;
+
+    @Column(name = "first_overdue_date", nullable = false)
+    private LocalDate firstOverdueDate;

Review Comment:
   Can you help me understand more what is "firstOverdueDate"?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] FINERACT-1992-FINERACT-Installment-level-delinquency-calculation [fineract]

Posted by "ruchiD (via GitHub)" <gi...@apache.org>.
ruchiD commented on code in PR #3515:
URL: https://github.com/apache/fineract/pull/3515#discussion_r1373537985


##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyReadPlatformServiceImpl.java:
##########
@@ -126,4 +133,18 @@ public CollectionData calculateLoanCollectionData(final Long loanId) {
         return collectionData;
     }
 
+    @Override
+    public Collection<LoanInstallmentDelinquencyTagData> retrieveLoanInstallmentsCurrentDelinquencyTag(Long loanId) {
+
+        List<LoanInstallmentDelinquencyTagData> loanInstallmentsDelinquencyData = new ArrayList<>();
+        List<LoanInstallmentDelinquencyTag> loanInstallmentsCurrentDelinquency = repositoryLoanInstallmentDelinquencyTag
+                .findByLoanId(loanId);
+        for (LoanInstallmentDelinquencyTag installmentDelinquencyTag : loanInstallmentsCurrentDelinquency) {

Review Comment:
   done. Fetching only Delinquency Range and  outstanding amount for installments



##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java:
##########
@@ -382,4 +408,96 @@ public int compare(DelinquencyRange o1, DelinquencyRange o2) {
         return ranges;
     }
 
+    private void applyDelinquencyDetailsForLoanInstallments(final Loan loan, final DelinquencyBucket delinquencyBucket,
+            final Map<Long, CollectionData> installmentsCollectionData) {
+        for (Map.Entry<Long, CollectionData> installmentCollectionData : installmentsCollectionData.entrySet()) {
+            Optional<LoanRepaymentScheduleInstallment> installment = loan.getRepaymentScheduleInstallments().stream()

Review Comment:
   done



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@fineract.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org