adamsaghy commented on code in PR #2566:
URL: https://github.com/apache/fineract/pull/2566#discussion_r962936719


##########
integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyBucketsIntegrationTest.java:
##########
@@ -321,4 +323,214 @@ public void testLoanClassificationJob() {
         GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
     }
 
+    @Test
+    public void testLoanClassificationRealtime() {
+        // Given
+        final LoanTransactionHelper loanTransactionHelper = new 
LoanTransactionHelper(this.requestSpec, this.responseSpec);
+
+        ArrayList<Integer> rangeIds = new ArrayList<>();
+        // First Range
+        String jsonRange = DelinquencyRangesHelper.getAsJSON(1, 3);
+        PostDelinquencyRangeResponse delinquencyRangeResponse = 
DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec,
+                jsonRange);
+        rangeIds.add(delinquencyRangeResponse.getResourceId());
+        jsonRange = DelinquencyRangesHelper.getAsJSON(4, 60);
+
+        GetDelinquencyRangesResponse range = 
DelinquencyRangesHelper.getDelinquencyRange(requestSpec, responseSpec,
+                delinquencyRangeResponse.getResourceId());
+
+        // Second Range
+        delinquencyRangeResponse = 
DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec, 
jsonRange);
+        rangeIds.add(delinquencyRangeResponse.getResourceId());
+
+        range = DelinquencyRangesHelper.getDelinquencyRange(requestSpec, 
responseSpec, delinquencyRangeResponse.getResourceId());
+        final String classificationExpected = range.getClassification();
+        log.info("Expected Delinquency Range classification after Disbursement 
{}", classificationExpected);
+
+        String jsonBucket = DelinquencyBucketsHelper.getAsJSON(rangeIds);
+        PostDelinquencyBucketResponse delinquencyBucketResponse = 
DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec,
+                responseSpec, jsonBucket);
+        assertNotNull(delinquencyBucketResponse);
+        final GetDelinquencyBucketsResponse delinquencyBucket = 
DelinquencyBucketsHelper.getDelinquencyBucket(requestSpec, responseSpec,
+                delinquencyBucketResponse.getResourceId());
+
+        // Client and Loan account creation
+        final Integer clientId = ClientHelper.createClient(this.requestSpec, 
this.responseSpec, "01 January 2012");
+        final HashMap<String, Object> loanProductMap = new 
LoanProductTestBuilder().build(null, delinquencyBucket.getId());
+        final Integer loanProductId = 
loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap));
+
+        final GetLoanProductsProductIdResponse getLoanProductsProductResponse 
= loanTransactionHelper.getLoanProduct(loanProductId);
+        assertNotNull(getLoanProductsProductResponse);
+        log.info("Loan Product Bucket Name: {}", 
getLoanProductsProductResponse.getDelinquencyBucket().getName());
+        
assertEquals(getLoanProductsProductResponse.getDelinquencyBucket().getName(), 
delinquencyBucket.getName());
+
+        LocalDate todaysDate = Utils.getLocalDateOfTenant();
+        todaysDate = todaysDate.minusDays(40);
+        String operationDate = Utils.dateFormatter.format(todaysDate);
+        final String principalAmount = "10000";
+
+        final String loanApplicationJSON = new 
LoanApplicationTestBuilder().withPrincipal(principalAmount).withLoanTermFrequency("12")
+                
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("12").withRepaymentEveryAfter("1")
+                .withRepaymentFrequencyTypeAsMonths() //
+                .withInterestRatePerPeriod("2") //
+                .withExpectedDisbursementDate(operationDate) //
+                .withInterestTypeAsDecliningBalance() //
+                .withSubmittedOnDate(operationDate) //
+                .build(clientId.toString(), loanProductId.toString(), null);
+        final Integer loanId = 
loanTransactionHelper.getLoanId(loanApplicationJSON);
+        loanTransactionHelper.approveLoan(operationDate, principalAmount, 
loanId, null);
+        
loanTransactionHelper.disburseLoanWithNetDisbursalAmount(operationDate, loanId, 
principalAmount);
+
+        GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
+        log.info("Loan Delinquency Range after Disbursement {}", 
getLoansLoanIdResponse.getDelinquencyRange().getClassification());
+        assertNotNull(getLoansLoanIdResponse);
+        // First Loan Delinquency Classification after Disbursement command
+        
assertEquals(getLoansLoanIdResponse.getDelinquencyRange().getClassification(), 
classificationExpected);
+
+        // When
+        // Apply a partial repayment
+        todaysDate = Utils.getLocalDateOfTenant();
+        operationDate = Utils.dateFormatter.format(todaysDate);
+        loanTransactionHelper.makeRepayment(operationDate, 100.0f, loanId);
+
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, 
responseSpec, loanId);
+        log.info("Loan Delinquency Range after Repayment {}", 
getLoansLoanIdResponse.getDelinquencyRange());
+        assertNotNull(getLoansLoanIdResponse.getDelinquencyRange());
+        // First Loan Delinquency Classification remains after Repayment 
because the installment is not fully paid
+        
assertEquals(getLoansLoanIdResponse.getDelinquencyRange().getClassification(), 
classificationExpected);
+
+        // Apply a repayment to get a full paid installment
+        loanTransactionHelper.makeRepayment(operationDate, 1000.0f, loanId);
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, 
responseSpec, loanId);
+        log.info("Loan Delinquency Range after Repayment {}", 
getLoansLoanIdResponse.getDelinquencyRange());
+        assertNotNull(getLoansLoanIdResponse);
+        // The Loan Delinquency Classification after Repayment command must be 
null
+        assertNull(getLoansLoanIdResponse.getDelinquencyRange());
+        // Get the Delinquency Tags
+        ArrayList<GetDelinquencyTagHistoryResponse> getDelinquencyTagsHistory 
= loanTransactionHelper.getLoanDelinquencyTags(requestSpec,
+                responseSpec, loanId);
+        assertNotNull(getDelinquencyTagsHistory);
+        log.info("Delinquency Tag History items {}", 
getDelinquencyTagsHistory.size());
+        assertEquals(1, getDelinquencyTagsHistory.size());
+        assertNotNull(getDelinquencyTagsHistory.get(0).getLiftedOnDate());

