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 875935605..09416e5b0 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.ExternalAssetOwnerTransferJournalEntr 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 class AccountingServiceImpl implements AccountingService { public void createJournalEntriesForBuybackAssetTransfer(final Loan loan, final ExternalAssetOwnerTransfer transfer) { List 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 2edba122e..0eb599449 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 class ExternalAssetOwnerHelper extends IntegrationTest { 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 3c759d36e..28a349db6 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 @@ -477,6 +477,123 @@ public class InitiateExternalAssetOwnerTransferTest { } } + @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 {