FINERACT-2071: Fixing journal entries on buyback
diff --git a/fineract-investor/src/main/java/org/apache/fineract/investor/service/AccountingServiceImpl.java b/fineract-investor/src/main/java/org/apache/fineract/investor/service/AccountingServiceImpl.java
index 8759356..09416e5 100644
--- a/fineract-investor/src/main/java/org/apache/fineract/investor/service/AccountingServiceImpl.java
+++ b/fineract-investor/src/main/java/org/apache/fineract/investor/service/AccountingServiceImpl.java
@@ -40,6 +40,7 @@
 import org.apache.fineract.investor.domain.ExternalAssetOwnerTransferJournalEntryMappingRepository;
 import org.apache.fineract.organisation.office.domain.Office;
 import org.apache.fineract.portfolio.loanaccount.domain.Loan;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
 import org.jetbrains.annotations.NotNull;
 import org.springframework.stereotype.Service;
 
@@ -69,7 +70,8 @@
     public void createJournalEntriesForBuybackAssetTransfer(final Loan loan, final ExternalAssetOwnerTransfer transfer) {
         List<JournalEntry> journalEntryList = createJournalEntries(loan, transfer, false);
         createMappingToTransfer(transfer, journalEntryList);
-        createMappingToOwner(transfer, journalEntryList, JournalEntryType.CREDIT);
+        createMappingToOwner(transfer, journalEntryList,
+                LoanStatus.OVERPAID.equals(loan.getStatus()) ? JournalEntryType.DEBIT : JournalEntryType.CREDIT);
     }
 
     @NotNull
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/ExternalAssetOwnerHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/ExternalAssetOwnerHelper.java
index 2edba12..0eb5994 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/ExternalAssetOwnerHelper.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/ExternalAssetOwnerHelper.java
@@ -98,7 +98,8 @@
 
     public PagedRequestExternalAssetOwnerSearchRequest buildExternalAssetOwnerSearchRequest(String text, String attribute,
             LocalDate fromDate, LocalDate toDate, Integer page, Integer size) {
-        final Integer DEFAULT_PAGE_SIZE = 50;
+        // increase it if tests create more than 100 items
+        final Integer DEFAULT_PAGE_SIZE = 100;
         PagedRequestExternalAssetOwnerSearchRequest pagedRequest = new PagedRequestExternalAssetOwnerSearchRequest();
         ExternalAssetOwnerSearchRequest searchRequest = new ExternalAssetOwnerSearchRequest();
         searchRequest.text(text);
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/investor/externalassetowner/InitiateExternalAssetOwnerTransferTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/investor/externalassetowner/InitiateExternalAssetOwnerTransferTest.java
index 3c759d3..28a349d 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/investor/externalassetowner/InitiateExternalAssetOwnerTransferTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/investor/externalassetowner/InitiateExternalAssetOwnerTransferTest.java
@@ -478,6 +478,123 @@
     }
 
     @Test