Review Comment:
   Please check explicitly:
   - the proper date was stored as "liftedOnDate"
   - in the history the proper classification was stored
   - the proper date was stored as "addedOnDate"



##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java:
##########
@@ -167,9 +167,26 @@ public CommandProcessingResult 
applyDelinquencyTagToLoan(Long loanId, JsonComman
     @Override
     public void applyDelinquencyTagToLoan(Long loanId, Long ageDays) {
         final Loan loan = 
this.loanRepository.findOneWithNotFoundDetection(loanId);
-        final DelinquencyBucket delinquencyBucket = 
loan.getLoanProduct().getDelinquencyBucket();
-        if (delinquencyBucket != null) {
-            lookUpDelinquencyRange(loan, delinquencyBucket, ageDays);
+        applyDelinquencyTagToLoan(loan, ageDays);
+    }
+
+    @Override
+    public void applyDelinquencyTagToLoan(final Loan loan, Long ageDays) {
+        if (loan.hasDelinquencyBucket()) {
+            lookUpDelinquencyRange(loan, 
loan.getLoanProduct().getDelinquencyBucket(), ageDays);
+        }
+    }
+
+    @Override
+    public void removeDelinquencyTagToLoan(final Loan loan) {
+        setLoanDelinquencyTag(loan, null);
+    }
+
+    @Override
+    public void cleanLoanDelinquencyTags(Loan loan) {

Review Comment:
   @josehernandezfintecheandomx I dont think we should ever delete any history 
entries. What do you think?



##########
integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyBucketsIntegrationTest.java:
##########
@@ -321,4 +321,89 @@ public void testLoanClassificationJob() {
         GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
     }
 
+    @Test
+    public void testLoanClassificationRealtime() {
+        // Given
+        final LoanTransactionHelper loanTransactionHelper = new 
LoanTransactionHelper(this.requestSpec, this.responseSpec);
+
+        ArrayList<Integer> rangeIds = new ArrayList<>();
+        // First Range
+        String jsonRange = DelinquencyRangesHelper.getAsJSON(1, 3);
+        PostDelinquencyRangeResponse delinquencyRangeResponse = 
DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec,
+                jsonRange);
+        rangeIds.add(delinquencyRangeResponse.getResourceId());
+        jsonRange = DelinquencyRangesHelper.getAsJSON(4, 60);
+
+        GetDelinquencyRangesResponse range = 
DelinquencyRangesHelper.getDelinquencyRange(requestSpec, responseSpec,
+                delinquencyRangeResponse.getResourceId());
+
+        // Second Range
+        delinquencyRangeResponse = 
DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec, 
jsonRange);
+        rangeIds.add(delinquencyRangeResponse.getResourceId());
+
+        range = DelinquencyRangesHelper.getDelinquencyRange(requestSpec, 
responseSpec, delinquencyRangeResponse.getResourceId());
+        final String classificationExpected = range.getClassification();
+        log.info("Expected Delinquency Range classification after Disbursement 
{}", classificationExpected);
+
+        String jsonBucket = DelinquencyBucketsHelper.getAsJSON(rangeIds);
+        PostDelinquencyBucketResponse delinquencyBucketResponse = 
DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec,
+                responseSpec, jsonBucket);
+        assertNotNull(delinquencyBucketResponse);
+        final GetDelinquencyBucketsResponse delinquencyBucket = 
DelinquencyBucketsHelper.getDelinquencyBucket(requestSpec, responseSpec,
+                delinquencyBucketResponse.getResourceId());
+
+        // Client and Loan account creation
+        final Integer clientId = ClientHelper.createClient(this.requestSpec, 
this.responseSpec, "01 January 2012");
+        final HashMap<String, Object> loanProductMap = new 
LoanProductTestBuilder().build(null, delinquencyBucket.getId());
+        final Integer loanProductId = 
loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap));
+
+        final GetLoanProductsProductIdResponse getLoanProductsProductResponse 
= loanTransactionHelper.getLoanProduct(loanProductId);
+        assertNotNull(getLoanProductsProductResponse);
+        log.info("Loan Product Bucket Name: {}", 
getLoanProductsProductResponse.getDelinquencyBucket().getName());
+        
assertEquals(getLoanProductsProductResponse.getDelinquencyBucket().getName(), 
delinquencyBucket.getName());
+
+        LocalDate todaysDate = Utils.getLocalDateOfTenant();
+        todaysDate = todaysDate.minusDays(40);
+        String operationDate = Utils.dateFormatter.format(todaysDate);
+        final String principalAmount = "10000";
+
+        final String loanApplicationJSON = new 
LoanApplicationTestBuilder().withPrincipal(principalAmount).withLoanTermFrequency("12")
+                
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("12").withRepaymentEveryAfter("1")
+                .withRepaymentFrequencyTypeAsMonths() //
+                .withInterestRatePerPeriod("2") //
+                .withExpectedDisbursementDate(operationDate) //
+                .withInterestTypeAsDecliningBalance() //
+                .withSubmittedOnDate(operationDate) //
+                .build(clientId.toString(), loanProductId.toString(), null);
+        final Integer loanId = 
loanTransactionHelper.getLoanId(loanApplicationJSON);
+        loanTransactionHelper.approveLoan(operationDate, principalAmount, 
loanId, null);
+        
loanTransactionHelper.disburseLoanWithNetDisbursalAmount(operationDate, loanId, 
principalAmount);
+
+        GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
+        log.info("Loan Delinquency Range after Disbursement {}", 
getLoansLoanIdResponse.getDelinquencyRange().getClassification());
+        assertNotNull(getLoansLoanIdResponse);
+        // First Loan Delinquency Classification after Disbursement command
+        
assertEquals(getLoansLoanIdResponse.getDelinquencyRange().getClassification(), 
classificationExpected);
+
+        // When
+        // Apply a partial repayment
+        todaysDate = Utils.getLocalDateOfTenant();
+        operationDate = Utils.dateFormatter.format(todaysDate);
+        loanTransactionHelper.makeRepayment(operationDate, 100.0f, loanId);
+
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, 
responseSpec, loanId);
+        log.info("Loan Delinquency Range after Repayment {}", 
getLoansLoanIdResponse.getDelinquencyRange());
+        assertNotNull(getLoansLoanIdResponse.getDelinquencyRange());
+        // First Loan Delinquency Classification remains after Repayment 
because the installment is not fully paid
+        
assertEquals(getLoansLoanIdResponse.getDelinquencyRange().getClassification(), 
classificationExpected);
+
+        // Apply a repayment to get a full paid installment
+        loanTransactionHelper.makeRepayment(operationDate, 1000.0f, loanId);
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, 
responseSpec, loanId);
+        log.info("Loan Delinquency Range after Repayment {}", 
getLoansLoanIdResponse.getDelinquencyRange());
+        assertNotNull(getLoansLoanIdResponse);
+        // The Loan Delinquency Classification after Repayment command must be 
null
+        assertNull(getLoansLoanIdResponse.getDelinquencyRange());
+    }
+
 }

