FINERACT-2467: Add previous owner id to transaction summary report with asset owner

This commit is contained in:
mariiaKraievska
2026-02-11 11:59:31 +01:00
committed by Adam Saghy
parent 02fb166b5b
commit 7faaf96246
3 changed files with 3232 additions and 0 deletions
@@ -53,6 +53,7 @@ import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import okhttp3.ResponseBody;
import org.apache.fineract.accounting.common.AccountingConstants;
import org.apache.fineract.accounting.journalentry.domain.JournalEntryType;
import org.apache.fineract.client.models.ExternalAssetOwnerRequest;
@@ -105,6 +106,7 @@ import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.lang.NonNull;
import retrofit2.Response;
@SuppressWarnings("rawtypes")
@ExtendWith({ ExternalEventsExtension.class })
@@ -1080,8 +1082,14 @@ public class InitiateExternalAssetOwnerTransferTest extends BaseLoanIntegrationT
assertNotNull(jsonPath.getString("columnHeaders[9].columnDisplayType"));
assertFalse(jsonPath.getBoolean("columnHeaders[9].isColumnNullable"));
assertNotNull(jsonPath.getString("columnHeaders[10].columnType"));
assertNotNull(jsonPath.getString("columnHeaders[10].columnDisplayType"));
assertFalse(jsonPath.getBoolean("columnHeaders[10].isColumnNullable"));
assertNotNull(retrieveResponse.getContent().get(0).getOwner());
final var ownerId = retrieveResponse.getContent().get(0).getOwner().getExternalId();
assertNotNull(retrieveResponse.getContent().get(2).getPreviousOwner());
final var previousOwnerId = retrieveResponse.getContent().get(2).getPreviousOwner().getExternalId();
assertEquals("2020-03-03", jsonPath.getString("data[0].row[0]"));
assertTrue(jsonPath.getString("data[0].row[1]").matches("^LOAN_PRODUCT_.{6}$"));
@@ -1093,6 +1101,7 @@ public class InitiateExternalAssetOwnerTransferTest extends BaseLoanIntegrationT
assertNull(jsonPath.getString("data[0].row[7]"));
assertEquals(9.68, jsonPath.getDouble("data[0].row[8]"), 0.01);
assertEquals(ownerId, jsonPath.getString("data[0].row[9]"));
assertNull(jsonPath.getString("data[0].row[10]"));
assertEquals("2020-03-03", jsonPath.getString("data[1].row[0]"));
assertTrue(jsonPath.getString("data[1].row[1]").matches("^LOAN_PRODUCT_.{6}$"));
@@ -1104,6 +1113,7 @@ public class InitiateExternalAssetOwnerTransferTest extends BaseLoanIntegrationT
assertNull(jsonPath.getString("data[1].row[7]"));
assertEquals(-757.42, jsonPath.getDouble("data[1].row[8]"), 0.01);
assertNull(jsonPath.getString("data[1].row[9]"));
assertEquals(previousOwnerId, jsonPath.getString("data[1].row[10]"));
assertEquals("2020-03-03", jsonPath.getString("data[2].row[0]"));
assertTrue(jsonPath.getString("data[2].row[1]").matches("^LOAN_PRODUCT_.{6}$"));
@@ -1115,6 +1125,7 @@ public class InitiateExternalAssetOwnerTransferTest extends BaseLoanIntegrationT
assertNull(jsonPath.getString("data[2].row[7]"));
assertEquals(-5.00, jsonPath.getDouble("data[2].row[8]"), 0.01);
assertNull(jsonPath.getString("data[2].row[9]"));
assertEquals(previousOwnerId, jsonPath.getString("data[2].row[10]"));
assertEquals("2020-03-03", jsonPath.getString("data[3].row[0]"));
assertTrue(jsonPath.getString("data[3].row[1]").matches("^LOAN_PRODUCT_.{6}$"));
@@ -1126,6 +1137,7 @@ public class InitiateExternalAssetOwnerTransferTest extends BaseLoanIntegrationT
assertNull(jsonPath.getString("data[3].row[7]"));
assertEquals(-15000.00, jsonPath.getDouble("data[3].row[8]"), 0.01);
assertNull(jsonPath.getString("data[3].row[9]"));
assertEquals(previousOwnerId, jsonPath.getString("data[3].row[10]"));
assertEquals("2020-03-03", jsonPath.getString("data[4].row[0]"));
assertTrue(jsonPath.getString("data[4].row[1]").matches("^LOAN_PRODUCT_.{6}$"));
@@ -1137,6 +1149,7 @@ public class InitiateExternalAssetOwnerTransferTest extends BaseLoanIntegrationT
assertNull(jsonPath.getString("data[4].row[7]"));
assertEquals(0.00, jsonPath.getDouble("data[4].row[8]"), 0.01);
assertEquals(ownerId, jsonPath.getString("data[4].row[9]"));
assertNull(jsonPath.getString("data[4].row[10]"));
assertEquals("2020-03-03", jsonPath.getString("data[5].row[0]"));
assertTrue(jsonPath.getString("data[5].row[1]").matches("^LOAN_PRODUCT_.{6}$"));
@@ -1148,6 +1161,7 @@ public class InitiateExternalAssetOwnerTransferTest extends BaseLoanIntegrationT
assertNull(jsonPath.getString("data[5].row[7]"));
assertEquals(0.00, jsonPath.getDouble("data[5].row[8]"), 0.01);
assertEquals(ownerId, jsonPath.getString("data[5].row[9]"));
assertNull(jsonPath.getString("data[5].row[10]"));
assertEquals("2020-03-03", jsonPath.getString("data[6].row[0]"));
assertTrue(jsonPath.getString("data[6].row[1]").matches("^LOAN_PRODUCT_.{6}$"));
@@ -1159,6 +1173,7 @@ public class InitiateExternalAssetOwnerTransferTest extends BaseLoanIntegrationT
assertNull(jsonPath.getString("data[6].row[7]"));
assertEquals(-5.00, jsonPath.getDouble("data[6].row[8]"), 0.01);
assertEquals(ownerId, jsonPath.getString("data[6].row[9]"));
assertNull(jsonPath.getString("data[6].row[10]"));
assertEquals("2020-03-03", jsonPath.getString("data[7].row[0]"));
assertTrue(jsonPath.getString("data[7].row[1]").matches("^LOAN_PRODUCT_.{6}$"));
@@ -1170,6 +1185,7 @@ public class InitiateExternalAssetOwnerTransferTest extends BaseLoanIntegrationT
assertNull(jsonPath.getString("data[7].row[7]"));
assertEquals(0.00, jsonPath.getDouble("data[7].row[8]"), 0.01);
assertEquals(ownerId, jsonPath.getString("data[7].row[9]"));
assertNull(jsonPath.getString("data[7].row[10]"));
assertEquals("2020-03-03", jsonPath.getString("data[8].row[0]"));
assertTrue(jsonPath.getString("data[8].row[1]").matches("^LOAN_PRODUCT_.{6}$"));
@@ -1181,6 +1197,101 @@ public class InitiateExternalAssetOwnerTransferTest extends BaseLoanIntegrationT
assertNull(jsonPath.getString("data[8].row[7]"));
assertEquals(0.00, jsonPath.getDouble("data[8].row[8]"), 0.01);
assertEquals(ownerId, jsonPath.getString("data[8].row[9]"));
assertNull(jsonPath.getString("data[8].row[10]"));
} finally {
ExternalEventHelper.deleteAllExternalEvents(REQUEST_SPEC, new ResponseSpecBuilder().expectStatusCode(Matchers.is(204)).build());
cleanUpAndRestoreBusinessDate();
}
}
@Test
public void transactionSummaryReportWithAssetOwner_CheckFromAssetOwnerIdForBuyback() throws IOException {
try {
globalConfigurationHelper.manageConfigurations(GlobalConfigurationConstants.ENABLE_AUTO_GENERATED_EXTERNAL_ID, true);
setInitialBusinessDate("2023-08-16");
ExternalEventHelper.deleteAllExternalEvents(REQUEST_SPEC, new ResponseSpecBuilder().expectStatusCode(Matchers.is(204)).build());
ExternalEventHelper.changeEventState(REQUEST_SPEC, RESPONSE_SPEC, "LoanOwnershipTransferBusinessEvent", true);
final Integer officeId = OFFICE_HELPER.createOffice("1 January 2020");
final Integer clientID = ClientHelper.createClient(REQUEST_SPEC, RESPONSE_SPEC, "1 January 2020", officeId.toString());
final Integer loanID = createLoanForClient(clientID);
// Create first sale transfer
final PostInitiateTransferResponse firstSaleTransferResponse = createSaleTransfer(loanID, "2023-08-16");
validateResponse(firstSaleTransferResponse, loanID);
// Verify the transfer is PENDING initially
getAndValidateExternalAssetOwnerTransferByLoan(loanID,
ExpectedExternalTransferData.expected(PENDING, firstSaleTransferResponse.getResourceExternalId(), "2023-08-16",
"2023-08-16", "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")));
// Execute COB job on the next day to activate the transfer
updateBusinessDateAndExecuteCOBJob("2023-08-17");
// Verify the transfer is ACTIVE after COB job
getAndValidateExternalAssetOwnerTransferByLoan(loanID,
ExpectedExternalTransferData.expected(PENDING, firstSaleTransferResponse.getResourceExternalId(), "2023-08-16",
"2023-08-16", "2023-08-16", 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, firstSaleTransferResponse.getResourceExternalId(), "2023-08-16",
"2023-08-17", "9999-12-31", true, new BigDecimal("15914.980000"), new BigDecimal("15000.000000"),
new BigDecimal("757.420000"), new BigDecimal("157.560000"), new BigDecimal("0.000000"),
new BigDecimal("0.000000")));
// Get the owner ID of the first transfer for later verification
PageExternalTransferData retrieveResponse = EXTERNAL_ASSET_OWNER_HELPER.retrieveTransfersByLoanId(loanID.longValue());
assertNotNull(retrieveResponse.getContent().get(1).getOwner());
final String firstOwnerId = retrieveResponse.getContent().get(1).getOwner().getExternalId();
assertNull(retrieveResponse.getContent().get(1).getPreviousOwner(), "First sale transfer should not have previous_owner_id");
// Create buyback transfer
updateBusinessDateAndExecuteCOBJob("2023-08-18");
final PostInitiateTransferResponse buybackTransferResponse = createBuybackTransfer(loanID, "2023-08-18");
validateResponse(buybackTransferResponse, loanID);
// Execute COB job to process buyback
updateBusinessDateAndExecuteCOBJob("2023-08-19");
// Verify buyback has previous_owner_id set
retrieveResponse = EXTERNAL_ASSET_OWNER_HELPER.retrieveTransfersByLoanId(loanID.longValue());
assertNotNull(retrieveResponse.getContent().get(2).getPreviousOwner());
assertEquals(firstOwnerId, retrieveResponse.getContent().get(2).getPreviousOwner().getExternalId(),
"Buyback transfer should have previous_owner_id set to first owner");
// Run report on settlement date of buyback to check that from_asset_owner_id is populated
final Response<ResponseBody> reportResult = reportHelper.runReport("Transaction Summary Report with Asset Owner",
Map.of("R_endDate", "2023-08-18", "R_officeId", officeId.toString(), "output-type", "CSV"));
assertNotNull(reportResult.body());
final String csvContent = reportResult.body().string();
final JsonPath jsonPath = JsonPath.from(csvContent);
// Find Asset Buyback entries to verify from_asset_owner_id is populated
final List<Map<String, Object>> buybackRows = new ArrayList<>();
final int dataSize = jsonPath.getInt("data.size()");
for (int i = 0; i < dataSize; i++) {
final String transactionType = jsonPath.getString("data[" + i + "].row[2]");
final String transactionDate = jsonPath.getString("data[" + i + "].row[0]");
// Find Asset Buyback entries for the buyback date
if ("Asset Buyback".equals(transactionType) && "2023-08-18".equals(transactionDate)) {
buybackRows.add(jsonPath.getMap("data[" + i + "]"));
}
}
// Verify that Asset Buyback entries exist
assertFalse(buybackRows.isEmpty(), "Asset Buyback entries should exist in the report");
// Verify that from_asset_owner_id is populated with previous_owner_id for buyback
for (Map<String, Object> row : buybackRows) {
final List<Object> rowData = (List<Object>) row.get("row");
assertNotNull(rowData.get(10), "from_asset_owner_id should be populated for buyback transfer");
assertEquals(firstOwnerId, rowData.get(10),
"from_asset_owner_id should equal the first owner's external ID for buyback transfer");
}
} finally {
ExternalEventHelper.deleteAllExternalEvents(REQUEST_SPEC, new ResponseSpecBuilder().expectStatusCode(Matchers.is(204)).build());
cleanUpAndRestoreBusinessDate();