+    public void saleOverpaidLoanToExternalAssetOwnerAndBuybackADayLater() {
+        try {
+            GlobalConfigurationHelper.manageConfigurations(REQUEST_SPEC, RESPONSE_SPEC,
+                    GlobalConfigurationHelper.ENABLE_AUTOGENERATED_EXTERNAL_ID, true);
+            setInitialBusinessDate("2020-03-02");
+            Integer clientID = createClient();
+            Integer loanID = createLoanForClient(clientID);
+            addPenaltyForLoan(loanID, "10");
+
+            PostInitiateTransferResponse saleTransferResponse = createSaleTransfer(loanID, "2020-03-02");
+            validateResponse(saleTransferResponse, loanID);
+            getAndValidateExternalAssetOwnerTransferByLoan(loanID,
+                    ExpectedExternalTransferData.expected(PENDING, saleTransferResponse.getResourceExternalId(), "2020-03-02", "2020-03-02",
+                            "9999-12-31", false, new BigDecimal("15767.420000"), new BigDecimal("15000.000000"),
+                            new BigDecimal("757.420000"), new BigDecimal("10.000000"), new BigDecimal("0.000000"),
+                            new BigDecimal("0.000000")));
+            getAndValidateThereIsNoActiveMapping(saleTransferResponse.getResourceExternalId());
+            PageExternalTransferData retrieveResponse = EXTERNAL_ASSET_OWNER_HELPER.retrieveTransfersByLoanId(loanID.longValue());
+            retrieveResponse.getContent().forEach(transfer -> getAndValidateThereIsNoJournalEntriesForTransfer(transfer.getTransferId()));
+
+            updateBusinessDateAndExecuteCOBJob("2020-03-03");
+            getAndValidateExternalAssetOwnerTransferByLoan(loanID,
+                    ExpectedExternalTransferData.expected(PENDING, saleTransferResponse.getResourceExternalId(), "2020-03-02", "2020-03-02",
+                            "2020-03-02", false, new BigDecimal("15767.420000"), new BigDecimal("15000.000000"),
+                            new BigDecimal("757.420000"), new BigDecimal("10.000000"), new BigDecimal("0.000000"),
+                            new BigDecimal("0.000000")),
+                    ExpectedExternalTransferData.expected(ACTIVE, saleTransferResponse.getResourceExternalId(), "2020-03-02", "2020-03-03",
+                            "9999-12-31", true, new BigDecimal("15767.420000"), new BigDecimal("15000.000000"),
+                            new BigDecimal("757.420000"), new BigDecimal("10.000000"), new BigDecimal("0.000000"),
+                            new BigDecimal("0.000000")));
+            getAndValidateThereIsActiveMapping(loanID);
+            retrieveResponse = EXTERNAL_ASSET_OWNER_HELPER.retrieveTransfersByLoanId(loanID.longValue());
+            LocalDate expectedDate = LocalDate.of(2020, 3, 2);
+            getAndValidateThereIsJournalEntriesForTransfer(retrieveResponse.getContent().get(1).getTransferId(),
+                    ExpectedJournalEntryData.expected((long) ASSET_ACCOUNT.getAccountID(), (long) JournalEntryType.CREDIT.getValue(),
+                            BigDecimal.valueOf(15757.420000), expectedDate, expectedDate),
+                    ExpectedJournalEntryData.expected((long) FEE_PENALTY_ACCOUNT.getAccountID(), (long) JournalEntryType.CREDIT.getValue(),
+                            BigDecimal.valueOf(10.000000), expectedDate, expectedDate),
+                    ExpectedJournalEntryData.expected((long) TRANSFER_ACCOUNT.getAccountID(), (long) JournalEntryType.DEBIT.getValue(),
+                            BigDecimal.valueOf(15767.420000), expectedDate, expectedDate),
+                    ExpectedJournalEntryData.expected((long) ASSET_ACCOUNT.getAccountID(), (long) JournalEntryType.DEBIT.getValue(),
+                            BigDecimal.valueOf(15757.420000), expectedDate, expectedDate),
+                    ExpectedJournalEntryData.expected((long) FEE_PENALTY_ACCOUNT.getAccountID(), (long) JournalEntryType.DEBIT.getValue(),
+                            BigDecimal.valueOf(10.000000), expectedDate, expectedDate),
+                    ExpectedJournalEntryData.expected((long) TRANSFER_ACCOUNT.getAccountID(), (long) JournalEntryType.CREDIT.getValue(),
+                            BigDecimal.valueOf(15767.420000), expectedDate, expectedDate));
+
+            PostInitiateTransferResponse buybackTransferResponse = createBuybackTransfer(loanID, "2020-03-03");
+            validateResponse(buybackTransferResponse, loanID);
+            getAndValidateExternalAssetOwnerTransferByLoan(loanID,
+                    ExpectedExternalTransferData.expected(PENDING, saleTransferResponse.getResourceExternalId(), "2020-03-02", "2020-03-02",
+                            "2020-03-02", false, new BigDecimal("15767.420000"), new BigDecimal("15000.000000"),
+                            new BigDecimal("757.420000"), new BigDecimal("10.000000"), new BigDecimal("0.000000"),
+                            new BigDecimal("0.000000")),
+                    ExpectedExternalTransferData.expected(ACTIVE, saleTransferResponse.getResourceExternalId(), "2020-03-02", "2020-03-03",
+                            "9999-12-31", true, new BigDecimal("15767.420000"), new BigDecimal("15000.000000"),
+                            new BigDecimal("757.420000"), new BigDecimal("10.000000"), new BigDecimal("0.000000"),
+                            new BigDecimal("0.000000")),
+                    ExpectedExternalTransferData.expected(BUYBACK, buybackTransferResponse.getResourceExternalId(), "2020-03-03",
+                            "2020-03-03", "9999-12-31", false, new BigDecimal("15767.420000"), new BigDecimal("15000.000000"),
+                            new BigDecimal("757.420000"), new BigDecimal("10.000000"), new BigDecimal("0.000000"),
+                            new BigDecimal("0.000000")));
+            getAndValidateThereIsActiveMapping(loanID);
+            retrieveResponse = EXTERNAL_ASSET_OWNER_HELPER.retrieveTransfersByLoanId(loanID.longValue());
+            getAndValidateThereIsNoJournalEntriesForTransfer(retrieveResponse.getContent().get(2).getTransferId());
+
+            LOAN_TRANSACTION_HELPER.makeLoanRepayment((long) loanID, new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy")
+                    .transactionDate(dateFormatter.format(expectedDate)).locale("en").transactionAmount(15777.42));
+            LocalDate repaymentSubmittedOnDate = expectedDate.plusDays(1);
+            getAndValidateOwnerJournalEntries(ownerExternalId,
+                    ExpectedJournalEntryData.expected((long) ASSET_ACCOUNT.getAccountID(), (long) JournalEntryType.DEBIT.getValue(),
+                            BigDecimal.valueOf(15757.420000), expectedDate, expectedDate),
+                    ExpectedJournalEntryData.expected((long) FEE_PENALTY_ACCOUNT.getAccountID(), (long) JournalEntryType.DEBIT.getValue(),
+                            BigDecimal.valueOf(10.000000), expectedDate, expectedDate),
+                    ExpectedJournalEntryData.expected((long) OVERPAYMENT_ACCOUNT.getAccountID(), (long) JournalEntryType.DEBIT.getValue(),
+                            BigDecimal.valueOf(10.000000), repaymentSubmittedOnDate, repaymentSubmittedOnDate));
+
+            updateBusinessDateAndExecuteCOBJob("2020-03-04");
+            getAndValidateExternalAssetOwnerTransferByLoan(loanID,
+                    ExpectedExternalTransferData.expected(PENDING, saleTransferResponse.getResourceExternalId(), "2020-03-02", "2020-03-02",
+                            "2020-03-02", false, new BigDecimal("15767.420000"), new BigDecimal("15000.000000"),
+                            new BigDecimal("757.420000"), new BigDecimal("10.000000"), new BigDecimal("0.000000"),
+                            new BigDecimal("0.000000")),
+                    ExpectedExternalTransferData.expected(ACTIVE, saleTransferResponse.getResourceExternalId(), "2020-03-02", "2020-03-03",
+                            "2020-03-03", true, new BigDecimal("15767.420000"), new BigDecimal("15000.000000"),
+                            new BigDecimal("757.420000"), new BigDecimal("10.000000"), new BigDecimal("0.000000"),
+                            new BigDecimal("0.000000")),
+                    ExpectedExternalTransferData.expected(BUYBACK, buybackTransferResponse.getResourceExternalId(), "2020-03-03",
+                            "2020-03-03", "2020-03-03", true, new BigDecimal("0.000000"), new BigDecimal("0.000000"),
+                            new BigDecimal("0.000000"), new BigDecimal("0.000000"), new BigDecimal("0.000000"),
+                            new BigDecimal("10.000000")));
+            getAndValidateThereIsNoActiveMapping(saleTransferResponse.getResourceExternalId());
+            retrieveResponse = EXTERNAL_ASSET_OWNER_HELPER.retrieveTransfersByLoanId(loanID.longValue());
+            expectedDate = LocalDate.of(2020, 3, 3);
+            getAndValidateThereIsJournalEntriesForTransfer(retrieveResponse.getContent().get(2).getTransferId(),
+                    ExpectedJournalEntryData.expected((long) OVERPAYMENT_ACCOUNT.getAccountID(), (long) JournalEntryType.DEBIT.getValue(),
+                            BigDecimal.valueOf(10.000000), expectedDate, expectedDate),
+                    ExpectedJournalEntryData.expected((long) TRANSFER_ACCOUNT.getAccountID(), (long) JournalEntryType.CREDIT.getValue(),
+                            BigDecimal.valueOf(10.000000), expectedDate, expectedDate),
+                    ExpectedJournalEntryData.expected((long) OVERPAYMENT_ACCOUNT.getAccountID(), (long) JournalEntryType.CREDIT.getValue(),
+                            BigDecimal.valueOf(10.000000), expectedDate, expectedDate),
+                    ExpectedJournalEntryData.expected((long) TRANSFER_ACCOUNT.getAccountID(), (long) JournalEntryType.DEBIT.getValue(),
+                            BigDecimal.valueOf(10.000000), expectedDate, expectedDate));
+            LocalDate previousDayDate = LocalDate.of(2020, 3, 2);
+            getAndValidateOwnerJournalEntries(ownerExternalId,
+                    ExpectedJournalEntryData.expected((long) ASSET_ACCOUNT.getAccountID(), (long) JournalEntryType.DEBIT.getValue(),
+                            BigDecimal.valueOf(15757.420000), previousDayDate, previousDayDate),
+                    ExpectedJournalEntryData.expected((long) FEE_PENALTY_ACCOUNT.getAccountID(), (long) JournalEntryType.DEBIT.getValue(),
+                            BigDecimal.valueOf(10.000000), previousDayDate, previousDayDate),
+                    ExpectedJournalEntryData.expected((long) OVERPAYMENT_ACCOUNT.getAccountID(), (long) JournalEntryType.DEBIT.getValue(),
+                            BigDecimal.valueOf(10.000000), expectedDate, expectedDate));
+        } finally {
+            cleanUpAndRestoreBusinessDate();
+        }
+    }
+
+    @Test
     public void saleIsNotAllowedWhenTransferIsAlreadyPending() {
         try {
             GlobalConfigurationHelper.manageConfigurations(REQUEST_SPEC, RESPONSE_SPEC,