Review Comment:
   @josehernandezfintecheandomx Would you take a look please?



##########
integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyBucketsIntegrationTest.java:
##########
@@ -321,4 +323,214 @@ public void testLoanClassificationJob() {
         GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
     }
 
+    @Test
+    public void testLoanClassificationRealtime() {
+        // Given
+        final LoanTransactionHelper loanTransactionHelper = new 
LoanTransactionHelper(this.requestSpec, this.responseSpec);
+
+        ArrayList<Integer> rangeIds = new ArrayList<>();
+        // First Range
+        String jsonRange = DelinquencyRangesHelper.getAsJSON(1, 3);
+        PostDelinquencyRangeResponse delinquencyRangeResponse = 
DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec,
+                jsonRange);
+        rangeIds.add(delinquencyRangeResponse.getResourceId());
+        jsonRange = DelinquencyRangesHelper.getAsJSON(4, 60);
+
+        GetDelinquencyRangesResponse range = 
DelinquencyRangesHelper.getDelinquencyRange(requestSpec, responseSpec,
+                delinquencyRangeResponse.getResourceId());
+
+        // Second Range
+        delinquencyRangeResponse = 
DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec, 
jsonRange);
+        rangeIds.add(delinquencyRangeResponse.getResourceId());
+
+        range = DelinquencyRangesHelper.getDelinquencyRange(requestSpec, 
responseSpec, delinquencyRangeResponse.getResourceId());
+        final String classificationExpected = range.getClassification();
+        log.info("Expected Delinquency Range classification after Disbursement 
{}", classificationExpected);
+
+        String jsonBucket = DelinquencyBucketsHelper.getAsJSON(rangeIds);
+        PostDelinquencyBucketResponse delinquencyBucketResponse = 
DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec,
+                responseSpec, jsonBucket);
+        assertNotNull(delinquencyBucketResponse);
+        final GetDelinquencyBucketsResponse delinquencyBucket = 
DelinquencyBucketsHelper.getDelinquencyBucket(requestSpec, responseSpec,
+                delinquencyBucketResponse.getResourceId());
+
+        // Client and Loan account creation
+        final Integer clientId = ClientHelper.createClient(this.requestSpec, 
this.responseSpec, "01 January 2012");
+        final HashMap<String, Object> loanProductMap = new 
LoanProductTestBuilder().build(null, delinquencyBucket.getId());
+        final Integer loanProductId = 
loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap));
+
+        final GetLoanProductsProductIdResponse getLoanProductsProductResponse 
= loanTransactionHelper.getLoanProduct(loanProductId);
+        assertNotNull(getLoanProductsProductResponse);
+        log.info("Loan Product Bucket Name: {}", 
getLoanProductsProductResponse.getDelinquencyBucket().getName());
+        
assertEquals(getLoanProductsProductResponse.getDelinquencyBucket().getName(), 
delinquencyBucket.getName());
+
+        LocalDate todaysDate = Utils.getLocalDateOfTenant();
+        todaysDate = todaysDate.minusDays(40);
+        String operationDate = Utils.dateFormatter.format(todaysDate);
+        final String principalAmount = "10000";
+
+        final String loanApplicationJSON = new 
LoanApplicationTestBuilder().withPrincipal(principalAmount).withLoanTermFrequency("12")
+                
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("12").withRepaymentEveryAfter("1")
+                .withRepaymentFrequencyTypeAsMonths() //
+                .withInterestRatePerPeriod("2") //
+                .withExpectedDisbursementDate(operationDate) //
+                .withInterestTypeAsDecliningBalance() //
+                .withSubmittedOnDate(operationDate) //
+                .build(clientId.toString(), loanProductId.toString(), null);
+        final Integer loanId = 
loanTransactionHelper.getLoanId(loanApplicationJSON);
+        loanTransactionHelper.approveLoan(operationDate, principalAmount, 
loanId, null);
+        
loanTransactionHelper.disburseLoanWithNetDisbursalAmount(operationDate, loanId, 
principalAmount);
+
+        GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
+        log.info("Loan Delinquency Range after Disbursement {}", 
getLoansLoanIdResponse.getDelinquencyRange().getClassification());
+        assertNotNull(getLoansLoanIdResponse);
+        // First Loan Delinquency Classification after Disbursement command
+        
assertEquals(getLoansLoanIdResponse.getDelinquencyRange().getClassification(), 
classificationExpected);
+
+        // When
+        // Apply a partial repayment
+        todaysDate = Utils.getLocalDateOfTenant();
+        operationDate = Utils.dateFormatter.format(todaysDate);
+        loanTransactionHelper.makeRepayment(operationDate, 100.0f, loanId);
+
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, 
responseSpec, loanId);
+        log.info("Loan Delinquency Range after Repayment {}", 
getLoansLoanIdResponse.getDelinquencyRange());
+        assertNotNull(getLoansLoanIdResponse.getDelinquencyRange());
+        // First Loan Delinquency Classification remains after Repayment 
because the installment is not fully paid
+        
assertEquals(getLoansLoanIdResponse.getDelinquencyRange().getClassification(), 
classificationExpected);
+
+        // Apply a repayment to get a full paid installment
+        loanTransactionHelper.makeRepayment(operationDate, 1000.0f, loanId);
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, 
responseSpec, loanId);
+        log.info("Loan Delinquency Range after Repayment {}", 
getLoansLoanIdResponse.getDelinquencyRange());
+        assertNotNull(getLoansLoanIdResponse);
+        // The Loan Delinquency Classification after Repayment command must be 
null
+        assertNull(getLoansLoanIdResponse.getDelinquencyRange());
+        // Get the Delinquency Tags
+        ArrayList<GetDelinquencyTagHistoryResponse> getDelinquencyTagsHistory 
= loanTransactionHelper.getLoanDelinquencyTags(requestSpec,
+                responseSpec, loanId);
+        assertNotNull(getDelinquencyTagsHistory);
+        log.info("Delinquency Tag History items {}", 
getDelinquencyTagsHistory.size());
+        assertEquals(1, getDelinquencyTagsHistory.size());
+        assertNotNull(getDelinquencyTagsHistory.get(0).getLiftedOnDate());
+        log.info("Delinquency Tag Item with Lifted On {}", 
getDelinquencyTagsHistory.get(0).getLiftedOnDate());
+    }
+
+    @Test
+    public void testLoanClassificationRealtimeOlderLoan() {
+        // Given
+        final LoanTransactionHelper loanTransactionHelper = new 
LoanTransactionHelper(this.requestSpec, this.responseSpec);
+
+        ArrayList<Integer> rangeIds = new ArrayList<>();
+        // First Range
+        String jsonRange = DelinquencyRangesHelper.getAsJSON(4, 30);
+        PostDelinquencyRangeResponse delinquencyRangeResponse = 
DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec,
+                jsonRange);
+        rangeIds.add(delinquencyRangeResponse.getResourceId());
+        GetDelinquencyRangesResponse range = 
DelinquencyRangesHelper.getDelinquencyRange(requestSpec, responseSpec,
+                delinquencyRangeResponse.getResourceId());
+        final String classificationExpected02 = range.getClassification();
+        log.info("Expected Delinquency Range classification after first 
repayment {}", classificationExpected02);
+
+        // Second Range
+        jsonRange = DelinquencyRangesHelper.getAsJSON(31, 60);
+        delinquencyRangeResponse = 
DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec, 
jsonRange);
+        rangeIds.add(delinquencyRangeResponse.getResourceId());
+
+        range = DelinquencyRangesHelper.getDelinquencyRange(requestSpec, 
responseSpec, delinquencyRangeResponse.getResourceId());
+        final String classificationExpected01 = range.getClassification();
+        log.info("Expected Delinquency Range classification after Disbursement 
{}", classificationExpected01);
+
+        // Third Range
+        jsonRange = DelinquencyRangesHelper.getAsJSON(61, 90);
+        delinquencyRangeResponse = 
DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec, 
jsonRange);
+        rangeIds.add(delinquencyRangeResponse.getResourceId());
+
+        range = DelinquencyRangesHelper.getDelinquencyRange(requestSpec, 
responseSpec, delinquencyRangeResponse.getResourceId());
+
+        String jsonBucket = DelinquencyBucketsHelper.getAsJSON(rangeIds);
+        PostDelinquencyBucketResponse delinquencyBucketResponse = 
DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec,
+                responseSpec, jsonBucket);
+        assertNotNull(delinquencyBucketResponse);
+        final GetDelinquencyBucketsResponse delinquencyBucket = 
DelinquencyBucketsHelper.getDelinquencyBucket(requestSpec, responseSpec,
+                delinquencyBucketResponse.getResourceId());
+
+        // Client and Loan account creation
+        final Integer clientId = ClientHelper.createClient(this.requestSpec, 
this.responseSpec, "01 January 2012");
+        final HashMap<String, Object> loanProductMap = new 
LoanProductTestBuilder().build(null, delinquencyBucket.getId());
+        final Integer loanProductId = 
loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap));
+
+        final GetLoanProductsProductIdResponse getLoanProductsProductResponse 
= loanTransactionHelper.getLoanProduct(loanProductId);
+        assertNotNull(getLoanProductsProductResponse);
+        log.info("Loan Product Bucket Name: {}", 
getLoanProductsProductResponse.getDelinquencyBucket().getName());
+        
assertEquals(getLoanProductsProductResponse.getDelinquencyBucket().getName(), 
delinquencyBucket.getName());
+
+        LocalDate todaysDate = Utils.getLocalDateOfTenant();
+        // Older date to have more than one overdue installment
+        todaysDate = todaysDate.minusDays(85);
+        String operationDate = Utils.dateFormatter.format(todaysDate);
+        final String principalAmount = "10000";
+
+        final String loanApplicationJSON = new 
LoanApplicationTestBuilder().withPrincipal(principalAmount).withLoanTermFrequency("12")
+                
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("12").withRepaymentEveryAfter("1")
+                .withRepaymentFrequencyTypeAsMonths() //
+                .withInterestRatePerPeriod("2") //
+                .withExpectedDisbursementDate(operationDate) //
+                .withInterestTypeAsDecliningBalance() //
+                .withSubmittedOnDate(operationDate) //
+                .build(clientId.toString(), loanProductId.toString(), null);
+        final Integer loanId = 
loanTransactionHelper.getLoanId(loanApplicationJSON);
+        loanTransactionHelper.approveLoan(operationDate, principalAmount, 
loanId, null);
+        
loanTransactionHelper.disburseLoanWithNetDisbursalAmount(operationDate, loanId, 
principalAmount);
+
+        GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
+        assertNotNull(getLoansLoanIdResponse);
+        log.info("Loan Delinquency Range after Disbursement in null? {}", 
(getLoansLoanIdResponse.getDelinquencyRange() == null));
+        assertNotNull(getLoansLoanIdResponse.getDelinquencyRange());
+        log.info("Loan Delinquency Range after Disbursement {}", 
getLoansLoanIdResponse.getDelinquencyRange().getClassification());
+        // First Loan Delinquency Classification after Disbursement command
+        
assertEquals(getLoansLoanIdResponse.getDelinquencyRange().getClassification(), 
classificationExpected01);
+
+        GetLoansLoanIdRepaymentSchedule getLoanRepaymentSchedule = 
getLoansLoanIdResponse.getRepaymentSchedule();
+        if (getLoanRepaymentSchedule != null) {
+            log.info("Loan with {} periods", 
getLoanRepaymentSchedule.getPeriods().size());
+            for (GetLoansLoanIdRepaymentPeriod period : 
getLoanRepaymentSchedule.getPeriods()) {
+                log.info("Period number {} for due date {} and outstanding 
{}", period.getPeriod(), period.getDueDate(),
+                        period.getTotalOutstandingForPeriod());
+            }
+        }
+        // When
+        // Apply a repayment to get a first full paid installment
+        todaysDate = Utils.getLocalDateOfTenant();
+        operationDate = Utils.dateFormatter.format(todaysDate);
+        loanTransactionHelper.makeRepayment(operationDate, 1050.0f, loanId);
+
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, 
responseSpec, loanId);
+        log.info("Loan Delinquency Range after first Repayment {}", 
getLoansLoanIdResponse.getDelinquencyRange());
+        assertNotNull(getLoansLoanIdResponse.getDelinquencyRange());
+        // First Loan Delinquency Classification remains after Repayment 
because the installment is not fully paid
+        
assertEquals(getLoansLoanIdResponse.getDelinquencyRange().getClassification(), 
classificationExpected02);
+
+        ArrayList<GetDelinquencyTagHistoryResponse> getDelinquencyTagsHistory 
= loanTransactionHelper.getLoanDelinquencyTags(requestSpec,
+                responseSpec, loanId);
+        assertNotNull(getDelinquencyTagsHistory);
+        log.info("Delinquency Tag History items {}", 
getDelinquencyTagsHistory.size());
+        log.info("Delinquency Tag Item with Lifted On {}", 
getDelinquencyTagsHistory.get(0).getLiftedOnDate());
+        log.info("Loan Id {} with Loan status {}", 
getLoansLoanIdResponse.getId(), getLoansLoanIdResponse.getStatus().getCode());
+
+        // Apply a repayment to get a second full paid installment
+        loanTransactionHelper.makeRepayment(operationDate, 1020.0f, loanId);
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, 
responseSpec, loanId);
+        log.info("Loan Delinquency Range after second Repayment {}", 
getLoansLoanIdResponse.getDelinquencyRange());
+        assertNotNull(getLoansLoanIdResponse);
+        // The Loan Delinquency Classification after Repayment command must be 
null
+        assertNull(getLoansLoanIdResponse.getDelinquencyRange());
+
+        getDelinquencyTagsHistory = 
loanTransactionHelper.getLoanDelinquencyTags(requestSpec, responseSpec, loanId);
+        assertNotNull(getDelinquencyTagsHistory);
+        log.info("Delinquency Tag History items {}", 
getDelinquencyTagsHistory.size());

