FINERACT-2152: API Create and retrieve interest pause

This commit is contained in:
Andrii Kulminskyi
2024-12-19 22:24:02 +01:00
committed by Adam Saghy
parent e94e6c421a
commit c2ec015e64
39 changed files with 1112 additions and 43 deletions
@@ -133,6 +133,9 @@ public class CommandSource extends AbstractPersistableCustom<Long> {
@Column(name = "result_status_code")
private Integer resultStatusCode;
@Column(name = "loan_external_id", length = 100)
private ExternalId loanExternalId;
public static CommandSource fullEntryFrom(final CommandWrapper wrapper, final JsonCommand command, final AppUser maker,
String idempotencyKey, Integer status) {
@@ -156,6 +159,7 @@ public class CommandSource extends AbstractPersistableCustom<Long> {
.transactionId(command.getTransactionId()) //
.creditBureauId(command.getCreditBureauId()) //
.organisationCreditBureauId(command.getOrganisationCreditBureauId()) //
.loanExternalId(command.getLoanExternalId()) //
.build(); //
}
@@ -195,5 +199,6 @@ public class CommandSource extends AbstractPersistableCustom<Long> {
this.resourceExternalId = result.getResourceExternalId();
this.subResourceId = result.getSubResourceId();
this.subResourceExternalId = result.getSubResourceExternalId();
this.loanExternalId = result.getLoanExternalId();
}
}
@@ -19,6 +19,7 @@
package org.apache.fineract.commands.domain;
import lombok.Getter;
import org.apache.fineract.infrastructure.core.domain.ExternalId;
import org.apache.fineract.useradministration.api.PasswordPreferencesApiConstants;
@Getter
@@ -43,6 +44,7 @@ public class CommandWrapper {
private final Long creditBureauId;
private final Long organisationCreditBureauId;
private final String jobName;
private final ExternalId loanExternalId;
private final String idempotencyKey;
@@ -61,9 +63,11 @@ public class CommandWrapper {
public static CommandWrapper fromExistingCommand(final Long commandId, final String actionName, final String entityName,
final Long resourceId, final Long subresourceId, final String resourceGetUrl, final Long productId, final Long officeId,
final Long groupId, final Long clientId, final Long loanId, final Long savingsId, final String transactionId,
final Long creditBureauId, final Long organisationCreditBureauId, final String idempotencyKey) {
final Long creditBureauId, final Long organisationCreditBureauId, final String idempotencyKey,
final ExternalId loanExternalId) {
return new CommandWrapper(commandId, actionName, entityName, resourceId, subresourceId, resourceGetUrl, productId, officeId,
groupId, clientId, loanId, savingsId, transactionId, creditBureauId, organisationCreditBureauId, idempotencyKey);
groupId, clientId, loanId, savingsId, transactionId, creditBureauId, organisationCreditBureauId, idempotencyKey,
loanExternalId);
}
private CommandWrapper(final Long commandId, final String actionName, final String entityName, final Long resourceId,
@@ -87,12 +91,13 @@ public class CommandWrapper {
this.organisationCreditBureauId = null;
this.jobName = null;
this.idempotencyKey = null;
this.loanExternalId = null;
}
public CommandWrapper(final Long officeId, final Long groupId, final Long clientId, final Long loanId, final Long savingsId,
final String actionName, final String entityName, final Long entityId, final Long subentityId, final String href,
final String json, final String transactionId, final Long productId, final Long templateId, final Long creditBureauId,
final Long organisationCreditBureauId, final String jobName, final String idempotencyKey) {
final Long organisationCreditBureauId, final String jobName, final String idempotencyKey, final ExternalId loanExternalId) {
this.commandId = null;
this.officeId = officeId;
@@ -114,12 +119,13 @@ public class CommandWrapper {
this.organisationCreditBureauId = organisationCreditBureauId;
this.jobName = jobName;
this.idempotencyKey = idempotencyKey;
this.loanExternalId = loanExternalId;
}
private CommandWrapper(final Long commandId, final String actionName, final String entityName, final Long resourceId,
final Long subresourceId, final String resourceGetUrl, final Long productId, final Long officeId, final Long groupId,
final Long clientId, final Long loanId, final Long savingsId, final String transactionId, final Long creditBureauId,
final Long organisationCreditBureauId, final String idempotencyKey) {
final Long organisationCreditBureauId, final String idempotencyKey, final ExternalId loanExternalId) {
this.commandId = commandId;
this.officeId = officeId;
@@ -140,6 +146,7 @@ public class CommandWrapper {
this.organisationCreditBureauId = organisationCreditBureauId;
this.jobName = null;
this.idempotencyKey = idempotencyKey;
this.loanExternalId = loanExternalId;
}
public boolean isCreate() {
@@ -240,6 +247,14 @@ public class CommandWrapper {
return this.entityName.equalsIgnoreCase(PasswordPreferencesApiConstants.ENTITY_NAME);
}
public boolean isInterestPauseResource() {
return this.entityName.equalsIgnoreCase("INTEREST_PAUSE");
}
public boolean isInterestPauseExternalIdResource() {
return this.entityName.equalsIgnoreCase("INTEREST_PAUSE") && this.href.contains("/external-id/");
}
public Long commandId() {
return this.commandId;
}
@@ -21,6 +21,7 @@ package org.apache.fineract.commands.service;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.apache.fineract.commands.domain.CommandWrapper;
import org.apache.fineract.infrastructure.accountnumberformat.service.AccountNumberFormatConstants;
import org.apache.fineract.infrastructure.core.domain.ExternalId;
import org.apache.fineract.portfolio.client.api.ClientApiConstants;
import org.apache.fineract.portfolio.paymenttype.api.PaymentTypeApiResourceConstants;
import org.apache.fineract.portfolio.savings.DepositsApiConstants;
@@ -47,18 +48,19 @@ public class CommandWrapperBuilder {
private Long organisationCreditBureauId;
private String jobName;
private String idempotencyKey;
private ExternalId loanExternalId;
@SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "TODO: fix this!")
public CommandWrapper build() {
return new CommandWrapper(this.officeId, this.groupId, this.clientId, this.loanId, this.savingsId, this.actionName, this.entityName,
this.entityId, this.subentityId, this.href, this.json, this.transactionId, this.productId, this.templateId,
this.creditBureauId, this.organisationCreditBureauId, this.jobName, this.idempotencyKey);
this.creditBureauId, this.organisationCreditBureauId, this.jobName, this.idempotencyKey, this.loanExternalId);
}
public CommandWrapper build(String idempotencyKey) {
return new CommandWrapper(this.officeId, this.groupId, this.clientId, this.loanId, this.savingsId, this.actionName, this.entityName,
this.entityId, this.subentityId, this.href, this.json, this.transactionId, this.productId, this.templateId,
this.creditBureauId, this.organisationCreditBureauId, this.jobName, idempotencyKey);
this.creditBureauId, this.organisationCreditBureauId, this.jobName, idempotencyKey, this.loanExternalId);
}
public CommandWrapperBuilder updateCreditBureau() {
@@ -3714,4 +3716,20 @@ public class CommandWrapperBuilder {
this.href = "/loans/" + loanId + "/delinquency-action";
return this;
}
public CommandWrapperBuilder createInterestPause(final long loanId) {
this.actionName = "CREATE";
this.entityName = "INTEREST_PAUSE";
this.loanId = loanId;
this.href = "/v1/loans/" + loanId + "/interest-pauses";
return this;
}
public CommandWrapperBuilder createInterestPauseByExternalId(final String loanExternalId) {
this.actionName = "CREATE";
this.entityName = "INTEREST_PAUSE";
this.loanExternalId = new ExternalId(loanExternalId);
this.href = "/v1/loans/external-id/" + loanExternalId + "/interest-pauses";
return this;
}
}
@@ -73,7 +73,7 @@ public class PortfolioCommandSourceWritePlatformServiceImpl implements Portfolio
JsonCommand command = JsonCommand.from(json, parsedCommand, this.fromApiJsonHelper, wrapper.getEntityName(), wrapper.getEntityId(),
wrapper.getSubentityId(), wrapper.getGroupId(), wrapper.getClientId(), wrapper.getLoanId(), wrapper.getSavingsId(),
wrapper.getTransactionId(), wrapper.getHref(), wrapper.getProductId(), wrapper.getCreditBureauId(),
wrapper.getOrganisationCreditBureauId(), wrapper.getJobName());
wrapper.getOrganisationCreditBureauId(), wrapper.getJobName(), wrapper.getLoanExternalId());
return this.processAndLogCommandService.executeCommand(wrapper, command, isApprovedByChecker);
}
@@ -88,14 +88,16 @@ public class PortfolioCommandSourceWritePlatformServiceImpl implements Portfolio
commandSourceInput.getResourceGetUrl(), commandSourceInput.getProductId(), commandSourceInput.getOfficeId(),
commandSourceInput.getGroupId(), commandSourceInput.getClientId(), commandSourceInput.getLoanId(),
commandSourceInput.getSavingsId(), commandSourceInput.getTransactionId(), commandSourceInput.getCreditBureauId(),
commandSourceInput.getOrganisationCreditBureauId(), commandSourceInput.getIdempotencyKey());
commandSourceInput.getOrganisationCreditBureauId(), commandSourceInput.getIdempotencyKey(),
commandSourceInput.getLoanExternalId());
final JsonElement parsedCommand = this.fromApiJsonHelper.parse(commandSourceInput.getCommandAsJson());
final JsonCommand command = JsonCommand.fromExistingCommand(makerCheckerId, commandSourceInput.getCommandAsJson(), parsedCommand,
this.fromApiJsonHelper, commandSourceInput.getEntityName(), commandSourceInput.getResourceId(),
commandSourceInput.getSubResourceId(), commandSourceInput.getGroupId(), commandSourceInput.getClientId(),
commandSourceInput.getLoanId(), commandSourceInput.getSavingsId(), commandSourceInput.getTransactionId(),
commandSourceInput.getResourceGetUrl(), commandSourceInput.getProductId(), commandSourceInput.getCreditBureauId(),
commandSourceInput.getOrganisationCreditBureauId(), commandSourceInput.getJobName());
commandSourceInput.getOrganisationCreditBureauId(), commandSourceInput.getJobName(),
commandSourceInput.getLoanExternalId());
return this.processAndLogCommandService.executeCommand(wrapper, command, true);
}
@@ -249,6 +249,8 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
} else {
throw new UnsupportedCommandException(wrapper.commandName());
}
} else if (wrapper.isInterestPauseResource() || wrapper.isInterestPauseExternalIdResource()) {
handler = applicationContext.getBean("interestPauseCommandHandler", NewCommandSourceHandler.class);
} else {
handler = commandHandlerProvider.getHandler(wrapper.entityName(), wrapper.actionName());
}
@@ -71,30 +71,34 @@ public final class JsonCommand {
private final Long creditBureauId;
private final Long organisationCreditBureauId;
private final String jobName;
private final ExternalId loanExternalId;
public static JsonCommand from(final String jsonCommand, final JsonElement parsedCommand, final FromJsonHelper fromApiJsonHelper,
final String entityName, final Long resourceId, final Long subresourceId, final Long groupId, final Long clientId,
final Long loanId, final Long savingsId, final String transactionId, final String url, final Long productId,
final Long creditBureauId, final Long organisationCreditBureauId, final String jobName) {
final Long creditBureauId, final Long organisationCreditBureauId, final String jobName, final ExternalId loanExternalId) {
return new JsonCommand(null, jsonCommand, parsedCommand, fromApiJsonHelper, entityName, resourceId, subresourceId, groupId,
clientId, loanId, savingsId, transactionId, url, productId, creditBureauId, organisationCreditBureauId, jobName);
clientId, loanId, savingsId, transactionId, url, productId, creditBureauId, organisationCreditBureauId, jobName,
loanExternalId);
}
public static JsonCommand fromExistingCommand(final Long commandId, final String jsonCommand, final JsonElement parsedCommand,
final FromJsonHelper fromApiJsonHelper, final String entityName, final Long resourceId, final Long subresourceId,
final String url, final Long productId, final Long creditBureauId, final Long organisationCreditBureauId,
final String jobName) {
final String url, final Long productId, final Long creditBureauId, final Long organisationCreditBureauId, final String jobName,
final ExternalId loanExternalId) {
return new JsonCommand(commandId, jsonCommand, parsedCommand, fromApiJsonHelper, entityName, resourceId, subresourceId, null, null,
null, null, null, url, productId, creditBureauId, organisationCreditBureauId, jobName);
null, null, null, url, productId, creditBureauId, organisationCreditBureauId, jobName, loanExternalId);
}
public static JsonCommand fromExistingCommand(final Long commandId, final String jsonCommand, final JsonElement parsedCommand,
final FromJsonHelper fromApiJsonHelper, final String entityName, final Long resourceId, final Long subresourceId,
final Long groupId, final Long clientId, final Long loanId, final Long savingsId, final String transactionId, final String url,
final Long productId, Long creditBureauId, final Long organisationCreditBureauId, final String jobName) {
final Long productId, Long creditBureauId, final Long organisationCreditBureauId, final String jobName,
final ExternalId loanExternalId) {
return new JsonCommand(commandId, jsonCommand, parsedCommand, fromApiJsonHelper, entityName, resourceId, subresourceId, groupId,
clientId, loanId, savingsId, transactionId, url, productId, creditBureauId, organisationCreditBureauId, jobName);
clientId, loanId, savingsId, transactionId, url, productId, creditBureauId, organisationCreditBureauId, jobName,
loanExternalId);
}
@@ -103,7 +107,7 @@ public final class JsonCommand {
return new JsonCommand(command.commandId, jsonCommand, parsedCommand, command.fromApiJsonHelper, command.entityName,
command.resourceId, command.subresourceId, command.groupId, command.clientId, command.loanId, command.savingsId,
command.transactionId, command.url, command.productId, command.creditBureauId, command.organisationCreditBureauId,
command.jobName);
command.jobName, command.loanExternalId);
}
public static JsonCommand fromExistingCommand(JsonCommand command, final JsonElement parsedCommand, final Long clientId) {
@@ -111,13 +115,14 @@ public final class JsonCommand {
return new JsonCommand(command.commandId, jsonCommand, parsedCommand, command.fromApiJsonHelper, command.entityName,
command.resourceId, command.subresourceId, command.groupId, clientId, command.loanId, command.savingsId,
command.transactionId, command.url, command.productId, command.creditBureauId, command.organisationCreditBureauId,
command.jobName);
command.jobName, command.loanExternalId);
}
public JsonCommand(final Long commandId, final String jsonCommand, final JsonElement parsedCommand,
final FromJsonHelper fromApiJsonHelper, final String entityName, final Long resourceId, final Long subresourceId,
final Long groupId, final Long clientId, final Long loanId, final Long savingsId, final String transactionId, final String url,
final Long productId, final Long creditBureauId, final Long organisationCreditBureauId, final String jobName) {
final Long productId, final Long creditBureauId, final Long organisationCreditBureauId, final String jobName,
final ExternalId loanExternalId) {
this.commandId = commandId;
this.jsonCommand = jsonCommand;
@@ -136,6 +141,7 @@ public final class JsonCommand {
this.creditBureauId = creditBureauId;
this.organisationCreditBureauId = organisationCreditBureauId;
this.jobName = jobName;
this.loanExternalId = loanExternalId;
}
public static JsonCommand fromJsonElement(final Long resourceId, final JsonElement parsedCommand) {
@@ -165,6 +171,7 @@ public final class JsonCommand {
this.creditBureauId = null;
this.organisationCreditBureauId = null;
this.jobName = null;
this.loanExternalId = null;
}
public JsonCommand(final Long resourceId, final JsonElement parsedCommand, final FromJsonHelper fromApiJsonHelper) {
@@ -185,10 +192,12 @@ public final class JsonCommand {
this.creditBureauId = null;
this.organisationCreditBureauId = null;
this.jobName = null;
this.loanExternalId = null;
}
public static JsonCommand from(final String jsonCommand) {
return new JsonCommand(null, jsonCommand, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null);
return new JsonCommand(null, jsonCommand, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null);
}
@@ -49,12 +49,13 @@ public class CommandProcessingResult implements Serializable {
private Boolean rollbackTransaction;
private final ExternalId resourceExternalId;
private final ExternalId subResourceExternalId;
private final ExternalId loanExternalId;
private CommandProcessingResult(final Long commandId, final Long officeId, final Long groupId, final Long clientId, final Long loanId,
final Long savingsId, final String resourceIdentifier, final Long resourceId, final String transactionId,
final Map<String, Object> changes, final Long productId, final Long gsimId, final Long glimId,
final Map<String, Object> creditBureauReportData, Boolean rollbackTransaction, final Long subResourceId,
final ExternalId resourceExternalId, final ExternalId subResourceExternalId) {
final ExternalId resourceExternalId, final ExternalId subResourceExternalId, final ExternalId loanExternalId) {
this.commandId = commandId;
this.officeId = officeId;
this.groupId = groupId;
@@ -73,12 +74,13 @@ public class CommandProcessingResult implements Serializable {
this.subResourceId = subResourceId;
this.resourceExternalId = resourceExternalId;
this.subResourceExternalId = subResourceExternalId;
this.loanExternalId = loanExternalId;
}
protected CommandProcessingResult(final Long resourceId, final Long officeId, final Long commandId, final Map<String, Object> changes,
Long clientId) {
this(commandId, officeId, null, clientId, null, null, resourceId == null ? null : resourceId.toString(), resourceId, null, changes,
null, null, null, null, null, null, ExternalId.empty(), ExternalId.empty());
null, null, null, null, null, null, ExternalId.empty(), ExternalId.empty(), ExternalId.empty());
}
protected CommandProcessingResult(final Long resourceId, final Long officeId, final Long commandId, final Map<String, Object> changes) {
@@ -94,7 +96,7 @@ public class CommandProcessingResult implements Serializable {
commandResult.loanId, commandResult.savingsId, commandResult.resourceIdentifier, resourceId, commandResult.transactionId,
commandResult.changes, commandResult.productId, commandResult.gsimId, commandResult.glimId,
commandResult.creditBureauReportData, commandResult.rollbackTransaction, commandResult.subResourceId,
commandResult.resourceExternalId, commandResult.subResourceExternalId);
commandResult.resourceExternalId, commandResult.subResourceExternalId, commandResult.loanExternalId);
}
public static CommandProcessingResult fromCommandProcessingResult(CommandProcessingResult commandResult) {
@@ -105,10 +107,10 @@ public class CommandProcessingResult implements Serializable {
final Long loanId, final Long savingsId, final String resourceIdentifier, final Long entityId, final Long gsimId,
final Long glimId, final Map<String, Object> creditBureauReportData, final String transactionId,
final Map<String, Object> changes, final Long productId, final Boolean rollbackTransaction, final Long subResourceId,
final ExternalId resourceExternalId, final ExternalId subResourceExternalId) {
final ExternalId resourceExternalId, final ExternalId subResourceExternalId, final ExternalId loanExternalId) {
return new CommandProcessingResult(commandId, officeId, groupId, clientId, loanId, savingsId, resourceIdentifier, entityId,
transactionId, changes, productId, gsimId, glimId, creditBureauReportData, rollbackTransaction, subResourceId,
resourceExternalId, subResourceExternalId);
resourceExternalId, subResourceExternalId, loanExternalId);
}
public static CommandProcessingResult commandOnlyResult(final Long commandId) {
@@ -46,10 +46,13 @@ public class CommandProcessingResultBuilder {
private ExternalId subEntityExternalId = ExternalId.empty();
private ExternalId loanExternalId = ExternalId.empty();
public CommandProcessingResult build() {
return CommandProcessingResult.fromDetails(this.commandId, this.officeId, this.groupId, this.clientId, this.loanId, this.savingsId,
this.resourceIdentifier, this.entityId, this.gsimId, this.glimId, this.creditBureauReportData, this.transactionId,
this.changes, this.productId, this.rollbackTransaction, this.subEntityId, this.entityExternalId, this.subEntityExternalId);
this.changes, this.productId, this.rollbackTransaction, this.subEntityId, this.entityExternalId, this.subEntityExternalId,
this.loanExternalId);
}
public CommandProcessingResultBuilder withCommandId(final Long withCommandId) {
@@ -142,4 +145,8 @@ public class CommandProcessingResultBuilder {
return this;
}
public CommandProcessingResultBuilder withLoanExternalId(final ExternalId loanExternalId) {
this.loanExternalId = loanExternalId;
return this;
}
}
@@ -58,7 +58,7 @@ public class IdempotencyCommandProcessFailedExceptionTest {
public void testInconsistentStatus() {
IdempotentCommandExceptionMapper mapper = new IdempotentCommandExceptionMapper();
CommandWrapper command = new CommandWrapper(null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null);
null, null, null, null, null);
CommandSource source = CommandSource.fullEntryFrom(command, JsonCommand.from("{}"), null, "dummy-key", null);
IdempotentCommandProcessFailedException exception = new IdempotentCommandProcessFailedException(command, null, source);
Response result = mapper.toResponse(exception);