This is an automated email from the ASF dual-hosted git repository.

arnold pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git


The following commit(s) were added to refs/heads/develop by this push:
     new 0487bece0 FINERACT-1661 Allow merchant_issued and payout refunds when 
fullyPaid/Overpaid
0487bece0 is described below

commit 0487bece0b02a00a70ed03d3ba1e727d41e16e7c
Author: John Woodlock <[email protected]>
AuthorDate: Fri Jul 8 01:27:56 2022 +0100

    FINERACT-1661 Allow merchant_issued and payout refunds when 
fullyPaid/Overpaid
---
 .../portfolio/loanaccount/domain/Loan.java         | 20 +++++++++-
 ...lanceRefundandRepaymentTypeIntegrationTest.java | 43 +++++++++++++++++++---
 .../common/loans/LoanTransactionHelper.java        |  8 ++--
 3 files changed, 60 insertions(+), 11 deletions(-)

diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
index f8ef7d7d2..642b69b1e 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
@@ -3098,7 +3098,7 @@ public class Loan extends AbstractPersistableCustom {
         if (!isHolidayValidationDone) {
             holidayDetailDTO = scheduleGeneratorDTO.getHolidayDetailDTO();
         }
-        validateAccountStatus(event);
+        validateRepaymentTypeAccountStatus(repaymentTransaction, event);
         validateActivityNotBeforeClientOrGroupTransferDate(event, 
repaymentTransaction.getTransactionDate());
         validateActivityNotBeforeLastTransactionDate(event, 
repaymentTransaction.getTransactionDate());
         if (!isHolidayValidationDone) {
@@ -3116,6 +3116,24 @@ public class Loan extends AbstractPersistableCustom {
         return changedTransactionDetail;
     }
 
+    private void validateRepaymentTypeAccountStatus(LoanTransaction 
repaymentTransaction, LoanEvent event) {
+        if (repaymentTransaction.isGoodwillCredit() || 
repaymentTransaction.isMerchantIssuedRefund()
+                || repaymentTransaction.isPayoutRefund()) {
+
+            if (!(isOpen() || isClosedObligationsMet() || isOverPaid())) {
+                final List<ApiParameterError> dataValidationErrors = new 
ArrayList<>();
+                final String defaultUserMessage = "Loan must be Active, Fully 
Paid or Overpaid";
+                final ApiParameterError error = 
ApiParameterError.generalError("error.msg.loan.must.be.active.fully.paid.or.overpaid",
+                        defaultUserMessage);
+                dataValidationErrors.add(error);
+                throw new 
PlatformApiDataValidationException(dataValidationErrors);
+            }
+        } else {
+            validateAccountStatus(event);
+        }
+
+    }
+
     public void makeChargePayment(final Long chargeId, final 
LoanLifecycleStateMachine loanLifecycleStateMachine,
             final List<Long> existingTransactionIds, final List<Long> 
existingReversedTransactionIds,
             final HolidayDetailDTO holidayDetailDTO, final LoanTransaction 
paymentTransaction, final Integer installmentNumber) {
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanCreditBalanceRefundandRepaymentTypeIntegrationTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanCreditBalanceRefundandRepaymentTypeIntegrationTest.java
index ebc94ded9..7e5a9748e 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanCreditBalanceRefundandRepaymentTypeIntegrationTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanCreditBalanceRefundandRepaymentTypeIntegrationTest.java
@@ -62,6 +62,7 @@ public class 
ClientLoanCreditBalanceRefundandRepaymentTypeIntegrationTest {
     private Account incomeAccount;
     private Account expenseAccount;
     private Account overpaymentAccount;
+    private static final String REPAYMENT = "repayment";
     private static final String MERCHANT_ISSUED_REFUND = 
"merchantIssuedRefund";
     private static final String PAYOUT_REFUND = "payoutRefund";
     private static final String GOODWILL_CREDIT = "goodwillCredit";
@@ -343,8 +344,8 @@ public class 
ClientLoanCreditBalanceRefundandRepaymentTypeIntegrationTest {
     }
 
     private void verifyRepaymentTransactionTypeMatches(final String 
repaymentTransactionType) {
-        HashMap loanStatusHashMap = 
this.loanTransactionHelper.makeRepaymentTypePayment(repaymentTransactionType, 
"06 January 2022",
-                200.00f, this.disbursedLoanID);
+        HashMap loanStatusHashMap = (HashMap) 
this.loanTransactionHelper.makeRepaymentTypePayment(repaymentTransactionType,
+                "06 January 2022", 200.00f, this.disbursedLoanID, "");
         Integer newTransactionId = (Integer) 
loanStatusHashMap.get("resourceId");
         loanStatusHashMap = 
this.loanTransactionHelper.getLoanTransactionDetails(this.disbursedLoanID, 
newTransactionId);
 
@@ -353,6 +354,36 @@ public class 
ClientLoanCreditBalanceRefundandRepaymentTypeIntegrationTest {
         Assertions.assertTrue(Boolean.TRUE.equals(isTypeCorrect), "Not " + 
repaymentTransactionType);
     }
 
+    @Test
+    public void repaymentTransactionTypeWhenPaidTest() {
+        verifyRepaymentTransactionTypeWhenPaid(MERCHANT_ISSUED_REFUND);
+        verifyRepaymentTransactionTypeWhenPaid(PAYOUT_REFUND);
+        verifyRepaymentTransactionTypeWhenPaid(GOODWILL_CREDIT);
+        verifyRepaymentTransactionTypeWhenPaid(REPAYMENT);
+
+    }
+
+    private void verifyRepaymentTransactionTypeWhenPaid(final String 
repaymentTransactionType) {
+
+        disburseLoanOfAccountingRule(ACCRUAL_PERIODIC);
+        // Overpay loan
+        Integer resourceId = (Integer) 
this.loanTransactionHelper.makeRepaymentTypePayment(REPAYMENT, "06 January 
2022", 13000.00f,
+                this.disbursedLoanID, "resourceId");
+        Assertions.assertNotNull(resourceId);
+
+        if (repaymentTransactionType.equalsIgnoreCase(REPAYMENT)) {
+            ArrayList<HashMap> errors = (ArrayList<HashMap>) 
this.loanTransactionHelperValidationError.makeRepaymentTypePayment(
+                    repaymentTransactionType, "06 January 2022", 1.00f, 
this.disbursedLoanID, CommonConstants.RESPONSE_ERROR);
+
+            
assertEquals("error.msg.loan.repayment.or.waiver.account.is.not.active",
+                    
errors.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
+        } else {
+            resourceId = (Integer) 
this.loanTransactionHelper.makeRepaymentTypePayment(repaymentTransactionType, 
"06 January 2022", 1.00f,
+                    this.disbursedLoanID, "resourceId");
+            Assertions.assertNotNull(resourceId);
+        }
+    }
+
     @Test
     public void 
newGoodwillCreditCreatesCorrectJournalEntriesForPeriodicAccrualsTest() {
 
@@ -366,8 +397,8 @@ public class 
ClientLoanCreditBalanceRefundandRepaymentTypeIntegrationTest {
         final Float overpaidAmount = 159.00f;
         final Float goodwillAmount = totalOutstanding + overpaidAmount;
         final String goodwillDate = "09 January 2022";
-        HashMap loanStatusHashMap = 
this.loanTransactionHelper.makeRepaymentTypePayment(GOODWILL_CREDIT, 
goodwillDate, goodwillAmount,
-                this.disbursedLoanID);
+        HashMap loanStatusHashMap = (HashMap) 
this.loanTransactionHelper.makeRepaymentTypePayment(GOODWILL_CREDIT, 
goodwillDate,
+                goodwillAmount, this.disbursedLoanID, "");
 
         // only a single credit for principal and interest as test sets up 
same GL account for both (summed up)
         this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, 
goodwillDate,
@@ -392,8 +423,8 @@ public class 
ClientLoanCreditBalanceRefundandRepaymentTypeIntegrationTest {
         final Float overpaidAmount = 159.00f;
         final Float goodwillAmount = totalOutstanding + overpaidAmount;
         final String goodwillDate = "09 January 2022";
-        HashMap loanStatusHashMap = 
this.loanTransactionHelper.makeRepaymentTypePayment(GOODWILL_CREDIT, 
goodwillDate, goodwillAmount,
-                this.disbursedLoanID);
+        HashMap loanStatusHashMap = (HashMap) 
this.loanTransactionHelper.makeRepaymentTypePayment(GOODWILL_CREDIT, 
goodwillDate,
+                goodwillAmount, this.disbursedLoanID, "");
 
         this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, 
goodwillDate,
                 new JournalEntry(principalOutstanding, 
JournalEntry.TransactionType.CREDIT));
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
index b0a0121ed..4b88a2aa8 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
@@ -349,10 +349,10 @@ public class LoanTransactionHelper {
                 getCreditBalanceRefundBodyAsJSON(date, amountToBePaid, 
externalId), jsonAttributeToGetback);
     }
 
-    public HashMap makeRepaymentTypePayment(final String repaymentTypeCommand, 
final String date, final Float amountToBePaid,
-            final Integer loanID) {
-        return (HashMap) 
performLoanTransaction(createLoanTransactionURL(repaymentTypeCommand, loanID),
-                getRepaymentBodyAsJSON(date, amountToBePaid), "");
+    public Object makeRepaymentTypePayment(final String repaymentTypeCommand, 
final String date, final Float amountToBePaid,
+            final Integer loanID, String jsonAttributeToGetback) {
+        return 
performLoanTransaction(createLoanTransactionURL(repaymentTypeCommand, loanID), 
getRepaymentBodyAsJSON(date, amountToBePaid),
+                jsonAttributeToGetback);
     }
 
     public HashMap makeRepayment(final String date, final Float 
amountToBePaid, final Integer loanID) {

Reply via email to