Review Comment:
   Please check whether the history entry has the proper values: 
classification, added on date, lifted on date



##########
integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyBucketsIntegrationTest.java:
##########
@@ -321,4 +323,214 @@ public void testLoanClassificationJob() {
         GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
     }
 
+    @Test
+    public void testLoanClassificationRealtime() {
+        // Given
+        final LoanTransactionHelper loanTransactionHelper = new 
LoanTransactionHelper(this.requestSpec, this.responseSpec);
+
+        ArrayList<Integer> rangeIds = new ArrayList<>();
+        // First Range
+        String jsonRange = DelinquencyRangesHelper.getAsJSON(1, 3);
+        PostDelinquencyRangeResponse delinquencyRangeResponse = 
DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec,
+                jsonRange);
+        rangeIds.add(delinquencyRangeResponse.getResourceId());
+        jsonRange = DelinquencyRangesHelper.getAsJSON(4, 60);
+
+        GetDelinquencyRangesResponse range = 
DelinquencyRangesHelper.getDelinquencyRange(requestSpec, responseSpec,
+                delinquencyRangeResponse.getResourceId());
+
+        // Second Range
+        delinquencyRangeResponse = 
DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec, 
jsonRange);
+        rangeIds.add(delinquencyRangeResponse.getResourceId());
+
+        range = DelinquencyRangesHelper.getDelinquencyRange(requestSpec, 
responseSpec, delinquencyRangeResponse.getResourceId());
+        final String classificationExpected = range.getClassification();
+        log.info("Expected Delinquency Range classification after Disbursement 
{}", classificationExpected);
+
+        String jsonBucket = DelinquencyBucketsHelper.getAsJSON(rangeIds);
+        PostDelinquencyBucketResponse delinquencyBucketResponse = 
DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec,
+                responseSpec, jsonBucket);
+        assertNotNull(delinquencyBucketResponse);
+        final GetDelinquencyBucketsResponse delinquencyBucket = 
DelinquencyBucketsHelper.getDelinquencyBucket(requestSpec, responseSpec,
+                delinquencyBucketResponse.getResourceId());
+
+        // Client and Loan account creation
+        final Integer clientId = ClientHelper.createClient(this.requestSpec, 
this.responseSpec, "01 January 2012");
+        final HashMap<String, Object> loanProductMap = new 
LoanProductTestBuilder().build(null, delinquencyBucket.getId());
+        final Integer loanProductId = 
loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap));
+
+        final GetLoanProductsProductIdResponse getLoanProductsProductResponse 
= loanTransactionHelper.getLoanProduct(loanProductId);
+        assertNotNull(getLoanProductsProductResponse);
+        log.info("Loan Product Bucket Name: {}", 
getLoanProductsProductResponse.getDelinquencyBucket().getName());
+        
assertEquals(getLoanProductsProductResponse.getDelinquencyBucket().getName(), 
delinquencyBucket.getName());
+
+        LocalDate todaysDate = Utils.getLocalDateOfTenant();
+        todaysDate = todaysDate.minusDays(40);
+        String operationDate = Utils.dateFormatter.format(todaysDate);
+        final String principalAmount = "10000";
+
+        final String loanApplicationJSON = new 
LoanApplicationTestBuilder().withPrincipal(principalAmount).withLoanTermFrequency("12")
+                
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("12").withRepaymentEveryAfter("1")
+                .withRepaymentFrequencyTypeAsMonths() //
+                .withInterestRatePerPeriod("2") //
+                .withExpectedDisbursementDate(operationDate) //
+                .withInterestTypeAsDecliningBalance() //
+                .withSubmittedOnDate(operationDate) //
+                .build(clientId.toString(), loanProductId.toString(), null);
+        final Integer loanId = 
loanTransactionHelper.getLoanId(loanApplicationJSON);
+        loanTransactionHelper.approveLoan(operationDate, principalAmount, 
loanId, null);
+        
loanTransactionHelper.disburseLoanWithNetDisbursalAmount(operationDate, loanId, 
principalAmount);
+
+        GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
+        log.info("Loan Delinquency Range after Disbursement {}", 
getLoansLoanIdResponse.getDelinquencyRange().getClassification());
+        assertNotNull(getLoansLoanIdResponse);
+        // First Loan Delinquency Classification after Disbursement command
+        
assertEquals(getLoansLoanIdResponse.getDelinquencyRange().getClassification(), 
classificationExpected);
+
+        // When
+        // Apply a partial repayment
+        todaysDate = Utils.getLocalDateOfTenant();
+        operationDate = Utils.dateFormatter.format(todaysDate);
+        loanTransactionHelper.makeRepayment(operationDate, 100.0f, loanId);
+
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, 
responseSpec, loanId);
+        log.info("Loan Delinquency Range after Repayment {}", 
getLoansLoanIdResponse.getDelinquencyRange());
+        assertNotNull(getLoansLoanIdResponse.getDelinquencyRange());
+        // First Loan Delinquency Classification remains after Repayment 
because the installment is not fully paid
+        
assertEquals(getLoansLoanIdResponse.getDelinquencyRange().getClassification(), 
classificationExpected);
+
+        // Apply a repayment to get a full paid installment
+        loanTransactionHelper.makeRepayment(operationDate, 1000.0f, loanId);
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, 
responseSpec, loanId);
+        log.info("Loan Delinquency Range after Repayment {}", 
getLoansLoanIdResponse.getDelinquencyRange());
+        assertNotNull(getLoansLoanIdResponse);
+        // The Loan Delinquency Classification after Repayment command must be 
null
+        assertNull(getLoansLoanIdResponse.getDelinquencyRange());
+        // Get the Delinquency Tags
+        ArrayList<GetDelinquencyTagHistoryResponse> getDelinquencyTagsHistory 
= loanTransactionHelper.getLoanDelinquencyTags(requestSpec,
+                responseSpec, loanId);
+        assertNotNull(getDelinquencyTagsHistory);
+        log.info("Delinquency Tag History items {}", 
getDelinquencyTagsHistory.size());
+        assertEquals(1, getDelinquencyTagsHistory.size());
+        assertNotNull(getDelinquencyTagsHistory.get(0).getLiftedOnDate());
+        log.info("Delinquency Tag Item with Lifted On {}", 
getDelinquencyTagsHistory.get(0).getLiftedOnDate());
+    }
+
+    @Test
+    public void testLoanClassificationRealtimeOlderLoan() {
+        // Given
+        final LoanTransactionHelper loanTransactionHelper = new 
LoanTransactionHelper(this.requestSpec, this.responseSpec);
+
+        ArrayList<Integer> rangeIds = new ArrayList<>();
+        // First Range
+        String jsonRange = DelinquencyRangesHelper.getAsJSON(4, 30);
+        PostDelinquencyRangeResponse delinquencyRangeResponse = 
DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec,
+                jsonRange);
+        rangeIds.add(delinquencyRangeResponse.getResourceId());
+        GetDelinquencyRangesResponse range = 
DelinquencyRangesHelper.getDelinquencyRange(requestSpec, responseSpec,
+                delinquencyRangeResponse.getResourceId());
+        final String classificationExpected02 = range.getClassification();
+        log.info("Expected Delinquency Range classification after first 
repayment {}", classificationExpected02);
+
+        // Second Range
+        jsonRange = DelinquencyRangesHelper.getAsJSON(31, 60);
+        delinquencyRangeResponse = 
DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec, 
jsonRange);
+        rangeIds.add(delinquencyRangeResponse.getResourceId());
+
+        range = DelinquencyRangesHelper.getDelinquencyRange(requestSpec, 
responseSpec, delinquencyRangeResponse.getResourceId());
+        final String classificationExpected01 = range.getClassification();
+        log.info("Expected Delinquency Range classification after Disbursement 
{}", classificationExpected01);
+
+        // Third Range
+        jsonRange = DelinquencyRangesHelper.getAsJSON(61, 90);
+        delinquencyRangeResponse = 
DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec, 
jsonRange);
+        rangeIds.add(delinquencyRangeResponse.getResourceId());
+
+        range = DelinquencyRangesHelper.getDelinquencyRange(requestSpec, 
responseSpec, delinquencyRangeResponse.getResourceId());
+
+        String jsonBucket = DelinquencyBucketsHelper.getAsJSON(rangeIds);
+        PostDelinquencyBucketResponse delinquencyBucketResponse = 
DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec,
+                responseSpec, jsonBucket);
+        assertNotNull(delinquencyBucketResponse);
+        final GetDelinquencyBucketsResponse delinquencyBucket = 
DelinquencyBucketsHelper.getDelinquencyBucket(requestSpec, responseSpec,
+                delinquencyBucketResponse.getResourceId());
+
+        // Client and Loan account creation
+        final Integer clientId = ClientHelper.createClient(this.requestSpec, 
this.responseSpec, "01 January 2012");
+        final HashMap<String, Object> loanProductMap = new 
LoanProductTestBuilder().build(null, delinquencyBucket.getId());
+        final Integer loanProductId = 
loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap));
+
+        final GetLoanProductsProductIdResponse getLoanProductsProductResponse 
= loanTransactionHelper.getLoanProduct(loanProductId);
+        assertNotNull(getLoanProductsProductResponse);
+        log.info("Loan Product Bucket Name: {}", 
getLoanProductsProductResponse.getDelinquencyBucket().getName());
+        
assertEquals(getLoanProductsProductResponse.getDelinquencyBucket().getName(), 
delinquencyBucket.getName());
+
+        LocalDate todaysDate = Utils.getLocalDateOfTenant();
+        // Older date to have more than one overdue installment
+        todaysDate = todaysDate.minusDays(85);
+        String operationDate = Utils.dateFormatter.format(todaysDate);
+        final String principalAmount = "10000";
+
+        final String loanApplicationJSON = new 
LoanApplicationTestBuilder().withPrincipal(principalAmount).withLoanTermFrequency("12")
+                
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("12").withRepaymentEveryAfter("1")
+                .withRepaymentFrequencyTypeAsMonths() //
+                .withInterestRatePerPeriod("2") //
+                .withExpectedDisbursementDate(operationDate) //
+                .withInterestTypeAsDecliningBalance() //
+                .withSubmittedOnDate(operationDate) //
+                .build(clientId.toString(), loanProductId.toString(), null);
+        final Integer loanId = 
loanTransactionHelper.getLoanId(loanApplicationJSON);
+        loanTransactionHelper.approveLoan(operationDate, principalAmount, 
loanId, null);
+        
loanTransactionHelper.disburseLoanWithNetDisbursalAmount(operationDate, loanId, 
principalAmount);
+
+        GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
+        assertNotNull(getLoansLoanIdResponse);
+        log.info("Loan Delinquency Range after Disbursement in null? {}", 
(getLoansLoanIdResponse.getDelinquencyRange() == null));
+        assertNotNull(getLoansLoanIdResponse.getDelinquencyRange());
+        log.info("Loan Delinquency Range after Disbursement {}", 
getLoansLoanIdResponse.getDelinquencyRange().getClassification());
+        // First Loan Delinquency Classification after Disbursement command
+        
assertEquals(getLoansLoanIdResponse.getDelinquencyRange().getClassification(), 
classificationExpected01);
+
+        GetLoansLoanIdRepaymentSchedule getLoanRepaymentSchedule = 
getLoansLoanIdResponse.getRepaymentSchedule();
+        if (getLoanRepaymentSchedule != null) {
+            log.info("Loan with {} periods", 
getLoanRepaymentSchedule.getPeriods().size());
+            for (GetLoansLoanIdRepaymentPeriod period : 
getLoanRepaymentSchedule.getPeriods()) {
+                log.info("Period number {} for due date {} and outstanding 
{}", period.getPeriod(), period.getDueDate(),
+                        period.getTotalOutstandingForPeriod());
+            }
+        }
+        // When
+        // Apply a repayment to get a first full paid installment
+        todaysDate = Utils.getLocalDateOfTenant();
+        operationDate = Utils.dateFormatter.format(todaysDate);
+        loanTransactionHelper.makeRepayment(operationDate, 1050.0f, loanId);
+
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, 
responseSpec, loanId);
+        log.info("Loan Delinquency Range after first Repayment {}", 
getLoansLoanIdResponse.getDelinquencyRange());
+        assertNotNull(getLoansLoanIdResponse.getDelinquencyRange());
+        // First Loan Delinquency Classification remains after Repayment 
because the installment is not fully paid
+        
assertEquals(getLoansLoanIdResponse.getDelinquencyRange().getClassification(), 
classificationExpected02);
+
+        ArrayList<GetDelinquencyTagHistoryResponse> getDelinquencyTagsHistory 
= loanTransactionHelper.getLoanDelinquencyTags(requestSpec,
+                responseSpec, loanId);
+        assertNotNull(getDelinquencyTagsHistory);
+        log.info("Delinquency Tag History items {}", 
getDelinquencyTagsHistory.size());

