FINERACT-1926: Fix request validation

This commit is contained in:
Adam Saghy
2023-06-16 20:58:38 +02:00
committed by Arnold Gálovics
parent 58d4cb6a8d
commit d5686ed45a
2 changed files with 143 additions and 17 deletions
@@ -89,7 +89,9 @@ public class ExternalAssetOwnersWriteServiceImpl implements ExternalAssetOwnersW
@Transactional
public CommandProcessingResult buybackLoanByLoanId(JsonCommand command) {
final JsonElement json = fromApiJsonHelper.parse(command.json());
validateBuybackRequestBody(command.json());
Long loanId = command.getLoanId();
validateLoan(loanId);
LocalDate settlementDate = getSettlementDateFromJson(json);
ExternalId externalId = getTransferExternalIdFromJson(json);
validateSettlementDate(settlementDate);
@@ -99,6 +101,12 @@ public class ExternalAssetOwnersWriteServiceImpl implements ExternalAssetOwnersW
return buildResponseData(externalAssetOwnerTransfer);
}
private void validateLoan(Long loanId) {
if (!loanRepository.existsById(loanId)) {
throw new LoanNotFoundException(loanId);
}
}
private void validateEffectiveTransferForSale(final ExternalAssetOwnerTransfer externalAssetOwnerTransfer) {
List<ExternalAssetOwnerTransfer> effectiveTransfers = externalAssetOwnerTransferRepository
.findEffectiveTransfers(externalAssetOwnerTransfer.getLoanId(), externalAssetOwnerTransfer.getSettlementDate());
@@ -244,6 +252,32 @@ public class ExternalAssetOwnersWriteServiceImpl implements ExternalAssetOwnersW
}
}
private void validateBuybackRequestBody(String apiRequestBodyAsJson) {
final Set<String> requestParameters = new HashSet<>(
Arrays.asList(ExternalTransferRequestParameters.SETTLEMENT_DATE, ExternalTransferRequestParameters.TRANSFER_EXTERNAL_ID,
ExternalTransferRequestParameters.DATEFORMAT, ExternalTransferRequestParameters.LOCALE));
final Type typeOfMap = new TypeToken<Map<String, Object>>() {
}.getType();
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, apiRequestBodyAsJson, requestParameters);
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loantransfer");
final JsonElement json = fromApiJsonHelper.parse(apiRequestBodyAsJson);
String transferExternalId = fromApiJsonHelper.extractStringNamed(ExternalTransferRequestParameters.TRANSFER_EXTERNAL_ID, json);
baseDataValidator.reset().parameter(ExternalTransferRequestParameters.TRANSFER_EXTERNAL_ID).value(transferExternalId).ignoreIfNull()
.notExceedingLengthOf(100);
LocalDate settlementDate = fromApiJsonHelper.extractLocalDateNamed(ExternalTransferRequestParameters.SETTLEMENT_DATE, json);
baseDataValidator.reset().parameter(ExternalTransferRequestParameters.SETTLEMENT_DATE).value(settlementDate).notNull();
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
dataValidationErrors);
}
}
private LocalDate getSettlementDateFromJson(JsonElement json) {
String dateFormat = fromApiJsonHelper.extractStringNamed(ExternalTransferRequestParameters.DATEFORMAT, json);
String locale = fromApiJsonHelper.extractStringNamed(ExternalTransferRequestParameters.LOCALE, json);
@@ -146,7 +146,7 @@ public class InitiateExternalAssetOwnerTransferTest {
Integer loanID = createLoanForClient(clientID);
addPenaltyForLoan(loanID, "10");
PostInitiateTransferResponse saleTransferResponse = createExternalAssetOwnerTransfer(loanID, "sale", "2020-03-02");
PostInitiateTransferResponse saleTransferResponse = createSaleTransfer(loanID, "2020-03-02");
validateResponse(saleTransferResponse, loanID);
getAndValidateExternalAssetOwnerTransferByLoan(loanID,
ExpectedExternalTransferData.expected(PENDING, saleTransferResponse.getResourceExternalId(), "2020-03-02", "2020-03-02",
@@ -184,7 +184,7 @@ public class InitiateExternalAssetOwnerTransferTest {
ExpectedJournalEntryData.expected((long) TRANSFER_ACCOUNT.getAccountID(), (long) JournalEntryType.CREDIT.getValue(),
BigDecimal.valueOf(15767.420000), expectedDate, expectedDate));
PostInitiateTransferResponse buybackTransferResponse = createExternalAssetOwnerTransfer(loanID, "buyback", "2020-03-03");
PostInitiateTransferResponse buybackTransferResponse = createBuybackTransfer(loanID, "2020-03-03");
validateResponse(buybackTransferResponse, loanID);
getAndValidateExternalAssetOwnerTransferByLoan(loanID,
ExpectedExternalTransferData.expected(PENDING, saleTransferResponse.getResourceExternalId(), "2020-03-02", "2020-03-02",
@@ -278,10 +278,10 @@ public class InitiateExternalAssetOwnerTransferTest {
Integer clientID = createClient();
Integer loanID = createLoanForClient(clientID);
createExternalAssetOwnerTransfer(loanID, "sale", "2020-03-02");
createSaleTransfer(loanID, "2020-03-02");
CallFailedRuntimeException exception = assertThrows(CallFailedRuntimeException.class,
() -> createExternalAssetOwnerTransfer(loanID, "sale", "2020-03-02"));
() -> createSaleTransfer(loanID, "2020-03-02"));
assertTrue(exception.getMessage().contains("External asset owner transfer is already in PENDING state for this loan"));
} finally {
cleanUpAndRestoreBusinessDate();
@@ -302,7 +302,7 @@ public class InitiateExternalAssetOwnerTransferTest {
LOAN_TRANSACTION_HELPER.makeRepayment("04 March 2020", 16000.0f, loanID);
CallFailedRuntimeException exception = assertThrows(CallFailedRuntimeException.class,
() -> createExternalAssetOwnerTransfer(loanID, "sale", "2020-03-02"));
() -> createSaleTransfer(loanID, "2020-03-02"));
assertTrue(exception.getMessage().contains("Loan is not in active status"));
} finally {
cleanUpAndRestoreBusinessDate();
@@ -318,9 +318,9 @@ public class InitiateExternalAssetOwnerTransferTest {
Integer clientID = createClient();
Integer loanID = createLoanForClient(clientID);
PostInitiateTransferResponse saleTransferResponse = createExternalAssetOwnerTransfer(loanID, "sale", "2020-03-02");
PostInitiateTransferResponse saleTransferResponse = createSaleTransfer(loanID, "2020-03-02");
validateResponse(saleTransferResponse, loanID);
PostInitiateTransferResponse buybackTransferResponse = createExternalAssetOwnerTransfer(loanID, "buyback", "2020-03-02");
PostInitiateTransferResponse buybackTransferResponse = createBuybackTransfer(loanID, "2020-03-02");
validateResponse(buybackTransferResponse, loanID);
getAndValidateExternalAssetOwnerTransferByLoan(loanID,
@@ -369,8 +369,8 @@ public class InitiateExternalAssetOwnerTransferTest {
Integer clientID = createClient();
Integer loanID = createLoanForClient(clientID);
PostInitiateTransferResponse saleTransferResponse = createExternalAssetOwnerTransfer(loanID, "sale", "2020-03-04");
PostInitiateTransferResponse buybackTransferResponse = createExternalAssetOwnerTransfer(loanID, "buyback", "2020-03-04");
PostInitiateTransferResponse saleTransferResponse = createSaleTransfer(loanID, "2020-03-04");
PostInitiateTransferResponse buybackTransferResponse = createBuybackTransfer(loanID, "2020-03-04");
getAndValidateExternalAssetOwnerTransferByLoan(loanID,
ExpectedExternalTransferData.expected(PENDING, saleTransferResponse.getResourceExternalId(), "2020-03-04", "2020-03-02",
@@ -383,11 +383,11 @@ public class InitiateExternalAssetOwnerTransferTest {
new BigDecimal("0.000000")));
CallFailedRuntimeException exception = assertThrows(CallFailedRuntimeException.class,
() -> createExternalAssetOwnerTransfer(loanID, "sale", "2020-03-04"));
() -> createSaleTransfer(loanID, "2020-03-04"));
assertTrue(exception.getMessage().contains("This loan cannot be sold, there is already an in progress transfer"));
CallFailedRuntimeException exception2 = assertThrows(CallFailedRuntimeException.class,
() -> createExternalAssetOwnerTransfer(loanID, "buyback", "2020-03-04"));
() -> createBuybackTransfer(loanID, "2020-03-04"));
assertTrue(exception2.getMessage()
.contains("This loan cannot be bought back, external asset owner buyback transfer is already in progress"));
} finally {
@@ -395,19 +395,111 @@ public class InitiateExternalAssetOwnerTransferTest {
}
}
@Test
public void buybackExceptionHandling() {
try {
GlobalConfigurationHelper.manageConfigurations(REQUEST_SPEC, RESPONSE_SPEC,
GlobalConfigurationHelper.ENABLE_AUTOGENERATED_EXTERNAL_ID, true);
setInitialBusinessDate("2020-03-02");
CallFailedRuntimeException exception = assertThrows(CallFailedRuntimeException.class, () -> createBuybackTransfer(1, null));
assertTrue(exception.getMessage().contains("The parameter `settlementDate` is mandatory."));
CallFailedRuntimeException exception2 = assertThrows(CallFailedRuntimeException.class,
() -> createBuybackTransfer(1, "1970-01-01"));
assertTrue(exception2.getMessage().contains("Settlement date cannot be in the past"));
CallFailedRuntimeException exception3 = assertThrows(CallFailedRuntimeException.class, () -> {
Integer clientID = createClient();
Integer loanID = createLoanForClient(clientID);
createSaleTransfer(loanID, "2020-03-03");
createBuybackTransfer(loanID, "2020-03-02");
});
assertTrue(exception3.getMessage().contains(
"This loan cannot be bought back, settlement date is earlier than effective transfer settlement date: 2020-03-03"));
CallFailedRuntimeException exception4 = assertThrows(CallFailedRuntimeException.class, () -> {
Integer clientID = createClient();
Integer loanID = createLoanForClient(clientID);
createBuybackTransfer(loanID, "2020-03-03");
});
assertTrue(exception4.getMessage().contains("This loan cannot be bought back, it is not owned by an external asset owner"));
CallFailedRuntimeException exception5 = assertThrows(CallFailedRuntimeException.class,
() -> createBuybackTransfer(-1, "2020-03-03"));
assertTrue(exception5.getMessage().contains("Loan with identifier -1 does not exist"));
} finally {
cleanUpAndRestoreBusinessDate();
}
}
@Test
public void saleExceptionHandling() {
try {
GlobalConfigurationHelper.manageConfigurations(REQUEST_SPEC, RESPONSE_SPEC,
GlobalConfigurationHelper.ENABLE_AUTOGENERATED_EXTERNAL_ID, true);
setInitialBusinessDate("2020-03-02");
Integer clientID = createClient();
Integer loanID = createLoanForClient(clientID);
CallFailedRuntimeException exception = assertThrows(CallFailedRuntimeException.class, () -> createSaleTransfer(loanID, null));
assertTrue(exception.getMessage().contains("The parameter `settlementDate` is mandatory."));
CallFailedRuntimeException exception2 = assertThrows(CallFailedRuntimeException.class,
() -> createSaleTransfer(loanID, "2020-03-02", UUID.randomUUID().toString(), null, "1.0"));
assertTrue(exception2.getMessage().contains("The parameter `ownerExternalId` is mandatory."));
CallFailedRuntimeException exception3 = assertThrows(CallFailedRuntimeException.class,
() -> createSaleTransfer(loanID, "2020-03-02", null, UUID.randomUUID().toString(), null));
assertTrue(exception3.getMessage().contains("The parameter `purchasePriceRatio` is mandatory."));
CallFailedRuntimeException exception4 = assertThrows(CallFailedRuntimeException.class,
() -> createSaleTransfer(loanID, "1970-01-01"));
assertTrue(exception4.getMessage().contains("Settlement date cannot be in the past"));
CallFailedRuntimeException exception5 = assertThrows(CallFailedRuntimeException.class, () -> {
createSaleTransfer(loanID, "2020-03-03");
createBuybackTransfer(loanID, "2020-03-04");
createSaleTransfer(loanID, "2020-03-05");
});
assertTrue(exception5.getMessage().contains("This loan cannot be sold, there is already an in progress transfer"));
CallFailedRuntimeException exception6 = assertThrows(CallFailedRuntimeException.class, () -> {
Integer loanID2 = createLoanForClient(clientID);
createSaleTransfer(loanID2, "2020-03-03");
updateBusinessDateAndExecuteCOBJob("2020-03-04");
createSaleTransfer(loanID2, "2020-03-05");
});
assertTrue(exception6.getMessage().contains("This loan cannot be sold, because it is owned by an external asset owner"));
} finally {
cleanUpAndRestoreBusinessDate();
}
}
private void updateBusinessDateAndExecuteCOBJob(String date) {
BusinessDateHelper.updateBusinessDate(REQUEST_SPEC, RESPONSE_SPEC, BUSINESS_DATE, LocalDate.parse(date));
SCHEDULER_JOB_HELPER.executeAndAwaitJob("Loan COB");
}
private PostInitiateTransferResponse createExternalAssetOwnerTransfer(Integer loanID, String command, String settlementDate) {
private PostInitiateTransferResponse createSaleTransfer(Integer loanID, String settlementDate) {
String transferExternalId = UUID.randomUUID().toString();
if (command.equals("sale")) {
ownerExternalId = UUID.randomUUID().toString();
}
PostInitiateTransferResponse saleResponse = EXTERNAL_ASSET_OWNER_HELPER.initiateTransferByLoanId(loanID.longValue(), command,
ownerExternalId = UUID.randomUUID().toString();
return createSaleTransfer(loanID, settlementDate, transferExternalId, ownerExternalId, "1.0");
}
private PostInitiateTransferResponse createSaleTransfer(Integer loanID, String settlementDate, String transferExternalId,
String ownerExternalId, String purchasePriceRatio) {
PostInitiateTransferResponse saleResponse = EXTERNAL_ASSET_OWNER_HELPER.initiateTransferByLoanId(loanID.longValue(), "sale",
new PostInitiateTransferRequest().settlementDate(settlementDate).dateFormat("yyyy-MM-dd").locale("en")
.transferExternalId(transferExternalId).ownerExternalId(ownerExternalId).purchasePriceRatio("1.0"));
.transferExternalId(transferExternalId).ownerExternalId(ownerExternalId).purchasePriceRatio(purchasePriceRatio));
assertEquals(transferExternalId, saleResponse.getResourceExternalId());
return saleResponse;
}
private PostInitiateTransferResponse createBuybackTransfer(Integer loanID, String settlementDate) {
String transferExternalId = UUID.randomUUID().toString();
PostInitiateTransferResponse saleResponse = EXTERNAL_ASSET_OWNER_HELPER.initiateTransferByLoanId(loanID.longValue(), "buyback",
new PostInitiateTransferRequest().settlementDate(settlementDate).dateFormat("yyyy-MM-dd").locale("en")
.transferExternalId(transferExternalId));
assertEquals(transferExternalId, saleResponse.getResourceExternalId());
return saleResponse;
}