Review Comment:
   Please check whether the history entry has the proper values: 
classification, added on date, lifted on date



##########
integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyBucketsIntegrationTest.java:
##########
@@ -321,4 +321,89 @@ public void testLoanClassificationJob() {
         GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
     }
 
+    @Test
+    public void testLoanClassificationRealtime() {
+        // Given
+        final LoanTransactionHelper loanTransactionHelper = new 
LoanTransactionHelper(this.requestSpec, this.responseSpec);
+
+        ArrayList<Integer> rangeIds = new ArrayList<>();
+        // First Range
+        String jsonRange = DelinquencyRangesHelper.getAsJSON(1, 3);
+        PostDelinquencyRangeResponse delinquencyRangeResponse = 
DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec,
+                jsonRange);
+        rangeIds.add(delinquencyRangeResponse.getResourceId());
+        jsonRange = DelinquencyRangesHelper.getAsJSON(4, 60);
+
+        GetDelinquencyRangesResponse range = 
DelinquencyRangesHelper.getDelinquencyRange(requestSpec, responseSpec,
+                delinquencyRangeResponse.getResourceId());
+
+        // Second Range
+        delinquencyRangeResponse = 
DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec, 
jsonRange);
+        rangeIds.add(delinquencyRangeResponse.getResourceId());
+
+        range = DelinquencyRangesHelper.getDelinquencyRange(requestSpec, 
responseSpec, delinquencyRangeResponse.getResourceId());
+        final String classificationExpected = range.getClassification();
+        log.info("Expected Delinquency Range classification after Disbursement 
{}", classificationExpected);
+
+        String jsonBucket = DelinquencyBucketsHelper.getAsJSON(rangeIds);
+        PostDelinquencyBucketResponse delinquencyBucketResponse = 
DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec,
+                responseSpec, jsonBucket);
+        assertNotNull(delinquencyBucketResponse);
+        final GetDelinquencyBucketsResponse delinquencyBucket = 
DelinquencyBucketsHelper.getDelinquencyBucket(requestSpec, responseSpec,
+                delinquencyBucketResponse.getResourceId());
+
+        // Client and Loan account creation
+        final Integer clientId = ClientHelper.createClient(this.requestSpec, 
this.responseSpec, "01 January 2012");
+        final HashMap<String, Object> loanProductMap = new 
LoanProductTestBuilder().build(null, delinquencyBucket.getId());
+        final Integer loanProductId = 
loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap));
+
+        final GetLoanProductsProductIdResponse getLoanProductsProductResponse 
= loanTransactionHelper.getLoanProduct(loanProductId);
+        assertNotNull(getLoanProductsProductResponse);
+        log.info("Loan Product Bucket Name: {}", 
getLoanProductsProductResponse.getDelinquencyBucket().getName());
+        
assertEquals(getLoanProductsProductResponse.getDelinquencyBucket().getName(), 
delinquencyBucket.getName());
+
+        LocalDate todaysDate = Utils.getLocalDateOfTenant();
+        todaysDate = todaysDate.minusDays(40);
+        String operationDate = Utils.dateFormatter.format(todaysDate);
+        final String principalAmount = "10000";
+
+        final String loanApplicationJSON = new 
LoanApplicationTestBuilder().withPrincipal(principalAmount).withLoanTermFrequency("12")
+                
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("12").withRepaymentEveryAfter("1")
+                .withRepaymentFrequencyTypeAsMonths() //
+                .withInterestRatePerPeriod("2") //
+                .withExpectedDisbursementDate(operationDate) //
+                .withInterestTypeAsDecliningBalance() //
+                .withSubmittedOnDate(operationDate) //
+                .build(clientId.toString(), loanProductId.toString(), null);
+        final Integer loanId = 
loanTransactionHelper.getLoanId(loanApplicationJSON);
+        loanTransactionHelper.approveLoan(operationDate, principalAmount, 
loanId, null);
+        
loanTransactionHelper.disburseLoanWithNetDisbursalAmount(operationDate, loanId, 
principalAmount);
+
+        GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
+        log.info("Loan Delinquency Range after Disbursement {}", 
getLoansLoanIdResponse.getDelinquencyRange().getClassification());
+        assertNotNull(getLoansLoanIdResponse);
+        // First Loan Delinquency Classification after Disbursement command
+        
assertEquals(getLoansLoanIdResponse.getDelinquencyRange().getClassification(), 
classificationExpected);
+
+        // When
+        // Apply a partial repayment
+        todaysDate = Utils.getLocalDateOfTenant();
+        operationDate = Utils.dateFormatter.format(todaysDate);
+        loanTransactionHelper.makeRepayment(operationDate, 100.0f, loanId);
+
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, 
responseSpec, loanId);
+        log.info("Loan Delinquency Range after Repayment {}", 
getLoansLoanIdResponse.getDelinquencyRange());
+        assertNotNull(getLoansLoanIdResponse.getDelinquencyRange());
+        // First Loan Delinquency Classification remains after Repayment 
because the installment is not fully paid
+        
assertEquals(getLoansLoanIdResponse.getDelinquencyRange().getClassification(), 
classificationExpected);
+
+        // Apply a repayment to get a full paid installment
+        loanTransactionHelper.makeRepayment(operationDate, 1000.0f, loanId);
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, 
responseSpec, loanId);
+        log.info("Loan Delinquency Range after Repayment {}", 
getLoansLoanIdResponse.getDelinquencyRange());
+        assertNotNull(getLoansLoanIdResponse);
+        // The Loan Delinquency Classification after Repayment command must be 
null
+        assertNull(getLoansLoanIdResponse.getDelinquencyRange());
+    }
+
 }

Review Comment:
   The following use cases are still not covered:
   - Check what happens if a backdated repayment make the instalment unpaid -> 
will the delinquency classfication applied? History entries are correct?
   - Check what happens if the repayment that paid off fully the loan (which 
had priorly delinquency classification) is got reverted -> will the delinquency 
classfication applied? History entries are correct?
   - Check what happens if the repayment that paid off fully the loan (which 
had priorly delinquency classification) is got reverted -> will the delinquency 
classfication applied? History entries are correct?
   - Check what happens if the loan was delinquent but it got fully **prepaid** 
and closed -> will the delinquency classfication applied? History entries are 
correct?
   - Check what happens if the loan was delinquent but it got fully **prepaid** 
and closed -> will the delinquency classfication applied? History entries are 
correct?



-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to