FINERACT-1760: Enhanced external id support for loan transactions
This commit is contained in:
+29
-18
@@ -26,7 +26,9 @@ import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.useradministration.domain.AppUser;
|
||||
|
||||
@@ -62,7 +64,7 @@ public class CommandSource extends AbstractPersistableCustom {
|
||||
private Long resourceId;
|
||||
|
||||
@Column(name = "subresource_id")
|
||||
private Long subresourceId;
|
||||
private Long subResourceId;
|
||||
|
||||
@Column(name = "command_as_json", length = 1000)
|
||||
private String commandAsJson;
|
||||
@@ -110,6 +112,12 @@ public class CommandSource extends AbstractPersistableCustom {
|
||||
@Column(name = "idempotency_key", length = 50)
|
||||
private String idempotencyKey;
|
||||
|
||||
@Column(name = "resource_external_id")
|
||||
private ExternalId resourceExternalId;
|
||||
|
||||
@Column(name = "subresource_external_id")
|
||||
private ExternalId subResourceExternalId;
|
||||
|
||||
public static CommandSource fullEntryFrom(final CommandWrapper wrapper, final JsonCommand command, final AppUser maker,
|
||||
String idempotencyKey) {
|
||||
return new CommandSource(wrapper.actionName(), wrapper.entityName(), wrapper.getHref(), command.entityId(), command.subentityId(),
|
||||
@@ -121,12 +129,12 @@ public class CommandSource extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
private CommandSource(final String actionName, final String entityName, final String href, final Long resourceId,
|
||||
final Long subresourceId, final String commandSerializedAsJson, final AppUser maker, final String idempotencyKey) {
|
||||
final Long subResourceId, final String commandSerializedAsJson, final AppUser maker, final String idempotencyKey) {
|
||||
this.actionName = actionName;
|
||||
this.entityName = entityName;
|
||||
this.resourceGetUrl = href;
|
||||
this.resourceId = resourceId;
|
||||
this.subresourceId = subresourceId;
|
||||
this.subResourceId = subResourceId;
|
||||
this.commandAsJson = commandSerializedAsJson;
|
||||
this.maker = maker;
|
||||
this.madeOnDate = DateUtils.getOffsetDateTimeOfTenant();
|
||||
@@ -170,8 +178,8 @@ public class CommandSource extends AbstractPersistableCustom {
|
||||
this.resourceId = resourceId;
|
||||
}
|
||||
|
||||
public void updateSubresourceId(final Long subresourceId) {
|
||||
this.subresourceId = subresourceId;
|
||||
public void updateSubResourceId(final Long subResourceId) {
|
||||
this.subResourceId = subResourceId;
|
||||
}
|
||||
|
||||
public void updateJsonTo(final String json) {
|
||||
@@ -182,8 +190,8 @@ public class CommandSource extends AbstractPersistableCustom {
|
||||
return this.resourceId;
|
||||
}
|
||||
|
||||
public Long subresourceId() {
|
||||
return this.subresourceId;
|
||||
public Long subResourceId() {
|
||||
return this.subResourceId;
|
||||
}
|
||||
|
||||
public boolean hasJson() {
|
||||
@@ -210,8 +218,8 @@ public class CommandSource extends AbstractPersistableCustom {
|
||||
return this.resourceId;
|
||||
}
|
||||
|
||||
public Long getSubresourceId() {
|
||||
return this.subresourceId;
|
||||
public Long getSubResourceId() {
|
||||
return this.subResourceId;
|
||||
}
|
||||
|
||||
public void markAsAwaitingApproval() {
|
||||
@@ -226,15 +234,18 @@ public class CommandSource extends AbstractPersistableCustom {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void updateForAudit(final Long officeId, final Long groupId, final Long clientId, final Long loanId, final Long savingsId,
|
||||
final Long productId, final String transactionId) {
|
||||
this.officeId = officeId;
|
||||
this.groupId = groupId;
|
||||
this.clientId = clientId;
|
||||
this.loanId = loanId;
|
||||
this.savingsId = savingsId;
|
||||
this.productId = productId;
|
||||
this.transactionId = transactionId;
|
||||
public void updateForAudit(final CommandProcessingResult result) {
|
||||
this.officeId = result.getOfficeId();
|
||||
this.groupId = result.getGroupId();
|
||||
this.clientId = result.getClientId();
|
||||
this.loanId = result.getLoanId();
|
||||
this.savingsId = result.getSavingsId();
|
||||
this.productId = result.getProductId();
|
||||
this.transactionId = result.getTransactionId();
|
||||
this.resourceId = result.getResourceId();
|
||||
this.resourceExternalId = result.getResourceExternalId();
|
||||
this.subResourceId = result.getSubResourceId();
|
||||
this.subResourceExternalId = result.getSubResourceExternalId();
|
||||
}
|
||||
|
||||
public String getResourceGetUrl() {
|
||||
|
||||
+2
-2
@@ -82,7 +82,7 @@ public class PortfolioCommandSourceWritePlatformServiceImpl implements Portfolio
|
||||
validateIsUpdateAllowed();
|
||||
|
||||
final CommandWrapper wrapper = CommandWrapper.fromExistingCommand(makerCheckerId, commandSourceInput.getActionName(),
|
||||
commandSourceInput.getEntityName(), commandSourceInput.resourceId(), commandSourceInput.subresourceId(),
|
||||
commandSourceInput.getEntityName(), commandSourceInput.resourceId(), commandSourceInput.subResourceId(),
|
||||
commandSourceInput.getResourceGetUrl(), commandSourceInput.getProductId(), commandSourceInput.getOfficeId(),
|
||||
commandSourceInput.getGroupId(), commandSourceInput.getClientId(), commandSourceInput.getLoanId(),
|
||||
commandSourceInput.getSavingsId(), commandSourceInput.getTransactionId(), commandSourceInput.getCreditBureauId(),
|
||||
@@ -90,7 +90,7 @@ public class PortfolioCommandSourceWritePlatformServiceImpl implements Portfolio
|
||||
final JsonElement parsedCommand = this.fromApiJsonHelper.parse(commandSourceInput.json());
|
||||
final JsonCommand command = JsonCommand.fromExistingCommand(makerCheckerId, commandSourceInput.json(), parsedCommand,
|
||||
this.fromApiJsonHelper, commandSourceInput.getEntityName(), commandSourceInput.resourceId(),
|
||||
commandSourceInput.subresourceId(), commandSourceInput.getGroupId(), commandSourceInput.getClientId(),
|
||||
commandSourceInput.subResourceId(), commandSourceInput.getGroupId(), commandSourceInput.getClientId(),
|
||||
commandSourceInput.getLoanId(), commandSourceInput.getSavingsId(), commandSourceInput.getTransactionId(),
|
||||
commandSourceInput.getResourceGetUrl(), commandSourceInput.getProductId(), commandSourceInput.getCreditBureauId(),
|
||||
commandSourceInput.getOrganisationCreditBureauId(), commandSourceInput.getJobName());
|
||||
|
||||
+2
-3
@@ -110,9 +110,8 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
? (requestIdempotencyKey == null ? idempotencyKeyGenerator.create() : requestIdempotencyKey)
|
||||
: wrapper.getIdempotencyKey());
|
||||
}
|
||||
commandSourceResult.updateResourceId(result.getResourceId());
|
||||
commandSourceResult.updateForAudit(result.getOfficeId(), result.getGroupId(), result.getClientId(), result.getLoanId(),
|
||||
result.getSavingsId(), result.getProductId(), result.getTransactionId());
|
||||
|
||||
commandSourceResult.updateForAudit(result);
|
||||
|
||||
String changesOnlyJson;
|
||||
boolean rollBack = (rollbackTransaction || result.isRollbackTransaction()) && !isApprovedByChecker;
|
||||
|
||||
+2
@@ -124,4 +124,6 @@ public interface ConfigurationDomainService {
|
||||
Long retrieveRepaymentDueDays();
|
||||
|
||||
Long retrieveRepaymentOverdueDays();
|
||||
|
||||
boolean isExternalIdAutoGenerationEnabled();
|
||||
}
|
||||
|
||||
+7
@@ -43,6 +43,7 @@ public class ConfigurationDomainServiceJpa implements ConfigurationDomainService
|
||||
public static final String EXTERNAL_EVENTS_PURGE_DAYS = "purge-external-events-older-than-days";
|
||||
private static final String DAYS_BEFORE_REPAYMENT_IS_DUE = "days-before-repayment-is-due";
|
||||
private static final String DAYS_AFTER_REPAYMENT_IS_OVERDUE = "days-after-repayment-is-overdue";
|
||||
private static final String ENABLE_EXTERNAL_ID_AUTO_GENERATION = "enable-auto-generated-external-id";
|
||||
private final PermissionRepository permissionRepository;
|
||||
private final GlobalConfigurationRepositoryWrapper globalConfigurationRepository;
|
||||
private final PlatformCacheRepository cacheTypeRepository;
|
||||
@@ -473,4 +474,10 @@ public class ConfigurationDomainServiceJpa implements ConfigurationDomainService
|
||||
final GlobalConfigurationPropertyData property = getGlobalConfigurationPropertyData(DAYS_AFTER_REPAYMENT_IS_OVERDUE);
|
||||
return property.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExternalIdAutoGenerationEnabled() {
|
||||
final GlobalConfigurationPropertyData property = getGlobalConfigurationPropertyData(ENABLE_EXTERNAL_ID_AUTO_GENERATION);
|
||||
return property.isEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.infrastructure.configuration.service;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Temporary (static) configuration service container.
|
||||
*
|
||||
* Provide static access to the configuration service TODO: To be deleted when the code cleanup / refactor finished (of
|
||||
* Loan.java) and we dont need this workaround anymore
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class TemporaryConfigurationServiceContainer implements InitializingBean {
|
||||
|
||||
private static volatile ConfigurationDomainService STATIC_REF_CONFIGURATION_SERVICE;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
|
||||
// To avoid any abuse of this temporary solution, only the `isExternalIdAutoGenerationEnabled()` is exposed
|
||||
public static boolean isExternalIdAutoGenerationEnabled() {
|
||||
return TemporaryConfigurationServiceContainer.STATIC_REF_CONFIGURATION_SERVICE.isExternalIdAutoGenerationEnabled();
|
||||
}
|
||||
|
||||
@SuppressFBWarnings("ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD")
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
TemporaryConfigurationServiceContainer.STATIC_REF_CONFIGURATION_SERVICE = configurationDomainService;
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.infrastructure.core.api;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import java.lang.reflect.Type;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
|
||||
/**
|
||||
* GSON Serializer for ExternalId
|
||||
*
|
||||
*/
|
||||
public class ExternalIdAdapter implements JsonSerializer<ExternalId> {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unused")
|
||||
public JsonElement serialize(ExternalId src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
if (src == null || src.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return new JsonPrimitive(src.getValue());
|
||||
}
|
||||
}
|
||||
+21
-6
@@ -23,6 +23,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
|
||||
/**
|
||||
* Represents the successful result of an REST API call that results in processing a command.
|
||||
@@ -47,27 +48,33 @@ public class CommandProcessingResult implements Serializable {
|
||||
private final Long gsimId;
|
||||
private final Long glimId;
|
||||
private Boolean rollbackTransaction;
|
||||
private final ExternalId resourceExternalId;
|
||||
private final ExternalId subResourceExternalId;
|
||||
|
||||
public static CommandProcessingResult fromCommandProcessingResult(CommandProcessingResult commandResult) {
|
||||
return new CommandProcessingResult(commandResult.commandId, commandResult.officeId, commandResult.groupId, commandResult.clientId,
|
||||
commandResult.loanId, commandResult.savingsId, commandResult.resourceIdentifier, commandResult.resourceId,
|
||||
commandResult.transactionId, commandResult.changes, commandResult.productId, commandResult.gsimId, commandResult.glimId,
|
||||
commandResult.creditBureauReportData, commandResult.rollbackTransaction, commandResult.subResourceId);
|
||||
commandResult.creditBureauReportData, commandResult.rollbackTransaction, commandResult.subResourceId,
|
||||
commandResult.resourceExternalId, commandResult.subResourceExternalId);
|
||||
}
|
||||
|
||||
public static CommandProcessingResult fromCommandProcessingResult(CommandProcessingResult commandResult, final Long resourceId) {
|
||||
return new CommandProcessingResult(commandResult.commandId, commandResult.officeId, commandResult.groupId, commandResult.clientId,
|
||||
commandResult.loanId, commandResult.savingsId, commandResult.resourceIdentifier, resourceId, commandResult.transactionId,
|
||||
commandResult.changes, commandResult.productId, commandResult.gsimId, commandResult.glimId,
|
||||
commandResult.creditBureauReportData, commandResult.rollbackTransaction, commandResult.subResourceId);
|
||||
commandResult.creditBureauReportData, commandResult.rollbackTransaction, commandResult.subResourceId,
|
||||
commandResult.resourceExternalId, commandResult.subResourceExternalId);
|
||||
}
|
||||
|
||||
public static CommandProcessingResult fromDetails(final Long commandId, final Long officeId, final Long groupId, final Long clientId,
|
||||
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 Map<String, Object> changes, final Long productId, final Boolean rollbackTransaction, final Long subResourceId,
|
||||
final ExternalId resourceExternalId, final ExternalId subResourceExternalId) {
|
||||
return new CommandProcessingResult(commandId, officeId, groupId, clientId, loanId, savingsId, resourceIdentifier, entityId,
|
||||
transactionId, changes, productId, gsimId, glimId, creditBureauReportData, rollbackTransaction, subResourceId);
|
||||
transactionId, changes, productId, gsimId, glimId, creditBureauReportData, rollbackTransaction, subResourceId,
|
||||
resourceExternalId, subResourceExternalId);
|
||||
}
|
||||
|
||||
public static CommandProcessingResult commandOnlyResult(final Long commandId) {
|
||||
@@ -121,12 +128,15 @@ public class CommandProcessingResult implements Serializable {
|
||||
this.glimId = null;
|
||||
this.creditBureauReportData = null;
|
||||
this.subResourceId = null;
|
||||
this.resourceExternalId = ExternalId.empty();
|
||||
this.subResourceExternalId = ExternalId.empty();
|
||||
}
|
||||
|
||||
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> changesOnly, final Long productId, final Long gsimId, final Long glimId,
|
||||
final Map<String, Object> creditBureauReportData, Boolean rollbackTransaction, final Long subResourceId) {
|
||||
final Map<String, Object> creditBureauReportData, Boolean rollbackTransaction, final Long subResourceId,
|
||||
final ExternalId resourceExternalId, final ExternalId subResourceExternalId) {
|
||||
this.commandId = commandId;
|
||||
this.officeId = officeId;
|
||||
this.groupId = groupId;
|
||||
@@ -143,6 +153,8 @@ public class CommandProcessingResult implements Serializable {
|
||||
this.creditBureauReportData = creditBureauReportData;
|
||||
this.rollbackTransaction = rollbackTransaction;
|
||||
this.subResourceId = subResourceId;
|
||||
this.resourceExternalId = resourceExternalId;
|
||||
this.subResourceExternalId = subResourceExternalId;
|
||||
}
|
||||
|
||||
protected CommandProcessingResult(final Long resourceId, final Long officeId, final Long commandId,
|
||||
@@ -166,11 +178,14 @@ public class CommandProcessingResult implements Serializable {
|
||||
this.glimId = null;
|
||||
this.creditBureauReportData = null;
|
||||
this.subResourceId = null;
|
||||
this.resourceExternalId = ExternalId.empty();
|
||||
this.subResourceExternalId = ExternalId.empty();
|
||||
}
|
||||
|
||||
protected CommandProcessingResult(final Long resourceId, final Long officeId, final Long commandId,
|
||||
final Map<String, Object> changesOnly, long clientId) {
|
||||
this(commandId, officeId, null, clientId, null, null, null, resourceId, null, changesOnly, null, null, null, null, null, null);
|
||||
this(commandId, officeId, null, clientId, null, null, null, resourceId, null, changesOnly, null, null, null, null, null, null,
|
||||
ExternalId.empty(), ExternalId.empty());
|
||||
}
|
||||
|
||||
public void setOfficeId(final Long officeId) {
|
||||
|
||||
+15
-1
@@ -19,6 +19,7 @@
|
||||
package org.apache.fineract.infrastructure.core.data;
|
||||
|
||||
import java.util.Map;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
|
||||
/**
|
||||
* Represents the successful result of an REST API call that results in processing a command.
|
||||
@@ -41,11 +42,14 @@ public class CommandProcessingResultBuilder {
|
||||
private Map<String, Object> creditBureauReportData;
|
||||
private Long productId;
|
||||
private boolean rollbackTransaction = false;
|
||||
private ExternalId entityExternalId = ExternalId.empty();
|
||||
|
||||
private ExternalId subEntityExternalId = 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.changes, this.productId, this.rollbackTransaction, this.subEntityId, this.entityExternalId, this.subEntityExternalId);
|
||||
}
|
||||
|
||||
public CommandProcessingResultBuilder withCommandId(final Long withCommandId) {
|
||||
@@ -128,4 +132,14 @@ public class CommandProcessingResultBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandProcessingResultBuilder withEntityExternalId(final ExternalId entityExternalId) {
|
||||
this.entityExternalId = entityExternalId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandProcessingResultBuilder withSubEntityExternalId(final ExternalId subEntityExternalId) {
|
||||
this.subEntityExternalId = subEntityExternalId;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.infrastructure.core.domain;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.UUID;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformInternalServerException;
|
||||
|
||||
/**
|
||||
* ExternalId Value object
|
||||
*/
|
||||
@Getter
|
||||
@EqualsAndHashCode
|
||||
public class ExternalId implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1;
|
||||
private static final ExternalId empty = new ExternalId();
|
||||
private final String value;
|
||||
|
||||
private ExternalId() {
|
||||
this.value = null;
|
||||
}
|
||||
|
||||
public ExternalId(String value) {
|
||||
if (StringUtils.isBlank(value)) {
|
||||
throw new IllegalArgumentException("error.external.id.cannot.be.blank");
|
||||
}
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Create a new ExternalId object where value is a newly generated UUID
|
||||
*/
|
||||
public static ExternalId generate() {
|
||||
return new ExternalId(UUID.randomUUID().toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Create and return an empty ExternalId object
|
||||
*/
|
||||
public static ExternalId empty() {
|
||||
return empty;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether value is null for the ExternalId object (return true if value is null)
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return value == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws exception if value was not set (value is null) for this object
|
||||
*
|
||||
* @throws PlatformInternalServerException
|
||||
* if value was not set (value is null) for this object
|
||||
*/
|
||||
public void throwExceptionIfEmpty() {
|
||||
if (isEmpty()) {
|
||||
throw new PlatformInternalServerException("error.external.id.is.not.set", "Internal state violation: External id is not set");
|
||||
}
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.infrastructure.core.domain;
|
||||
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.Converter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@Converter(autoApply = true)
|
||||
public class ExternalIdConverter implements AttributeConverter<ExternalId, String> {
|
||||
|
||||
@Override
|
||||
public String convertToDatabaseColumn(ExternalId externalId) {
|
||||
return externalId != null ? externalId.getValue() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExternalId convertToEntityAttribute(String externalId) {
|
||||
return StringUtils.isBlank(externalId) ? ExternalId.empty() : new ExternalId(externalId);
|
||||
}
|
||||
|
||||
}
|
||||
+3
@@ -31,6 +31,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.apache.fineract.infrastructure.core.api.DateAdapter;
|
||||
import org.apache.fineract.infrastructure.core.api.ExternalIdAdapter;
|
||||
import org.apache.fineract.infrastructure.core.api.JodaDateTimeAdapter;
|
||||
import org.apache.fineract.infrastructure.core.api.JodaMonthDayAdapter;
|
||||
import org.apache.fineract.infrastructure.core.api.LocalDateAdapter;
|
||||
@@ -39,6 +40,7 @@ import org.apache.fineract.infrastructure.core.api.LocalTimeAdapter;
|
||||
import org.apache.fineract.infrastructure.core.api.OffsetDateTimeAdapter;
|
||||
import org.apache.fineract.infrastructure.core.api.ParameterListExclusionStrategy;
|
||||
import org.apache.fineract.infrastructure.core.api.ParameterListInclusionStrategy;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.exception.UnsupportedParameterException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -122,5 +124,6 @@ public final class GoogleGsonSerializerHelper {
|
||||
builder.registerTypeAdapter(MonthDay.class, new JodaMonthDayAdapter());
|
||||
builder.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter());
|
||||
builder.registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeAdapter());
|
||||
builder.registerTypeAdapter(ExternalId.class, new ExternalIdAdapter());
|
||||
}
|
||||
}
|
||||
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.infrastructure.core.service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class ExternalIdFactory {
|
||||
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
|
||||
public static ExternalId produce(String value) {
|
||||
return StringUtils.isBlank(value) ? ExternalId.empty() : new ExternalId(value);
|
||||
}
|
||||
|
||||
public ExternalId createFromCommand(JsonCommand command, final String externalIdKey) {
|
||||
String externalIdStr = null;
|
||||
if (command.parsedJson() != null) {
|
||||
externalIdStr = command.stringValueOfParameterNamedAllowingNull(externalIdKey);
|
||||
}
|
||||
return create(externalIdStr);
|
||||
}
|
||||
|
||||
public ExternalId create(String externalIdStr) {
|
||||
if (StringUtils.isBlank(externalIdStr)) {
|
||||
if (configurationDomainService.isExternalIdAutoGenerationEnabled()) {
|
||||
return ExternalId.generate();
|
||||
} else {
|
||||
return ExternalId.empty();
|
||||
}
|
||||
}
|
||||
return new ExternalId(externalIdStr);
|
||||
}
|
||||
|
||||
public ExternalId create() {
|
||||
return create(null);
|
||||
}
|
||||
}
|
||||
+4
@@ -19,8 +19,10 @@
|
||||
package org.apache.fineract.infrastructure.event.external.service.serialization.mapper.loan;
|
||||
|
||||
import org.apache.fineract.avro.loan.v1.LoanAccountDataV1;
|
||||
import org.apache.fineract.avro.loan.v1.LoanTransactionDataV1;
|
||||
import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.support.AvroMapperConfig;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanAccountData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionData;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
|
||||
@@ -33,4 +35,6 @@ public interface LoanAccountDataMapper {
|
||||
@Mapping(source = "topup", target = "isTopup")
|
||||
@Mapping(source = "interestRecalculationEnabled", target = "isInterestRecalculationEnabled")
|
||||
LoanAccountDataV1 map(LoanAccountData source);
|
||||
|
||||
LoanTransactionDataV1 map(LoanTransactionData source);
|
||||
}
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.infrastructure.event.external.service.serialization.mapper.support;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class AvroExternalIdMapper {
|
||||
|
||||
public String mapExternalId(ExternalId source) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
return source.getValue();
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -24,5 +24,5 @@ import org.mapstruct.MappingConstants;
|
||||
import org.mapstruct.ReportingPolicy;
|
||||
|
||||
@MapperConfig(componentModel = MappingConstants.ComponentModel.SPRING, unmappedTargetPolicy = ReportingPolicy.ERROR, builder = @Builder(disableBuilder = true), uses = {
|
||||
AvroDateTimeMapper.class, AvroMonthDayMapper.class })
|
||||
AvroDateTimeMapper.class, AvroMonthDayMapper.class, AvroExternalIdMapper.class })
|
||||
public class AvroMapperConfig {}
|
||||
|
||||
+1
@@ -72,6 +72,7 @@ public class JobSchedulerServiceImpl implements ApplicationListener<ContextRefre
|
||||
schedulerDetail.setSuspended(false);
|
||||
schedularWritePlatformService.updateSchedulerDetail(schedulerDetail);
|
||||
}
|
||||
ThreadLocalContextUtil.reset();
|
||||
}
|
||||
log.info("Scheduling batch jobs has finished");
|
||||
}
|
||||
|
||||
+5
-4
@@ -22,6 +22,7 @@ import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Locale;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.portfolio.account.PortfolioAccountType;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferDetails;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
@@ -47,7 +48,7 @@ public class AccountTransferDTO {
|
||||
private final Integer transferType;
|
||||
private final AccountTransferDetails accountTransferDetails;
|
||||
private final String noteText;
|
||||
private final String txnExternalId;
|
||||
private final ExternalId txnExternalId;
|
||||
private final Loan loan;
|
||||
private final Loan fromLoan;
|
||||
private final Loan toLoan;
|
||||
@@ -61,7 +62,7 @@ public class AccountTransferDTO {
|
||||
final Long toAccountId, final String description, final Locale locale, final DateTimeFormatter fmt,
|
||||
final PaymentDetail paymentDetail, final Integer fromTransferType, final Integer toTransferType, final Long chargeId,
|
||||
Integer loanInstallmentNumber, Integer transferType, final AccountTransferDetails accountTransferDetails, final String noteText,
|
||||
final String txnExternalId, final Loan loan, SavingsAccount toSavingsAccount, final SavingsAccount fromSavingsAccount,
|
||||
final ExternalId txnExternalId, final Loan loan, SavingsAccount toSavingsAccount, final SavingsAccount fromSavingsAccount,
|
||||
final Boolean isRegularTransaction, Boolean isExceptionForBalanceCheck) {
|
||||
this.transactionDate = transactionDate;
|
||||
this.transactionAmount = transactionAmount;
|
||||
@@ -93,7 +94,7 @@ public class AccountTransferDTO {
|
||||
public AccountTransferDTO(final LocalDate transactionDate, final BigDecimal transactionAmount,
|
||||
final PortfolioAccountType fromAccountType, final PortfolioAccountType toAccountType, final Long fromAccountId,
|
||||
final Long toAccountId, final String description, final Locale locale, final DateTimeFormatter fmt,
|
||||
final Integer fromTransferType, final Integer toTransferType, final String txnExternalId, final Loan fromLoan,
|
||||
final Integer fromTransferType, final Integer toTransferType, final ExternalId txnExternalId, final Loan fromLoan,
|
||||
final Loan toLoan) {
|
||||
this.transactionDate = transactionDate;
|
||||
this.transactionAmount = transactionAmount;
|
||||
@@ -190,7 +191,7 @@ public class AccountTransferDTO {
|
||||
return this.noteText;
|
||||
}
|
||||
|
||||
public String getTxnExternalId() {
|
||||
public ExternalId getTxnExternalId() {
|
||||
return this.txnExternalId;
|
||||
}
|
||||
|
||||
|
||||
+4
@@ -158,4 +158,8 @@ public class AccountTransferDetails extends AbstractPersistableCustom {
|
||||
return new AccountTransferDetails(fromOffice, fromClient, null, fromLoanAccount, toOffice, toClient, null, toLoanAccount,
|
||||
transferType, null);
|
||||
}
|
||||
|
||||
public List<AccountTransferTransaction> getAccountTransferTransactions() {
|
||||
return accountTransferTransactions;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -25,6 +25,7 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformServiceUnavailableException;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
@@ -107,8 +108,8 @@ public class ExecuteStandingInstructionsTasklet implements Tasklet {
|
||||
AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, transactionAmount, data.fromAccountType(),
|
||||
data.toAccountType(), data.fromAccount().getId(), data.toAccount().getId(),
|
||||
data.name() + " Standing instruction trasfer ", null, null, null, null, data.toTransferType(), null, null,
|
||||
data.transferType().getValue(), null, null, null, null, null, fromSavingsAccount, isRegularTransaction,
|
||||
isExceptionForBalanceCheck);
|
||||
data.transferType().getValue(), null, null, ExternalId.empty(), null, null, fromSavingsAccount,
|
||||
isRegularTransaction, isExceptionForBalanceCheck);
|
||||
final boolean transferCompleted = transferAmount(errors, accountTransferDTO, data.getId());
|
||||
|
||||
if (transferCompleted) {
|
||||
|
||||
+40
-40
@@ -31,11 +31,14 @@ import java.time.format.DateTimeFormatter;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.portfolio.account.PortfolioAccountType;
|
||||
import org.apache.fineract.portfolio.account.data.AccountTransferDTO;
|
||||
import org.apache.fineract.portfolio.account.data.AccountTransfersDataValidator;
|
||||
@@ -63,11 +66,11 @@ import org.apache.fineract.portfolio.savings.domain.SavingsAccountAssembler;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountDomainService;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountTransaction;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AccountTransfersWritePlatformServiceImpl implements AccountTransfersWritePlatformService {
|
||||
|
||||
private final AccountTransfersDataValidator accountTransfersDataValidator;
|
||||
@@ -82,28 +85,7 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
|
||||
private final LoanReadPlatformService loanReadPlatformService;
|
||||
private final GSIMRepositoy gsimRepository;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
|
||||
@Autowired
|
||||
public AccountTransfersWritePlatformServiceImpl(final AccountTransfersDataValidator accountTransfersDataValidator,
|
||||
final AccountTransferAssembler accountTransferAssembler, final AccountTransferRepository accountTransferRepository,
|
||||
final SavingsAccountAssembler savingsAccountAssembler, final SavingsAccountDomainService savingsAccountDomainService,
|
||||
final LoanAssembler loanAssembler, final LoanAccountDomainService loanAccountDomainService,
|
||||
final SavingsAccountWritePlatformService savingsAccountWritePlatformService,
|
||||
final AccountTransferDetailRepository accountTransferDetailRepository, final LoanReadPlatformService loanReadPlatformService,
|
||||
final GSIMRepositoy gsimRepository, ConfigurationDomainService configurationDomainService) {
|
||||
this.accountTransfersDataValidator = accountTransfersDataValidator;
|
||||
this.accountTransferAssembler = accountTransferAssembler;
|
||||
this.accountTransferRepository = accountTransferRepository;
|
||||
this.savingsAccountAssembler = savingsAccountAssembler;
|
||||
this.savingsAccountDomainService = savingsAccountDomainService;
|
||||
this.loanAccountAssembler = loanAssembler;
|
||||
this.loanAccountDomainService = loanAccountDomainService;
|
||||
this.savingsAccountWritePlatformService = savingsAccountWritePlatformService;
|
||||
this.accountTransferDetailRepository = accountTransferDetailRepository;
|
||||
this.loanReadPlatformService = loanReadPlatformService;
|
||||
this.gsimRepository = gsimRepository;
|
||||
this.configurationDomainService = configurationDomainService;
|
||||
}
|
||||
private final ExternalIdFactory externalIdFactory;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
@@ -178,9 +160,11 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
|
||||
final HolidayDetailDTO holidayDetailDto = null;
|
||||
final boolean isRecoveryRepayment = false;
|
||||
final String chargeRefundChargeType = null;
|
||||
|
||||
ExternalId externalId = externalIdFactory.create();
|
||||
final LoanTransaction loanRepaymentTransaction = this.loanAccountDomainService.makeRepayment(LoanTransactionType.REPAYMENT,
|
||||
toLoanAccount, new CommandProcessingResultBuilder(), transactionDate, transactionAmount, paymentDetail, null, null,
|
||||
isRecoveryRepayment, chargeRefundChargeType, isAccountTransfer, holidayDetailDto, isHolidayValidationDone);
|
||||
toLoanAccount, transactionDate, transactionAmount, paymentDetail, null, externalId, isRecoveryRepayment,
|
||||
chargeRefundChargeType, isAccountTransfer, holidayDetailDto, isHolidayValidationDone);
|
||||
|
||||
final AccountTransferDetails accountTransferDetails = this.accountTransferAssembler.assembleSavingsToLoanTransfer(command,
|
||||
fromSavingsAccount, toLoanAccount, withdrawal, loanRepaymentTransaction);
|
||||
@@ -193,9 +177,9 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
|
||||
|
||||
fromLoanAccountId = command.longValueOfParameterNamed(fromAccountIdParamName);
|
||||
final Loan fromLoanAccount = this.loanAccountAssembler.assembleFrom(fromLoanAccountId);
|
||||
|
||||
ExternalId externalId = externalIdFactory.create();
|
||||
final LoanTransaction loanRefundTransaction = this.loanAccountDomainService.makeRefund(fromLoanAccountId,
|
||||
new CommandProcessingResultBuilder(), transactionDate, transactionAmount, paymentDetail, null, null);
|
||||
new CommandProcessingResultBuilder(), transactionDate, transactionAmount, paymentDetail, null, externalId);
|
||||
|
||||
final Long toSavingsAccountId = command.longValueOfParameterNamed(toAccountIdParamName);
|
||||
final SavingsAccount toSavingsAccount = this.savingsAccountAssembler.assembleFrom(toSavingsAccountId, backdatedTxnsAllowedTill);
|
||||
@@ -329,12 +313,16 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
|
||||
accountTransferDTO.getFmt(), accountTransferDTO.getTransactionDate(), accountTransferDTO.getTransactionAmount(),
|
||||
accountTransferDTO.getPaymentDetail(), transactionBooleanValues, backdatedTxnsAllowedTill);
|
||||
|
||||
LoanTransaction loanTransaction = null;
|
||||
LoanTransaction loanTransaction;
|
||||
|
||||
ExternalId txnExternalId = accountTransferDTO.getTxnExternalId();
|
||||
// Safety net (it might need to generate new one)
|
||||
ExternalId externalId = externalIdFactory.create(txnExternalId.getValue());
|
||||
|
||||
if (AccountTransferType.fromInt(accountTransferDTO.getTransferType()).isChargePayment()) {
|
||||
loanTransaction = this.loanAccountDomainService.makeChargePayment(toLoanAccount, accountTransferDTO.getChargeId(),
|
||||
accountTransferDTO.getTransactionDate(), accountTransferDTO.getTransactionAmount(),
|
||||
accountTransferDTO.getPaymentDetail(), null, null, accountTransferDTO.getToTransferType(),
|
||||
accountTransferDTO.getPaymentDetail(), null, externalId, accountTransferDTO.getToTransferType(),
|
||||
accountTransferDTO.getLoanInstallmentNumber());
|
||||
|
||||
} else {
|
||||
@@ -343,9 +331,9 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
|
||||
final HolidayDetailDTO holidayDetailDto = null;
|
||||
final String chargeRefundChargeType = null;
|
||||
loanTransaction = this.loanAccountDomainService.makeRepayment(LoanTransactionType.REPAYMENT, toLoanAccount,
|
||||
new CommandProcessingResultBuilder(), accountTransferDTO.getTransactionDate(),
|
||||
accountTransferDTO.getTransactionAmount(), accountTransferDTO.getPaymentDetail(), null, null, isRecoveryRepayment,
|
||||
chargeRefundChargeType, isAccountTransfer, holidayDetailDto, isHolidayValidationDone);
|
||||
accountTransferDTO.getTransactionDate(), accountTransferDTO.getTransactionAmount(),
|
||||
accountTransferDTO.getPaymentDetail(), null, externalId, isRecoveryRepayment, chargeRefundChargeType,
|
||||
isAccountTransfer, holidayDetailDto, isHolidayValidationDone);
|
||||
}
|
||||
|
||||
accountTransferDetails = this.accountTransferAssembler.assembleSavingsToLoanTransfer(accountTransferDTO, fromSavingsAccount,
|
||||
@@ -354,8 +342,8 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
|
||||
transferTransactionId = accountTransferDetails.getId();
|
||||
} else if (isSavingsToSavingsAccountTransfer(accountTransferDTO.getFromAccountType(), accountTransferDTO.getToAccountType())) {
|
||||
|
||||
SavingsAccount fromSavingsAccount = null;
|
||||
SavingsAccount toSavingsAccount = null;
|
||||
SavingsAccount fromSavingsAccount;
|
||||
SavingsAccount toSavingsAccount;
|
||||
if (accountTransferDetails == null) {
|
||||
if (accountTransferDTO.getFromSavingsAccount() == null) {
|
||||
fromSavingsAccount = this.savingsAccountAssembler.assembleFrom(accountTransferDTO.getFromAccountId(),
|
||||
@@ -421,15 +409,20 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
|
||||
this.savingsAccountAssembler.setHelpers(toSavingsAccount);
|
||||
}
|
||||
LoanTransaction loanTransaction = null;
|
||||
|
||||
ExternalId txnExternalId = accountTransferDTO.getTxnExternalId();
|
||||
// Safety net (it might need to generate new one)
|
||||
ExternalId externalId = externalIdFactory.create(txnExternalId.getValue());
|
||||
|
||||
if (LoanTransactionType.DISBURSEMENT.getValue().equals(accountTransferDTO.getFromTransferType())) {
|
||||
loanTransaction = this.loanAccountDomainService.makeDisburseTransaction(accountTransferDTO.getFromAccountId(),
|
||||
accountTransferDTO.getTransactionDate(), accountTransferDTO.getTransactionAmount(),
|
||||
accountTransferDTO.getPaymentDetail(), accountTransferDTO.getNoteText(), accountTransferDTO.getTxnExternalId());
|
||||
accountTransferDTO.getPaymentDetail(), accountTransferDTO.getNoteText(), externalId);
|
||||
} else {
|
||||
loanTransaction = this.loanAccountDomainService.makeRefund(accountTransferDTO.getFromAccountId(),
|
||||
new CommandProcessingResultBuilder(), accountTransferDTO.getTransactionDate(),
|
||||
accountTransferDTO.getTransactionAmount(), accountTransferDTO.getPaymentDetail(), accountTransferDTO.getNoteText(),
|
||||
accountTransferDTO.getTxnExternalId());
|
||||
externalId);
|
||||
}
|
||||
|
||||
final SavingsAccountTransaction deposit = this.savingsAccountDomainService.handleDeposit(toSavingsAccount,
|
||||
@@ -474,13 +467,18 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
|
||||
this.loanAccountAssembler.setHelpers(toLoanAccount);
|
||||
}
|
||||
|
||||
ExternalId externalIdForDisbursement = accountTransferDTO.getTxnExternalId();
|
||||
|
||||
LoanTransaction disburseTransaction = this.loanAccountDomainService.makeDisburseTransaction(accountTransferDTO.getFromAccountId(),
|
||||
accountTransferDTO.getTransactionDate(), accountTransferDTO.getTransactionAmount(), accountTransferDTO.getPaymentDetail(),
|
||||
accountTransferDTO.getNoteText(), accountTransferDTO.getTxnExternalId(), true);
|
||||
accountTransferDTO.getNoteText(), externalIdForDisbursement, true);
|
||||
final String chargeRefundChargeType = null;
|
||||
|
||||
ExternalId externalIdForRepayment = externalIdFactory.create();
|
||||
|
||||
LoanTransaction repayTransaction = this.loanAccountDomainService.makeRepayment(LoanTransactionType.REPAYMENT, toLoanAccount,
|
||||
new CommandProcessingResultBuilder(), accountTransferDTO.getTransactionDate(), accountTransferDTO.getTransactionAmount(),
|
||||
accountTransferDTO.getPaymentDetail(), null, null, false, chargeRefundChargeType, isAccountTransfer, null, false, true);
|
||||
accountTransferDTO.getTransactionDate(), accountTransferDTO.getTransactionAmount(), accountTransferDTO.getPaymentDetail(),
|
||||
null, externalIdForRepayment, false, chargeRefundChargeType, isAccountTransfer, null, false, true);
|
||||
|
||||
AccountTransferDetails accountTransferDetails = this.accountTransferAssembler.assembleLoanToLoanTransfer(accountTransferDTO,
|
||||
fromLoanAccount, toLoanAccount, disburseTransaction, repayTransaction);
|
||||
@@ -541,8 +539,10 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
|
||||
throw new InvalidPaidInAdvanceAmountException(overpaid.toPlainString());
|
||||
}
|
||||
|
||||
ExternalId externalId = externalIdFactory.create();
|
||||
|
||||
final LoanTransaction loanRefundTransaction = this.loanAccountDomainService.makeRefundForActiveLoan(fromLoanAccountId,
|
||||
new CommandProcessingResultBuilder(), transactionDate, transactionAmount, paymentDetail, null, null);
|
||||
new CommandProcessingResultBuilder(), transactionDate, transactionAmount, paymentDetail, null, externalId);
|
||||
|
||||
final Long toSavingsAccountId = command.longValueOfParameterNamed(toAccountIdParamName);
|
||||
final SavingsAccount toSavingsAccount = this.savingsAccountAssembler.assembleFrom(toSavingsAccountId, backdatedTxnsAllowedTill);
|
||||
|
||||
+6
-24
@@ -20,39 +20,21 @@ package org.apache.fineract.portfolio.collectionsheet.command;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
|
||||
|
||||
/**
|
||||
* Immutable command for Single loan repayment.
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class SingleRepaymentCommand {
|
||||
|
||||
private final Long loanId;
|
||||
private final ExternalId externalId;
|
||||
private final BigDecimal transactionAmount;
|
||||
private final LocalDate transactionDate;
|
||||
private final PaymentDetail paymentDetail;
|
||||
|
||||
public SingleRepaymentCommand(final Long loanId, final BigDecimal transactionAmount, final LocalDate transactionDate,
|
||||
final PaymentDetail paymentDetail) {
|
||||
this.loanId = loanId;
|
||||
this.transactionAmount = transactionAmount;
|
||||
this.transactionDate = transactionDate;
|
||||
this.paymentDetail = paymentDetail;
|
||||
}
|
||||
|
||||
public Long getLoanId() {
|
||||
return this.loanId;
|
||||
}
|
||||
|
||||
public BigDecimal getTransactionAmount() {
|
||||
return this.transactionAmount;
|
||||
}
|
||||
|
||||
public LocalDate getTransactionDate() {
|
||||
return this.transactionDate;
|
||||
}
|
||||
|
||||
public PaymentDetail getPaymentDetail() {
|
||||
return this.paymentDetail;
|
||||
}
|
||||
}
|
||||
|
||||
+6
-1
@@ -25,10 +25,12 @@ import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Locale;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.AbstractFromApiJsonDeserializer;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromApiJsonDeserializer;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.portfolio.collectionsheet.command.CollectionSheetBulkRepaymentCommand;
|
||||
import org.apache.fineract.portfolio.collectionsheet.command.SingleRepaymentCommand;
|
||||
import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
|
||||
@@ -90,6 +92,8 @@ public final class CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer
|
||||
final JsonObject loanTransactionElement = array.get(i).getAsJsonObject();
|
||||
|
||||
final Long loanId = this.fromApiJsonHelper.extractLongNamed("loanId", loanTransactionElement);
|
||||
final String externalIdStr = this.fromApiJsonHelper.extractStringNamed("externalId", loanTransactionElement);
|
||||
final ExternalId externalId = ExternalIdFactory.produce(externalIdStr);
|
||||
final BigDecimal transactionAmount = this.fromApiJsonHelper.extractBigDecimalNamed("transactionAmount",
|
||||
loanTransactionElement, locale);
|
||||
PaymentDetail detail = paymentDetail;
|
||||
@@ -97,7 +101,8 @@ public final class CollectionSheetBulkRepaymentCommandFromApiJsonDeserializer
|
||||
detail = this.paymentDetailAssembler.fetchPaymentDetail(loanTransactionElement);
|
||||
}
|
||||
if (transactionAmount != null && transactionAmount.intValue() > 0) {
|
||||
loanRepaymentTransactions[i] = new SingleRepaymentCommand(loanId, transactionAmount, transactionDate, detail);
|
||||
loanRepaymentTransactions[i] = new SingleRepaymentCommand(loanId, externalId, transactionAmount, transactionDate,
|
||||
detail);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -91,7 +91,7 @@ public class CollectionSheetWritePlatformServiceJpaRepositoryImpl implements Col
|
||||
}
|
||||
|
||||
final PaymentDetail paymentDetail = this.paymentDetailWritePlatformService.createAndPersistPaymentDetail(command, changes);
|
||||
changes.putAll(updateBulkReapayments(command, paymentDetail));
|
||||
changes.putAll(updateBulkRepayments(command, paymentDetail));
|
||||
|
||||
changes.putAll(updateBulkDisbursals(command));
|
||||
|
||||
@@ -122,7 +122,7 @@ public class CollectionSheetWritePlatformServiceJpaRepositoryImpl implements Col
|
||||
|
||||
final PaymentDetail paymentDetail = null;
|
||||
|
||||
changes.putAll(updateBulkReapayments(command, paymentDetail));
|
||||
changes.putAll(updateBulkRepayments(command, paymentDetail));
|
||||
|
||||
changes.putAll(updateBulkDisbursals(command));
|
||||
|
||||
@@ -135,7 +135,7 @@ public class CollectionSheetWritePlatformServiceJpaRepositoryImpl implements Col
|
||||
.with(changes).with(changes).build();
|
||||
}
|
||||
|
||||
private Map<String, Object> updateBulkReapayments(final JsonCommand command, final PaymentDetail paymentDetail) {
|
||||
private Map<String, Object> updateBulkRepayments(final JsonCommand command, final PaymentDetail paymentDetail) {
|
||||
final Map<String, Object> changes = new HashMap<>();
|
||||
final CollectionSheetBulkRepaymentCommand bulkRepaymentCommand = this.bulkRepaymentCommandFromApiJsonDeserializer
|
||||
.commandFromApiJson(command.json(), paymentDetail);
|
||||
|
||||
+21
@@ -270,6 +270,12 @@ final class LoanChargesApiResourceSwagger {
|
||||
public Long savingsId;
|
||||
@Schema(example = "12")
|
||||
public Long resourceId;
|
||||
@Schema(example = "12")
|
||||
public Long subResourceId;
|
||||
@Schema(example = "786444UUUYYH7")
|
||||
public String resourceExternalId;
|
||||
@Schema(example = "786444UUUYYH7")
|
||||
public String subResourceExternalId;
|
||||
public PostLoansLoanIdChargesChargeIdChanges changes;
|
||||
|
||||
static final class PostLoansLoanIdChargesChargeIdChanges {
|
||||
@@ -288,6 +294,21 @@ final class LoanChargesApiResourceSwagger {
|
||||
public Double amount;
|
||||
@Schema(example = "786444UUUYYH7")
|
||||
public String externalId;
|
||||
|
||||
@Schema(example = "100.00")
|
||||
public Double principalPortion;
|
||||
@Schema(example = "100.00")
|
||||
public Double interestPortion;
|
||||
@Schema(example = "100.00")
|
||||
public Double feeChargesPortion;
|
||||
@Schema(example = "100.00")
|
||||
public Double penaltyChargesPortion;
|
||||
@Schema(example = "100.00")
|
||||
public Double outstandingLoanBalance;
|
||||
@Schema(example = "19 September 2013")
|
||||
public Double date;
|
||||
@Schema(example = "1")
|
||||
public Long id;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+403
-122
@@ -51,11 +51,13 @@ import org.apache.fineract.commands.service.CommandWrapperBuilder;
|
||||
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
|
||||
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.exception.UnrecognizedQueryParamException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
|
||||
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||
import org.apache.fineract.infrastructure.core.service.CommandParameterUtil;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanRepaymentScheduleInstallmentData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionData;
|
||||
@@ -67,7 +69,7 @@ import org.apache.fineract.portfolio.paymenttype.service.PaymentTypeReadPlatform
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Path("/loans/{loanId}/transactions")
|
||||
@Path("/loans")
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
@Scope("singleton")
|
||||
@@ -88,7 +90,7 @@ public class LoanTransactionsApiResource {
|
||||
private final LoanChargePaidByReadPlatformService loanChargePaidByReadPlatformService;
|
||||
|
||||
@GET
|
||||
@Path("template")
|
||||
@Path("{loanId}/transactions/template")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve Loan Transaction Template", description = "This is a convenience resource. It can be useful when building maintenance user interface screens for client applications. The template data returned consists of any or all of:\n"
|
||||
@@ -104,109 +106,115 @@ public class LoanTransactionsApiResource {
|
||||
+ "loans/1/transactions/template?command=creditBalanceRefund (returned 'amount' field will have the overpaid value)")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.GetLoansLoanIdTransactionsTemplateResponse.class))) })
|
||||
public String retrieveTransactionTemplate(@PathParam("loanId") @Parameter(description = "loanId") final Long loanId,
|
||||
public String retrieveTransactionTemplate(@PathParam("loanId") @Parameter(description = "loanId", required = true) final Long loanId,
|
||||
@QueryParam("command") @Parameter(description = "command") final String commandParam, @Context final UriInfo uriInfo,
|
||||
@QueryParam("dateFormat") @Parameter(description = "dateFormat") final String dateFormat,
|
||||
@QueryParam("transactionDate") @Parameter(description = "transactionDate") final DateParam transactionDateParam,
|
||||
@QueryParam("locale") @Parameter(description = "locale") final String locale) {
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
|
||||
|
||||
LoanTransactionData transactionData = null;
|
||||
if (CommandParameterUtil.is(commandParam, "repayment")) {
|
||||
transactionData = this.loanReadPlatformService.retrieveLoanTransactionTemplate(loanId);
|
||||
} else if (CommandParameterUtil.is(commandParam, "merchantIssuedRefund")) {
|
||||
LocalDate transactionDate = DateUtils.getBusinessLocalDate();
|
||||
transactionData = this.loanReadPlatformService.retrieveLoanPrePaymentTemplate(LoanTransactionType.MERCHANT_ISSUED_REFUND,
|
||||
loanId, transactionDate);
|
||||
} else if (CommandParameterUtil.is(commandParam, "payoutRefund")) {
|
||||
LocalDate transactionDate = DateUtils.getBusinessLocalDate();
|
||||
transactionData = this.loanReadPlatformService.retrieveLoanPrePaymentTemplate(LoanTransactionType.PAYOUT_REFUND, loanId,
|
||||
transactionDate);
|
||||
} else if (CommandParameterUtil.is(commandParam, "goodwillCredit")) {
|
||||
LocalDate transactionDate = DateUtils.getBusinessLocalDate();
|
||||
transactionData = this.loanReadPlatformService.retrieveLoanPrePaymentTemplate(LoanTransactionType.GOODWILL_CREDIT, loanId,
|
||||
transactionDate);
|
||||
} else if (CommandParameterUtil.is(commandParam, "waiveinterest")) {
|
||||
transactionData = this.loanReadPlatformService.retrieveWaiveInterestDetails(loanId);
|
||||
} else if (CommandParameterUtil.is(commandParam, "writeoff")) {
|
||||
transactionData = this.loanReadPlatformService.retrieveLoanWriteoffTemplate(loanId);
|
||||
} else if (CommandParameterUtil.is(commandParam, "close-rescheduled")) {
|
||||
transactionData = this.loanReadPlatformService.retrieveNewClosureDetails();
|
||||
} else if (CommandParameterUtil.is(commandParam, "close")) {
|
||||
transactionData = this.loanReadPlatformService.retrieveNewClosureDetails();
|
||||
} else if (CommandParameterUtil.is(commandParam, "disburse")) {
|
||||
transactionData = this.loanReadPlatformService.retrieveDisbursalTemplate(loanId, true);
|
||||
transactionData.setNumberOfRepayments(this.loanReadPlatformService.retrieveNumberOfRepayments(loanId));
|
||||
final List<LoanRepaymentScheduleInstallmentData> loanRepaymentScheduleInstallmentData = this.loanReadPlatformService
|
||||
.getRepaymentDataResponse(loanId);
|
||||
transactionData.setLoanRepaymentScheduleInstallments(loanRepaymentScheduleInstallmentData);
|
||||
} else if (CommandParameterUtil.is(commandParam, "disburseToSavings")) {
|
||||
transactionData = this.loanReadPlatformService.retrieveDisbursalTemplate(loanId, false);
|
||||
} else if (CommandParameterUtil.is(commandParam, "recoverypayment")) {
|
||||
transactionData = this.loanReadPlatformService.retrieveRecoveryPaymentTemplate(loanId);
|
||||
} else if (CommandParameterUtil.is(commandParam, "prepayLoan")) {
|
||||
LocalDate transactionDate = null;
|
||||
if (transactionDateParam == null) {
|
||||
transactionDate = DateUtils.getBusinessLocalDate();
|
||||
} else {
|
||||
transactionDate = transactionDateParam.getDate("transactionDate", dateFormat, locale);
|
||||
}
|
||||
transactionData = this.loanReadPlatformService.retrieveLoanPrePaymentTemplate(LoanTransactionType.REPAYMENT, loanId,
|
||||
transactionDate);
|
||||
} else if (CommandParameterUtil.is(commandParam, "refundbycash")) {
|
||||
transactionData = this.loanReadPlatformService.retrieveRefundByCashTemplate(loanId);
|
||||
} else if (CommandParameterUtil.is(commandParam, "refundbytransfer")) {
|
||||
transactionData = this.loanReadPlatformService.retrieveDisbursalTemplate(loanId, true);
|
||||
} else if (CommandParameterUtil.is(commandParam, "foreclosure")) {
|
||||
LocalDate transactionDate = null;
|
||||
if (transactionDateParam == null) {
|
||||
transactionDate = DateUtils.getBusinessLocalDate();
|
||||
} else {
|
||||
transactionDate = transactionDateParam.getDate("transactionDate", dateFormat, locale);
|
||||
}
|
||||
transactionData = this.loanReadPlatformService.retrieveLoanForeclosureTemplate(loanId, transactionDate);
|
||||
} else if (CommandParameterUtil.is(commandParam, "creditBalanceRefund")) {
|
||||
transactionData = this.loanReadPlatformService.retrieveCreditBalanceRefundTemplate(loanId);
|
||||
} else {
|
||||
throw new UnrecognizedQueryParamException("command", commandParam);
|
||||
}
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, transactionData, this.responseDataParameters);
|
||||
return retrieveTransactionTemplate(loanId, null, commandParam, uriInfo, dateFormat, transactionDateParam, locale);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{transactionId}")
|
||||
@Path("external-id/{loanExternalId}/transactions/template")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve Loan Transaction Template", description = "This is a convenience resource. It can be useful when building maintenance user interface screens for client applications. The template data returned consists of any or all of:\n"
|
||||
+ "\n" + "Field Defaults\n" + "Allowed Value Lists\n\n" + "Example Requests:\n" + "\n"
|
||||
+ "loans/1/transactions/template?command=repayment" + "loans/1/transactions/template?command=merchantIssuedRefund"
|
||||
+ "loans/1/transactions/template?command=payoutRefund" + "loans/1/transactions/template?command=goodwillCredit" + "\n"
|
||||
+ "loans/1/transactions/template?command=waiveinterest" + "\n" + "loans/1/transactions/template?command=writeoff" + "\n"
|
||||
+ "loans/1/transactions/template?command=close-rescheduled" + "\n" + "loans/1/transactions/template?command=close" + "\n"
|
||||
+ "loans/1/transactions/template?command=disburse" + "\n" + "loans/1/transactions/template?command=disburseToSavings" + "\n"
|
||||
+ "loans/1/transactions/template?command=recoverypayment" + "\n" + "loans/1/transactions/template?command=prepayLoan" + "\n"
|
||||
+ "loans/1/transactions/template?command=refundbycash" + "\n" + "loans/1/transactions/template?command=refundbytransfer" + "\n"
|
||||
+ "loans/1/transactions/template?command=foreclosure" + "\n"
|
||||
+ "loans/1/transactions/template?command=creditBalanceRefund (returned 'amount' field will have the overpaid value)")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.GetLoansLoanIdTransactionsTemplateResponse.class))) })
|
||||
public String retrieveTransactionTemplate(
|
||||
@PathParam("loanExternalId") @Parameter(description = "loanExternalId", required = true) final String loanExternalId,
|
||||
@QueryParam("command") @Parameter(description = "command") final String commandParam, @Context final UriInfo uriInfo,
|
||||
@QueryParam("dateFormat") @Parameter(description = "dateFormat") final String dateFormat,
|
||||
@QueryParam("transactionDate") @Parameter(description = "transactionDate") final DateParam transactionDateParam,
|
||||
@QueryParam("locale") @Parameter(description = "locale") final String locale) {
|
||||
|
||||
return retrieveTransactionTemplate(null, loanExternalId, commandParam, uriInfo, dateFormat, transactionDateParam, locale);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{loanId}/transactions/{transactionId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve a Transaction Details", description = "Retrieves a Transaction Details\n\n" + "Example Request:\n" + "\n"
|
||||
+ "loans/5/transactions/3")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.GetLoansLoanIdTransactionsTransactionIdResponse.class))) })
|
||||
public String retrieveTransaction(@PathParam("loanId") @Parameter(description = "loanId") final Long loanId,
|
||||
@PathParam("transactionId") @Parameter(description = "transactionId") final Long transactionId,
|
||||
public String retrieveTransaction(@PathParam("loanId") @Parameter(description = "loanId", required = true) final Long loanId,
|
||||
@PathParam("transactionId") @Parameter(description = "transactionId", required = true) final Long transactionId,
|
||||
@QueryParam("fields") @Parameter(in = ParameterIn.QUERY, name = "fields", description = "Optional Loan Transaction attribute list to be in the response", required = false, example = "id,date,amount") final String fields,
|
||||
@Context final UriInfo uriInfo) {
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
|
||||
return retrieveTransaction(loanId, null, transactionId, null, uriInfo);
|
||||
}
|
||||
|
||||
LoanTransactionData transactionData = this.loanReadPlatformService.retrieveLoanTransaction(loanId, transactionId);
|
||||
transactionData.setLoanChargePaidByList(this.loanChargePaidByReadPlatformService.getLoanChargesPaidByTransactionId(transactionId));
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
if (settings.isTemplate()) {
|
||||
final Collection<PaymentTypeData> paymentTypeOptions = this.paymentTypeReadPlatformService.retrieveAllPaymentTypes();
|
||||
transactionData = LoanTransactionData.templateOnTop(transactionData, paymentTypeOptions);
|
||||
}
|
||||
@GET
|
||||
@Path("{loanId}/transactions/external-id/{externalTransactionId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve a Transaction Details", description = "Retrieves a Transaction Details\n\n" + "Example Request:\n" + "\n"
|
||||
+ "loans/5/transactions/external-id/5dd80a7c-ccba-4446-b378-01eb6f53e871")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.GetLoansLoanIdTransactionsTransactionIdResponse.class))) })
|
||||
public String retrieveTransactionByTransactionExternalId(
|
||||
@PathParam("loanId") @Parameter(description = "loanId", required = true) final Long loanId,
|
||||
@PathParam("externalTransactionId") @Parameter(description = "externalTransactionId", required = true) final String externalTransactionId,
|
||||
@QueryParam("fields") @Parameter(in = ParameterIn.QUERY, name = "fields", description = "Optional Loan Transaction attribute list to be in the response", required = false, example = "id,date,amount") final String fields,
|
||||
@Context final UriInfo uriInfo) {
|
||||
|
||||
return this.toApiJsonSerializer.serialize(settings, transactionData, this.responseDataParameters);
|
||||
return retrieveTransaction(loanId, null, null, externalTransactionId, uriInfo);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("external-id/{loanExternalId}/transactions/{transactionId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve a Transaction Details", description = "Retrieves a Transaction Details\n\n" + "Example Request:\n" + "\n"
|
||||
+ "loans/5/transactions/3")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.GetLoansLoanIdTransactionsTransactionIdResponse.class))) })
|
||||
public String retrieveTransactionByLoanExternalIdAndTransactionId(
|
||||
@PathParam("loanExternalId") @Parameter(description = "loanExternalId", required = true) final String loanExternalId,
|
||||
@PathParam("transactionId") @Parameter(description = "transactionId", required = true) final Long transactionId,
|
||||
@QueryParam("fields") @Parameter(in = ParameterIn.QUERY, name = "fields", description = "Optional Loan Transaction attribute list to be in the response", required = false, example = "id,date,amount") final String fields,
|
||||
@Context final UriInfo uriInfo) {
|
||||
|
||||
return retrieveTransaction(null, loanExternalId, transactionId, null, uriInfo);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("external-id/{loanExternalId}/transactions/external-id/{externalTransactionId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve a Transaction Details", description = "Retrieves a Transaction Details\n\n" + "Example Request:\n" + "\n"
|
||||
+ "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854/transactions/external-id/5dd80a7c-ccba-4446-b378-01eb6f53e871")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.GetLoansLoanIdTransactionsTransactionIdResponse.class))) })
|
||||
public String retrieveTransactionByLoanExternalIdAndTransactionExternalId(
|
||||
@PathParam("loanExternalId") @Parameter(description = "loanExternalId", required = true) final String loanExternalId,
|
||||
@PathParam("externalTransactionId") @Parameter(description = "externalTransactionId", required = true) final String externalTransactionId,
|
||||
@QueryParam("fields") @Parameter(in = ParameterIn.QUERY, name = "fields", description = "Optional Loan Transaction attribute list to be in the response", required = false, example = "id,date,amount") final String fields,
|
||||
@Context final UriInfo uriInfo) {
|
||||
|
||||
return retrieveTransaction(null, loanExternalId, null, externalTransactionId, uriInfo);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("{loanId}/transactions")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Significant Loan Transactions", description = "This API covers the major loan transaction functionality\n\n"
|
||||
+ "Example Requests:\n" + "\n" + "loans/1/transactions?command=repayment" + " | Make a Repayment | \n"
|
||||
+ "Example Requests:\n\n" + "loans/1/transactions?command=repayment" + " | Make a Repayment | \n"
|
||||
+ "loans/1/transactions?command=merchantIssuedRefund" + " | Merchant Issued Refund | \n"
|
||||
+ "loans/1/transactions?command=payoutRefund" + " | Payout Refund | \n" + "loans/1/transactions?command=goodwillCredit"
|
||||
+ " | Goodwil Credit | \n" + "loans/1/transactions?command=chargeRefund" + " | Charge Refund | \n"
|
||||
@@ -220,41 +228,234 @@ public class LoanTransactionsApiResource {
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PostLoansLoanIdTransactionsRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PostLoansLoanIdTransactionsResponse.class))) })
|
||||
public String executeLoanTransaction(@PathParam("loanId") @Parameter(description = "loanId") final Long loanId,
|
||||
public String executeLoanTransaction(@PathParam("loanId") @Parameter(description = "loanId", required = true) final Long loanId,
|
||||
@QueryParam("command") @Parameter(description = "command") final String commandParam,
|
||||
@Parameter(hidden = true) final String apiRequestBodyAsJson) {
|
||||
|
||||
return executeTransaction(loanId, null, commandParam, apiRequestBodyAsJson);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("external-id/{loanExternalId}/transactions")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Significant Loan Transactions", description = "This API covers the major loan transaction functionality\n\n"
|
||||
+ "Example Requests:\n\n" + "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854/transactions?command=repayment"
|
||||
+ " | Make a Repayment | \n"
|
||||
+ "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854/transactions?command=merchantIssuedRefund"
|
||||
+ " | Merchant Issued Refund | \n" + "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854/transactions?command=payoutRefund"
|
||||
+ " | Payout Refund | \n" + "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854/transactions?command=goodwillCredit"
|
||||
+ " | Goodwil Credit | \n" + "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854/transactions?command=chargeRefund"
|
||||
+ " | Charge Refund | \n" + "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854/transactions?command=waiveinterest"
|
||||
+ " | Waive Interest | \n" + "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854/transactions?command=writeoff"
|
||||
+ " | Write-off Loan | \n" + "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854/transactions?command=close-rescheduled"
|
||||
+ " | Close Rescheduled Loan | \n" + "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854/transactions?command=close"
|
||||
+ " | Close Loan | \n" + "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854/transactions?command=undowriteoff"
|
||||
+ " | Undo Loan Write-off | \n" + "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854/transactions?command=recoverypayment"
|
||||
+ " | Make Recovery Payment | \n" + "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854/transactions?command=refundByCash"
|
||||
+ " | Make a Refund of an Active Loan by Cash | \n"
|
||||
+ "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854/transactions?command=foreclosure"
|
||||
+ " | Foreclosure of an Active Loan | \n"
|
||||
+ "loans/external-id/7dd80a7c-ycba-a446-t378-91eb6f53e854/transactions?command=creditBalanceRefund" + " | Credit Balance Refund"
|
||||
+ " | \n")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PostLoansLoanIdTransactionsRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PostLoansLoanIdTransactionsResponse.class))) })
|
||||
public String executeLoanTransaction(
|
||||
@PathParam("loanExternalId") @Parameter(description = "loanExternalId", required = true) final String loanExternalId,
|
||||
@QueryParam("command") @Parameter(description = "command") final String commandParam,
|
||||
@Parameter(hidden = true) final String apiRequestBodyAsJson) {
|
||||
|
||||
return executeTransaction(null, loanExternalId, commandParam, apiRequestBodyAsJson);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("{loanId}/transactions/{transactionId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Adjust a Transaction", description = "Note: there is no need to specify command={transactionType} parameter.\n\n"
|
||||
+ "Mandatory Fields: transactionDate, transactionAmount")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PostLoansLoanIdTransactionsTransactionIdRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PostLoansLoanIdTransactionsResponse.class))) })
|
||||
public String adjustLoanTransaction(@PathParam("loanId") @Parameter(description = "loanId", required = true) final Long loanId,
|
||||
@PathParam("transactionId") @Parameter(description = "transactionId", required = true) final Long transactionId,
|
||||
@Parameter(hidden = true) final String apiRequestBodyAsJson,
|
||||
@QueryParam("command") @Parameter(description = "command") final String commandParam) {
|
||||
|
||||
return adjustTransaction(loanId, null, transactionId, null, apiRequestBodyAsJson, commandParam);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("external-id/{loanExternalId}/transactions/{transactionId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Adjust a Transaction", description = "Note: there is no need to specify command={transactionType} parameter.\n\n"
|
||||
+ "Mandatory Fields: transactionDate, transactionAmount")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PostLoansLoanIdTransactionsTransactionIdRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PostLoansLoanIdTransactionsResponse.class))) })
|
||||
public String adjustLoanTransaction(
|
||||
@PathParam("loanExternalId") @Parameter(description = "loanExternalId", required = true) final String loanExternalId,
|
||||
@PathParam("transactionId") @Parameter(description = "transactionId", required = true) final Long transactionId,
|
||||
@Parameter(hidden = true) final String apiRequestBodyAsJson,
|
||||
@QueryParam("command") @Parameter(description = "command") final String commandParam) {
|
||||
|
||||
return adjustTransaction(null, loanExternalId, transactionId, null, apiRequestBodyAsJson, commandParam);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("{loanId}/transactions/external-id/{externalTransactionId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Adjust a Transaction", description = "Note: there is no need to specify command={transactionType} parameter.\n\n"
|
||||
+ "Mandatory Fields: transactionDate, transactionAmount")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PostLoansLoanIdTransactionsTransactionIdRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PostLoansLoanIdTransactionsResponse.class))) })
|
||||
public String adjustLoanTransaction(@PathParam("loanId") @Parameter(description = "loanId", required = true) final Long loanId,
|
||||
@PathParam("externalTransactionId") @Parameter(description = "externalTransactionId", required = true) final String transactionExternalId,
|
||||
@Parameter(hidden = true) final String apiRequestBodyAsJson,
|
||||
@QueryParam("command") @Parameter(description = "command") final String commandParam) {
|
||||
|
||||
return adjustTransaction(loanId, null, null, transactionExternalId, apiRequestBodyAsJson, commandParam);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("external-id/{loanExternalId}/transactions/external-id/{externalTransactionId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Adjust a Transaction", description = "Note: there is no need to specify command={transactionType} parameter.\n\n"
|
||||
+ "Mandatory Fields: transactionDate, transactionAmount")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PostLoansLoanIdTransactionsTransactionIdRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PostLoansLoanIdTransactionsResponse.class))) })
|
||||
public String adjustLoanTransaction(
|
||||
@PathParam("loanExternalId") @Parameter(description = "loanExternalId", required = true) final String loanExternalId,
|
||||
@PathParam("externalTransactionId") @Parameter(description = "externalTransactionId", required = true) final String transactionExternalId,
|
||||
@Parameter(hidden = true) final String apiRequestBodyAsJson,
|
||||
@QueryParam("command") @Parameter(description = "command") final String commandParam) {
|
||||
|
||||
return adjustTransaction(null, loanExternalId, null, transactionExternalId, apiRequestBodyAsJson, commandParam);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("{loanId}/transactions/{transactionId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Undo a Waive Charge Transaction", description = "Undo a Waive Charge Transaction")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PutChargeTransactionChangesRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PutChargeTransactionChangesResponse.class))) })
|
||||
public String undoWaiveCharge(@PathParam("loanId") @Parameter(description = "loanId", required = true) final Long loanId,
|
||||
@PathParam("transactionId") @Parameter(description = "transactionId", required = true) final Long transactionId) {
|
||||
|
||||
return undoWaiveCharge(loanId, null, transactionId, null);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("external-id/{loanExternalId}/transactions/{transactionId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Undo a Waive Charge Transaction", description = "Undo a Waive Charge Transaction")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PutChargeTransactionChangesRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PutChargeTransactionChangesResponse.class))) })
|
||||
public String undoWaiveCharge(
|
||||
@PathParam("loanExternalId") @Parameter(description = "loanExternalId", required = true) final String loanExternalId,
|
||||
@PathParam("transactionId") @Parameter(description = "transactionId", required = true) final Long transactionId) {
|
||||
|
||||
return undoWaiveCharge(null, loanExternalId, transactionId, null);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("{loanId}/transactions/external-id/{transactionExternalId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Undo a Waive Charge Transaction", description = "Undo a Waive Charge Transaction")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PutChargeTransactionChangesRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PutChargeTransactionChangesResponse.class))) })
|
||||
public String undoWaiveCharge(@PathParam("loanId") @Parameter(description = "loanId", required = true) final Long loanId,
|
||||
@PathParam("transactionExternalId") @Parameter(description = "transactionExternalId", required = true) final String transactionExternalId) {
|
||||
|
||||
return undoWaiveCharge(loanId, null, null, transactionExternalId);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("external-id/{loanExternalId}/transactions/external-id/{transactionExternalId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Undo a Waive Charge Transaction", description = "Undo a Waive Charge Transaction")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PutChargeTransactionChangesRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PutChargeTransactionChangesResponse.class))) })
|
||||
public String undoWaiveCharge(
|
||||
@PathParam("loanExternalId") @Parameter(description = "loanExternalId", required = true) final String loanExternalId,
|
||||
@PathParam("transactionExternalId") @Parameter(description = "transactionExternalId", required = true) final String transactionExternalId) {
|
||||
|
||||
return undoWaiveCharge(null, loanExternalId, null, transactionExternalId);
|
||||
}
|
||||
|
||||
private String retrieveTransaction(final Long loanId, final String loanExternalIdStr, final Long transactionId,
|
||||
final String transactionExternalIdStr, final UriInfo uriInfo) {
|
||||
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
|
||||
|
||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||
ExternalId transactionExternalId = ExternalIdFactory.produce(transactionExternalIdStr);
|
||||
|
||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
||||
Long resolvedLoanTransactionId = getResolvedLoanTransactionId(transactionId, transactionExternalId);
|
||||
|
||||
LoanTransactionData transactionData = this.loanReadPlatformService.retrieveLoanTransaction(resolvedLoanId,
|
||||
resolvedLoanTransactionId);
|
||||
transactionData.setLoanChargePaidByList(
|
||||
this.loanChargePaidByReadPlatformService.getLoanChargesPaidByTransactionId(transactionData.getId()));
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
if (settings.isTemplate()) {
|
||||
final Collection<PaymentTypeData> paymentTypeOptions = this.paymentTypeReadPlatformService.retrieveAllPaymentTypes();
|
||||
transactionData = LoanTransactionData.templateOnTop(transactionData, paymentTypeOptions);
|
||||
}
|
||||
|
||||
return this.toApiJsonSerializer.serialize(settings, transactionData, this.responseDataParameters);
|
||||
}
|
||||
|
||||
private String executeTransaction(final Long loanId, final String loanExternalIdStr, final String commandParam,
|
||||
final String apiRequestBodyAsJson) {
|
||||
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
|
||||
|
||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
||||
|
||||
CommandWrapper commandRequest = null;
|
||||
if (CommandParameterUtil.is(commandParam, "repayment")) {
|
||||
commandRequest = builder.loanRepaymentTransaction(loanId).build();
|
||||
commandRequest = builder.loanRepaymentTransaction(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "merchantIssuedRefund")) {
|
||||
commandRequest = builder.loanMerchantIssuedRefundTransaction(loanId).build();
|
||||
commandRequest = builder.loanMerchantIssuedRefundTransaction(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "payoutRefund")) {
|
||||
commandRequest = builder.loanPayoutRefundTransaction(loanId).build();
|
||||
commandRequest = builder.loanPayoutRefundTransaction(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "goodwillCredit")) {
|
||||
commandRequest = builder.loanGoodwillCreditTransaction(loanId).build();
|
||||
commandRequest = builder.loanGoodwillCreditTransaction(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "chargeRefund")) {
|
||||
commandRequest = builder.refundLoanCharge(loanId).build();
|
||||
commandRequest = builder.refundLoanCharge(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "waiveinterest")) {
|
||||
commandRequest = builder.waiveInterestPortionTransaction(loanId).build();
|
||||
commandRequest = builder.waiveInterestPortionTransaction(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "writeoff")) {
|
||||
commandRequest = builder.writeOffLoanTransaction(loanId).build();
|
||||
commandRequest = builder.writeOffLoanTransaction(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "close-rescheduled")) {
|
||||
commandRequest = builder.closeLoanAsRescheduledTransaction(loanId).build();
|
||||
commandRequest = builder.closeLoanAsRescheduledTransaction(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "close")) {
|
||||
commandRequest = builder.closeLoanTransaction(loanId).build();
|
||||
commandRequest = builder.closeLoanTransaction(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "undowriteoff")) {
|
||||
commandRequest = builder.undoWriteOffLoanTransaction(loanId).build();
|
||||
commandRequest = builder.undoWriteOffLoanTransaction(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "recoverypayment")) {
|
||||
commandRequest = builder.loanRecoveryPaymentTransaction(loanId).build();
|
||||
commandRequest = builder.loanRecoveryPaymentTransaction(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "refundByCash")) {
|
||||
commandRequest = builder.refundLoanTransactionByCash(loanId).build();
|
||||
commandRequest = builder.refundLoanTransactionByCash(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "foreclosure")) {
|
||||
commandRequest = builder.loanForeclosure(loanId).build();
|
||||
commandRequest = builder.loanForeclosure(resolvedLoanId).build();
|
||||
} else if (CommandParameterUtil.is(commandParam, "creditBalanceRefund")) {
|
||||
commandRequest = builder.creditBalanceRefund(loanId).build();
|
||||
commandRequest = builder.creditBalanceRefund(resolvedLoanId).build();
|
||||
}
|
||||
|
||||
if (commandRequest == null) {
|
||||
@@ -264,27 +465,92 @@ public class LoanTransactionsApiResource {
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("{transactionId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Adjust a Transaction", description = "Note: there is no need to specify command={transactionType} parameter.\n\n"
|
||||
+ "Mandatory Fields: transactionDate, transactionAmount")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PostLoansLoanIdTransactionsTransactionIdRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PostLoansLoanIdTransactionsTransactionIdResponse.class))) })
|
||||
public String adjustLoanTransaction(@PathParam("loanId") @Parameter(description = "loanId") final Long loanId,
|
||||
@PathParam("transactionId") @Parameter(description = "transactionId") final Long transactionId,
|
||||
@Parameter(hidden = true) final String apiRequestBodyAsJson,
|
||||
@QueryParam("command") @Parameter(description = "command") final String commandParam) {
|
||||
private String retrieveTransactionTemplate(Long loanId, String loanExternalIdStr, String commandParam, UriInfo uriInfo,
|
||||
String dateFormat, DateParam transactionDateParam, String locale) {
|
||||
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
|
||||
|
||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||
|
||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
||||
LoanTransactionData transactionData;
|
||||
|
||||
if (CommandParameterUtil.is(commandParam, "repayment")) {
|
||||
transactionData = this.loanReadPlatformService.retrieveLoanTransactionTemplate(resolvedLoanId);
|
||||
} else if (CommandParameterUtil.is(commandParam, "merchantIssuedRefund")) {
|
||||
LocalDate transactionDate = DateUtils.getBusinessLocalDate();
|
||||
transactionData = this.loanReadPlatformService.retrieveLoanPrePaymentTemplate(LoanTransactionType.MERCHANT_ISSUED_REFUND,
|
||||
resolvedLoanId, transactionDate);
|
||||
} else if (CommandParameterUtil.is(commandParam, "payoutRefund")) {
|
||||
LocalDate transactionDate = DateUtils.getBusinessLocalDate();
|
||||
transactionData = this.loanReadPlatformService.retrieveLoanPrePaymentTemplate(LoanTransactionType.PAYOUT_REFUND, resolvedLoanId,
|
||||
transactionDate);
|
||||
} else if (CommandParameterUtil.is(commandParam, "goodwillCredit")) {
|
||||
LocalDate transactionDate = DateUtils.getBusinessLocalDate();
|
||||
transactionData = this.loanReadPlatformService.retrieveLoanPrePaymentTemplate(LoanTransactionType.GOODWILL_CREDIT,
|
||||
resolvedLoanId, transactionDate);
|
||||
} else if (CommandParameterUtil.is(commandParam, "waiveinterest")) {
|
||||
transactionData = this.loanReadPlatformService.retrieveWaiveInterestDetails(resolvedLoanId);
|
||||
} else if (CommandParameterUtil.is(commandParam, "writeoff")) {
|
||||
transactionData = this.loanReadPlatformService.retrieveLoanWriteoffTemplate(resolvedLoanId);
|
||||
} else if (CommandParameterUtil.is(commandParam, "close-rescheduled")) {
|
||||
transactionData = this.loanReadPlatformService.retrieveNewClosureDetails();
|
||||
} else if (CommandParameterUtil.is(commandParam, "close")) {
|
||||
transactionData = this.loanReadPlatformService.retrieveNewClosureDetails();
|
||||
} else if (CommandParameterUtil.is(commandParam, "disburse")) {
|
||||
transactionData = this.loanReadPlatformService.retrieveDisbursalTemplate(resolvedLoanId, true);
|
||||
transactionData.setNumberOfRepayments(this.loanReadPlatformService.retrieveNumberOfRepayments(resolvedLoanId));
|
||||
final List<LoanRepaymentScheduleInstallmentData> loanRepaymentScheduleInstallmentData = this.loanReadPlatformService
|
||||
.getRepaymentDataResponse(resolvedLoanId);
|
||||
transactionData.setLoanRepaymentScheduleInstallments(loanRepaymentScheduleInstallmentData);
|
||||
} else if (CommandParameterUtil.is(commandParam, "disburseToSavings")) {
|
||||
transactionData = this.loanReadPlatformService.retrieveDisbursalTemplate(resolvedLoanId, false);
|
||||
} else if (CommandParameterUtil.is(commandParam, "recoverypayment")) {
|
||||
transactionData = this.loanReadPlatformService.retrieveRecoveryPaymentTemplate(resolvedLoanId);
|
||||
} else if (CommandParameterUtil.is(commandParam, "prepayLoan")) {
|
||||
LocalDate transactionDate;
|
||||
if (transactionDateParam == null) {
|
||||
transactionDate = DateUtils.getBusinessLocalDate();
|
||||
} else {
|
||||
transactionDate = transactionDateParam.getDate("transactionDate", dateFormat, locale);
|
||||
}
|
||||
transactionData = this.loanReadPlatformService.retrieveLoanPrePaymentTemplate(LoanTransactionType.REPAYMENT, resolvedLoanId,
|
||||
transactionDate);
|
||||
} else if (CommandParameterUtil.is(commandParam, "refundbycash")) {
|
||||
transactionData = this.loanReadPlatformService.retrieveRefundByCashTemplate(resolvedLoanId);
|
||||
} else if (CommandParameterUtil.is(commandParam, "refundbytransfer")) {
|
||||
transactionData = this.loanReadPlatformService.retrieveDisbursalTemplate(resolvedLoanId, true);
|
||||
} else if (CommandParameterUtil.is(commandParam, "foreclosure")) {
|
||||
LocalDate transactionDate;
|
||||
if (transactionDateParam == null) {
|
||||
transactionDate = DateUtils.getBusinessLocalDate();
|
||||
} else {
|
||||
transactionDate = transactionDateParam.getDate("transactionDate", dateFormat, locale);
|
||||
}
|
||||
transactionData = this.loanReadPlatformService.retrieveLoanForeclosureTemplate(resolvedLoanId, transactionDate);
|
||||
} else if (CommandParameterUtil.is(commandParam, "creditBalanceRefund")) {
|
||||
transactionData = this.loanReadPlatformService.retrieveCreditBalanceRefundTemplate(resolvedLoanId);
|
||||
} else {
|
||||
throw new UnrecognizedQueryParamException("command", commandParam);
|
||||
}
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, transactionData, this.responseDataParameters);
|
||||
}
|
||||
|
||||
private String adjustTransaction(final Long loanId, final String loanExternalIdStr, final Long transactionId,
|
||||
final String transactionExternalIdStr, final String apiRequestBodyAsJson, final String commandParam) {
|
||||
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson);
|
||||
|
||||
CommandWrapper commandRequest = null;
|
||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||
ExternalId transactionExternalId = ExternalIdFactory.produce(transactionExternalIdStr);
|
||||
|
||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
||||
Long resolvedTransactionId = getResolvedLoanTransactionId(transactionId, transactionExternalId);
|
||||
CommandWrapper commandRequest;
|
||||
if (CommandParameterUtil.is(commandParam, LoanApiConstants.CHARGEBACK_TRANSACTION_COMMAND)) {
|
||||
commandRequest = builder.chargebackTransaction(loanId, transactionId).build();
|
||||
commandRequest = builder.chargebackTransaction(resolvedLoanId, resolvedTransactionId).build();
|
||||
} else { // Default to adjust the Loan Transaction
|
||||
commandRequest = builder.adjustTransaction(loanId, transactionId).build();
|
||||
commandRequest = builder.adjustTransaction(resolvedLoanId, resolvedTransactionId).build();
|
||||
}
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
@@ -292,19 +558,34 @@ public class LoanTransactionsApiResource {
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("{transactionId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Undo a Waive Charge Transaction", description = "Undo a Waive Charge Transaction")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PutChargeTransactionChangesRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = LoanTransactionsApiResourceSwagger.PutChargeTransactionChangesResponse.class))) })
|
||||
public String undoWaiveCharge(@PathParam("loanId") @Parameter(description = "loanId") final Long loanId,
|
||||
@PathParam("transactionId") @Parameter(description = "transactionId") final Long transactionId) {
|
||||
private String undoWaiveCharge(final Long loanId, final String loanExternalIdStr, final Long transactionId,
|
||||
final String transactionExternalIdStr) {
|
||||
ExternalId loanExternalId = ExternalIdFactory.produce(loanExternalIdStr);
|
||||
ExternalId transactionExternalId = ExternalIdFactory.produce(transactionExternalIdStr);
|
||||
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().undoWaiveChargeTransaction(loanId, transactionId).build();
|
||||
Long resolvedLoanId = getResolvedLoanId(loanId, loanExternalId);
|
||||
Long resolvedTransactionId = getResolvedLoanTransactionId(transactionId, transactionExternalId);
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().undoWaiveChargeTransaction(resolvedLoanId, resolvedTransactionId)
|
||||
.build();
|
||||
CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}
|
||||
|
||||
private Long getResolvedLoanTransactionId(final Long transactionId, final ExternalId externalTransactionId) {
|
||||
Long resolvedLoanTransactionId = transactionId;
|
||||
if (resolvedLoanTransactionId == null) {
|
||||
externalTransactionId.throwExceptionIfEmpty();
|
||||
resolvedLoanTransactionId = this.loanReadPlatformService.retrieveLoanTransactionIdByExternalId(externalTransactionId);
|
||||
}
|
||||
return resolvedLoanTransactionId;
|
||||
}
|
||||
|
||||
private Long getResolvedLoanId(final Long loanId, final ExternalId loanExternalId) {
|
||||
Long resolvedLoanId = loanId;
|
||||
if (resolvedLoanId == null) {
|
||||
loanExternalId.throwExceptionIfEmpty();
|
||||
resolvedLoanId = this.loanReadPlatformService.retrieveLoanIdByExternalId(loanExternalId.getValue());
|
||||
}
|
||||
return resolvedLoanId;
|
||||
}
|
||||
}
|
||||
|
||||
+67
-14
@@ -89,6 +89,12 @@ final class LoanTransactionsApiResourceSwagger {
|
||||
|
||||
@Schema(example = "2")
|
||||
public Long id;
|
||||
@Schema(example = "3e7791ce-aa10-11ec-b909-0242ac120002")
|
||||
public String externalId;
|
||||
@Schema(example = "2")
|
||||
public Long loanId;
|
||||
@Schema(example = "3e7791ce-aa10-11ec-b909-0242ac120002")
|
||||
public String externalLoanId;
|
||||
@Schema(example = "loanTransactionType.repayment")
|
||||
public String code;
|
||||
@Schema(example = "Repayment")
|
||||
@@ -250,6 +256,8 @@ final class LoanTransactionsApiResourceSwagger {
|
||||
public String bankNumber;
|
||||
@Schema(example = "3")
|
||||
public Integer loanChargeId;
|
||||
@Schema(example = "28 June 2022")
|
||||
public String dueDate;
|
||||
|
||||
}
|
||||
|
||||
@@ -262,8 +270,37 @@ final class LoanTransactionsApiResourceSwagger {
|
||||
public Long officeId;
|
||||
@Schema(example = "1")
|
||||
public Long clientId;
|
||||
@Schema(example = "1")
|
||||
public Long loanId;
|
||||
@Schema(example = "22")
|
||||
public Long resourceId;
|
||||
@Schema(example = "95174ff9-1a75-4d72-a413-6f9b1cb988b7")
|
||||
public String resourceExternalId;
|
||||
@Schema(example = "22")
|
||||
public Long subResourceId;
|
||||
@Schema(example = "95174ff9-1a75-4d72-a413-6f9b1cb988b7")
|
||||
public String subResourceExternalId;
|
||||
public PostLoansLoanIdTransactionsResponse.Changes changes;
|
||||
|
||||
static final class Changes {
|
||||
|
||||
@Schema(example = "en_GB")
|
||||
public String locale;
|
||||
@Schema(example = "dd MMMM yyyy")
|
||||
public String dateFormat;
|
||||
@Schema(example = "28 June 2022")
|
||||
public String transactionDate;
|
||||
@Schema(example = "50,000.00")
|
||||
public Double transactionAmount;
|
||||
@Schema(example = "An optional note about why your adjusting or changing the transaction.")
|
||||
public String note;
|
||||
@Schema(example = "95174ff9-1a75-4d72-a413-6f9b1cb988b7")
|
||||
public String reversalExternalId;
|
||||
@Schema(example = "1")
|
||||
public Long paymentTypeId;
|
||||
@Schema(example = "4ff9b1cb988b7")
|
||||
public String externalId;
|
||||
}
|
||||
}
|
||||
|
||||
@Schema(description = "PostLoansLoanIdTransactionsTransactionIdRequest")
|
||||
@@ -289,15 +326,6 @@ final class LoanTransactionsApiResourceSwagger {
|
||||
public String externalId;
|
||||
}
|
||||
|
||||
@Schema(description = "PostLoansLoanIdTransactionsTransactionIdResponse")
|
||||
public static final class PostLoansLoanIdTransactionsTransactionIdResponse {
|
||||
|
||||
private PostLoansLoanIdTransactionsTransactionIdResponse() {}
|
||||
|
||||
@Schema(example = "16")
|
||||
public Long resourceId;
|
||||
}
|
||||
|
||||
@Schema(description = "PutChargeTransactionChangesResponse")
|
||||
public static final class PutChargeTransactionChangesResponse {
|
||||
|
||||
@@ -305,16 +333,41 @@ final class LoanTransactionsApiResourceSwagger {
|
||||
|
||||
static final class Changes {
|
||||
|
||||
private Changes() {}
|
||||
@Schema(example = "10.0")
|
||||
public Double amount;
|
||||
@Schema(example = "10.0")
|
||||
public Double principalPortion;
|
||||
@Schema(example = "10.0")
|
||||
public Double interestPortion;
|
||||
@Schema(example = "10.0")
|
||||
public Double feeChargesPortion;
|
||||
@Schema(example = "10.0")
|
||||
public Double penaltyChargesPortion;
|
||||
@Schema(example = "10.0")
|
||||
public Double outstandingLoanBalance;
|
||||
@Schema(example = "1")
|
||||
public Long id;
|
||||
@Schema(example = "95174ff9-1a75-4d72-a413-6f9b1cb988b7")
|
||||
public String externalId;
|
||||
@Schema(example = "28 June 2022")
|
||||
public String date;
|
||||
|
||||
@Schema(example = "amount")
|
||||
public String amount;
|
||||
}
|
||||
|
||||
@Schema(example = "1")
|
||||
public Long resourceId;
|
||||
@Schema(example = "48")
|
||||
public Long officeId;
|
||||
@Schema(example = "1")
|
||||
public Long clientId;
|
||||
@Schema(example = "1")
|
||||
public Long loanId;
|
||||
@Schema(example = "22")
|
||||
public Long resourceId;
|
||||
@Schema(example = "95174ff9-1a75-4d72-a413-6f9b1cb988b7")
|
||||
public String resourceExternalId;
|
||||
@Schema(example = "22")
|
||||
public Long subResourceId;
|
||||
@Schema(example = "95174ff9-1a75-4d72-a413-6f9b1cb988b7")
|
||||
public String subResourceExternalId;
|
||||
public PutChargeTransactionChangesResponse.Changes changes;
|
||||
|
||||
}
|
||||
|
||||
+10
-8
@@ -24,6 +24,7 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import lombok.Getter;
|
||||
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.portfolio.account.data.AccountTransferData;
|
||||
import org.apache.fineract.portfolio.paymentdetail.data.PaymentDetailData;
|
||||
@@ -56,7 +57,7 @@ public class LoanTransactionData {
|
||||
private final BigDecimal penaltyChargesPortion;
|
||||
private final BigDecimal overpaymentPortion;
|
||||
private final BigDecimal unrecognizedIncomePortion;
|
||||
private final String externalId;
|
||||
private final ExternalId externalId;
|
||||
private final AccountTransferData transfer;
|
||||
private final BigDecimal fixedEmiAmount;
|
||||
private final BigDecimal outstandingLoanBalance;
|
||||
@@ -212,7 +213,7 @@ public class LoanTransactionData {
|
||||
final PaymentDetailData paymentDetailData, final CurrencyData currency, final LocalDate date, final BigDecimal amount,
|
||||
final BigDecimal netDisbursalAmount, final BigDecimal principalPortion, final BigDecimal interestPortion,
|
||||
final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion, final BigDecimal overpaymentPortion,
|
||||
final String externalId, final AccountTransferData transfer, BigDecimal fixedEmiAmount, BigDecimal outstandingLoanBalance,
|
||||
final ExternalId externalId, final AccountTransferData transfer, BigDecimal fixedEmiAmount, BigDecimal outstandingLoanBalance,
|
||||
final BigDecimal unrecognizedIncomePortion, final boolean manuallyReversed, Long loanId, String externalLoanId) {
|
||||
this(id, officeId, officeName, transactionType, paymentDetailData, currency, date, amount, netDisbursalAmount, principalPortion,
|
||||
interestPortion, feeChargesPortion, penaltyChargesPortion, overpaymentPortion, unrecognizedIncomePortion, null, externalId,
|
||||
@@ -223,7 +224,7 @@ public class LoanTransactionData {
|
||||
final PaymentDetailData paymentDetailData, final CurrencyData currency, final LocalDate date, final BigDecimal amount,
|
||||
final BigDecimal netDisbursalAmount, final BigDecimal principalPortion, final BigDecimal interestPortion,
|
||||
final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion, final BigDecimal overpaymentPortion,
|
||||
BigDecimal unrecognizedIncomePortion, final Collection<PaymentTypeData> paymentTypeOptions, final String externalId,
|
||||
BigDecimal unrecognizedIncomePortion, final Collection<PaymentTypeData> paymentTypeOptions, final ExternalId externalId,
|
||||
final AccountTransferData transfer, final BigDecimal fixedEmiAmount, BigDecimal outstandingLoanBalance,
|
||||
boolean manuallyReversed, Long loanId, String externalLoanId) {
|
||||
this(id, externalLoanId, officeId, officeName, transactionType, paymentDetailData, currency, date, amount, netDisbursalAmount,
|
||||
@@ -236,7 +237,7 @@ public class LoanTransactionData {
|
||||
final PaymentDetailData paymentDetailData, final CurrencyData currency, final LocalDate date, final BigDecimal amount,
|
||||
final BigDecimal netDisbursalAmount, final BigDecimal principalPortion, final BigDecimal interestPortion,
|
||||
final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion, final BigDecimal overpaymentPortion,
|
||||
final BigDecimal unrecognizedIncomePortion, final String externalId, final AccountTransferData transfer,
|
||||
final BigDecimal unrecognizedIncomePortion, final ExternalId externalId, final AccountTransferData transfer,
|
||||
BigDecimal fixedEmiAmount, BigDecimal outstandingLoanBalance, LocalDate submittedOnDate, final boolean manuallyReversed,
|
||||
final String reversalExternalId, final LocalDate reversedOnDate, Long loanId, String externalLoanId) {
|
||||
this(id, externalLoanId, officeId, officeName, transactionType, paymentDetailData, currency, date, amount, netDisbursalAmount,
|
||||
@@ -250,7 +251,7 @@ public class LoanTransactionData {
|
||||
final LocalDate date, final BigDecimal amount, final BigDecimal netDisbursalAmount, final BigDecimal principalPortion,
|
||||
final BigDecimal interestPortion, final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion,
|
||||
final BigDecimal overpaymentPortion, final BigDecimal unrecognizedIncomePortion,
|
||||
final Collection<PaymentTypeData> paymentTypeOptions, final String externalId, final AccountTransferData transfer,
|
||||
final Collection<PaymentTypeData> paymentTypeOptions, final ExternalId externalId, final AccountTransferData transfer,
|
||||
final BigDecimal fixedEmiAmount, BigDecimal outstandingLoanBalance, final LocalDate submittedOnDate,
|
||||
final boolean manuallyReversed, final String reversalExternalId, final LocalDate reversedOnDate, Long loanId) {
|
||||
this.id = id;
|
||||
@@ -308,7 +309,7 @@ public class LoanTransactionData {
|
||||
final BigDecimal feeChargesPortion = null;
|
||||
final BigDecimal penaltyChargesPortion = null;
|
||||
final BigDecimal overpaymentPortion = null;
|
||||
final String externalId = null;
|
||||
final ExternalId externalId = ExternalId.empty();
|
||||
final BigDecimal outstandingLoanBalance = null;
|
||||
final AccountTransferData transfer = null;
|
||||
final LocalDate submittedOnDate = null;
|
||||
@@ -326,8 +327,9 @@ public class LoanTransactionData {
|
||||
BigDecimal netDisbursalAmount, final BigDecimal principalPortion, final BigDecimal interestPortion,
|
||||
final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion, final BigDecimal overpaymentPortion,
|
||||
BigDecimal unrecognizedIncomePortion, Collection<PaymentTypeData> paymentOptions, final AccountTransferData transfer,
|
||||
final String externalId, final BigDecimal fixedEmiAmount, BigDecimal outstandingLoanBalance, final LocalDate submittedOnDate,
|
||||
final boolean manuallyReversed, final LocalDate possibleNextRepaymentDate, Long loanId, String externalLoanId) {
|
||||
final ExternalId externalId, final BigDecimal fixedEmiAmount, BigDecimal outstandingLoanBalance,
|
||||
final LocalDate submittedOnDate, final boolean manuallyReversed, final LocalDate possibleNextRepaymentDate, Long loanId,
|
||||
String externalLoanId) {
|
||||
this.id = id;
|
||||
this.loanId = loanId;
|
||||
this.externalLoanId = externalLoanId;
|
||||
|
||||
+64
-16
@@ -61,9 +61,11 @@ import javax.persistence.UniqueConstraint;
|
||||
import javax.persistence.Version;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.codes.domain.CodeValue;
|
||||
import org.apache.fineract.infrastructure.configuration.service.TemporaryConfigurationServiceContainer;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.JsonParserHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
@@ -719,9 +721,12 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
transactionDate = currentDate;
|
||||
}
|
||||
}
|
||||
|
||||
ExternalId externalId = ExternalId.empty();
|
||||
if (TemporaryConfigurationServiceContainer.isExternalIdAutoGenerationEnabled()) {
|
||||
externalId = ExternalId.generate();
|
||||
}
|
||||
final LoanTransaction applyLoanChargeTransaction = LoanTransaction.accrueLoanCharge(this, getOffice(), chargeAmount,
|
||||
transactionDate, feeCharges, penaltyCharges);
|
||||
transactionDate, feeCharges, penaltyCharges, externalId);
|
||||
|
||||
Integer installmentNumber = null;
|
||||
final LoanChargePaidBy loanChargePaidBy = new LoanChargePaidBy(applyLoanChargeTransaction, loanCharge,
|
||||
@@ -1014,7 +1019,8 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
|
||||
public LoanTransaction waiveLoanCharge(final LoanCharge loanCharge, final LoanLifecycleStateMachine loanLifecycleStateMachine,
|
||||
final Map<String, Object> changes, final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds,
|
||||
final Integer loanInstallmentNumber, final ScheduleGeneratorDTO scheduleGeneratorDTO, final Money accruedCharge) {
|
||||
final Integer loanInstallmentNumber, final ScheduleGeneratorDTO scheduleGeneratorDTO, final Money accruedCharge,
|
||||
final ExternalId externalId) {
|
||||
|
||||
validateLoanIsNotClosed(loanCharge);
|
||||
|
||||
@@ -1066,7 +1072,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
|
||||
|
||||
final LoanTransaction waiveLoanChargeTransaction = LoanTransaction.waiveLoanCharge(this, getOffice(), amountWaived, transactionDate,
|
||||
feeChargesWaived, penaltyChargesWaived, unrecognizedIncome);
|
||||
feeChargesWaived, penaltyChargesWaived, unrecognizedIncome, externalId);
|
||||
final LoanChargePaidBy loanChargePaidBy = new LoanChargePaidBy(waiveLoanChargeTransaction, loanCharge,
|
||||
waiveLoanChargeTransaction.getAmount(getCurrency()).getAmount(), loanInstallmentNumber);
|
||||
waiveLoanChargeTransaction.getLoanChargesPaid().add(loanChargePaidBy);
|
||||
@@ -1332,12 +1338,18 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
private void updateAccrualsForNonPeriodicAccruals(final Collection<LoanTransaction> accruals) {
|
||||
|
||||
final Money interestApplied = Money.of(getCurrency(), this.summary.getTotalInterestCharged());
|
||||
ExternalId externalId = ExternalId.empty();
|
||||
boolean isExternalIdAutoGenerationEnabled = TemporaryConfigurationServiceContainer.isExternalIdAutoGenerationEnabled();
|
||||
|
||||
for (LoanTransaction loanTransaction : accruals) {
|
||||
if (loanTransaction.getInterestPortion(getCurrency()).isGreaterThanZero()) {
|
||||
if (loanTransaction.getInterestPortion(getCurrency()).isNotEqualTo(interestApplied)) {
|
||||
loanTransaction.reverse();
|
||||
if (isExternalIdAutoGenerationEnabled) {
|
||||
externalId = ExternalId.generate();
|
||||
}
|
||||
final LoanTransaction interestAppliedTransaction = LoanTransaction.accrueInterest(getOffice(), this, interestApplied,
|
||||
getDisbursementDate());
|
||||
getDisbursementDate(), externalId);
|
||||
addLoanTransaction(interestAppliedTransaction);
|
||||
}
|
||||
} else {
|
||||
@@ -2457,8 +2469,12 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
|
||||
if (((isMultiDisburmentLoan() && getDisbursedLoanDisbursementDetails().size() == 1) || !isMultiDisburmentLoan())
|
||||
&& isNoneOrCashOrUpfrontAccrualAccountingEnabledOnLoanProduct()) {
|
||||
ExternalId externalId = ExternalId.empty();
|
||||
if (TemporaryConfigurationServiceContainer.isExternalIdAutoGenerationEnabled()) {
|
||||
externalId = ExternalId.generate();
|
||||
}
|
||||
final LoanTransaction interestAppliedTransaction = LoanTransaction.accrueInterest(getOffice(), this, interestApplied,
|
||||
actualDisbursementDate);
|
||||
actualDisbursementDate, externalId);
|
||||
addLoanTransaction(interestAppliedTransaction);
|
||||
}
|
||||
|
||||
@@ -3415,6 +3431,10 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
private void processIncomeAccrualTransactionOnLoanClosure() {
|
||||
if (this.loanInterestRecalculationDetails != null && this.loanInterestRecalculationDetails.isCompoundingToBePostedAsTransaction()
|
||||
&& this.getStatus().isClosedObligationsMet()) {
|
||||
|
||||
ExternalId externalId = ExternalId.empty();
|
||||
boolean isExternalIdAutoGenerationEnabled = TemporaryConfigurationServiceContainer.isExternalIdAutoGenerationEnabled();
|
||||
|
||||
LocalDate closedDate = this.getClosedOnDate();
|
||||
reverseTransactionsOnOrAfter(retrieveListOfIncomePostingTransactions(), closedDate);
|
||||
reverseTransactionsOnOrAfter(retrieveListOfAccrualTransactions(), closedDate);
|
||||
@@ -3428,8 +3448,11 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
BigDecimal penaltyToPost = cumulativeIncomeFromInstallments.get(PENALTY)
|
||||
.subtract(cumulativeIncomeFromIncomePosting.get(PENALTY));
|
||||
BigDecimal amountToPost = interestToPost.add(feeToPost).add(penaltyToPost);
|
||||
if (isExternalIdAutoGenerationEnabled) {
|
||||
externalId = ExternalId.generate();
|
||||
}
|
||||
LoanTransaction finalIncomeTransaction = LoanTransaction.incomePosting(this, this.getOffice(), closedDate, amountToPost,
|
||||
interestToPost, feeToPost, penaltyToPost);
|
||||
interestToPost, feeToPost, penaltyToPost, externalId);
|
||||
addLoanTransaction(finalIncomeTransaction);
|
||||
if (isPeriodicAccrualAccountingEnabledOnLoanProduct()) {
|
||||
List<LoanTransaction> updatedAccrualTransactions = retrieveListOfAccrualTransactions();
|
||||
@@ -3439,8 +3462,11 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
}
|
||||
HashMap<String, Object> feeDetails = new HashMap<>();
|
||||
determineFeeDetails(lastAccruedDate, closedDate, feeDetails);
|
||||
if (isExternalIdAutoGenerationEnabled) {
|
||||
externalId = ExternalId.generate();
|
||||
}
|
||||
LoanTransaction finalAccrual = LoanTransaction.accrueTransaction(this, this.getOffice(), closedDate, amountToPost,
|
||||
interestToPost, feeToPost, penaltyToPost);
|
||||
interestToPost, feeToPost, penaltyToPost, externalId);
|
||||
updateLoanChargesPaidBy(finalAccrual, feeDetails, null);
|
||||
addLoanTransaction(finalAccrual);
|
||||
}
|
||||
@@ -3596,13 +3622,13 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
}
|
||||
|
||||
return LoanTransaction.waiver(getOffice(), this, possibleInterestToWaive, transactionDate, possibleInterestToWaive,
|
||||
possibleInterestToWaive.zero());
|
||||
possibleInterestToWaive.zero(), ExternalId.empty());
|
||||
}
|
||||
|
||||
public ChangedTransactionDetail adjustExistingTransaction(final LoanTransaction newTransactionDetail,
|
||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final LoanTransaction transactionForAdjustment,
|
||||
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds,
|
||||
final ScheduleGeneratorDTO scheduleGeneratorDTO, final String reversalExternalId) {
|
||||
final ScheduleGeneratorDTO scheduleGeneratorDTO, final ExternalId reversalExternalId) {
|
||||
|
||||
HolidayDetailDTO holidayDetailDTO = scheduleGeneratorDTO.getHolidayDetailDTO();
|
||||
validateActivityNotBeforeLastTransactionDate(LoanEvent.LOAN_REPAYMENT_OR_WAIVER, transactionForAdjustment.getTransactionDate());
|
||||
@@ -3752,11 +3778,18 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
final LocalDate writtenOffOnLocalDate = command.localDateValueOfParameterNamed(TRANSACTION_DATE);
|
||||
final String txnExternalId = command.stringValueOfParameterNamedAllowingNull(EXTERNAL_ID);
|
||||
|
||||
ExternalId externalId = StringUtils.isBlank(txnExternalId) ? ExternalId.empty() : new ExternalId(txnExternalId);
|
||||
|
||||
if (externalId.isEmpty() && TemporaryConfigurationServiceContainer.isExternalIdAutoGenerationEnabled()) {
|
||||
externalId = ExternalId.generate();
|
||||
}
|
||||
|
||||
this.closedOnDate = writtenOffOnLocalDate;
|
||||
this.writtenOffOnDate = writtenOffOnLocalDate;
|
||||
this.closedBy = currentUser;
|
||||
changes.put(CLOSED_ON_DATE, command.stringValueOfParameterNamed(TRANSACTION_DATE));
|
||||
changes.put(WRITTEN_OFF_ON_DATE, command.stringValueOfParameterNamed(TRANSACTION_DATE));
|
||||
changes.put("externalId", externalId);
|
||||
|
||||
if (writtenOffOnLocalDate.isBefore(getDisbursementDate())) {
|
||||
final String errorMessage = "The date on which a loan is written off cannot be before the loan disbursement date: "
|
||||
@@ -3772,7 +3805,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
throw new InvalidLoanStateTransitionException("writeoff", "cannot.be.a.future.date", errorMessage, writtenOffOnLocalDate);
|
||||
}
|
||||
|
||||
loanTransaction = LoanTransaction.writeoff(this, getOffice(), writtenOffOnLocalDate, txnExternalId);
|
||||
loanTransaction = LoanTransaction.writeoff(this, getOffice(), writtenOffOnLocalDate, externalId);
|
||||
LocalDate lastTransactionDate = getLastUserTransactionDate();
|
||||
if (lastTransactionDate.isAfter(writtenOffOnLocalDate)) {
|
||||
final String errorMessage = "The date of the writeoff transaction must occur on or before previous transactions.";
|
||||
@@ -3839,6 +3872,11 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
final LocalDate closureDate = command.localDateValueOfParameterNamed(TRANSACTION_DATE);
|
||||
final String txnExternalId = command.stringValueOfParameterNamedAllowingNull(EXTERNAL_ID);
|
||||
|
||||
ExternalId externalId = StringUtils.isBlank(txnExternalId) ? ExternalId.empty() : new ExternalId(txnExternalId);
|
||||
if (externalId.isEmpty() && TemporaryConfigurationServiceContainer.isExternalIdAutoGenerationEnabled()) {
|
||||
externalId = ExternalId.generate();
|
||||
}
|
||||
|
||||
this.closedOnDate = closureDate;
|
||||
changes.put(CLOSED_ON_DATE, command.stringValueOfParameterNamed(TRANSACTION_DATE));
|
||||
|
||||
@@ -3870,7 +3908,8 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
changes.put(PARAM_STATUS, LoanEnumerations.status(this.loanStatus));
|
||||
}
|
||||
this.closedOnDate = closureDate;
|
||||
loanTransaction = LoanTransaction.writeoff(this, getOffice(), closureDate, txnExternalId);
|
||||
changes.put("externalId", externalId);
|
||||
loanTransaction = LoanTransaction.writeoff(this, getOffice(), closureDate, externalId);
|
||||
final boolean isLastTransaction = isChronologicallyLatestTransaction(loanTransaction, getLoanTransactions());
|
||||
if (!isLastTransaction) {
|
||||
final String errorMessage = "The closing date of the loan must be on or after latest transaction date.";
|
||||
@@ -5419,27 +5458,36 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
interest = compoundingDetail.getAmount().subtract(fee).subtract(penalties);
|
||||
}
|
||||
|
||||
ExternalId externalId = ExternalId.empty();
|
||||
if (TemporaryConfigurationServiceContainer.isExternalIdAutoGenerationEnabled()) {
|
||||
externalId = ExternalId.generate();
|
||||
}
|
||||
|
||||
if (existingIncomeTransaction == null) {
|
||||
LoanTransaction transaction = LoanTransaction.incomePosting(this, this.getOffice(), compoundingDetail.getEffectiveDate(),
|
||||
compoundingDetail.getAmount(), interest, fee, penalties);
|
||||
compoundingDetail.getAmount(), interest, fee, penalties, externalId);
|
||||
addLoanTransaction(transaction);
|
||||
} else if (existingIncomeTransaction.getAmount(getCurrency()).getAmount().compareTo(compoundingDetail.getAmount()) != 0) {
|
||||
existingIncomeTransaction.reverse();
|
||||
LoanTransaction transaction = LoanTransaction.incomePosting(this, this.getOffice(), compoundingDetail.getEffectiveDate(),
|
||||
compoundingDetail.getAmount(), interest, fee, penalties);
|
||||
compoundingDetail.getAmount(), interest, fee, penalties, externalId);
|
||||
addLoanTransaction(transaction);
|
||||
}
|
||||
|
||||
if (TemporaryConfigurationServiceContainer.isExternalIdAutoGenerationEnabled()) {
|
||||
externalId = ExternalId.generate();
|
||||
}
|
||||
|
||||
if (isPeriodicAccrualAccountingEnabledOnLoanProduct()) {
|
||||
if (existingAccrualTransaction == null) {
|
||||
LoanTransaction accrual = LoanTransaction.accrueTransaction(this, this.getOffice(), compoundingDetail.getEffectiveDate(),
|
||||
compoundingDetail.getAmount(), interest, fee, penalties);
|
||||
compoundingDetail.getAmount(), interest, fee, penalties, externalId);
|
||||
updateLoanChargesPaidBy(accrual, feeDetails, null);
|
||||
addLoanTransaction(accrual);
|
||||
} else if (existingAccrualTransaction.getAmount(getCurrency()).getAmount().compareTo(compoundingDetail.getAmount()) != 0) {
|
||||
existingAccrualTransaction.reverse();
|
||||
LoanTransaction accrual = LoanTransaction.accrueTransaction(this, this.getOffice(), compoundingDetail.getEffectiveDate(),
|
||||
compoundingDetail.getAmount(), interest, fee, penalties);
|
||||
compoundingDetail.getAmount(), interest, fee, penalties, externalId);
|
||||
updateLoanChargesPaidBy(accrual, feeDetails, null);
|
||||
addLoanTransaction(accrual);
|
||||
}
|
||||
|
||||
+13
-12
@@ -23,32 +23,33 @@ import java.time.LocalDate;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.HolidayDetailDTO;
|
||||
import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
|
||||
|
||||
public interface LoanAccountDomainService {
|
||||
|
||||
LoanTransaction makeRepayment(LoanTransactionType repaymentTransactionType, Loan loan, CommandProcessingResultBuilder builderResult,
|
||||
LocalDate transactionDate, BigDecimal transactionAmount, PaymentDetail paymentDetail, String noteText, String txnExternalId,
|
||||
LoanTransaction makeRepayment(LoanTransactionType repaymentTransactionType, Loan loan, LocalDate transactionDate,
|
||||
BigDecimal transactionAmount, PaymentDetail paymentDetail, String noteText, ExternalId txnExternalId,
|
||||
boolean isRecoveryRepayment, String chargeRefundChargeType, boolean isAccountTransfer, HolidayDetailDTO holidayDetailDto,
|
||||
Boolean isHolidayValidationDone);
|
||||
|
||||
LoanTransaction makeRefund(Long accountId, CommandProcessingResultBuilder builderResult, LocalDate transactionDate,
|
||||
BigDecimal transactionAmount, PaymentDetail paymentDetail, String noteText, String txnExternalId);
|
||||
BigDecimal transactionAmount, PaymentDetail paymentDetail, String noteText, ExternalId txnExternalId);
|
||||
|
||||
LoanTransaction makeDisburseTransaction(Long loanId, LocalDate transactionDate, BigDecimal transactionAmount,
|
||||
PaymentDetail paymentDetail, String noteText, String txnExternalId, boolean isLoanToLoanTransfer);
|
||||
PaymentDetail paymentDetail, String noteText, ExternalId txnExternalId, boolean isLoanToLoanTransfer);
|
||||
|
||||
void reverseTransfer(LoanTransaction loanTransaction);
|
||||
|
||||
LoanTransaction makeChargePayment(Loan loan, Long chargeId, LocalDate transactionDate, BigDecimal transactionAmount,
|
||||
PaymentDetail paymentDetail, String noteText, String txnExternalId, Integer transactionType, Integer installmentNumber);
|
||||
PaymentDetail paymentDetail, String noteText, ExternalId txnExternalId, Integer transactionType, Integer installmentNumber);
|
||||
|
||||
LoanTransaction makeDisburseTransaction(Long loanId, LocalDate transactionDate, BigDecimal transactionAmount,
|
||||
PaymentDetail paymentDetail, String noteText, String txnExternalId);
|
||||
PaymentDetail paymentDetail, String noteText, ExternalId txnExternalId);
|
||||
|
||||
LoanTransaction makeRefundForActiveLoan(Long accountId, CommandProcessingResultBuilder builderResult, LocalDate transactionDate,
|
||||
BigDecimal transactionAmount, PaymentDetail paymentDetail, String noteText, String txnExternalId);
|
||||
BigDecimal transactionAmount, PaymentDetail paymentDetail, String noteText, ExternalId txnExternalId);
|
||||
|
||||
void updateLoanCollateralTransaction(Set<LoanCollateralManagement> loanCollateralManagementList);
|
||||
|
||||
@@ -71,8 +72,8 @@ public interface LoanAccountDomainService {
|
||||
*/
|
||||
void setLoanDelinquencyTag(Loan loan, LocalDate transactionDate);
|
||||
|
||||
LoanTransaction makeRepayment(LoanTransactionType repaymentTransactionType, Loan loan, CommandProcessingResultBuilder builderResult,
|
||||
LocalDate transactionDate, BigDecimal transactionAmount, PaymentDetail paymentDetail, String noteText, String txnExternalId,
|
||||
LoanTransaction makeRepayment(LoanTransactionType repaymentTransactionType, Loan loan, LocalDate transactionDate,
|
||||
BigDecimal transactionAmount, PaymentDetail paymentDetail, String noteText, ExternalId txnExternalId,
|
||||
boolean isRecoveryRepayment, String chargeRefundChargeType, boolean isAccountTransfer, HolidayDetailDTO holidayDetailDto,
|
||||
Boolean isHolidayValidationDone, boolean isLoanToLoanTransfer);
|
||||
|
||||
@@ -82,7 +83,7 @@ public interface LoanAccountDomainService {
|
||||
|
||||
void saveLoanWithDataIntegrityViolationChecks(Loan loan);
|
||||
|
||||
Map<String, Object> foreCloseLoan(Loan loan, LocalDate foreClourseDate, String noteText);
|
||||
Map<String, Object> foreCloseLoan(Loan loan, LocalDate foreClourseDate, String noteText, ExternalId externalId);
|
||||
|
||||
/**
|
||||
* Disables all standing instructions linked to a closed loan
|
||||
@@ -94,6 +95,6 @@ public interface LoanAccountDomainService {
|
||||
|
||||
void recalculateAccruals(Loan loan, boolean isInterestCalcualtionHappened);
|
||||
|
||||
CommandProcessingResultBuilder creditBalanceRefund(Long loanId, LocalDate transactionDate, BigDecimal transactionAmount,
|
||||
String noteText, String externalId);
|
||||
LoanTransaction creditBalanceRefund(Loan loan, LocalDate transactionDate, BigDecimal transactionAmount, String noteText,
|
||||
ExternalId externalId);
|
||||
}
|
||||
|
||||
+26
-30
@@ -34,10 +34,12 @@ import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDoma
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
|
||||
import org.apache.fineract.infrastructure.core.exception.MultiException;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanBalanceChangedBusinessEvent;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanBusinessEvent;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanChargePaymentPostBusinessEvent;
|
||||
@@ -124,17 +126,16 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
private final LoanCollateralManagementRepository loanCollateralManagementRepository;
|
||||
private final DelinquencyWritePlatformService delinquencyWritePlatformService;
|
||||
private final LoanLifecycleStateMachine defaultLoanLifecycleStateMachine;
|
||||
private final ExternalIdFactory externalIdFactory;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public LoanTransaction makeRepayment(final LoanTransactionType repaymentTransactionType, final Loan loan,
|
||||
final CommandProcessingResultBuilder builderResult, final LocalDate transactionDate, final BigDecimal transactionAmount,
|
||||
final PaymentDetail paymentDetail, final String noteText, final String txnExternalId, final boolean isRecoveryRepayment,
|
||||
final String chargeRefundChargeType, boolean isAccountTransfer, HolidayDetailDTO holidayDetailDto,
|
||||
Boolean isHolidayValidationDone) {
|
||||
return makeRepayment(repaymentTransactionType, loan, builderResult, transactionDate, transactionAmount, paymentDetail, noteText,
|
||||
txnExternalId, isRecoveryRepayment, chargeRefundChargeType, isAccountTransfer, holidayDetailDto, isHolidayValidationDone,
|
||||
false);
|
||||
final LocalDate transactionDate, final BigDecimal transactionAmount, final PaymentDetail paymentDetail, final String noteText,
|
||||
final ExternalId txnExternalId, final boolean isRecoveryRepayment, final String chargeRefundChargeType,
|
||||
boolean isAccountTransfer, HolidayDetailDTO holidayDetailDto, Boolean isHolidayValidationDone) {
|
||||
return makeRepayment(repaymentTransactionType, loan, transactionDate, transactionAmount, paymentDetail, noteText, txnExternalId,
|
||||
isRecoveryRepayment, chargeRefundChargeType, isAccountTransfer, holidayDetailDto, isHolidayValidationDone, false);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -155,10 +156,10 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
@Transactional
|
||||
@Override
|
||||
public LoanTransaction makeRepayment(final LoanTransactionType repaymentTransactionType, final Loan loan,
|
||||
final CommandProcessingResultBuilder builderResult, final LocalDate transactionDate, final BigDecimal transactionAmount,
|
||||
final PaymentDetail paymentDetail, final String noteText, final String txnExternalId, final boolean isRecoveryRepayment,
|
||||
final String chargeRefundChargeType, boolean isAccountTransfer, HolidayDetailDTO holidayDetailDto,
|
||||
Boolean isHolidayValidationDone, final boolean isLoanToLoanTransfer) {
|
||||
final LocalDate transactionDate, final BigDecimal transactionAmount, final PaymentDetail paymentDetail, final String noteText,
|
||||
final ExternalId txnExternalId, final boolean isRecoveryRepayment, final String chargeRefundChargeType,
|
||||
boolean isAccountTransfer, HolidayDetailDTO holidayDetailDto, Boolean isHolidayValidationDone,
|
||||
final boolean isLoanToLoanTransfer) {
|
||||
checkClientOrGroupActive(loan);
|
||||
|
||||
LoanBusinessEvent repaymentEvent = getLoanRepaymentTypeBusinessEvent(repaymentTransactionType, isRecoveryRepayment, loan);
|
||||
@@ -177,7 +178,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
|
||||
final Money repaymentAmount = Money.of(loan.getCurrency(), transactionAmount);
|
||||
LoanTransaction newRepaymentTransaction = null;
|
||||
LoanTransaction newRepaymentTransaction;
|
||||
if (isRecoveryRepayment) {
|
||||
newRepaymentTransaction = LoanTransaction.recoveryRepayment(loan.getOffice(), repaymentAmount, paymentDetail, transactionDate,
|
||||
txnExternalId);
|
||||
@@ -238,9 +239,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
// changes to closed
|
||||
disableStandingInstructionsLinkedToClosedLoan(loan);
|
||||
|
||||
builderResult.withEntityId(newRepaymentTransaction.getId()).withOfficeId(loan.getOfficeId()).withClientId(loan.getClientId())
|
||||
.withGroupId(loan.getGroupId());
|
||||
|
||||
if (AccountType.fromInt(loan.getLoanType()).isIndividualAccount()) {
|
||||
// Mark Post Dated Check as paid.
|
||||
final Set<LoanTransactionToRepaymentScheduleMapping> loanTransactionToRepaymentScheduleMappings = newRepaymentTransaction
|
||||
@@ -358,7 +356,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
@Override
|
||||
@Transactional
|
||||
public LoanTransaction makeChargePayment(final Loan loan, final Long chargeId, final LocalDate transactionDate,
|
||||
final BigDecimal transactionAmount, final PaymentDetail paymentDetail, final String noteText, final String txnExternalId,
|
||||
final BigDecimal transactionAmount, final PaymentDetail paymentDetail, final String noteText, final ExternalId txnExternalId,
|
||||
final Integer transactionType, Integer installmentNumber) {
|
||||
boolean isAccountTransfer = true;
|
||||
checkClientOrGroupActive(loan);
|
||||
@@ -437,7 +435,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
@Override
|
||||
public LoanTransaction makeRefund(final Long accountId, final CommandProcessingResultBuilder builderResult,
|
||||
final LocalDate transactionDate, final BigDecimal transactionAmount, final PaymentDetail paymentDetail, final String noteText,
|
||||
final String txnExternalId) {
|
||||
final ExternalId txnExternalId) {
|
||||
boolean isAccountTransfer = true;
|
||||
final Loan loan = this.loanAccountAssembler.assembleFrom(accountId);
|
||||
checkClientOrGroupActive(loan);
|
||||
@@ -477,14 +475,14 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
@Transactional
|
||||
@Override
|
||||
public LoanTransaction makeDisburseTransaction(final Long loanId, final LocalDate transactionDate, final BigDecimal transactionAmount,
|
||||
final PaymentDetail paymentDetail, final String noteText, final String txnExternalId) {
|
||||
final PaymentDetail paymentDetail, final String noteText, final ExternalId txnExternalId) {
|
||||
return makeDisburseTransaction(loanId, transactionDate, transactionAmount, paymentDetail, noteText, txnExternalId, false);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public LoanTransaction makeDisburseTransaction(final Long loanId, final LocalDate transactionDate, final BigDecimal transactionAmount,
|
||||
final PaymentDetail paymentDetail, final String noteText, final String txnExternalId, final boolean isLoanToLoanTransfer) {
|
||||
final PaymentDetail paymentDetail, final String noteText, final ExternalId txnExternalId, final boolean isLoanToLoanTransfer) {
|
||||
final Loan loan = this.loanAccountAssembler.assembleFrom(loanId);
|
||||
checkClientOrGroupActive(loan);
|
||||
boolean isAccountTransfer = true;
|
||||
@@ -636,9 +634,8 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResultBuilder creditBalanceRefund(Long loanId, LocalDate transactionDate, BigDecimal transactionAmount,
|
||||
String noteText, String externalId) {
|
||||
final Loan loan = this.loanAccountAssembler.assembleFrom(loanId);
|
||||
public LoanTransaction creditBalanceRefund(final Loan loan, final LocalDate transactionDate, final BigDecimal transactionAmount,
|
||||
final String noteText, final ExternalId externalId) {
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanCreditBalanceRefundPreBusinessEvent(loan));
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
@@ -663,15 +660,12 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
businessEventNotifierService
|
||||
.notifyPostBusinessEvent(new LoanCreditBalanceRefundPostBusinessEvent(newCreditBalanceRefundTransaction));
|
||||
|
||||
return new CommandProcessingResultBuilder().withEntityId(newCreditBalanceRefundTransaction.getId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId());
|
||||
return newCreditBalanceRefundTransaction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoanTransaction makeRefundForActiveLoan(Long accountId, CommandProcessingResultBuilder builderResult, LocalDate transactionDate,
|
||||
BigDecimal transactionAmount, PaymentDetail paymentDetail, String noteText, String txnExternalId) {
|
||||
BigDecimal transactionAmount, PaymentDetail paymentDetail, String noteText, ExternalId txnExternalId) {
|
||||
final Loan loan = this.loanAccountAssembler.assembleFrom(accountId);
|
||||
checkClientOrGroupActive(loan);
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanRefundPreBusinessEvent(loan));
|
||||
@@ -709,7 +703,8 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> foreCloseLoan(final Loan loan, final LocalDate foreClosureDate, final String noteText) {
|
||||
public Map<String, Object> foreCloseLoan(final Loan loan, final LocalDate foreClosureDate, final String noteText,
|
||||
final ExternalId externalId) {
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanForeClosurePreBusinessEvent(loan));
|
||||
MonetaryCurrency currency = loan.getCurrency();
|
||||
final Map<String, Object> changes = new LinkedHashMap<>();
|
||||
@@ -730,8 +725,10 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
Money penaltyPortion = foreCloseDetail.getPenaltyChargesCharged(currency).minus(accruedReceivables[2]);
|
||||
Money total = interestPortion.plus(feePortion).plus(penaltyPortion);
|
||||
if (total.isGreaterThanZero()) {
|
||||
ExternalId accrualExternalId = externalIdFactory.create();
|
||||
LoanTransaction accrualTransaction = LoanTransaction.accrueTransaction(loan, loan.getOffice(), foreClosureDate,
|
||||
total.getAmount(), interestPortion.getAmount(), feePortion.getAmount(), penaltyPortion.getAmount());
|
||||
total.getAmount(), interestPortion.getAmount(), feePortion.getAmount(), penaltyPortion.getAmount(),
|
||||
accrualExternalId);
|
||||
LocalDate fromDate = loan.getDisbursementDate();
|
||||
if (loan.getAccruedTill() != null) {
|
||||
fromDate = loan.getAccruedTill();
|
||||
@@ -761,7 +758,6 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
|
||||
if (payPrincipal.plus(interestPayable).plus(feePayable).plus(penaltyPayable).isGreaterThanZero()) {
|
||||
final PaymentDetail paymentDetail = null;
|
||||
String externalId = null;
|
||||
payment = LoanTransaction.repayment(loan.getOffice(), payPrincipal.plus(interestPayable).plus(feePayable).plus(penaltyPayable),
|
||||
paymentDetail, foreClosureDate, externalId);
|
||||
payment.updateLoan(loan);
|
||||
|
||||
+4
@@ -75,6 +75,8 @@ public interface LoanRepository extends JpaRepository<Loan, Long>, JpaSpecificat
|
||||
|
||||
String FIND_BY_ACCOUNT_NUMBER = "select loan from Loan loan where loan.accountNumber = :accountNumber";
|
||||
|
||||
String FIND_ID_BY_EXTERNAL_ID = "SELECT loan.id FROM Loan loan WHERE loan.externalId = :externalId";
|
||||
|
||||
@Query(FIND_GROUP_LOANS_DISBURSED_AFTER)
|
||||
List<Loan> getGroupLoansDisbursedAfter(@Param("disbursementDate") LocalDate disbursementDate, @Param("groupId") Long groupId,
|
||||
@Param("loanType") Integer loanType);
|
||||
@@ -168,4 +170,6 @@ public interface LoanRepository extends JpaRepository<Loan, Long>, JpaSpecificat
|
||||
@Query(FIND_ALL_NON_CLOSED)
|
||||
List<Long> findAllNonClosedLoanIds();
|
||||
|
||||
@Query(FIND_ID_BY_EXTERNAL_ID)
|
||||
Long findIdByExternalId(@Param("externalId") String externalId);
|
||||
}
|
||||
|
||||
+6
-4
@@ -62,8 +62,7 @@ public class LoanRepositoryWrapper {
|
||||
public Collection<Loan> findActiveLoansByLoanIdAndGroupId(Long clientId, Long groupId) {
|
||||
final Collection<Integer> loanStatuses = new ArrayList<>(Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.getValue(),
|
||||
LoanStatus.APPROVED.getValue(), LoanStatus.ACTIVE.getValue(), LoanStatus.OVERPAID.getValue()));
|
||||
final Collection<Loan> loans = this.repository.findByClientIdAndGroupIdAndLoanStatus(clientId, groupId, loanStatuses);
|
||||
return loans;
|
||||
return this.repository.findByClientIdAndGroupIdAndLoanStatus(clientId, groupId, loanStatuses);
|
||||
}
|
||||
|
||||
public Loan saveAndFlush(final Loan loan) {
|
||||
@@ -114,8 +113,7 @@ public class LoanRepositoryWrapper {
|
||||
|
||||
public List<LoanRepaymentScheduleInstallment> getLoanRepaymentScheduleInstallments(final Long loanId) {
|
||||
final Loan loan = this.repository.findById(loanId).orElseThrow(() -> new LoanNotFoundException(loanId));
|
||||
final List<LoanRepaymentScheduleInstallment> loanRepaymentScheduleInstallments = loan.getRepaymentScheduleInstallments();
|
||||
return loanRepaymentScheduleInstallments;
|
||||
return loan.getRepaymentScheduleInstallments();
|
||||
}
|
||||
|
||||
public Integer getNumberOfRepayments(final Long loanId) {
|
||||
@@ -253,4 +251,8 @@ public class LoanRepositoryWrapper {
|
||||
}
|
||||
return loan;
|
||||
}
|
||||
|
||||
public Long findIdByExternalId(String externalId) {
|
||||
return this.repository.findIdByExternalId(externalId);
|
||||
}
|
||||
}
|
||||
|
||||
+45
-41
@@ -38,6 +38,7 @@ import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
@@ -104,10 +105,10 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
private boolean reversed;
|
||||
|
||||
@Column(name = "external_id", length = 100, nullable = true, unique = true)
|
||||
private String externalId;
|
||||
private ExternalId externalId;
|
||||
|
||||
@Column(name = "reversal_external_id", length = 100, nullable = true, unique = true)
|
||||
private String reversalExternalId;
|
||||
private ExternalId reversalExternalId;
|
||||
|
||||
@Column(name = "reversed_on_date", nullable = true)
|
||||
private LocalDate reversedOnDate;
|
||||
@@ -136,30 +137,30 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
protected LoanTransaction() {}
|
||||
|
||||
public static LoanTransaction incomePosting(final Loan loan, final Office office, final LocalDate dateOf, final BigDecimal amount,
|
||||
final BigDecimal interestPortion, final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion) {
|
||||
final BigDecimal interestPortion, final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion,
|
||||
final ExternalId externalId) {
|
||||
final Integer typeOf = LoanTransactionType.INCOME_POSTING.getValue();
|
||||
final BigDecimal principalPortion = BigDecimal.ZERO;
|
||||
final BigDecimal overPaymentPortion = BigDecimal.ZERO;
|
||||
final boolean reversed = false;
|
||||
final PaymentDetail paymentDetail = null;
|
||||
final String externalId = null;
|
||||
return new LoanTransaction(loan, office, typeOf, dateOf, amount, principalPortion, interestPortion, feeChargesPortion,
|
||||
penaltyChargesPortion, overPaymentPortion, reversed, paymentDetail, externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction disbursement(final Office office, final Money amount, final PaymentDetail paymentDetail,
|
||||
final LocalDate disbursementDate, final String externalId) {
|
||||
final LocalDate disbursementDate, final ExternalId externalId) {
|
||||
return new LoanTransaction(null, office, LoanTransactionType.DISBURSEMENT, paymentDetail, amount.getAmount(), disbursementDate,
|
||||
externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction repayment(final Office office, final Money amount, final PaymentDetail paymentDetail,
|
||||
final LocalDate paymentDate, final String externalId) {
|
||||
final LocalDate paymentDate, final ExternalId externalId) {
|
||||
return new LoanTransaction(null, office, LoanTransactionType.REPAYMENT, paymentDetail, amount.getAmount(), paymentDate, externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction chargeback(final Office office, final Money amount, final PaymentDetail paymentDetail,
|
||||
final LocalDate paymentDate, final String externalId) {
|
||||
final LocalDate paymentDate, final ExternalId externalId) {
|
||||
LoanTransaction loanTransaction = new LoanTransaction(null, office, LoanTransactionType.CHARGEBACK, paymentDetail,
|
||||
amount.getAmount(), paymentDate, externalId);
|
||||
loanTransaction.principalPortion = amount.getAmount();
|
||||
@@ -167,13 +168,14 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
}
|
||||
|
||||
public static LoanTransaction repaymentType(final LoanTransactionType repaymentType, final Office office, final Money amount,
|
||||
final PaymentDetail paymentDetail, final LocalDate paymentDate, final String externalId, final String chargeRefundChargeType) {
|
||||
final PaymentDetail paymentDetail, final LocalDate paymentDate, final ExternalId externalId,
|
||||
final String chargeRefundChargeType) {
|
||||
return new LoanTransaction(null, office, repaymentType, paymentDetail, amount.getAmount(), paymentDate, externalId,
|
||||
chargeRefundChargeType);
|
||||
}
|
||||
|
||||
public static LoanTransaction chargeAdjustment(final Loan loan, final BigDecimal amount, final LocalDate transactionDate,
|
||||
final String externalId) {
|
||||
final ExternalId externalId) {
|
||||
return new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.CHARGE_ADJUSTMENT, amount, transactionDate, externalId);
|
||||
}
|
||||
|
||||
@@ -189,32 +191,32 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
}
|
||||
|
||||
public static LoanTransaction recoveryRepayment(final Office office, final Money amount, final PaymentDetail paymentDetail,
|
||||
final LocalDate paymentDate, final String externalId) {
|
||||
final LocalDate paymentDate, final ExternalId externalId) {
|
||||
return new LoanTransaction(null, office, LoanTransactionType.RECOVERY_REPAYMENT, paymentDetail, amount.getAmount(), paymentDate,
|
||||
externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction loanPayment(final Loan loan, final Office office, final Money amount, final PaymentDetail paymentDetail,
|
||||
final LocalDate paymentDate, final String externalId, final LoanTransactionType transactionType) {
|
||||
final LocalDate paymentDate, final ExternalId externalId, final LoanTransactionType transactionType) {
|
||||
return new LoanTransaction(loan, office, transactionType, paymentDetail, amount.getAmount(), paymentDate, externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction repaymentAtDisbursement(final Office office, final Money amount, final PaymentDetail paymentDetail,
|
||||
final LocalDate paymentDate, final String externalId) {
|
||||
final LocalDate paymentDate, final ExternalId externalId) {
|
||||
return new LoanTransaction(null, office, LoanTransactionType.REPAYMENT_AT_DISBURSEMENT, paymentDetail, amount.getAmount(),
|
||||
paymentDate, externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction waiver(final Office office, final Loan loan, final Money amount, final LocalDate waiveDate,
|
||||
final Money waived, final Money unrecognizedPortion) {
|
||||
final Money waived, final Money unrecognizedPortion, final ExternalId externalId) {
|
||||
LoanTransaction loanTransaction = new LoanTransaction(loan, office, LoanTransactionType.WAIVE_INTEREST, amount.getAmount(),
|
||||
waiveDate, null);
|
||||
waiveDate, externalId);
|
||||
loanTransaction.updateInterestComponent(waived, unrecognizedPortion);
|
||||
return loanTransaction;
|
||||
}
|
||||
|
||||
public static LoanTransaction accrueInterest(final Office office, final Loan loan, final Money amount,
|
||||
final LocalDate interestAppliedDate) {
|
||||
final LocalDate interestAppliedDate, final ExternalId externalId) {
|
||||
BigDecimal principalPortion = null;
|
||||
BigDecimal feesPortion = null;
|
||||
BigDecimal penaltiesPortion = null;
|
||||
@@ -222,51 +224,53 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
BigDecimal overPaymentPortion = null;
|
||||
boolean reversed = false;
|
||||
PaymentDetail paymentDetail = null;
|
||||
String externalId = null;
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.ACCRUAL.getValue(), interestAppliedDate, interestPortion,
|
||||
principalPortion, interestPortion, feesPortion, penaltiesPortion, overPaymentPortion, reversed, paymentDetail, externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction accrual(final Loan loan, final Office office, final Money amount, final Money interest,
|
||||
final Money feeCharges, final Money penaltyCharges, final LocalDate transactionDate) {
|
||||
final Money feeCharges, final Money penaltyCharges, final LocalDate transactionDate, final ExternalId externalId) {
|
||||
return accrueTransaction(loan, office, transactionDate, amount.getAmount(), interest.getAmount(), feeCharges.getAmount(),
|
||||
penaltyCharges.getAmount());
|
||||
penaltyCharges.getAmount(), externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction accrueTransaction(final Loan loan, final Office office, final LocalDate dateOf, final BigDecimal amount,
|
||||
final BigDecimal interestPortion, final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion) {
|
||||
final BigDecimal interestPortion, final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion,
|
||||
final ExternalId externalId) {
|
||||
BigDecimal principalPortion = null;
|
||||
BigDecimal overPaymentPortion = null;
|
||||
boolean reversed = false;
|
||||
PaymentDetail paymentDetail = null;
|
||||
String externalId = null;
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.ACCRUAL.getValue(), dateOf, amount, principalPortion, interestPortion,
|
||||
feeChargesPortion, penaltyChargesPortion, overPaymentPortion, reversed, paymentDetail, externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction initiateTransfer(final Office office, final Loan loan, final LocalDate transferDate) {
|
||||
public static LoanTransaction initiateTransfer(final Office office, final Loan loan, final LocalDate transferDate,
|
||||
final ExternalId externalId) {
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.INITIATE_TRANSFER.getValue(), transferDate,
|
||||
loan.getSummary().getTotalOutstanding(), loan.getSummary().getTotalPrincipalOutstanding(),
|
||||
loan.getSummary().getTotalInterestOutstanding(), loan.getSummary().getTotalFeeChargesOutstanding(),
|
||||
loan.getSummary().getTotalPenaltyChargesOutstanding(), null, false, null, null);
|
||||
loan.getSummary().getTotalPenaltyChargesOutstanding(), null, false, null, externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction approveTransfer(final Office office, final Loan loan, final LocalDate transferDate) {
|
||||
public static LoanTransaction approveTransfer(final Office office, final Loan loan, final LocalDate transferDate,
|
||||
final ExternalId externalId) {
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.APPROVE_TRANSFER.getValue(), transferDate,
|
||||
loan.getSummary().getTotalOutstanding(), loan.getSummary().getTotalPrincipalOutstanding(),
|
||||
loan.getSummary().getTotalInterestOutstanding(), loan.getSummary().getTotalFeeChargesOutstanding(),
|
||||
loan.getSummary().getTotalPenaltyChargesOutstanding(), null, false, null, null);
|
||||
loan.getSummary().getTotalPenaltyChargesOutstanding(), null, false, null, externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction withdrawTransfer(final Office office, final Loan loan, final LocalDate transferDate) {
|
||||
public static LoanTransaction withdrawTransfer(final Office office, final Loan loan, final LocalDate transferDate,
|
||||
final ExternalId externalId) {
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.WITHDRAW_TRANSFER.getValue(), transferDate,
|
||||
loan.getSummary().getTotalOutstanding(), loan.getSummary().getTotalPrincipalOutstanding(),
|
||||
loan.getSummary().getTotalInterestOutstanding(), loan.getSummary().getTotalFeeChargesOutstanding(),
|
||||
loan.getSummary().getTotalPenaltyChargesOutstanding(), null, false, null, null);
|
||||
loan.getSummary().getTotalPenaltyChargesOutstanding(), null, false, null, externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction refund(final Office office, final Money amount, final PaymentDetail paymentDetail,
|
||||
final LocalDate paymentDate, final String externalId) {
|
||||
final LocalDate paymentDate, final ExternalId externalId) {
|
||||
return new LoanTransaction(null, office, LoanTransactionType.REFUND, paymentDetail, amount.getAmount(), paymentDate, externalId);
|
||||
}
|
||||
|
||||
@@ -278,8 +282,7 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
}
|
||||
|
||||
public static LoanTransaction accrueLoanCharge(final Loan loan, final Office office, final Money amount, final LocalDate applyDate,
|
||||
final Money feeCharges, final Money penaltyCharges) {
|
||||
String externalId = null;
|
||||
final Money feeCharges, final Money penaltyCharges, final ExternalId externalId) {
|
||||
final LoanTransaction applyCharge = new LoanTransaction(loan, office, LoanTransactionType.ACCRUAL, amount.getAmount(), applyDate,
|
||||
externalId);
|
||||
applyCharge.updateChargesComponents(feeCharges, penaltyCharges);
|
||||
@@ -287,14 +290,14 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
}
|
||||
|
||||
public static LoanTransaction creditBalanceRefund(final Loan loan, final Office office, final Money amount, final LocalDate paymentDate,
|
||||
final String externalId) {
|
||||
final ExternalId externalId) {
|
||||
final PaymentDetail paymentDetail = null;
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.CREDIT_BALANCE_REFUND, paymentDetail, amount.getAmount(), paymentDate,
|
||||
externalId);
|
||||
}
|
||||
|
||||
public static LoanTransaction refundForActiveLoan(final Office office, final Money amount, final PaymentDetail paymentDetail,
|
||||
final LocalDate paymentDate, final String externalId) {
|
||||
final LocalDate paymentDate, final ExternalId externalId) {
|
||||
return new LoanTransaction(null, office, LoanTransactionType.REFUND_FOR_ACTIVE_LOAN, paymentDetail, amount.getAmount(), paymentDate,
|
||||
externalId);
|
||||
}
|
||||
@@ -312,7 +315,7 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
private LoanTransaction(final Loan loan, final Office office, final Integer typeOf, final LocalDate dateOf, final BigDecimal amount,
|
||||
final BigDecimal principalPortion, final BigDecimal interestPortion, final BigDecimal feeChargesPortion,
|
||||
final BigDecimal penaltyChargesPortion, final BigDecimal overPaymentPortion, final boolean reversed,
|
||||
final PaymentDetail paymentDetail, final String externalId) {
|
||||
final PaymentDetail paymentDetail, final ExternalId externalId) {
|
||||
|
||||
this.loan = loan;
|
||||
this.typeOf = typeOf;
|
||||
@@ -331,20 +334,21 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
}
|
||||
|
||||
public static LoanTransaction waiveLoanCharge(final Loan loan, final Office office, final Money waived, final LocalDate waiveDate,
|
||||
final Money feeChargesWaived, final Money penaltyChargesWaived, final Money unrecognizedCharge) {
|
||||
final Money feeChargesWaived, final Money penaltyChargesWaived, final Money unrecognizedCharge, final ExternalId externalId) {
|
||||
final LoanTransaction waiver = new LoanTransaction(loan, office, LoanTransactionType.WAIVE_CHARGES, waived.getAmount(), waiveDate,
|
||||
null);
|
||||
externalId);
|
||||
waiver.updateChargesComponents(feeChargesWaived, penaltyChargesWaived, unrecognizedCharge);
|
||||
|
||||
return waiver;
|
||||
}
|
||||
|
||||
public static LoanTransaction writeoff(final Loan loan, final Office office, final LocalDate writeOffDate, final String externalId) {
|
||||
public static LoanTransaction writeoff(final Loan loan, final Office office, final LocalDate writeOffDate,
|
||||
final ExternalId externalId) {
|
||||
return new LoanTransaction(loan, office, LoanTransactionType.WRITEOFF, null, writeOffDate, externalId);
|
||||
}
|
||||
|
||||
private LoanTransaction(final Loan loan, final Office office, final LoanTransactionType type, final BigDecimal amount,
|
||||
final LocalDate date, final String externalId) {
|
||||
final LocalDate date, final ExternalId externalId) {
|
||||
this.loan = loan;
|
||||
this.typeOf = type.getValue();
|
||||
this.amount = amount;
|
||||
@@ -355,7 +359,7 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
}
|
||||
|
||||
private LoanTransaction(final Loan loan, final Office office, final LoanTransactionType type, final PaymentDetail paymentDetail,
|
||||
final BigDecimal amount, final LocalDate date, final String externalId) {
|
||||
final BigDecimal amount, final LocalDate date, final ExternalId externalId) {
|
||||
this.loan = loan;
|
||||
this.typeOf = type.getValue();
|
||||
this.paymentDetail = paymentDetail;
|
||||
@@ -367,7 +371,7 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
}
|
||||
|
||||
private LoanTransaction(final Loan loan, final Office office, final LoanTransactionType type, final PaymentDetail paymentDetail,
|
||||
final BigDecimal amount, final LocalDate date, final String externalId, final String chargeRefundChargeType) {
|
||||
final BigDecimal amount, final LocalDate date, final ExternalId externalId, final String chargeRefundChargeType) {
|
||||
this.loan = loan;
|
||||
this.typeOf = type.getValue();
|
||||
this.paymentDetail = paymentDetail;
|
||||
@@ -386,7 +390,7 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
this.loanTransactionToRepaymentScheduleMappings.clear();
|
||||
}
|
||||
|
||||
public void reverse(final String reversalExternalId) {
|
||||
public void reverse(final ExternalId reversalExternalId) {
|
||||
this.reverse();
|
||||
this.reversalExternalId = reversalExternalId;
|
||||
}
|
||||
@@ -746,7 +750,7 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
this.loanChargesPaid = loanChargesPaid;
|
||||
}
|
||||
|
||||
public String getExternalId() {
|
||||
public ExternalId getExternalId() {
|
||||
return this.externalId;
|
||||
}
|
||||
|
||||
@@ -758,7 +762,7 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
return LoanTransactionType.CREDIT_BALANCE_REFUND.equals(getTypeOf()) && isNotReversed();
|
||||
}
|
||||
|
||||
public void updateExternalId(final String externalId) {
|
||||
public void updateExternalId(final ExternalId externalId) {
|
||||
this.externalId = externalId;
|
||||
}
|
||||
|
||||
|
||||
+6
@@ -21,13 +21,17 @@ package org.apache.fineract.portfolio.loanaccount.domain;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanScheduleDelinquencyData;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
public interface LoanTransactionRepository extends JpaRepository<LoanTransaction, Long>, JpaSpecificationExecutor<LoanTransaction> {
|
||||
|
||||
String FIND_ID_BY_EXTERNAL_ID = "SELECT lt.id FROM LoanTransaction lt WHERE lt.externalId = :externalId";
|
||||
|
||||
Optional<LoanTransaction> findByIdAndLoanId(Long transactionId, Long loanId);
|
||||
|
||||
@Query("""
|
||||
@@ -44,4 +48,6 @@ public interface LoanTransactionRepository extends JpaRepository<LoanTransaction
|
||||
""")
|
||||
Collection<LoanScheduleDelinquencyData> fetchLoanTransactionsByTypeAndLessOrEqualDate(Integer transactionType, LocalDate businessDate);
|
||||
|
||||
@Query(FIND_ID_BY_EXTERNAL_ID)
|
||||
Long findIdByExternalId(@Param("externalId") ExternalId externalId);
|
||||
}
|
||||
|
||||
+10
-2
@@ -18,8 +18,8 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanaccount.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
|
||||
/**
|
||||
* A {@link RuntimeException} thrown when loan resources are not found.
|
||||
@@ -30,11 +30,19 @@ public class LoanNotFoundException extends AbstractPlatformResourceNotFoundExcep
|
||||
super("error.msg.loan.id.invalid", "Loan with identifier " + id + " does not exist", id);
|
||||
}
|
||||
|
||||
public LoanNotFoundException(Long id, EmptyResultDataAccessException e) {
|
||||
public LoanNotFoundException(Long id, Exception e) {
|
||||
super("error.msg.loan.id.invalid", "Loan with identifier " + id + " does not exist", id, e);
|
||||
}
|
||||
|
||||
public LoanNotFoundException(String accountId) {
|
||||
super("error.msg.loan.account.id.invalid", "Loan with account ID " + accountId + " does not exist", accountId);
|
||||
}
|
||||
|
||||
public LoanNotFoundException(ExternalId externalId) {
|
||||
super("error.msg.loan.external.id.invalid", "Loan with external identifier " + externalId + " does not exist", externalId);
|
||||
}
|
||||
|
||||
public LoanNotFoundException(ExternalId externalId, Exception e) {
|
||||
super("error.msg.loan.external.id.invalid", "Loan with external identifier " + externalId + " does not exist", externalId, e);
|
||||
}
|
||||
}
|
||||
|
||||
+10
-4
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanaccount.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
|
||||
@@ -27,15 +28,20 @@ import org.springframework.dao.EmptyResultDataAccessException;
|
||||
public class LoanTransactionNotFoundException extends AbstractPlatformResourceNotFoundException {
|
||||
|
||||
public LoanTransactionNotFoundException(final Long id) {
|
||||
super("error.msg.loan.id.invalid", "Transaction with identifier " + id + " does not exist", id);
|
||||
super("error.msg.loan.transaction.id.invalid", "Transaction with identifier " + id + " does not exist", id);
|
||||
}
|
||||
|
||||
public LoanTransactionNotFoundException(final Long id, final Long loanId) {
|
||||
super("error.msg.loan.id.invalid", "Transaction with identifier " + id + " does not exist for loan with identifier " + loanId + ".",
|
||||
id, loanId);
|
||||
super("error.msg.loan.transaction.id.invalid",
|
||||
"Transaction with identifier " + id + " does not exist for loan with identifier " + loanId + ".", id, loanId);
|
||||
}
|
||||
|
||||
public LoanTransactionNotFoundException(Long id, EmptyResultDataAccessException e) {
|
||||
super("error.msg.loan.id.invalid", "Transaction with identifier " + id + " does not exist", id, e);
|
||||
super("error.msg.loan.transaction.id.invalid", "Transaction with identifier " + id + " does not exist", id, e);
|
||||
}
|
||||
|
||||
public LoanTransactionNotFoundException(ExternalId transactionExternalId, EmptyResultDataAccessException e) {
|
||||
super("error.msg.loan.transaction.id.invalid", "Transaction with external identifier " + transactionExternalId + " does not exist",
|
||||
transactionExternalId, e);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -30,6 +30,6 @@ public interface GuarantorDomainService {
|
||||
|
||||
void assignGuarantor(GuarantorFundingDetails guarantorFundingDetails, LocalDate transactionDate);
|
||||
|
||||
void transaferFundsFromGuarantor(Loan loan);
|
||||
void transferFundsFromGuarantor(Loan loan);
|
||||
|
||||
}
|
||||
|
||||
+9
-5
@@ -29,10 +29,13 @@ import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import javax.annotation.PostConstruct;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.infrastructure.event.business.BusinessEventListener;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanAdjustTransactionBusinessEvent;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanApprovedBusinessEvent;
|
||||
@@ -80,6 +83,8 @@ public class GuarantorDomainServiceImpl implements GuarantorDomainService {
|
||||
private final DepositAccountOnHoldTransactionRepository depositAccountOnHoldTransactionRepository;
|
||||
private final Map<Long, Long> releaseLoanIds = new HashMap<>(2);
|
||||
private final SavingsAccountAssembler savingsAccountAssembler;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
private final ExternalIdFactory externalIdFactory;
|
||||
|
||||
@PostConstruct
|
||||
public void addListeners() {
|
||||
@@ -204,7 +209,7 @@ public class GuarantorDomainServiceImpl implements GuarantorDomainService {
|
||||
* account to loan account and releases guarantor)
|
||||
*/
|
||||
@Override
|
||||
public void transaferFundsFromGuarantor(final Loan loan) {
|
||||
public void transferFundsFromGuarantor(final Loan loan) {
|
||||
if (loan.getGuaranteeAmount().compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return;
|
||||
}
|
||||
@@ -227,7 +232,6 @@ public class GuarantorDomainServiceImpl implements GuarantorDomainService {
|
||||
final AccountTransferDetails accountTransferDetails = null;
|
||||
final String noteText = null;
|
||||
|
||||
final String txnExternalId = null;
|
||||
final SavingsAccount toSavingsAccount = null;
|
||||
|
||||
Long loanId = loan.getId();
|
||||
@@ -245,11 +249,11 @@ public class GuarantorDomainServiceImpl implements GuarantorDomainService {
|
||||
remainingAmount = remainingAmount.multiply(loan.getPrincipal().getAmount()).divide(loan.getGuaranteeAmount(),
|
||||
MoneyHelper.getRoundingMode());
|
||||
}
|
||||
ExternalId externalId = externalIdFactory.create();
|
||||
AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, remainingAmount, fromAccountType,
|
||||
toAccountType, fromAccountId, toAccountId, description, locale, fmt, paymentDetail, fromTransferType,
|
||||
toTransferType, chargeId, loanInstallmentNumber, transferType, accountTransferDetails, noteText,
|
||||
txnExternalId, loan, toSavingsAccount, fromSavingsAccount, isRegularTransaction,
|
||||
isExceptionForBalanceCheck);
|
||||
toTransferType, chargeId, loanInstallmentNumber, transferType, accountTransferDetails, noteText, externalId,
|
||||
loan, toSavingsAccount, fromSavingsAccount, isRegularTransaction, isExceptionForBalanceCheck);
|
||||
transferAmount(accountTransferDTO);
|
||||
} finally {
|
||||
releaseLoanIds.remove(loanId);
|
||||
|
||||
+4
-3
@@ -23,6 +23,7 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
|
||||
import org.apache.fineract.portfolio.account.PortfolioAccountType;
|
||||
@@ -74,7 +75,7 @@ public class TransferFeeChargeForLoansTasklet implements Tasklet {
|
||||
portfolioAccountData.getId(), chargeData.getLoanId(), "Loan Charge Payment", null, null, null, null,
|
||||
LoanTransactionType.CHARGE_PAYMENT.getValue(), chargeData.getId(),
|
||||
installmentChargeData.getInstallmentNumber(), AccountTransferType.CHARGE_PAYMENT.getValue(), null, null,
|
||||
null, null, null, null, isRegularTransaction, isExceptionForBalanceCheck);
|
||||
ExternalId.empty(), null, null, null, isRegularTransaction, isExceptionForBalanceCheck);
|
||||
transferFeeCharge(accountTransferDTO, errors);
|
||||
}
|
||||
}
|
||||
@@ -86,8 +87,8 @@ public class TransferFeeChargeForLoansTasklet implements Tasklet {
|
||||
chargeData.getAmountOutstanding(), PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN,
|
||||
portfolioAccountData.getId(), chargeData.getLoanId(), "Loan Charge Payment", null, null, null, null,
|
||||
LoanTransactionType.CHARGE_PAYMENT.getValue(), chargeData.getId(), null,
|
||||
AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null, null, null, isRegularTransaction,
|
||||
isExceptionForBalanceCheck);
|
||||
AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, ExternalId.empty(), null, null, null,
|
||||
isRegularTransaction, isExceptionForBalanceCheck);
|
||||
transferFeeCharge(accountTransferDTO, errors);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1933,7 +1933,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
periods.add(disbursementPeriod);
|
||||
principal = principal.add(disbursementData.getPrincipal());
|
||||
} else if (!excludePastUndisbursed || disbursementData.isDisbursed()
|
||||
|| !disbursementData.disbursementDate().isBefore(DateUtils.getLocalDateOfTenant())) {
|
||||
|| !disbursementData.disbursementDate().isBefore(DateUtils.getBusinessLocalDate())) {
|
||||
/*
|
||||
* JW: sums up amounts by disbursal date in case of side-effect issues. Original assumed that there
|
||||
* were no duplicate disbursal dates and 'put' each amount into the map keyed by date
|
||||
|
||||
+5
-3
@@ -119,9 +119,10 @@ public final class LoanChargeApiJsonValidator {
|
||||
Set<String> transactionParameters = null;
|
||||
if (isChargeIdIncluded) {
|
||||
transactionParameters = new HashSet<>(
|
||||
Arrays.asList("transactionDate", "locale", "dateFormat", "chargeId", "dueDate", "installmentNumber"));
|
||||
Arrays.asList("transactionDate", "locale", "dateFormat", "chargeId", "dueDate", "installmentNumber", "externalId"));
|
||||
} else {
|
||||
transactionParameters = new HashSet<>(Arrays.asList("transactionDate", "locale", "dateFormat", "dueDate", "installmentNumber"));
|
||||
transactionParameters = new HashSet<>(
|
||||
Arrays.asList("transactionDate", "locale", "dateFormat", "dueDate", "installmentNumber", "externalId"));
|
||||
}
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {
|
||||
@@ -215,7 +216,8 @@ public final class LoanChargeApiJsonValidator {
|
||||
if (StringUtils.isBlank(json)) {
|
||||
return;
|
||||
}
|
||||
Set<String> transactionParameters = new HashSet<>(Arrays.asList("dueDate", "locale", "dateFormat", "installmentNumber"));
|
||||
Set<String> transactionParameters = new HashSet<>(
|
||||
Arrays.asList("dueDate", "locale", "dateFormat", "installmentNumber", "externalId"));
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {
|
||||
|
||||
|
||||
+10
-3
@@ -320,7 +320,7 @@ public final class LoanEventApiJsonValidator {
|
||||
}
|
||||
|
||||
final Set<String> disbursementParameters = new HashSet<>(
|
||||
Arrays.asList("transactionDate", "note", "locale", "dateFormat", "writeoffReasonId"));
|
||||
Arrays.asList("transactionDate", "note", "locale", "dateFormat", "writeoffReasonId", "externalId"));
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, disbursementParameters);
|
||||
@@ -335,6 +335,9 @@ public final class LoanEventApiJsonValidator {
|
||||
final String note = this.fromApiJsonHelper.extractStringNamed("note", element);
|
||||
baseDataValidator.reset().parameter("note").value(note).notExceedingLengthOf(1000);
|
||||
|
||||
final String externalId = this.fromApiJsonHelper.extractStringNamed("externalId", element);
|
||||
baseDataValidator.reset().parameter("externalId").value(externalId).ignoreIfNull().notExceedingLengthOf(100);
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
@@ -482,7 +485,7 @@ public final class LoanEventApiJsonValidator {
|
||||
baseDataValidator.reset().parameter("note").value(note).notExceedingLengthOf(1000);
|
||||
|
||||
final String externalId = this.fromApiJsonHelper.extractStringNamed("externalId", element);
|
||||
baseDataValidator.reset().parameter("externalId").value(externalId).notExceedingLengthOf(100);
|
||||
baseDataValidator.reset().parameter("externalId").value(externalId).ignoreIfNull().notExceedingLengthOf(100);
|
||||
|
||||
validatePaymentDetails(baseDataValidator, element);
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
@@ -494,7 +497,8 @@ public final class LoanEventApiJsonValidator {
|
||||
throw new InvalidJsonException();
|
||||
}
|
||||
|
||||
final Set<String> foreclosureParameters = new HashSet<>(Arrays.asList("transactionDate", "note", "locale", "dateFormat"));
|
||||
final Set<String> foreclosureParameters = new HashSet<>(
|
||||
Arrays.asList("transactionDate", "note", "locale", "dateFormat", "externalId"));
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, foreclosureParameters);
|
||||
@@ -509,6 +513,9 @@ public final class LoanEventApiJsonValidator {
|
||||
final String note = this.fromApiJsonHelper.extractStringNamed("note", element);
|
||||
baseDataValidator.reset().parameter("note").value(note).notExceedingLengthOf(1000);
|
||||
|
||||
final String externalId = this.fromApiJsonHelper.extractStringNamed("externalId", element);
|
||||
baseDataValidator.reset().parameter("externalId").value(externalId).ignoreIfNull().notExceedingLengthOf(100);
|
||||
|
||||
validatePaymentDetails(baseDataValidator, element);
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
+69
-42
@@ -41,9 +41,11 @@ import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanApplyOverdueChargeBusinessEvent;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.LoanBalanceChangedBusinessEvent;
|
||||
import org.apache.fineract.infrastructure.event.business.domain.loan.charge.LoanAddChargeBusinessEvent;
|
||||
@@ -60,6 +62,8 @@ import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.apache.fineract.portfolio.account.PortfolioAccountType;
|
||||
import org.apache.fineract.portfolio.account.data.AccountTransferDTO;
|
||||
import org.apache.fineract.portfolio.account.data.PortfolioAccountData;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferDetailRepository;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferDetails;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferType;
|
||||
import org.apache.fineract.portfolio.account.service.AccountAssociationsReadPlatformService;
|
||||
import org.apache.fineract.portfolio.account.service.AccountTransfersWritePlatformService;
|
||||
@@ -81,6 +85,7 @@ import org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollatera
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.group.domain.Group;
|
||||
import org.apache.fineract.portfolio.group.exception.GroupNotActiveException;
|
||||
import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanChargePaidByData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.ChangedTransactionDetail;
|
||||
@@ -146,6 +151,9 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory;
|
||||
private final ExternalIdFactory externalIdFactory;
|
||||
|
||||
private final AccountTransferDetailRepository accountTransferDetailRepository;
|
||||
|
||||
private static boolean isPartOfThisInstallment(LoanCharge loanCharge, LoanRepaymentScheduleInstallment e) {
|
||||
return e.getFromDate().isBefore(loanCharge.getDueDate()) && !loanCharge.getDueDate().isAfter(e.getDueDate());
|
||||
@@ -242,8 +250,12 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
this.loanAccountDomainService.setLoanDelinquencyTag(loan, DateUtils.getBusinessLocalDate());
|
||||
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanAddChargeBusinessEvent(loanCharge));
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(loanCharge.getId())
|
||||
.withOfficeId(loan.getOfficeId()).withClientId(loan.getClientId()).withGroupId(loan.getGroupId()).withLoanId(loanId)
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()) //
|
||||
.withEntityId(loanCharge.getId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
.withLoanId(loanId) //
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -342,17 +354,21 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanWaiveChargeUndoBusinessEvent(loanCharge));
|
||||
|
||||
// TODO: this needs to be fixed in the future! Principal portion is bigdecimal, interest portion is money, ...
|
||||
changes.put("principalPortion", loanTransaction.getPrincipalPortion());
|
||||
changes.put("interestPortion", loanTransaction.getInterestPortion(loan.getCurrency()));
|
||||
changes.put("feeChargesPortion", loanTransaction.getFeeChargesPortion(loan.getCurrency()));
|
||||
changes.put("penaltyChargesPortion", loanTransaction.getPenaltyChargesPortion(loan.getCurrency()));
|
||||
changes.put("outstandingLoanBalance", loanTransaction.getOutstandingLoanBalance());
|
||||
changes.put("id", loanTransaction.getId());
|
||||
changes.put("externalId", loanTransaction.getExternalId());
|
||||
changes.put("date", loanTransaction.getTransactionDate());
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(loanCharge.getId()) //
|
||||
.withSubEntityId(loanTransaction.getId()) //
|
||||
.withSubEntityExternalId(loanTransaction.getExternalId()) //
|
||||
.withLoanId(loanId) //
|
||||
.with(changes).build();
|
||||
}
|
||||
@@ -398,6 +414,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
final Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
checkClientOrGroupActive(loan);
|
||||
this.loanChargeApiJsonValidator.validateInstallmentChargeTransaction(command.json());
|
||||
final ExternalId externalId = externalIdFactory.createFromCommand(command, LoanApiConstants.externalIdParameterName);
|
||||
final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId);
|
||||
|
||||
// Charges may be waived only when the loan associated with them are
|
||||
@@ -442,6 +459,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
}
|
||||
|
||||
final Map<String, Object> changes = new LinkedHashMap<>(3);
|
||||
changes.put(LoanApiConstants.externalIdParameterName, externalId);
|
||||
|
||||
final List<Long> existingTransactionIds = new ArrayList<>();
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>();
|
||||
@@ -458,7 +476,8 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
}
|
||||
|
||||
final LoanTransaction waiveTransaction = loan.waiveLoanCharge(loanCharge, defaultLoanLifecycleStateMachine, changes,
|
||||
existingTransactionIds, existingReversedTransactionIds, loanInstallmentNumber, scheduleGeneratorDTO, accruedCharge);
|
||||
existingTransactionIds, existingReversedTransactionIds, loanInstallmentNumber, scheduleGeneratorDTO, accruedCharge,
|
||||
externalId);
|
||||
|
||||
this.loanTransactionRepository.saveAndFlush(waiveTransaction);
|
||||
this.loanRepositoryWrapper.save(loan);
|
||||
@@ -471,6 +490,8 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(loanChargeId) //
|
||||
.withSubEntityId(waiveTransaction.getId()) //
|
||||
.withSubEntityExternalId(waiveTransaction.getExternalId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
@@ -521,6 +542,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
final Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
checkClientOrGroupActive(loan);
|
||||
final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId);
|
||||
final ExternalId externalId = externalIdFactory.createFromCommand(command, LoanApiConstants.externalIdParameterName);
|
||||
|
||||
// Charges may be waived only when the loan associated with them are
|
||||
// active
|
||||
@@ -583,12 +605,15 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, amount, PortfolioAccountType.SAVINGS,
|
||||
PortfolioAccountType.LOAN, portfolioAccountData.getId(), loanId, "Loan Charge Payment", locale, fmt, null, null,
|
||||
LoanTransactionType.CHARGE_PAYMENT.getValue(), loanChargeId, loanInstallmentNumber,
|
||||
AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null, null, fromSavingsAccount, isRegularTransaction,
|
||||
AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, externalId, null, null, fromSavingsAccount, isRegularTransaction,
|
||||
isExceptionForBalanceCheck);
|
||||
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
Long transferTransactionId = this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
AccountTransferDetails transferDetails = this.accountTransferDetailRepository.findById(transferTransactionId).get();
|
||||
LoanTransaction loanTransaction = transferDetails.getAccountTransferTransactions().get(0).getToLoanTransaction();
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(loanChargeId) //
|
||||
.withSubEntityId(loanTransaction.getId()).withSubEntityExternalId(loanTransaction.getExternalId())
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
@@ -604,7 +629,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId);
|
||||
final LocalDate transactionDate = DateUtils.getBusinessLocalDate();
|
||||
final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed("amount");
|
||||
final String txnExternalId = command.stringValueOfParameterNamedAllowingNull("externalId");
|
||||
final ExternalId txnExternalId = externalIdFactory.createFromCommand(command, "externalId");
|
||||
final String locale = command.locale();
|
||||
|
||||
loanChargeAdjustmentEntranceValidation(loanCharge, transactionAmount);
|
||||
@@ -639,44 +664,12 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
changes.put("locale", locale);
|
||||
return commandProcessingResultBuilder.withCommandId(command.commandId()) //
|
||||
.withLoanId(loanId) //
|
||||
.withEntityId(loanTransaction.getId()).with(changes) //
|
||||
.withEntityId(loanChargeId).withSubEntityId(loanTransaction.getId()) //
|
||||
.withSubEntityExternalId(loanTransaction.getExternalId()) //
|
||||
.with(changes) //
|
||||
.build();
|
||||
}
|
||||
|
||||
private LoanTransaction applyChargeAdjustment(final Loan loan, final LoanCharge loanCharge, final BigDecimal transactionAmount,
|
||||
final LocalDate transactionDate, final String txnExternalId) {
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanChargeAdjustmentPreBusinessEvent(loan));
|
||||
final List<Long> existingTransactionIds = new ArrayList<>(loan.findExistingTransactionIds());
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>(loan.findExistingReversedTransactionIds());
|
||||
|
||||
LoanTransaction loanChargeAdjustmentTransaction = LoanTransaction.chargeAdjustment(loan, transactionAmount, transactionDate,
|
||||
txnExternalId);
|
||||
LoanTransactionRelation loanTransactionRelation = LoanTransactionRelation.linkToCharge(loanChargeAdjustmentTransaction, loanCharge,
|
||||
LoanTransactionRelationTypeEnum.CHARGE_ADJUSTMENT);
|
||||
loanChargeAdjustmentTransaction.getLoanTransactionRelations().add(loanTransactionRelation);
|
||||
|
||||
loanAccountDomainService.saveLoanTransactionWithDataIntegrityViolationChecks(loanChargeAdjustmentTransaction);
|
||||
|
||||
defaultLoanLifecycleStateMachine.transition(LoanEvent.LOAN_REPAYMENT_OR_WAIVER, loan);
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = loanRepaymentScheduleTransactionProcessorFactory
|
||||
.determineProcessor(loan.transactionProcessingStrategy());
|
||||
loanRepaymentScheduleTransactionProcessor.handleTransaction(loanChargeAdjustmentTransaction, loan.getCurrency(),
|
||||
loan.getRepaymentScheduleInstallments(), loan.getActiveCharges());
|
||||
|
||||
loan.addLoanTransaction(loanChargeAdjustmentTransaction);
|
||||
loan.updateLoanSummaryAndStatus();
|
||||
|
||||
loanAccountDomainService.saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||
|
||||
final Map<String, Object> accountingBridgeData = loan.deriveAccountingBridgeData(loan.getCurrency().getCode(),
|
||||
existingTransactionIds, existingReversedTransactionIds, false);
|
||||
this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
|
||||
|
||||
loanAccountDomainService.setLoanDelinquencyTag(loan, transactionDate);
|
||||
|
||||
return loanChargeAdjustmentTransaction;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void applyOverdueChargesForLoan(final Long loanId, Collection<OverdueLoanScheduleData> overdueLoanScheduleDataList) {
|
||||
@@ -744,6 +737,40 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
}
|
||||
}
|
||||
|
||||
private LoanTransaction applyChargeAdjustment(final Loan loan, final LoanCharge loanCharge, final BigDecimal transactionAmount,
|
||||
final LocalDate transactionDate, final ExternalId txnExternalId) {
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanChargeAdjustmentPreBusinessEvent(loan));
|
||||
final List<Long> existingTransactionIds = new ArrayList<>(loan.findExistingTransactionIds());
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>(loan.findExistingReversedTransactionIds());
|
||||
|
||||
LoanTransaction loanChargeAdjustmentTransaction = LoanTransaction.chargeAdjustment(loan, transactionAmount, transactionDate,
|
||||
txnExternalId);
|
||||
LoanTransactionRelation loanTransactionRelation = LoanTransactionRelation.linkToCharge(loanChargeAdjustmentTransaction, loanCharge,
|
||||
LoanTransactionRelationTypeEnum.CHARGE_ADJUSTMENT);
|
||||
loanChargeAdjustmentTransaction.getLoanTransactionRelations().add(loanTransactionRelation);
|
||||
|
||||
loanAccountDomainService.saveLoanTransactionWithDataIntegrityViolationChecks(loanChargeAdjustmentTransaction);
|
||||
|
||||
defaultLoanLifecycleStateMachine.transition(LoanEvent.LOAN_REPAYMENT_OR_WAIVER, loan);
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = loanRepaymentScheduleTransactionProcessorFactory
|
||||
.determineProcessor(loan.transactionProcessingStrategy());
|
||||
loanRepaymentScheduleTransactionProcessor.handleTransaction(loanChargeAdjustmentTransaction, loan.getCurrency(),
|
||||
loan.getRepaymentScheduleInstallments(), loan.getActiveCharges());
|
||||
|
||||
loan.addLoanTransaction(loanChargeAdjustmentTransaction);
|
||||
loan.updateLoanSummaryAndStatus();
|
||||
|
||||
loanAccountDomainService.saveAndFlushLoanWithDataIntegrityViolationChecks(loan);
|
||||
|
||||
final Map<String, Object> accountingBridgeData = loan.deriveAccountingBridgeData(loan.getCurrency().getCode(),
|
||||
existingTransactionIds, existingReversedTransactionIds, false);
|
||||
this.journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
|
||||
|
||||
loanAccountDomainService.setLoanDelinquencyTag(loan, transactionDate);
|
||||
|
||||
return loanChargeAdjustmentTransaction;
|
||||
}
|
||||
|
||||
private void undoWaivedCharge(final Map<String, Object> changes, final Loan loan, final LoanTransaction loanTransaction,
|
||||
final LoanChargePaidBy loanChargePaidBy) {
|
||||
switch (loanChargePaidBy.getLoanCharge().getChargeTimeType()) {
|
||||
@@ -1057,7 +1084,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
jsonObject.addProperty("dateFormat", dateFormat);
|
||||
}
|
||||
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(dateFormat);
|
||||
LocalDate transactionDate = DateUtils.getLocalDateOfTenant();
|
||||
LocalDate transactionDate = DateUtils.getBusinessLocalDate();
|
||||
String transactionDateString = transactionDate.format(dateTimeFormatter);
|
||||
jsonObject.addProperty("transactionDate", transactionDateString);
|
||||
if (!this.fromApiJsonHelper.parameterExists("transactionAmount", jsonObject)) {
|
||||
|
||||
+4
@@ -22,6 +22,7 @@ import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.service.Page;
|
||||
import org.apache.fineract.infrastructure.core.service.SearchParameters;
|
||||
import org.apache.fineract.organisation.staff.data.StaffData;
|
||||
@@ -155,4 +156,7 @@ public interface LoanReadPlatformService {
|
||||
|
||||
List<LoanTransactionRelationData> retrieveLoanTransactionRelationsByLoanTransactionId(Long loanTransactionId);
|
||||
|
||||
Long retrieveLoanTransactionIdByExternalId(ExternalId externalId);
|
||||
|
||||
Long retrieveLoanIdByExternalId(String externalId);
|
||||
}
|
||||
|
||||
+17
-4
@@ -41,6 +41,7 @@ import org.apache.fineract.infrastructure.codes.data.CodeValueData;
|
||||
import org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService;
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.Page;
|
||||
@@ -1372,7 +1373,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
final BigDecimal overPaymentPortion = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "overpayment");
|
||||
final BigDecimal unrecognizedIncomePortion = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "unrecognizedIncome");
|
||||
final BigDecimal outstandingLoanBalance = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "outstandingLoanBalance");
|
||||
final String externalId = rs.getString("externalId");
|
||||
final String externalIdStr = rs.getString("externalId");
|
||||
final ExternalId externalId = StringUtils.isBlank(externalIdStr) ? ExternalId.empty() : new ExternalId(externalIdStr);
|
||||
final String reversalExternalId = rs.getString("reversalExternalId");
|
||||
final LocalDate reversedOnDate = JdbcSupport.getLocalDate(rs, "reversedOnDate");
|
||||
|
||||
@@ -2186,7 +2188,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
|
||||
final LoanTransactionEnumData transactionType = LoanEnumerations.transactionType(loanTransactionType);
|
||||
return new LoanTransactionData(null, null, null, transactionType, null, currencyData, currentDate, transactionAmount, null,
|
||||
netDisbursal, null, null, null, null, null, paymentOptions, null, null, null, null, false, loanId, externalLoanId);
|
||||
netDisbursal, null, null, null, null, null, paymentOptions, ExternalId.empty(), null, null, null, false, loanId,
|
||||
externalLoanId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2308,6 +2311,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
// TODO: investigate whether it can be refactored to be more efficient
|
||||
StringBuilder sqlBuilder = new StringBuilder();
|
||||
sqlBuilder.append("(CASE ");
|
||||
sqlBuilder.append(
|
||||
@@ -2358,11 +2362,10 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
final String officeName = null;
|
||||
boolean manuallyReversed = false;
|
||||
final PaymentDetailData paymentDetailData = null;
|
||||
final String externalId = null;
|
||||
final AccountTransferData transfer = null;
|
||||
final BigDecimal fixedEmiAmount = null;
|
||||
return new LoanTransactionData(id, officeId, officeName, transactionType, paymentDetailData, currencyData, date, totalDue,
|
||||
netDisbursalAmount, principalPortion, interestDue, feeDue, penaltyDue, overPaymentPortion, externalId, transfer,
|
||||
netDisbursalAmount, principalPortion, interestDue, feeDue, penaltyDue, overPaymentPortion, ExternalId.empty(), transfer,
|
||||
fixedEmiAmount, outstandingLoanBalance, unrecognizedIncomePortion, manuallyReversed, loanId, externalLoanId);
|
||||
}
|
||||
|
||||
@@ -2402,4 +2405,14 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
return loanTransactionRelationMapper.map(loanTransactionRelations);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long retrieveLoanTransactionIdByExternalId(ExternalId externalId) {
|
||||
return loanTransactionRepository.findIdByExternalId(externalId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long retrieveLoanIdByExternalId(String externalId) {
|
||||
return loanRepositoryWrapper.findIdByExternalId(externalId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+151
-66
@@ -49,11 +49,13 @@ import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformServiceUnavailableException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.infrastructure.dataqueries.data.EntityTables;
|
||||
import org.apache.fineract.infrastructure.dataqueries.data.StatusEnum;
|
||||
import org.apache.fineract.infrastructure.dataqueries.service.EntityDatatableChecksWritePlatformService;
|
||||
@@ -244,6 +246,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
private final LoanLifecycleStateMachine defaultLoanLifecycleStateMachine;
|
||||
private final LoanAccountLockService loanAccountLockService;
|
||||
|
||||
private final ExternalIdFactory externalIdFactory;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult disburseGLIMLoan(final Long loanId, final JsonCommand command) {
|
||||
@@ -382,7 +386,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
Money disburseAmount = loan.adjustDisburseAmount(command, actualDisbursementDate);
|
||||
Money amountToDisburse = disburseAmount.copy();
|
||||
boolean recalculateSchedule = amountBeforeAdjust.isNotEqualTo(loan.getPrincipal());
|
||||
final String txnExternalId = command.stringValueOfParameterNamedAllowingNull("externalId");
|
||||
final ExternalId txnExternalId = externalIdFactory.createFromCommand(command, LoanApiConstants.externalIdParameterName);
|
||||
|
||||
if (loan.isTopup() && loan.getClientId() != null) {
|
||||
final Long loanIdToClose = loan.getTopupLoanDetails().getLoanIdToClose();
|
||||
@@ -486,8 +490,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(actualDisbursementDate, entrySet.getValue(),
|
||||
PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN, savingAccountData.getId(), loanId, "Loan Charge Payment",
|
||||
locale, fmt, null, null, LoanTransactionType.REPAYMENT_AT_DISBURSEMENT.getValue(), entrySet.getKey(), null,
|
||||
AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null, null, fromSavingsAccount, isRegularTransaction,
|
||||
isExceptionForBalanceCheck);
|
||||
AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, ExternalId.empty(), null, null, fromSavingsAccount,
|
||||
isRegularTransaction, isExceptionForBalanceCheck);
|
||||
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
}
|
||||
|
||||
@@ -505,17 +509,20 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanDisbursalBusinessEvent(loan));
|
||||
|
||||
Long entityId = loan.getId();
|
||||
ExternalId externalId = ExternalId.empty();
|
||||
|
||||
// During a disbursement, the entityId should be the disbursement transaction id
|
||||
if (!isAccountTransfer) {
|
||||
LoanTransaction disbursalTransaction = loan.getLoanTransactions().get(loan.getLoanTransactions().size() - 1);
|
||||
entityId = disbursalTransaction.getId();
|
||||
externalId = disbursalTransaction.getExternalId();
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanDisbursalTransactionBusinessEvent(disbursalTransaction));
|
||||
}
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(entityId) //
|
||||
.withEntityExternalId(externalId) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
@@ -608,7 +615,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan.transaction");
|
||||
if (realCause.getMessage().toLowerCase().contains("external_id_unique")) {
|
||||
baseDataValidator.reset().parameter("externalId").failWithCode("value.must.be.unique");
|
||||
baseDataValidator.reset().parameter(LoanApiConstants.externalIdParameterName).failWithCode("value.must.be.unique");
|
||||
}
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
||||
@@ -626,7 +633,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan.transaction");
|
||||
if (realCause.getMessage().toLowerCase().contains("external_id_unique")) {
|
||||
baseDataValidator.reset().parameter("externalId").failWithCode("value.must.be.unique");
|
||||
baseDataValidator.reset().parameter(LoanApiConstants.externalIdParameterName).failWithCode("value.must.be.unique");
|
||||
}
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
||||
@@ -687,7 +694,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
Money amountBeforeAdjust = loan.getPrincipal();
|
||||
Money disburseAmount = loan.adjustDisburseAmount(command, actualDisbursementDate);
|
||||
boolean recalculateSchedule = amountBeforeAdjust.isNotEqualTo(loan.getPrincipal());
|
||||
final String txnExternalId = command.stringValueOfParameterNamedAllowingNull("externalId");
|
||||
final ExternalId txnExternalId = externalIdFactory.createFromCommand(command, LoanApiConstants.externalIdParameterName);
|
||||
if (isAccountTransfer) {
|
||||
disburseLoanToSavings(loan, command, disburseAmount, paymentDetail);
|
||||
existingTransactionIds.addAll(loan.findExistingTransactionIds());
|
||||
@@ -753,7 +760,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(actualDisbursementDate, entrySet.getValue(),
|
||||
PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN, savingAccountData.getId(), loan.getId(),
|
||||
"Loan Charge Payment", locale, fmt, null, null, LoanTransactionType.REPAYMENT_AT_DISBURSEMENT.getValue(),
|
||||
entrySet.getKey(), null, AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null, null,
|
||||
entrySet.getKey(), null, AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, ExternalId.empty(), null, null,
|
||||
fromSavingsAccount, isRegularTransaction, isExceptionForBalanceCheck);
|
||||
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
}
|
||||
@@ -907,7 +914,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
final LocalDate transactionDate = command.localDateValueOfParameterNamed("transactionDate");
|
||||
final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed("transactionAmount");
|
||||
final String txnExternalId = command.stringValueOfParameterNamedAllowingNull("externalId");
|
||||
final ExternalId txnExternalId = externalIdFactory.createFromCommand(command, LoanApiConstants.externalIdParameterName);
|
||||
|
||||
final Map<String, Object> changes = new LinkedHashMap<>();
|
||||
changes.put("transactionDate", command.stringValueOfParameterNamed("transactionDate"));
|
||||
@@ -920,15 +927,18 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
if (StringUtils.isNotBlank(noteText)) {
|
||||
changes.put("note", noteText);
|
||||
}
|
||||
if (!txnExternalId.isEmpty()) {
|
||||
changes.put(LoanApiConstants.externalIdParameterName, txnExternalId);
|
||||
}
|
||||
final Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
final PaymentDetail paymentDetail = this.paymentDetailWritePlatformService.createAndPersistPaymentDetail(command, changes);
|
||||
final Boolean isHolidayValidationDone = false;
|
||||
final HolidayDetailDTO holidayDetailDto = null;
|
||||
boolean isAccountTransfer = false;
|
||||
final CommandProcessingResultBuilder commandProcessingResultBuilder = new CommandProcessingResultBuilder();
|
||||
LoanTransaction loanTransaction = this.loanAccountDomainService.makeRepayment(repaymentTransactionType, loan,
|
||||
commandProcessingResultBuilder, transactionDate, transactionAmount, paymentDetail, noteText, txnExternalId,
|
||||
isRecoveryRepayment, chargeRefundChargeType, isAccountTransfer, holidayDetailDto, isHolidayValidationDone);
|
||||
|
||||
LoanTransaction loanTransaction = this.loanAccountDomainService.makeRepayment(repaymentTransactionType, loan, transactionDate,
|
||||
transactionAmount, paymentDetail, noteText, txnExternalId, isRecoveryRepayment, chargeRefundChargeType, isAccountTransfer,
|
||||
holidayDetailDto, isHolidayValidationDone);
|
||||
|
||||
// Update loan transaction on repayment.
|
||||
if (AccountType.fromInt(loan.getLoanType()).isIndividualAccount()) {
|
||||
@@ -947,8 +957,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
this.loanAccountDomainService.updateLoanCollateralTransaction(loanCollateralManagements);
|
||||
}
|
||||
|
||||
return commandProcessingResultBuilder.withCommandId(command.commandId()) //
|
||||
.withLoanId(loanId) //
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()) //
|
||||
.withLoanId(loan.getId()) //
|
||||
.withEntityId(loanTransaction.getId()) //
|
||||
.withEntityExternalId(loanTransaction.getExternalId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
.with(changes) //
|
||||
.build();
|
||||
}
|
||||
@@ -993,15 +1008,18 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
if (singleLoanRepaymentCommand != null) {
|
||||
final Loan loan = this.loanAssembler.assembleFrom(singleLoanRepaymentCommand.getLoanId());
|
||||
final PaymentDetail paymentDetail = singleLoanRepaymentCommand.getPaymentDetail();
|
||||
ExternalId externalId = singleLoanRepaymentCommand.getExternalId();
|
||||
if (externalId.isEmpty() && configurationDomainService.isExternalIdAutoGenerationEnabled()) {
|
||||
externalId = ExternalId.generate();
|
||||
}
|
||||
if (paymentDetail != null && paymentDetail.getId() == null) {
|
||||
this.paymentDetailWritePlatformService.persistPaymentDetail(paymentDetail);
|
||||
}
|
||||
final CommandProcessingResultBuilder commandProcessingResultBuilder = new CommandProcessingResultBuilder();
|
||||
final String chargeRefundChargeType = null;
|
||||
LoanTransaction loanTransaction = this.loanAccountDomainService.makeRepayment(LoanTransactionType.REPAYMENT, loan,
|
||||
commandProcessingResultBuilder, bulkRepaymentCommand.getTransactionDate(),
|
||||
singleLoanRepaymentCommand.getTransactionAmount(), paymentDetail, bulkRepaymentCommand.getNote(), null,
|
||||
isRecoveryRepayment, chargeRefundChargeType, isAccountTransfer, holidayDetailDTO, isHolidayValidationDone);
|
||||
bulkRepaymentCommand.getTransactionDate(), singleLoanRepaymentCommand.getTransactionAmount(), paymentDetail,
|
||||
bulkRepaymentCommand.getNote(), externalId, isRecoveryRepayment, chargeRefundChargeType, isAccountTransfer,
|
||||
holidayDetailDTO, isHolidayValidationDone);
|
||||
transactionIds.add(loanTransaction.getId());
|
||||
}
|
||||
}
|
||||
@@ -1014,6 +1032,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
public CommandProcessingResult adjustLoanTransaction(final Long loanId, final Long transactionId, final JsonCommand command) {
|
||||
|
||||
this.loanEventApiJsonValidator.validateTransaction(command.json());
|
||||
LoanTransaction transactionToAdjust = this.loanTransactionRepository.findByIdAndLoanId(command.entityId(), command.getLoanId())
|
||||
.orElseThrow(() -> new LoanTransactionNotFoundException(command.entityId(), command.getLoanId()));
|
||||
|
||||
Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
if (loan.getStatus().isClosed() && loan.getLoanSubStatus() != null
|
||||
@@ -1022,8 +1042,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
throw new LoanForeclosureException("loan.cannot.be.reopened.as.it.is.foreclosured", defaultUserMessage, loanId);
|
||||
}
|
||||
checkClientOrGroupActive(loan);
|
||||
final LoanTransaction transactionToAdjust = this.loanTransactionRepository.findById(transactionId)
|
||||
.orElseThrow(() -> new LoanTransactionNotFoundException(transactionId));
|
||||
|
||||
businessEventNotifierService.notifyPreBusinessEvent(
|
||||
new LoanAdjustTransactionBusinessEvent(new LoanAdjustTransactionBusinessEvent.Data(transactionToAdjust)));
|
||||
if (this.accountTransfersReadPlatformService.isAccountTransfer(transactionId, PortfolioAccountType.LOAN)) {
|
||||
@@ -1049,8 +1068,10 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
final LocalDate transactionDate = command.localDateValueOfParameterNamed("transactionDate");
|
||||
final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed("transactionAmount");
|
||||
final String txnExternalId = command.stringValueOfParameterNamedAllowingNull("externalId");
|
||||
final String reversalExternalId = command.stringValueOfParameterNamedAllowingNull(LoanApiConstants.REVERSAL_EXTERNAL_ID_PARAMNAME);
|
||||
final ExternalId txnExternalId = externalIdFactory.createFromCommand(command, LoanApiConstants.externalIdParameterName);
|
||||
// TODO: can it be refactored to use the 'externalId' for reversal?
|
||||
final ExternalId reversalTxnExternalId = externalIdFactory.createFromCommand(command,
|
||||
LoanApiConstants.REVERSAL_EXTERNAL_ID_PARAMNAME);
|
||||
|
||||
final Map<String, Object> changes = new LinkedHashMap<>();
|
||||
changes.put("transactionDate", command.stringValueOfParameterNamed("transactionDate"));
|
||||
@@ -1077,7 +1098,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
}
|
||||
newTransactionDetail = LoanTransaction.waiver(loan.getOffice(), loan, transactionAmountAsMoney, transactionDate,
|
||||
interestComponent, unrecognizedIncome);
|
||||
interestComponent, unrecognizedIncome, txnExternalId);
|
||||
}
|
||||
|
||||
LocalDate recalculateFrom = null;
|
||||
@@ -1091,9 +1112,10 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
final ChangedTransactionDetail changedTransactionDetail = loan.adjustExistingTransaction(newTransactionDetail,
|
||||
defaultLoanLifecycleStateMachine, transactionToAdjust, existingTransactionIds, existingReversedTransactionIds,
|
||||
scheduleGeneratorDTO, reversalExternalId);
|
||||
scheduleGeneratorDTO, reversalTxnExternalId);
|
||||
|
||||
if (newTransactionDetail.isGreaterThanZero(loan.getPrincipal().getCurrency())) {
|
||||
boolean thereIsNewTransaction = newTransactionDetail.isGreaterThanZero(loan.getPrincipal().getCurrency());
|
||||
if (thereIsNewTransaction) {
|
||||
if (paymentDetail != null) {
|
||||
this.paymentDetailWritePlatformService.persistPaymentDetail(paymentDetail);
|
||||
}
|
||||
@@ -1122,7 +1144,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
/**
|
||||
* If a new transaction is not created, associate note with the transaction to be adjusted
|
||||
**/
|
||||
if (newTransactionDetail.isGreaterThanZero(loan.getPrincipal().getCurrency())) {
|
||||
if (thereIsNewTransaction) {
|
||||
note = Note.loanTransactionNote(loan, newTransactionDetail, noteText);
|
||||
} else {
|
||||
note = Note.loanTransactionNote(loan, transactionToAdjust, noteText);
|
||||
@@ -1151,14 +1173,27 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
this.loanAccountDomainService.setLoanDelinquencyTag(loan, DateUtils.getBusinessLocalDate());
|
||||
|
||||
LoanAdjustTransactionBusinessEvent.Data eventData = new LoanAdjustTransactionBusinessEvent.Data(transactionToAdjust);
|
||||
if (newTransactionDetail.isRepaymentType() && newTransactionDetail.isGreaterThanZero(loan.getPrincipal().getCurrency())) {
|
||||
if (newTransactionDetail.isRepaymentType() && thereIsNewTransaction) {
|
||||
eventData.setNewTransactionDetail(newTransactionDetail);
|
||||
}
|
||||
Long entityId = transactionToAdjust.getId();
|
||||
ExternalId entityExternalId = transactionToAdjust.getExternalId();
|
||||
|
||||
if (thereIsNewTransaction) {
|
||||
entityId = newTransactionDetail.getId();
|
||||
entityExternalId = newTransactionDetail.getExternalId();
|
||||
}
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanAdjustTransactionBusinessEvent(eventData));
|
||||
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(transactionId)
|
||||
.withOfficeId(loan.getOfficeId()).withClientId(loan.getClientId()).withGroupId(loan.getGroupId()).withLoanId(loanId)
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(entityId) //
|
||||
.withEntityExternalId(entityExternalId) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
.withLoanId(loanId) //
|
||||
.with(changes).build();
|
||||
}
|
||||
|
||||
@@ -1167,6 +1202,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
public CommandProcessingResult chargebackLoanTransaction(final Long loanId, final Long transactionId, final JsonCommand command) {
|
||||
this.loanEventApiJsonValidator.validateChargebackTransaction(command.json());
|
||||
|
||||
LoanTransaction loanTransaction = this.loanTransactionRepository.findByIdAndLoanId(command.entityId(), command.getLoanId())
|
||||
.orElseThrow(() -> new LoanTransactionNotFoundException(command.entityId(), command.getLoanId()));
|
||||
|
||||
Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
if (this.accountTransfersReadPlatformService.isAccountTransfer(transactionId, PortfolioAccountType.LOAN)) {
|
||||
throw new PlatformServiceUnavailableException("error.msg.loan.transfer.transaction.update.not.allowed",
|
||||
@@ -1187,9 +1225,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
checkClientOrGroupActive(loan);
|
||||
|
||||
LoanTransaction loanTransaction = this.loanTransactionRepository.findById(transactionId)
|
||||
.orElseThrow(() -> new LoanTransactionNotFoundException(transactionId));
|
||||
|
||||
if (loanTransaction.isReversed()) {
|
||||
throw new PlatformServiceUnavailableException("error.msg.loan.chargeback.operation.not.allowed",
|
||||
"Loan transaction:" + transactionId + " chargeback not allowed as loan transaction repayment is reversed",
|
||||
@@ -1207,7 +1242,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
final LocalDate transactionDate = DateUtils.getBusinessLocalDate();
|
||||
final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed(LoanApiConstants.TRANSACTION_AMOUNT_PARAMNAME);
|
||||
final String txnExternalId = command.stringValueOfParameterNamedAllowingNull(LoanApiConstants.externalIdParameterName);
|
||||
final ExternalId txnExternalId = externalIdFactory.createFromCommand(command, LoanApiConstants.externalIdParameterName);
|
||||
|
||||
final Map<String, Object> changes = new LinkedHashMap<>();
|
||||
changes.put("transactionAmount", command.stringValueOfParameterNamed(LoanApiConstants.TRANSACTION_AMOUNT_PARAMNAME));
|
||||
@@ -1247,8 +1282,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanChargebackTransactionBusinessEvent(loanTransaction));
|
||||
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(newTransaction.getId())
|
||||
.withOfficeId(loan.getOfficeId()).withClientId(loan.getClientId()).withGroupId(loan.getGroupId()).withLoanId(loanId)
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(newTransaction.getId()) //
|
||||
.withEntityExternalId(newTransaction.getExternalId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
.withLoanId(loanId) //
|
||||
.with(changes).build();
|
||||
}
|
||||
|
||||
@@ -1280,6 +1321,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
changes.put("dateFormat", command.dateFormat());
|
||||
final LocalDate transactionDate = command.localDateValueOfParameterNamed("transactionDate");
|
||||
final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed("transactionAmount");
|
||||
final ExternalId externalId = externalIdFactory.createFromCommand(command, LoanApiConstants.externalIdParameterName);
|
||||
|
||||
Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
checkClientOrGroupActive(loan);
|
||||
@@ -1298,7 +1340,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
}
|
||||
final LoanTransaction waiveInterestTransaction = LoanTransaction.waiver(loan.getOffice(), loan, transactionAmountAsMoney,
|
||||
transactionDate, interestComponent, unrecognizedIncome);
|
||||
transactionDate, interestComponent, unrecognizedIncome, externalId);
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanWaiveInterestBusinessEvent(waiveInterestTransaction));
|
||||
LocalDate recalculateFrom = null;
|
||||
if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
|
||||
@@ -1339,8 +1381,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanWaiveInterestBusinessEvent(waiveInterestTransaction));
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(waiveInterestTransaction.getId())
|
||||
.withOfficeId(loan.getOfficeId()).withClientId(loan.getClientId()).withGroupId(loan.getGroupId()).withLoanId(loanId)
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(waiveInterestTransaction.getId()) //
|
||||
.withEntityExternalId(waiveInterestTransaction.getExternalId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
.withLoanId(loanId) //
|
||||
.with(changes).build();
|
||||
}
|
||||
|
||||
@@ -1404,8 +1452,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
loanAccountDomainService.setLoanDelinquencyTag(loan, DateUtils.getBusinessLocalDate());
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan));
|
||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanWrittenOffPostBusinessEvent(writeOff));
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(writeOff.getId())
|
||||
.withOfficeId(loan.getOfficeId()).withClientId(loan.getClientId()).withGroupId(loan.getGroupId()).withLoanId(loanId)
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(writeOff.getId()) //
|
||||
.withEntityExternalId(writeOff.getExternalId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
.withLoanId(loanId) //
|
||||
.with(changes).build();
|
||||
}
|
||||
|
||||
@@ -1485,12 +1539,23 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
CommandProcessingResult result;
|
||||
if (possibleClosingTransaction != null) {
|
||||
|
||||
result = new CommandProcessingResultBuilder().withCommandId(command.commandId())
|
||||
.withEntityId(possibleClosingTransaction.getId()).withOfficeId(loan.getOfficeId()).withClientId(loan.getClientId())
|
||||
.withGroupId(loan.getGroupId()).withLoanId(loanId).with(changes).build();
|
||||
result = new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(possibleClosingTransaction.getId()) //
|
||||
.withEntityExternalId(possibleClosingTransaction.getExternalId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
.withLoanId(loanId) //
|
||||
.with(changes).build();
|
||||
} else {
|
||||
result = new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(loanId)
|
||||
.withOfficeId(loan.getOfficeId()).withClientId(loan.getClientId()).withGroupId(loan.getGroupId()).withLoanId(loanId)
|
||||
result = new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(loanId) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
.withLoanId(loanId) //
|
||||
.with(changes).build();
|
||||
}
|
||||
|
||||
@@ -1558,7 +1623,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
private void disburseLoanToLoan(final Loan loan, final JsonCommand command, final BigDecimal amount) {
|
||||
|
||||
final LocalDate transactionDate = command.localDateValueOfParameterNamed("actualDisbursementDate");
|
||||
final String txnExternalId = command.stringValueOfParameterNamedAllowingNull("externalId");
|
||||
final ExternalId txnExternalId = externalIdFactory.createFromCommand(command, LoanApiConstants.externalIdParameterName);
|
||||
|
||||
final Locale locale = command.extractLocale();
|
||||
final DateTimeFormatter fmt = DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(locale);
|
||||
@@ -1573,7 +1638,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
private void disburseLoanToSavings(final Loan loan, final JsonCommand command, final Money amount, final PaymentDetail paymentDetail) {
|
||||
|
||||
final LocalDate transactionDate = command.localDateValueOfParameterNamed("actualDisbursementDate");
|
||||
final String txnExternalId = command.stringValueOfParameterNamedAllowingNull("externalId");
|
||||
final ExternalId txnExternalId = externalIdFactory.createFromCommand(command, LoanApiConstants.externalIdParameterName);
|
||||
|
||||
final Locale locale = command.extractLocale();
|
||||
final DateTimeFormatter fmt = DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(locale);
|
||||
@@ -1606,8 +1671,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
final List<Long> existingTransactionIds = new ArrayList<>(loan.findExistingTransactionIds());
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>(loan.findExistingReversedTransactionIds());
|
||||
|
||||
final LoanTransaction newTransferTransaction = LoanTransaction.initiateTransfer(loan.getOffice(), loan, transferDate);
|
||||
ExternalId externalId = externalIdFactory.create();
|
||||
final LoanTransaction newTransferTransaction = LoanTransaction.initiateTransfer(loan.getOffice(), loan, transferDate, externalId);
|
||||
loan.addLoanTransaction(newTransferTransaction);
|
||||
LoanLifecycleStateMachine loanLifecycleStateMachine = defaultLoanLifecycleStateMachine;
|
||||
loanLifecycleStateMachine.transition(LoanEvent.LOAN_INITIATE_TRANSFER, loan);
|
||||
@@ -1628,8 +1693,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
businessEventNotifierService.notifyPreBusinessEvent(new LoanAcceptTransferBusinessEvent(loan));
|
||||
final List<Long> existingTransactionIds = new ArrayList<>(loan.findExistingTransactionIds());
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>(loan.findExistingReversedTransactionIds());
|
||||
|
||||
final LoanTransaction newTransferAcceptanceTransaction = LoanTransaction.approveTransfer(acceptedInOffice, loan, transferDate);
|
||||
ExternalId externalId = externalIdFactory.create();
|
||||
final LoanTransaction newTransferAcceptanceTransaction = LoanTransaction.approveTransfer(acceptedInOffice, loan, transferDate,
|
||||
externalId);
|
||||
loan.addLoanTransaction(newTransferAcceptanceTransaction);
|
||||
LoanLifecycleStateMachine loanLifecycleStateMachine = defaultLoanLifecycleStateMachine;
|
||||
if (loan.getTotalOverpaid() != null) {
|
||||
@@ -1659,7 +1725,10 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final List<Long> existingTransactionIds = new ArrayList<>(loan.findExistingTransactionIds());
|
||||
final List<Long> existingReversedTransactionIds = new ArrayList<>(loan.findExistingReversedTransactionIds());
|
||||
|
||||
final LoanTransaction newTransferAcceptanceTransaction = LoanTransaction.withdrawTransfer(loan.getOffice(), loan, transferDate);
|
||||
ExternalId externalId = externalIdFactory.create();
|
||||
|
||||
final LoanTransaction newTransferAcceptanceTransaction = LoanTransaction.withdrawTransfer(loan.getOffice(), loan, transferDate,
|
||||
externalId);
|
||||
loan.addLoanTransaction(newTransferAcceptanceTransaction);
|
||||
LoanLifecycleStateMachine loanLifecycleStateMachine = defaultLoanLifecycleStateMachine;
|
||||
loanLifecycleStateMachine.transition(LoanEvent.LOAN_WITHDRAW_TRANSFER, loan);
|
||||
@@ -2076,6 +2145,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
.withLoanId(loanId) //
|
||||
.withEntityId(writeOffTransaction.getId()) //
|
||||
.withEntityExternalId(writeOffTransaction.getExternalId()) //
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -2266,7 +2337,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
@Override
|
||||
public CommandProcessingResult recoverFromGuarantor(final Long loanId) {
|
||||
final Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
this.guarantorDomainService.transaferFundsFromGuarantor(loan);
|
||||
this.guarantorDomainService.transferFundsFromGuarantor(loan);
|
||||
return new CommandProcessingResultBuilder().withLoanId(loanId).build();
|
||||
}
|
||||
|
||||
@@ -2333,10 +2404,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
public CommandProcessingResult creditBalanceRefund(Long loanId, JsonCommand command) {
|
||||
this.loanEventApiJsonValidator.validateNewRefundTransaction(command.json());
|
||||
|
||||
Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
final LocalDate transactionDate = command.localDateValueOfParameterNamed("transactionDate");
|
||||
final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed("transactionAmount");
|
||||
final String noteText = command.stringValueOfParameterNamedAllowingNull("note");
|
||||
final String externalId = command.stringValueOfParameterNamedAllowingNull("externalId");
|
||||
final ExternalId externalId = externalIdFactory.createFromCommand(command, LoanApiConstants.externalIdParameterName);
|
||||
|
||||
final Map<String, Object> changes = new LinkedHashMap<>();
|
||||
changes.put("transactionDate", command.stringValueOfParameterNamed("transactionDate"));
|
||||
@@ -2347,15 +2419,21 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
if (StringUtils.isNotBlank(noteText)) {
|
||||
changes.put("note", noteText);
|
||||
}
|
||||
if (StringUtils.isNotBlank(externalId)) {
|
||||
changes.put("externalId", externalId);
|
||||
if (!externalId.isEmpty()) {
|
||||
changes.put(LoanApiConstants.externalIdParameterName, externalId);
|
||||
}
|
||||
|
||||
final CommandProcessingResultBuilder commandProcessingResultBuilder = this.loanAccountDomainService.creditBalanceRefund(loanId,
|
||||
transactionDate, transactionAmount, noteText, externalId);
|
||||
final LoanTransaction loanTransaction = this.loanAccountDomainService.creditBalanceRefund(loan, transactionDate, transactionAmount,
|
||||
noteText, externalId);
|
||||
|
||||
return commandProcessingResultBuilder //
|
||||
.withCommandId(command.commandId()).with(changes) //
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withEntityId(loanTransaction.getId()) //
|
||||
.withEntityExternalId(loanTransaction.getExternalId()) //
|
||||
.withOfficeId(loan.getOfficeId()) //
|
||||
.withClientId(loan.getClientId()) //
|
||||
.withGroupId(loan.getGroupId()) //
|
||||
.withCommandId(command.commandId()) //
|
||||
.with(changes) //
|
||||
.build();
|
||||
|
||||
}
|
||||
@@ -2398,6 +2476,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
this.loanEventApiJsonValidator.validateNewRefundTransaction(command.json());
|
||||
|
||||
final LocalDate transactionDate = command.localDateValueOfParameterNamed("transactionDate");
|
||||
ExternalId externalId = externalIdFactory.createFromCommand(command, LoanApiConstants.externalIdParameterName);
|
||||
|
||||
// checkRefundDateIsAfterAtLeastOneRepayment(loanId, transactionDate);
|
||||
|
||||
@@ -2409,6 +2488,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
changes.put("transactionAmount", command.stringValueOfParameterNamed("transactionAmount"));
|
||||
changes.put("locale", command.locale());
|
||||
changes.put("dateFormat", command.dateFormat());
|
||||
changes.put(LoanApiConstants.externalIdParameterName, externalId);
|
||||
|
||||
final String noteText = command.stringValueOfParameterNamed("note");
|
||||
if (StringUtils.isNotBlank(noteText)) {
|
||||
@@ -2419,11 +2499,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
final CommandProcessingResultBuilder commandProcessingResultBuilder = new CommandProcessingResultBuilder();
|
||||
|
||||
this.loanAccountDomainService.makeRefundForActiveLoan(loanId, commandProcessingResultBuilder, transactionDate, transactionAmount,
|
||||
paymentDetail, noteText, null);
|
||||
LoanTransaction loanTransaction = this.loanAccountDomainService.makeRefundForActiveLoan(loanId, commandProcessingResultBuilder,
|
||||
transactionDate, transactionAmount, paymentDetail, noteText, externalId);
|
||||
|
||||
return commandProcessingResultBuilder.withCommandId(command.commandId()) //
|
||||
return commandProcessingResultBuilder //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withLoanId(loanId) //
|
||||
.withEntityId(loanTransaction.getId()) //
|
||||
.withEntityExternalId(loanTransaction.getExternalId()) //
|
||||
.with(changes) //
|
||||
.build();
|
||||
|
||||
@@ -2502,9 +2585,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
final JsonElement element = fromApiJsonHelper.parse(json);
|
||||
final Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
final LocalDate transactionDate = this.fromApiJsonHelper.extractLocalDateNamed(LoanApiConstants.transactionDateParamName, element);
|
||||
final ExternalId externalId = externalIdFactory.createFromCommand(command, LoanApiConstants.externalIdParameterName);
|
||||
this.loanEventApiJsonValidator.validateLoanForeclosure(command.json());
|
||||
final Map<String, Object> changes = new LinkedHashMap<>();
|
||||
changes.put("transactionDate", transactionDate);
|
||||
changes.put("externalId", externalId);
|
||||
|
||||
String noteText = this.fromApiJsonHelper.extractStringNamed(LoanApiConstants.noteParamName, element);
|
||||
LoanRescheduleRequest loanRescheduleRequest = null;
|
||||
@@ -2519,11 +2604,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
this.loanScheduleHistoryWritePlatformService.createAndSaveLoanScheduleArchive(loan.getRepaymentScheduleInstallments(), loan,
|
||||
loanRescheduleRequest);
|
||||
|
||||
final Map<String, Object> modifications = this.loanAccountDomainService.foreCloseLoan(loan, transactionDate, noteText);
|
||||
final Map<String, Object> modifications = this.loanAccountDomainService.foreCloseLoan(loan, transactionDate, noteText, externalId);
|
||||
changes.putAll(modifications);
|
||||
|
||||
final CommandProcessingResultBuilder commandProcessingResultBuilder = new CommandProcessingResultBuilder();
|
||||
return commandProcessingResultBuilder.withLoanId(loanId) //
|
||||
return commandProcessingResultBuilder //
|
||||
.withLoanId(loanId) //
|
||||
.with(changes) //
|
||||
.build();
|
||||
}
|
||||
@@ -2566,5 +2652,4 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+11
-10
@@ -37,6 +37,7 @@ import org.apache.fineract.infrastructure.accountnumberformat.domain.AccountNumb
|
||||
import org.apache.fineract.infrastructure.accountnumberformat.domain.EntityAccountType;
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
@@ -242,8 +243,8 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
final boolean isExceptionForBalanceCheck = false;
|
||||
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(closedDate, account.getAccountBalance(),
|
||||
PortfolioAccountType.SAVINGS, PortfolioAccountType.SAVINGS, null, null, transferDescription, locale, fmt, null, null,
|
||||
null, null, null, AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, null, null, toSavingsAccount, account,
|
||||
isAccountTransfer, isExceptionForBalanceCheck);
|
||||
null, null, null, AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, ExternalId.empty(), null,
|
||||
toSavingsAccount, account, isAccountTransfer, isExceptionForBalanceCheck);
|
||||
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
updateAlreadyPostedTransactions(existingTransactionIds, account);
|
||||
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
|
||||
@@ -315,8 +316,8 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
final boolean isExceptionForBalanceCheck = false;
|
||||
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(closedDate, account.getAccountBalance(),
|
||||
PortfolioAccountType.SAVINGS, PortfolioAccountType.SAVINGS, null, null, transferDescription, null, fmt, null, null,
|
||||
null, null, null, AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, null, null, toSavingsAccount, account,
|
||||
isAccountTransfer, isExceptionForBalanceCheck);
|
||||
null, null, null, AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, ExternalId.empty(), null,
|
||||
toSavingsAccount, account, isAccountTransfer, isExceptionForBalanceCheck);
|
||||
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
updateAlreadyPostedTransactions(existingTransactionIds, account);
|
||||
account.updateClosedStatus();
|
||||
@@ -400,8 +401,8 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
final boolean isExceptionForBalanceCheck = false;
|
||||
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(closedDate, transactionAmount,
|
||||
PortfolioAccountType.SAVINGS, PortfolioAccountType.SAVINGS, null, null, transferDescription, locale, fmt, null, null,
|
||||
null, null, null, AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, null, null, toSavingsAccount, account,
|
||||
isRegularTransaction, isExceptionForBalanceCheck);
|
||||
null, null, null, AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, ExternalId.empty(), null,
|
||||
toSavingsAccount, account, isRegularTransaction, isExceptionForBalanceCheck);
|
||||
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
updateAlreadyPostedTransactions(existingTransactionIds, account);
|
||||
} else {
|
||||
@@ -491,8 +492,8 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
DepositAccountType.SAVINGS_DEPOSIT);
|
||||
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(closedDate, account.getAccountBalance(),
|
||||
PortfolioAccountType.SAVINGS, PortfolioAccountType.SAVINGS, null, null, transferDescription, locale, fmt, null, null,
|
||||
null, null, null, AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, null, null, toSavingsAccount, account,
|
||||
isRegularTransaction, isExceptionForBalanceCheck);
|
||||
null, null, null, AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, ExternalId.empty(), null,
|
||||
toSavingsAccount, account, isRegularTransaction, isExceptionForBalanceCheck);
|
||||
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
updateAlreadyPostedTransactions(existingTransactionIds, account);
|
||||
} else {
|
||||
@@ -547,8 +548,8 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
DepositAccountType.SAVINGS_DEPOSIT);
|
||||
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(closedDate, account.getAccountBalance(),
|
||||
PortfolioAccountType.SAVINGS, PortfolioAccountType.SAVINGS, null, null, transferDescription, locale, fmt, null, null,
|
||||
null, null, null, AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, null, null, toSavingsAccount, account,
|
||||
isRegularTransaction, isExceptionForBalanceCheck);
|
||||
null, null, null, AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, ExternalId.empty(), null,
|
||||
toSavingsAccount, account, isRegularTransaction, isExceptionForBalanceCheck);
|
||||
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
updateAlreadyPostedTransactions(existingTransactionIds, account);
|
||||
} else {
|
||||
|
||||
+3
-2
@@ -32,6 +32,7 @@ import java.util.Set;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.infrastructure.core.data.PaginationParameters;
|
||||
import org.apache.fineract.infrastructure.core.data.PaginationParametersDataValidator;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.Page;
|
||||
@@ -1700,8 +1701,8 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
|
||||
final LocalDate transactionDate = JdbcSupport.getLocalDate(rs, TRANSACTION_DATE);
|
||||
return new AccountTransferDTO(transactionDate, transactionAmount, PortfolioAccountType.SAVINGS, PortfolioAccountType.SAVINGS,
|
||||
fromAccountId, toAccountId, TRANSFER_INTEREST_TO_SAVINGS, null, null, null, null, null, null, null,
|
||||
AccountTransferType.INTEREST_TRANSFER.getValue(), null, null, null, null, null, null, isRegularTransaction,
|
||||
isExceptionForBalanceCheck);
|
||||
AccountTransferType.INTEREST_TRANSFER.getValue(), null, null, ExternalId.empty(), null, null, null,
|
||||
isRegularTransaction, isExceptionForBalanceCheck);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-4
@@ -47,6 +47,7 @@ import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformServiceUnavailableException;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
@@ -181,8 +182,8 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(account.getActivationLocalDate(),
|
||||
amountForDeposit.getAmount(), PortfolioAccountType.SAVINGS, PortfolioAccountType.SAVINGS,
|
||||
portfolioAccountData.getId(), account.getId(), "Account Transfer", locale, fmt, null, null, null, null, null,
|
||||
AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, null, null, account, fromSavingsAccount,
|
||||
isRegularTransaction, isExceptionForBalanceCheck);
|
||||
AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, ExternalId.empty(), null, account,
|
||||
fromSavingsAccount, isRegularTransaction, isExceptionForBalanceCheck);
|
||||
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
}
|
||||
final boolean isInterestTransfer = false;
|
||||
@@ -285,8 +286,8 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(account.getActivationLocalDate(),
|
||||
amountForDeposit.getAmount(), PortfolioAccountType.SAVINGS, PortfolioAccountType.SAVINGS,
|
||||
portfolioAccountData.getId(), account.getId(), "Account Transfer", locale, fmt, null, null, null, null, null,
|
||||
AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, null, null, account, fromSavingsAccount,
|
||||
isRegularTransaction, isExceptionForBalanceCheck);
|
||||
AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, ExternalId.empty(), null, account,
|
||||
fromSavingsAccount, isRegularTransaction, isExceptionForBalanceCheck);
|
||||
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
}
|
||||
updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds);
|
||||
|
||||
@@ -90,4 +90,5 @@
|
||||
<include file="parts/0068_loan_charge_adjustment.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0069_add_unique_constraint_for_reversal_external_id_of_loan_transactions.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0070_add_event_configuration_for_delinquency_range_change_event.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0071_add_external_id_support_for_loan_transaction.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
-->
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd">
|
||||
<changeSet author="fineract" id="1">
|
||||
<insert tableName="c_configuration">
|
||||
<column name="id" valueNumeric="50"/>
|
||||
<column name="name" value="enable-auto-generated-external-id"/>
|
||||
<column name="value"/>
|
||||
<column name="date_value"/>
|
||||
<column name="string_value"/>
|
||||
<column name="enabled" valueBoolean="false"/>
|
||||
<column name="is_trap_door" valueBoolean="false"/>
|
||||
<column name="description"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
<changeSet id="2" author="fineract">
|
||||
<addColumn tableName="m_portfolio_command_source">
|
||||
<column name="resource_external_id" type="VARCHAR(100)"/>
|
||||
<column name="subresource_external_id" type="VARCHAR(100)"/>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
+6
-3
@@ -5913,6 +5913,7 @@ public class ClientLoanIntegrationTest {
|
||||
this.loanTransactionHelper.makeRepayment(loanPrepaymentDate, Float.parseFloat(prepayAmount), loanID);
|
||||
loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
|
||||
LoanStatusChecker.verifyLoanAccountIsClosed(loanStatusHashMap);
|
||||
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(this.requestSpec, this.responseSpec, "42", false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -5984,6 +5985,7 @@ public class ClientLoanIntegrationTest {
|
||||
HashMap savingsAccountErrorData = validationErrorHelper.makeRepayment(retrieveDueDate, amount, loanID);
|
||||
ArrayList<HashMap> error = (ArrayList<HashMap>) savingsAccountErrorData.get("errors");
|
||||
assertEquals("error.msg.loan.transaction.cannot.be.a.future.date", error.get(0).get("userMessageGlobalisationCode"));
|
||||
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(this.requestSpec, this.responseSpec, "42", false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -6016,7 +6018,8 @@ public class ClientLoanIntegrationTest {
|
||||
ResponseSpecification responseSpec = new ResponseSpecBuilder().expectStatusCode(404).build();
|
||||
LoanTransactionHelper loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, responseSpec);
|
||||
HashMap response = loanTransactionHelper.undoWaiveChargesForLoan(-1, -2, "");
|
||||
assertEquals("error.msg.loan.id.invalid", ((Map) ((List) response.get("errors")).get(0)).get("userMessageGlobalisationCode"));
|
||||
assertEquals("error.msg.loan.transaction.id.invalid",
|
||||
((Map) ((List) response.get("errors")).get(0)).get("userMessageGlobalisationCode"));
|
||||
assertEquals("Transaction with identifier -2 does not exist for loan with identifier -1.",
|
||||
((Map) ((List) response.get("errors")).get(0)).get("defaultUserMessage"));
|
||||
}
|
||||
@@ -6176,13 +6179,13 @@ public class ClientLoanIntegrationTest {
|
||||
assertEquals(1000.0f, loanSummary.get("totalOutstanding"));
|
||||
|
||||
GetLoansLoanIdTransactionsTransactionIdResponse chargeAdjustmentTransaction = this.loanTransactionHelper
|
||||
.getLoanTransactionDetails((long) loanID, chargeAdjustmentResponse.getResourceId());
|
||||
.getLoanTransactionDetails((long) loanID, chargeAdjustmentResponse.getSubResourceId());
|
||||
assertEquals(10.0, chargeAdjustmentTransaction.getAmount());
|
||||
assertEquals(10.0, chargeAdjustmentTransaction.getPenaltyChargesPortion());
|
||||
assertEquals("loanTransactionType.chargeAdjustment", chargeAdjustmentTransaction.getType().getCode());
|
||||
assertEquals(externalId, chargeAdjustmentTransaction.getExternalId());
|
||||
GetLoanTransactionRelation transactionRelation = chargeAdjustmentTransaction.getTransactionRelations().iterator().next();
|
||||
assertEquals(chargeAdjustmentResponse.getResourceId(), transactionRelation.getFromLoanTransaction());
|
||||
assertEquals(chargeAdjustmentResponse.getSubResourceId(), transactionRelation.getFromLoanTransaction());
|
||||
assertEquals((long) penalty1LoanChargeId, transactionRelation.getToLoanCharge());
|
||||
assertEquals("CHARGE_ADJUSTMENT", transactionRelation.getRelationType());
|
||||
|
||||
|
||||
+431
@@ -0,0 +1,431 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.integrationtests;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import io.restassured.builder.RequestSpecBuilder;
|
||||
import io.restassured.builder.ResponseSpecBuilder;
|
||||
import io.restassured.http.ContentType;
|
||||
import io.restassured.specification.RequestSpecification;
|
||||
import io.restassured.specification.ResponseSpecification;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
import org.apache.fineract.client.models.PostClientsResponse;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdChargesChargeIdRequest;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdChargesChargeIdResponse;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsTransactionIdRequest;
|
||||
import org.apache.fineract.integrationtests.client.IntegrationTest;
|
||||
import org.apache.fineract.integrationtests.common.ClientHelper;
|
||||
import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
|
||||
import org.apache.fineract.integrationtests.common.Utils;
|
||||
import org.apache.fineract.integrationtests.common.accounting.Account;
|
||||
import org.apache.fineract.integrationtests.common.accounting.AccountHelper;
|
||||
import org.apache.fineract.integrationtests.common.charges.ChargesHelper;
|
||||
import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
|
||||
import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
|
||||
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
|
||||
import org.apache.fineract.integrationtests.common.savings.SavingsAccountHelper;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class ExternalIdSupportIntegrationTest extends IntegrationTest {
|
||||
|
||||
private ResponseSpecification responseSpec;
|
||||
private RequestSpecification requestSpec;
|
||||
|
||||
private ClientHelper clientHelper;
|
||||
private AccountHelper accountHelper;
|
||||
private LoanTransactionHelper loanTransactionHelper;
|
||||
|
||||
private DateTimeFormatter dateFormatter = new DateTimeFormatterBuilder().appendPattern("dd MMMM yyyy").toFormatter();
|
||||
|
||||
@BeforeAll
|
||||
public void init() {
|
||||
Utils.initializeRESTAssured();
|
||||
this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
|
||||
this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
|
||||
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
|
||||
this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec);
|
||||
this.accountHelper = new AccountHelper(this.requestSpec, this.responseSpec);
|
||||
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(requestSpec, responseSpec, 50, true);
|
||||
final Account assetAccount = this.accountHelper.createAssetAccount();
|
||||
final Account assetFeeAndPenaltyAccount = this.accountHelper.createAssetAccount();
|
||||
final Account incomeAccount = this.accountHelper.createIncomeAccount();
|
||||
final Account expenseAccount = this.accountHelper.createExpenseAccount();
|
||||
final Account overpaymentAccount = this.accountHelper.createLiabilityAccount();
|
||||
|
||||
Integer penalty = ChargesHelper.createCharges(requestSpec, responseSpec,
|
||||
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "10", true));
|
||||
|
||||
Integer penalty2 = ChargesHelper.createCharges(requestSpec, responseSpec,
|
||||
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "10", true, 1));
|
||||
|
||||
final String loanProductJSON = new LoanProductTestBuilder().withPrincipal("1000").withRepaymentTypeAsMonth()
|
||||
.withRepaymentAfterEvery("1").withNumberOfRepayments("1").withRepaymentTypeAsMonth().withinterestRatePerPeriod("0")
|
||||
.withInterestRateFrequencyTypeAsMonths().withAmortizationTypeAsEqualPrincipalPayment().withInterestTypeAsFlat()
|
||||
.withAccountingRulePeriodicAccrual(new Account[] { assetAccount, incomeAccount, expenseAccount, overpaymentAccount })
|
||||
.withDaysInMonth("30").withDaysInYear("365").withMoratorium("0", "0")
|
||||
.withFeeAndPenaltyAssetAccount(assetFeeAndPenaltyAccount).build(null);
|
||||
final Integer loanProductID = this.loanTransactionHelper.getLoanProductId(loanProductJSON);
|
||||
|
||||
final PostClientsResponse client = clientHelper.createClient(ClientHelper.defaultClientCreationRequest());
|
||||
|
||||
String loanExternalIdStr = UUID.randomUUID().toString();
|
||||
final HashMap loan = applyForLoanApplication(client.getClientId().intValue(), loanProductID, loanExternalIdStr);
|
||||
Integer loanId = (Integer) loan.get("resourceId");
|
||||
|
||||
this.loanTransactionHelper.approveLoan("02 September 2022", loanId);
|
||||
String txnExternalIdStr = UUID.randomUUID().toString();
|
||||
final HashMap disbursedLoanResult = this.loanTransactionHelper.disburseLoan("03 September 2022", loanId, "1000", txnExternalIdStr);
|
||||
|
||||
// Check whether the provided external id was retrieved
|
||||
assertEquals(txnExternalIdStr, disbursedLoanResult.get("resourceExternalId"));
|
||||
|
||||
LocalDate targetDate = LocalDate.of(2022, 9, 7);
|
||||
final String penaltyCharge1AddedDate = dateFormatter.format(targetDate);
|
||||
|
||||
Integer penalty1LoanChargeId = this.loanTransactionHelper.addChargesForLoan(loanId,
|
||||
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(penalty), penaltyCharge1AddedDate, "10"));
|
||||
|
||||
Integer penalty2LoanChargeId = this.loanTransactionHelper.addChargesForLoan(loanId,
|
||||
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(penalty), penaltyCharge1AddedDate, "10"));
|
||||
|
||||
// Check whether we can fetch transaction templates with proper result http code (HTTP 200..300)
|
||||
ok(fineract().loanTransactions.retrieveTransactionTemplate1(loanExternalIdStr, "repayment", null, null, null));
|
||||
ok(fineract().loanTransactions.retrieveTransactionTemplate1(loanExternalIdStr, "payoutRefund", null, null, null));
|
||||
ok(fineract().loanTransactions.retrieveTransactionTemplate1(loanExternalIdStr, "waiveinterest", null, null, null));
|
||||
ok(fineract().loanTransactions.retrieveTransactionTemplate1(loanExternalIdStr, "close-rescheduled", null, null, null));
|
||||
ok(fineract().loanTransactions.retrieveTransactionTemplate1(loanExternalIdStr, "disburse", null, null, null));
|
||||
ok(fineract().loanTransactions.retrieveTransactionTemplate1(loanExternalIdStr, "recoverypayment", null, null, null));
|
||||
ok(fineract().loanTransactions.retrieveTransactionTemplate1(loanExternalIdStr, "refundbycash", null, null, null));
|
||||
ok(fineract().loanTransactions.retrieveTransactionTemplate1(loanExternalIdStr, "foreclosure", null, null, null));
|
||||
ok(fineract().loanTransactions.retrieveTransactionTemplate1(loanExternalIdStr, "creditBalanceRefund", null, null, null));
|
||||
|
||||
// Check whether an external id was generated
|
||||
String waiveChargeExternalIdStr = UUID.randomUUID().toString();
|
||||
PostLoansLoanIdChargesChargeIdResponse waiveLoanChargeResult = loanTransactionHelper.waiveLoanCharge((long) loanId,
|
||||
(long) penalty1LoanChargeId, new PostLoansLoanIdChargesChargeIdRequest().externalId(waiveChargeExternalIdStr));
|
||||
assertEquals(waiveChargeExternalIdStr, waiveLoanChargeResult.getSubResourceExternalId());
|
||||
|
||||
// Check whether an external id was generated
|
||||
HashMap undoWaiveLoanChargeResult = loanTransactionHelper.undoWaiveLoanCharge((long) loanId, waiveChargeExternalIdStr);
|
||||
assertEquals(waiveChargeExternalIdStr, undoWaiveLoanChargeResult.get("subResourceExternalId"));
|
||||
|
||||
// Check whether an external id was generated
|
||||
waiveLoanChargeResult = loanTransactionHelper.waiveLoanCharge((long) loanId, (long) penalty1LoanChargeId,
|
||||
new PostLoansLoanIdChargesChargeIdRequest());
|
||||
assertNotNull(waiveLoanChargeResult.getSubResourceExternalId());
|
||||
|
||||
// Check whether an external id was generated
|
||||
undoWaiveLoanChargeResult = loanTransactionHelper.undoWaiveLoanCharge(loanExternalIdStr, waiveLoanChargeResult.getSubResourceId());
|
||||
assertNotNull(undoWaiveLoanChargeResult.get("subResourceExternalId"));
|
||||
|
||||
// Check whether an external id was generated
|
||||
waiveChargeExternalIdStr = UUID.randomUUID().toString();
|
||||
waiveLoanChargeResult = loanTransactionHelper.waiveLoanCharge((long) loanId, (long) penalty1LoanChargeId,
|
||||
new PostLoansLoanIdChargesChargeIdRequest().externalId(waiveChargeExternalIdStr));
|
||||
assertEquals(waiveChargeExternalIdStr, waiveLoanChargeResult.getSubResourceExternalId());
|
||||
|
||||
// Check whether an external id was generated
|
||||
undoWaiveLoanChargeResult = loanTransactionHelper.undoWaiveLoanCharge(loanExternalIdStr,
|
||||
waiveLoanChargeResult.getSubResourceExternalId());
|
||||
assertEquals(waiveChargeExternalIdStr, undoWaiveLoanChargeResult.get("subResourceExternalId"));
|
||||
|
||||
// Check whether an external id was generated
|
||||
final PostLoansLoanIdTransactionsResponse repaymentResult = loanTransactionHelper.makeLoanRepayment(loanExternalIdStr,
|
||||
new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate("06 September 2022").locale("en")
|
||||
.transactionAmount(5.0));
|
||||
assertNotNull(repaymentResult.getResourceExternalId());
|
||||
|
||||
// Check whether the provided external id was retrieved
|
||||
String transactionExternalIdStr = UUID.randomUUID().toString();
|
||||
final PostLoansLoanIdTransactionsResponse repaymentResultWithExternalId = loanTransactionHelper.makeLoanRepayment(loanExternalIdStr,
|
||||
new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate("06 September 2022").locale("en")
|
||||
.transactionAmount(5.0).externalId(transactionExternalIdStr));
|
||||
assertEquals(transactionExternalIdStr, repaymentResultWithExternalId.getResourceExternalId());
|
||||
|
||||
// Check whether an external id was generated
|
||||
final PostLoansLoanIdTransactionsResponse merchantIssuedRefundResult = loanTransactionHelper
|
||||
.makeMerchantIssuedRefund(loanExternalIdStr, new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy")
|
||||
.transactionDate("06 September 2022").locale("en").transactionAmount(5.0));
|
||||
assertNotNull(merchantIssuedRefundResult.getResourceExternalId());
|
||||
|
||||
// Check whether the provided external id was retrieved
|
||||
transactionExternalIdStr = UUID.randomUUID().toString();
|
||||
final PostLoansLoanIdTransactionsResponse merchantIssuedRefundResultWithExternalId = loanTransactionHelper
|
||||
.makeMerchantIssuedRefund(loanExternalIdStr, new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy")
|
||||
.transactionDate("06 September 2022").locale("en").transactionAmount(5.0).externalId(transactionExternalIdStr));
|
||||
assertEquals(transactionExternalIdStr, merchantIssuedRefundResultWithExternalId.getResourceExternalId());
|
||||
|
||||
// Check whether an external id was generated
|
||||
final PostLoansLoanIdTransactionsResponse payoutRefundResult = loanTransactionHelper.makePayoutRefund(loanExternalIdStr,
|
||||
new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate("06 September 2022").locale("en")
|
||||
.transactionAmount(5.0));
|
||||
assertNotNull(payoutRefundResult.getResourceExternalId());
|
||||
|
||||
// Check whether the provided external id was retrieved
|
||||
transactionExternalIdStr = UUID.randomUUID().toString();
|
||||
final PostLoansLoanIdTransactionsResponse payoutRefundResultWithExternalId = loanTransactionHelper
|
||||
.makePayoutRefund(loanExternalIdStr, new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy")
|
||||
.transactionDate("06 September 2022").locale("en").transactionAmount(5.0).externalId(transactionExternalIdStr));
|
||||
assertEquals(transactionExternalIdStr, payoutRefundResultWithExternalId.getResourceExternalId());
|
||||
|
||||
// Check whether an external id was generated
|
||||
final PostLoansLoanIdTransactionsResponse goodWillCreditResult = loanTransactionHelper.makeGoodwillCredit(loanExternalIdStr,
|
||||
new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate("06 September 2022").locale("en")
|
||||
.transactionAmount(5.0));
|
||||
assertNotNull(goodWillCreditResult.getResourceExternalId());
|
||||
|
||||
// Check whether the provided external id was retrieved
|
||||
transactionExternalIdStr = UUID.randomUUID().toString();
|
||||
final PostLoansLoanIdTransactionsResponse goodWillCreditResultWithExternalId = loanTransactionHelper
|
||||
.makeGoodwillCredit(loanExternalIdStr, new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy")
|
||||
.transactionDate("06 September 2022").locale("en").transactionAmount(5.0).externalId(transactionExternalIdStr));
|
||||
assertEquals(transactionExternalIdStr, goodWillCreditResultWithExternalId.getResourceExternalId());
|
||||
|
||||
// Check whether an external id was generated
|
||||
final PostLoansLoanIdTransactionsResponse writeoffResult = loanTransactionHelper.makeWriteoff(loanExternalIdStr,
|
||||
new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate("06 September 2022").locale("en"));
|
||||
assertNotNull(writeoffResult.getResourceExternalId());
|
||||
|
||||
// Check whether an external id was generated
|
||||
final PostLoansLoanIdTransactionsResponse makeRecoveryPaymentResult = loanTransactionHelper.makeRecoveryPayment(loanExternalIdStr,
|
||||
new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate("06 September 2022").locale("en")
|
||||
.transactionAmount(5.0));
|
||||
assertNotNull(makeRecoveryPaymentResult.getResourceExternalId());
|
||||
|
||||
// Check whether the provided external id was retrieved
|
||||
transactionExternalIdStr = UUID.randomUUID().toString();
|
||||
final PostLoansLoanIdTransactionsResponse makeRecoveryPaymentResultWithExternalId = loanTransactionHelper
|
||||
.makeRecoveryPayment(loanExternalIdStr, new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy")
|
||||
.transactionDate("06 September 2022").locale("en").transactionAmount(5.0).externalId(transactionExternalIdStr));
|
||||
assertEquals(transactionExternalIdStr, makeRecoveryPaymentResultWithExternalId.getResourceExternalId());
|
||||
|
||||
// Check whether an external id was generated
|
||||
final PostLoansLoanIdTransactionsResponse undoWriteoffResult = loanTransactionHelper.makeUndoWriteoff(loanExternalIdStr,
|
||||
new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate("06 September 2022").locale("en")
|
||||
.transactionAmount(5.0));
|
||||
assertNotNull(undoWriteoffResult.getResourceExternalId());
|
||||
|
||||
// Check whether the provided external id was retrieved
|
||||
transactionExternalIdStr = UUID.randomUUID().toString();
|
||||
final PostLoansLoanIdTransactionsResponse writeoffResultWithExternalId = loanTransactionHelper.makeWriteoff(loanExternalIdStr,
|
||||
new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate("06 September 2022").locale("en")
|
||||
.externalId(transactionExternalIdStr));
|
||||
assertEquals(transactionExternalIdStr, writeoffResultWithExternalId.getResourceExternalId());
|
||||
|
||||
// Check whether the provided external id was retrieved
|
||||
final PostLoansLoanIdTransactionsResponse undoWriteoffResultWithExternalId = loanTransactionHelper
|
||||
.makeUndoWriteoff(loanExternalIdStr, new PostLoansLoanIdTransactionsRequest());
|
||||
assertEquals(transactionExternalIdStr, undoWriteoffResultWithExternalId.getResourceExternalId());
|
||||
|
||||
// Overpay the account
|
||||
transactionExternalIdStr = UUID.randomUUID().toString();
|
||||
final PostLoansLoanIdTransactionsResponse overpaymentResultWithExternalId = loanTransactionHelper
|
||||
.makeLoanRepayment(loanExternalIdStr, new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy")
|
||||
.transactionDate("06 September 2022").locale("en").transactionAmount(5000.0).externalId(transactionExternalIdStr));
|
||||
assertEquals(transactionExternalIdStr, overpaymentResultWithExternalId.getResourceExternalId());
|
||||
|
||||
// Check whether an external id was generated
|
||||
final PostLoansLoanIdTransactionsResponse makeCreditBalanceRefundResult = loanTransactionHelper
|
||||
.makeCreditBalanceRefund(loanExternalIdStr, new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy")
|
||||
.transactionDate("06 September 2022").locale("en").transactionAmount(5.0));
|
||||
assertNotNull(makeCreditBalanceRefundResult.getResourceExternalId());
|
||||
|
||||
// Check whether the provided external id was retrieved
|
||||
transactionExternalIdStr = UUID.randomUUID().toString();
|
||||
final PostLoansLoanIdTransactionsResponse makeCreditBalanceRefundResultWithExternalId = loanTransactionHelper
|
||||
.makeCreditBalanceRefund(loanExternalIdStr, new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy")
|
||||
.transactionDate("06 September 2022").locale("en").transactionAmount(5.0).externalId(transactionExternalIdStr));
|
||||
assertEquals(transactionExternalIdStr, makeCreditBalanceRefundResultWithExternalId.getResourceExternalId());
|
||||
|
||||
// Check whether an external id was generated
|
||||
final PostLoansLoanIdTransactionsResponse chargeRefundResult = loanTransactionHelper.makeChargeRefund(loanExternalIdStr,
|
||||
new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").locale("en").loanChargeId(penalty1LoanChargeId)
|
||||
.transactionAmount(1.0));
|
||||
assertNotNull(chargeRefundResult.getResourceExternalId());
|
||||
|
||||
// Check whether the provided external id was retrieved
|
||||
transactionExternalIdStr = UUID.randomUUID().toString();
|
||||
final PostLoansLoanIdTransactionsResponse chargeRefundResultWithExternalId = loanTransactionHelper
|
||||
.makeChargeRefund(loanExternalIdStr, new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").locale("en")
|
||||
.loanChargeId(penalty1LoanChargeId).transactionAmount(1.0).externalId(transactionExternalIdStr));
|
||||
assertEquals(transactionExternalIdStr, chargeRefundResultWithExternalId.getResourceExternalId());
|
||||
|
||||
// Create a loan with interest and test the rest of the transactions
|
||||
|
||||
final String loanProductWithInterestJSON = new LoanProductTestBuilder().withPrincipal("10000.0").withRepaymentTypeAsMonth()
|
||||
.withRepaymentAfterEvery("2").withNumberOfRepayments("5").withRepaymentTypeAsMonth().withinterestRatePerPeriod("1")
|
||||
.withInterestRateFrequencyTypeAsMonths().withAmortizationTypeAsEqualPrincipalPayment().withInterestTypeAsFlat()
|
||||
.withAccounting("1", null).build(null);
|
||||
final Integer loanProductWithInterestID = this.loanTransactionHelper.getLoanProductId(loanProductWithInterestJSON);
|
||||
|
||||
LocalDate aMonthBefore = Utils.getLocalDateOfTenant().minusMonths(1);
|
||||
String formattedDate = dateFormatter.format(aMonthBefore);
|
||||
|
||||
final Integer savingsId = SavingsAccountHelper.openSavingsAccount(this.requestSpec, this.responseSpec,
|
||||
client.getClientId().intValue(), "10000.0");
|
||||
|
||||
loanExternalIdStr = UUID.randomUUID().toString();
|
||||
final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal("10000.0").withLoanTermFrequency("10")
|
||||
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("5").withRepaymentEveryAfter("2")
|
||||
.withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("1").withInterestTypeAsFlatBalance()
|
||||
.withAmortizationTypeAsEqualPrincipalPayments().withInterestCalculationPeriodTypeSameAsRepaymentPeriod()
|
||||
.withExpectedDisbursementDate(formattedDate).withSubmittedOnDate(formattedDate).withLoanType("individual")
|
||||
.withExternalId(loanExternalIdStr)
|
||||
.build(client.getClientId().toString(), loanProductWithInterestID.toString(), savingsId.toString());
|
||||
final HashMap loanWithInterest = this.loanTransactionHelper.getLoanId(loanApplicationJSON, "");
|
||||
Integer loanWithInterestId = (Integer) loanWithInterest.get("resourceId");
|
||||
|
||||
this.loanTransactionHelper.approveLoan(formattedDate, loanWithInterestId);
|
||||
final HashMap disbursedLoanWithInterestResult = this.loanTransactionHelper.disburseLoan(formattedDate, loanWithInterestId, "1000",
|
||||
null);
|
||||
// Check whether an external id was generated
|
||||
assertNotNull(disbursedLoanWithInterestResult.get("resourceExternalId"));
|
||||
LocalDate aMonthBeforePlus3Days = aMonthBefore.plusDays(3);
|
||||
formattedDate = dateFormatter.format(aMonthBeforePlus3Days);
|
||||
|
||||
Integer penalty3LoanChargeId = this.loanTransactionHelper.addChargesForLoan(loanWithInterestId,
|
||||
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(penalty), formattedDate, "10"));
|
||||
|
||||
Integer penalty4LoanChargeId = this.loanTransactionHelper.addChargesForLoan(loanWithInterestId,
|
||||
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(penalty2), formattedDate, "1000"));
|
||||
|
||||
Integer penalty5LoanChargeId = this.loanTransactionHelper.addChargesForLoan(loanWithInterestId,
|
||||
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(penalty2), formattedDate, "1000"));
|
||||
|
||||
// Check whether an external id was generated
|
||||
final PostLoansLoanIdTransactionsResponse waiveInterestResult = loanTransactionHelper.makeWaiveInterest(loanExternalIdStr,
|
||||
new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate(formattedDate).locale("en")
|
||||
.transactionAmount(5.0));
|
||||
assertNotNull(waiveInterestResult.getResourceExternalId());
|
||||
|
||||
// Check whether the provided external id was retrieved
|
||||
String waiveInterestTxnExternalIdStr = UUID.randomUUID().toString();
|
||||
final PostLoansLoanIdTransactionsResponse waiveInterestResultWithExternalId = loanTransactionHelper
|
||||
.makeWaiveInterest(loanExternalIdStr, new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy")
|
||||
.transactionDate(formattedDate).locale("en").transactionAmount(1.0).externalId(waiveInterestTxnExternalIdStr));
|
||||
assertEquals(waiveInterestTxnExternalIdStr, waiveInterestResultWithExternalId.getResourceExternalId());
|
||||
|
||||
String inAdvanceRepaymentTxnExternalIdStr = UUID.randomUUID().toString();
|
||||
final PostLoansLoanIdTransactionsResponse inAdvanceRepaymentResult = loanTransactionHelper.makeLoanRepayment(loanExternalIdStr,
|
||||
new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate(formattedDate).locale("en")
|
||||
.transactionAmount(500.0).externalId(inAdvanceRepaymentTxnExternalIdStr));
|
||||
|
||||
String inAdvanceRepayment2TxnExternalIdStr = UUID.randomUUID().toString();
|
||||
final PostLoansLoanIdTransactionsResponse inAdvanceRepayment2Result = loanTransactionHelper.makeLoanRepayment(loanExternalIdStr,
|
||||
new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate(formattedDate).locale("en")
|
||||
.transactionAmount(50.0).externalId(inAdvanceRepayment2TxnExternalIdStr));
|
||||
|
||||
// Check whether an external id was generated
|
||||
final PostLoansLoanIdTransactionsResponse makeRefundByCashResult = loanTransactionHelper.makeRefundByCash(loanExternalIdStr,
|
||||
new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate(formattedDate).locale("en")
|
||||
.transactionAmount(1.0));
|
||||
assertNotNull(makeRefundByCashResult.getResourceExternalId());
|
||||
|
||||
// Check whether the provided external id was retrieved
|
||||
String makeRefundTxnExternalIdStr = UUID.randomUUID().toString();
|
||||
final PostLoansLoanIdTransactionsResponse makeRefundByCashResultWithExternalId = loanTransactionHelper
|
||||
.makeRefundByCash(loanExternalIdStr, new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy")
|
||||
.transactionDate(formattedDate).locale("en").transactionAmount(5.0).externalId(makeRefundTxnExternalIdStr));
|
||||
assertEquals(makeRefundTxnExternalIdStr, makeRefundByCashResultWithExternalId.getResourceExternalId());
|
||||
|
||||
PostLoansLoanIdTransactionsResponse adjustmentResult = loanTransactionHelper.reverseLoanTransaction((long) loanWithInterestId,
|
||||
inAdvanceRepayment2TxnExternalIdStr, new PostLoansLoanIdTransactionsTransactionIdRequest().transactionDate(formattedDate)
|
||||
.locale("en").dateFormat("dd MMMM yyyy").transactionAmount(0.0));
|
||||
assertEquals(inAdvanceRepayment2TxnExternalIdStr, adjustmentResult.getResourceExternalId());
|
||||
|
||||
adjustmentResult = loanTransactionHelper.reverseLoanTransaction(loanExternalIdStr, inAdvanceRepaymentResult.getResourceId(),
|
||||
new PostLoansLoanIdTransactionsTransactionIdRequest().transactionDate(formattedDate).locale("en").dateFormat("dd MMMM yyyy")
|
||||
.transactionAmount(0.0));
|
||||
assertEquals(inAdvanceRepaymentTxnExternalIdStr, adjustmentResult.getResourceExternalId());
|
||||
|
||||
String adjustTransactionExternalId = UUID.randomUUID().toString();
|
||||
adjustmentResult = loanTransactionHelper.adjustLoanTransaction(loanExternalIdStr, waiveInterestTxnExternalIdStr,
|
||||
new PostLoansLoanIdTransactionsTransactionIdRequest().transactionDate(formattedDate).locale("en").dateFormat("dd MMMM yyyy")
|
||||
.transactionAmount(2.0).externalId(adjustTransactionExternalId));
|
||||
assertEquals(adjustTransactionExternalId, adjustmentResult.getResourceExternalId());
|
||||
|
||||
adjustmentResult = loanTransactionHelper.adjustLoanTransaction(loanExternalIdStr, adjustmentResult.getResourceExternalId(),
|
||||
new PostLoansLoanIdTransactionsTransactionIdRequest().transactionDate(formattedDate).locale("en").dateFormat("dd MMMM yyyy")
|
||||
.transactionAmount(1.0));
|
||||
assertNotNull(adjustmentResult.getResourceExternalId());
|
||||
|
||||
String repaymentForChargeback = UUID.randomUUID().toString();
|
||||
final PostLoansLoanIdTransactionsResponse repaymentForChargebackResult = loanTransactionHelper.makeLoanRepayment(loanExternalIdStr,
|
||||
new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate(formattedDate).locale("en")
|
||||
.transactionAmount(5.0).externalId(repaymentForChargeback));
|
||||
|
||||
String chargebackTransactionExternalId = UUID.randomUUID().toString();
|
||||
PostLoansLoanIdTransactionsResponse chargebackResult = loanTransactionHelper.chargebackLoanTransaction(loanExternalIdStr,
|
||||
repaymentForChargebackResult.getResourceExternalId(), new PostLoansLoanIdTransactionsTransactionIdRequest().locale("en")
|
||||
.transactionAmount(2.0).externalId(chargebackTransactionExternalId).paymentTypeId(1L));
|
||||
assertEquals(chargebackTransactionExternalId, chargebackResult.getResourceExternalId());
|
||||
|
||||
chargebackResult = loanTransactionHelper.chargebackLoanTransaction(loanExternalIdStr,
|
||||
repaymentForChargebackResult.getResourceExternalId(),
|
||||
new PostLoansLoanIdTransactionsTransactionIdRequest().locale("en").transactionAmount(2.0).paymentTypeId(2L));
|
||||
assertNotNull(chargebackResult.getResourceExternalId());
|
||||
|
||||
// Check whether the provided external id was retrieved
|
||||
String chargeAdjustmentExternalIdStr = UUID.randomUUID().toString();
|
||||
PostLoansLoanIdChargesChargeIdResponse chargeAdjustmentResult = loanTransactionHelper.chargeAdjustment((long) loanWithInterestId,
|
||||
(long) penalty3LoanChargeId,
|
||||
new PostLoansLoanIdChargesChargeIdRequest().externalId(chargeAdjustmentExternalIdStr).amount(1.0).locale("en"));
|
||||
assertEquals(chargeAdjustmentExternalIdStr, chargeAdjustmentResult.getSubResourceExternalId());
|
||||
|
||||
// Check whether an external id was generated
|
||||
chargeAdjustmentResult = loanTransactionHelper.chargeAdjustment((long) loanWithInterestId, (long) penalty3LoanChargeId,
|
||||
new PostLoansLoanIdChargesChargeIdRequest().amount(1.0).locale("en"));
|
||||
assertNotNull(chargeAdjustmentResult.getSubResourceExternalId());
|
||||
|
||||
HashMap payChargeResult = this.loanTransactionHelper.payChargesForLoan(loanWithInterestId, penalty4LoanChargeId,
|
||||
LoanTransactionHelper.getPayChargeJSON(formattedDate, null), "");
|
||||
assertNotNull(payChargeResult.get("subResourceExternalId"));
|
||||
|
||||
String payChargeExternalIdStr = UUID.randomUUID().toString();
|
||||
payChargeResult = this.loanTransactionHelper.payChargesForLoan(loanWithInterestId, penalty5LoanChargeId,
|
||||
LoanTransactionHelper.getPayChargeJSON(formattedDate, null, payChargeExternalIdStr), "");
|
||||
assertEquals(payChargeExternalIdStr, payChargeResult.get("subResourceExternalId"));
|
||||
|
||||
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(requestSpec, responseSpec, 50, false);
|
||||
}
|
||||
|
||||
private HashMap applyForLoanApplication(final Integer clientID, final Integer loanProductID, final String externalId) {
|
||||
final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal("1000").withLoanTermFrequency("1")
|
||||
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("1").withRepaymentEveryAfter("1")
|
||||
.withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("0").withInterestTypeAsFlatBalance()
|
||||
.withAmortizationTypeAsEqualPrincipalPayments().withInterestCalculationPeriodTypeSameAsRepaymentPeriod()
|
||||
.withExpectedDisbursementDate("03 September 2022").withSubmittedOnDate("01 September 2022").withLoanType("individual")
|
||||
.withExternalId(externalId).build(clientID.toString(), loanProductID.toString(), null);
|
||||
return (HashMap) this.loanTransactionHelper.createLoanAccount(loanApplicationJSON, "");
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -75,7 +75,7 @@ public class LoanAuditingIntegrationTest {
|
||||
public void checkAuditDates() throws InterruptedException {
|
||||
final Integer staffId = StaffHelper.createStaff(this.requestSpec, this.responseSpec);
|
||||
String username = Utils.randomNameGenerator("user", 8);
|
||||
final Integer userId = (Integer) UserHelper.createUser(this.requestSpec, this.responseSpec, 1, staffId, username, "password",
|
||||
final Integer userId = (Integer) UserHelper.createUser(this.requestSpec, this.responseSpec, 1, staffId, username, "P4ssw0rd",
|
||||
"resourceId");
|
||||
|
||||
LOG.info("-------------------------Creating Client---------------------------");
|
||||
@@ -129,7 +129,7 @@ public class LoanAuditingIntegrationTest {
|
||||
|
||||
this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
|
||||
this.requestSpec.header("Authorization",
|
||||
"Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(username, "password"));
|
||||
"Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(username, "P4ssw0rd"));
|
||||
|
||||
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
|
||||
loanStatusHashMap = this.loanTransactionHelper.approveLoan("11 July 2022", loanID);
|
||||
|
||||
+2
-2
@@ -74,7 +74,7 @@ public class LoanTransactionAuditingIntegrationTest {
|
||||
public void checkAuditDates() throws InterruptedException {
|
||||
final Integer staffId = StaffHelper.createStaff(this.requestSpec, this.responseSpec);
|
||||
String username = Utils.randomNameGenerator("user", 8);
|
||||
final Integer userId = (Integer) UserHelper.createUser(this.requestSpec, this.responseSpec, 1, staffId, username, "password",
|
||||
final Integer userId = (Integer) UserHelper.createUser(this.requestSpec, this.responseSpec, 1, staffId, username, "P4ssw0rd",
|
||||
"resourceId");
|
||||
|
||||
LOG.info("-------------------------Creating Client---------------------------");
|
||||
@@ -138,7 +138,7 @@ public class LoanTransactionAuditingIntegrationTest {
|
||||
|
||||
this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
|
||||
this.requestSpec.header("Authorization",
|
||||
"Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(username, "password"));
|
||||
"Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(username, "P4ssw0rd"));
|
||||
|
||||
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
|
||||
this.loanTransactionHelper.reverseRepayment(loanID, transactionId, "11 July 2022");
|
||||
|
||||
+11
-3
@@ -98,9 +98,9 @@ public class GlobalConfigurationHelper {
|
||||
ArrayList<HashMap> expectedGlobalConfigurations = getAllDefaultGlobalConfigurations();
|
||||
ArrayList<HashMap> actualGlobalConfigurations = getAllGlobalConfigurations(requestSpec, responseSpec);
|
||||
|
||||
// There are currently 37 global configurations.
|
||||
Assertions.assertEquals(44, expectedGlobalConfigurations.size());
|
||||
Assertions.assertEquals(44, actualGlobalConfigurations.size());
|
||||
// There are currently 45 global configurations.
|
||||
Assertions.assertEquals(45, expectedGlobalConfigurations.size());
|
||||
Assertions.assertEquals(45, actualGlobalConfigurations.size());
|
||||
|
||||
for (int i = 0; i < expectedGlobalConfigurations.size(); i++) {
|
||||
|
||||
@@ -488,6 +488,14 @@ public class GlobalConfigurationHelper {
|
||||
loanRepaymentOverdueDaysDefault.put("trapDoor", false);
|
||||
defaults.add(loanRepaymentOverdueDaysDefault);
|
||||
|
||||
HashMap<String, Object> isAutomaticExternalIdGenerationEnabled = new HashMap<>();
|
||||
isAutomaticExternalIdGenerationEnabled.put("id", 50);
|
||||
isAutomaticExternalIdGenerationEnabled.put("name", "enable-auto-generated-external-id");
|
||||
isAutomaticExternalIdGenerationEnabled.put("value", 0);
|
||||
isAutomaticExternalIdGenerationEnabled.put("enabled", false);
|
||||
isAutomaticExternalIdGenerationEnabled.put("trapDoor", false);
|
||||
defaults.add(isAutomaticExternalIdGenerationEnabled);
|
||||
|
||||
return defaults;
|
||||
}
|
||||
|
||||
|
||||
+208
-6
@@ -58,7 +58,6 @@ import org.apache.fineract.client.models.PostLoansLoanIdResponse;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsTransactionIdRequest;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsTransactionIdResponse;
|
||||
import org.apache.fineract.client.models.PutLoansLoanIdResponse;
|
||||
import org.apache.fineract.client.util.JSON;
|
||||
import org.apache.fineract.integrationtests.client.IntegrationTest;
|
||||
@@ -116,8 +115,17 @@ public class LoanTransactionHelper extends IntegrationTest {
|
||||
return this.getLoanId(loanApplicationJSON, this.requestSpec, this.responseSpec);
|
||||
}
|
||||
|
||||
public HashMap getLoanId(final String loanApplicationJSON, final String responseAttribute) {
|
||||
return (HashMap) this.getLoanId(loanApplicationJSON, responseAttribute, this.requestSpec, this.responseSpec);
|
||||
}
|
||||
|
||||
public Object getLoanId(final String loanApplicationJSON, final String responseAttribute, RequestSpecification requestSpec,
|
||||
ResponseSpecification responseSpec) {
|
||||
return Utils.performServerPost(requestSpec, responseSpec, APPLY_LOAN_URL, loanApplicationJSON, responseAttribute);
|
||||
}
|
||||
|
||||
public Integer getLoanId(final String loanApplicationJSON, RequestSpecification requestSpec, ResponseSpecification responseSpec) {
|
||||
return Utils.performServerPost(requestSpec, responseSpec, APPLY_LOAN_URL, loanApplicationJSON, "loanId");
|
||||
return (Integer) getLoanId(loanApplicationJSON, "loanId", requestSpec, responseSpec);
|
||||
}
|
||||
|
||||
public HashMap<String, Integer> getGlimId(final String loanApplicationJSON) {
|
||||
@@ -258,12 +266,12 @@ public class LoanTransactionHelper extends IntegrationTest {
|
||||
return Utils.performServerGet(requestSpec, responseSpec, GET_REPAYMENTS_URL, "loanRepaymentScheduleInstallments");
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsTransactionIdResponse applyLoanTransactionCommand(final Integer loanId, final Integer transactionId,
|
||||
public PostLoansLoanIdTransactionsResponse applyLoanTransactionCommand(final Integer loanId, final Integer transactionId,
|
||||
final String command, final String payload, final ResponseSpecification responseSpec) {
|
||||
final String LOAN_TRANSACTION_URL = "/fineract-provider/api/v1/loans/" + loanId + "/transactions/" + transactionId + "?command="
|
||||
+ command + "&" + Utils.TENANT_IDENTIFIER;
|
||||
final String response = Utils.performServerPost(requestSpec, responseSpec, LOAN_TRANSACTION_URL, payload, null);
|
||||
return GSON.fromJson(response, PostLoansLoanIdTransactionsTransactionIdResponse.class);
|
||||
return GSON.fromJson(response, PostLoansLoanIdTransactionsResponse.class);
|
||||
}
|
||||
|
||||
public HashMap approveLoan(final String approvalDate, final Integer loanID) {
|
||||
@@ -305,6 +313,11 @@ public class LoanTransactionHelper extends IntegrationTest {
|
||||
getDisburseLoanAsJSON(date, null, netDisbursalAmount));
|
||||
}
|
||||
|
||||
public HashMap disburseLoan(final String date, final Integer loanID, final String netDisbursalAmount, final String externalId) {
|
||||
return (HashMap) performLoanTransaction(createLoanOperationURL(DISBURSE_LOAN_COMMAND, loanID),
|
||||
getDisburseLoanAsJSON(date, null, netDisbursalAmount, externalId), "");
|
||||
}
|
||||
|
||||
public HashMap disburseLoanWithTransactionAmount(final String date, final Integer loanID, final String transactionAmount) {
|
||||
return performLoanTransaction(createLoanOperationURL(DISBURSE_LOAN_COMMAND, loanID),
|
||||
getDisburseLoanAsJSON(date, transactionAmount, null));
|
||||
@@ -469,12 +482,179 @@ public class LoanTransactionHelper extends IntegrationTest {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction(loanId, request, "repayment"));
|
||||
}
|
||||
|
||||
public HashMap undoWaiveLoanCharge(final Long loanId, final String transactionExternalId) {
|
||||
log.info("--------------------------------- UNDO WAIVE CHARGES FOR LOAN --------------------------------");
|
||||
final String TRANSAC_URL = "/fineract-provider/api/v1/loans/" + loanId + "/transactions/external-id/" + transactionExternalId + "?"
|
||||
+ Utils.TENANT_IDENTIFIER;
|
||||
return Utils.performServerPut(requestSpec, responseSpec, TRANSAC_URL, "", "");
|
||||
}
|
||||
|
||||
public HashMap undoWaiveLoanCharge(final String loanExternalId, final Long transactionId) {
|
||||
log.info("--------------------------------- UNDO WAIVE CHARGES FOR LOAN --------------------------------");
|
||||
final String TRANSAC_URL = "/fineract-provider/api/v1/loans/external-id/" + loanExternalId + "/transactions/" + transactionId + "?"
|
||||
+ Utils.TENANT_IDENTIFIER;
|
||||
return Utils.performServerPut(requestSpec, responseSpec, TRANSAC_URL, "", "");
|
||||
}
|
||||
|
||||
public HashMap undoWaiveLoanCharge(final String loanExternalId, final String transactionExternalId) {
|
||||
log.info("--------------------------------- UNDO WAIVE CHARGES FOR LOAN --------------------------------");
|
||||
final String TRANSAC_URL = "/fineract-provider/api/v1/loans/external-id/" + loanExternalId + "/transactions/external-id/"
|
||||
+ transactionExternalId + "?" + Utils.TENANT_IDENTIFIER;
|
||||
return Utils.performServerPut(requestSpec, responseSpec, TRANSAC_URL, "", "");
|
||||
}
|
||||
|
||||
public PostLoansLoanIdChargesChargeIdResponse waiveLoanCharge(final Long loanId, final Long chargeId,
|
||||
final PostLoansLoanIdChargesChargeIdRequest request) {
|
||||
return ok(fineract().loanCharges.executeLoanCharge1(loanId, chargeId, request, "waive"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse makeLoanRepayment(final String loanExternalId,
|
||||
final PostLoansLoanIdTransactionsRequest request) {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction1(loanExternalId, request, "repayment"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse makeMerchantIssuedRefund(final Long loanId,
|
||||
final PostLoansLoanIdTransactionsRequest request) {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction(loanId, request, "merchantIssuedRefund"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse makeMerchantIssuedRefund(final String loanExternalId,
|
||||
final PostLoansLoanIdTransactionsRequest request) {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction1(loanExternalId, request, "merchantIssuedRefund"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse makePayoutRefund(final Long loanId, final PostLoansLoanIdTransactionsRequest request) {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction(loanId, request, "payoutRefund"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse makePayoutRefund(final String loanExternalId,
|
||||
final PostLoansLoanIdTransactionsRequest request) {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction1(loanExternalId, request, "payoutRefund"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse makeChargeRefund(final Long loanId, final PostLoansLoanIdTransactionsRequest request) {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction(loanId, request, "chargeRefund"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse makeChargeRefund(final String loanExternalId,
|
||||
final PostLoansLoanIdTransactionsRequest request) {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction1(loanExternalId, request, "chargeRefund"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse makeGoodwillCredit(final Long loanId, final PostLoansLoanIdTransactionsRequest request) {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction(loanId, request, "goodwillCredit"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse makeGoodwillCredit(final String loanExternalId,
|
||||
final PostLoansLoanIdTransactionsRequest request) {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction1(loanExternalId, request, "goodwillCredit"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse makeWaiveInterest(final Long loanId, final PostLoansLoanIdTransactionsRequest request) {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction(loanId, request, "waiveinterest"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse makeWaiveInterest(final String loanExternalId,
|
||||
final PostLoansLoanIdTransactionsRequest request) {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction1(loanExternalId, request, "waiveinterest"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse makeWriteoff(final Long loanId, final PostLoansLoanIdTransactionsRequest request) {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction(loanId, request, "writeoff"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse makeWriteoff(final String loanExternalId, final PostLoansLoanIdTransactionsRequest request) {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction1(loanExternalId, request, "writeoff"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse makeUndoWriteoff(final Long loanId, final PostLoansLoanIdTransactionsRequest request) {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction(loanId, request, "undowriteoff"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse makeUndoWriteoff(final String loanExternalId,
|
||||
final PostLoansLoanIdTransactionsRequest request) {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction1(loanExternalId, request, "undowriteoff"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse makeRecoveryPayment(final Long loanId, final PostLoansLoanIdTransactionsRequest request) {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction(loanId, request, "recoverypayment"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse makeRecoveryPayment(final String loanExternalId,
|
||||
final PostLoansLoanIdTransactionsRequest request) {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction1(loanExternalId, request, "recoverypayment"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse makeRefundByCash(final Long loanId, final PostLoansLoanIdTransactionsRequest request) {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction(loanId, request, "refundByCash"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse makeRefundByCash(final String loanExternalId,
|
||||
final PostLoansLoanIdTransactionsRequest request) {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction1(loanExternalId, request, "refundByCash"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse makeCreditBalanceRefund(final Long loanId,
|
||||
final PostLoansLoanIdTransactionsRequest request) {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction(loanId, request, "creditBalanceRefund"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse makeCreditBalanceRefund(final String loanExternalId,
|
||||
final PostLoansLoanIdTransactionsRequest request) {
|
||||
return ok(fineract().loanTransactions.executeLoanTransaction1(loanExternalId, request, "creditBalanceRefund"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse reverseLoanTransaction(final String loanExternalId, final Long transactionId,
|
||||
final PostLoansLoanIdTransactionsTransactionIdRequest request) {
|
||||
return ok(fineract().loanTransactions.adjustLoanTransaction2(loanExternalId, transactionId, request, "undo"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse reverseLoanTransaction(final String loanExternalId, final String transactionExternalId,
|
||||
final PostLoansLoanIdTransactionsTransactionIdRequest request) {
|
||||
return ok(fineract().loanTransactions.adjustLoanTransaction3(loanExternalId, transactionExternalId, request, "undo"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse reverseLoanTransaction(final Long loanId, final String transactionExternalId,
|
||||
final PostLoansLoanIdTransactionsTransactionIdRequest request) {
|
||||
return ok(fineract().loanTransactions.adjustLoanTransaction1(loanId, transactionExternalId, request, "undo"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse chargebackLoanTransaction(final String loanExternalId, final Long transactionId,
|
||||
final PostLoansLoanIdTransactionsTransactionIdRequest request) {
|
||||
return ok(fineract().loanTransactions.adjustLoanTransaction2(loanExternalId, transactionId, request, "chargeback"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse chargebackLoanTransaction(final String loanExternalId, final String transactionExternalId,
|
||||
final PostLoansLoanIdTransactionsTransactionIdRequest request) {
|
||||
return ok(fineract().loanTransactions.adjustLoanTransaction3(loanExternalId, transactionExternalId, request, "chargeback"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse chargebackLoanTransaction(final Long loanId, final String transactionExternalId,
|
||||
final PostLoansLoanIdTransactionsTransactionIdRequest request) {
|
||||
return ok(fineract().loanTransactions.adjustLoanTransaction1(loanId, transactionExternalId, request, "chargeback"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse adjustLoanTransaction(final String loanExternalId, final Long transactionId,
|
||||
final PostLoansLoanIdTransactionsTransactionIdRequest request) {
|
||||
return ok(fineract().loanTransactions.adjustLoanTransaction2(loanExternalId, transactionId, request, "adjust"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse adjustLoanTransaction(final String loanExternalId, final String transactionExternalId,
|
||||
final PostLoansLoanIdTransactionsTransactionIdRequest request) {
|
||||
return ok(fineract().loanTransactions.adjustLoanTransaction3(loanExternalId, transactionExternalId, request, "adjust"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse adjustLoanTransaction(final Long loanId, final String transactionExternalId,
|
||||
final PostLoansLoanIdTransactionsTransactionIdRequest request) {
|
||||
return ok(fineract().loanTransactions.adjustLoanTransaction1(loanId, transactionExternalId, request, "adjust"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse reverseLoanTransaction(final Integer loanId, final Long transactionId, String date,
|
||||
ResponseSpecification responseSpec) {
|
||||
return postLoanTransaction(createLoanTransactionURL(UNDO, loanId, transactionId.intValue()), getUndoJsonBody(date), responseSpec);
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsTransactionIdResponse reverseLoanTransaction(final Long loanId, final Long transactionId,
|
||||
public PostLoansLoanIdTransactionsResponse reverseLoanTransaction(final Long loanId, final Long transactionId,
|
||||
final PostLoansLoanIdTransactionsTransactionIdRequest request) {
|
||||
return ok(fineract().loanTransactions.adjustLoanTransaction(loanId, transactionId, request, "undo"));
|
||||
}
|
||||
@@ -574,6 +754,13 @@ public class LoanTransactionHelper extends IntegrationTest {
|
||||
return (Integer) response.get("resourceId");
|
||||
}
|
||||
|
||||
public HashMap payChargesForLoan(final Integer loanId, final Integer loanchargeId, final String json, final String responseAttribute) {
|
||||
log.info("--------------------------------- WAIVE CHARGES FOR LOAN --------------------------------");
|
||||
final String CHARGES_URL = "/fineract-provider/api/v1/loans/" + loanId + "/charges/" + loanchargeId + "?command=pay&"
|
||||
+ Utils.TENANT_IDENTIFIER;
|
||||
return Utils.performServerPost(requestSpec, responseSpec, CHARGES_URL, json, responseAttribute);
|
||||
}
|
||||
|
||||
public ArrayList<HashMap> getLoanTransactionDetails(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||
final Integer loanID) {
|
||||
final String URL = "/fineract-provider/api/v1/loans/" + loanID + "?associations=all&exclude=guarantors,futureSchedule&"
|
||||
@@ -616,6 +803,11 @@ public class LoanTransactionHelper extends IntegrationTest {
|
||||
|
||||
private String getDisburseLoanAsJSON(final String actualDisbursementDate, final String transactionAmount,
|
||||
final String netDisbursalAmount) {
|
||||
return getDisburseLoanAsJSON(actualDisbursementDate, transactionAmount, netDisbursalAmount, null);
|
||||
}
|
||||
|
||||
private String getDisburseLoanAsJSON(final String actualDisbursementDate, final String transactionAmount,
|
||||
final String netDisbursalAmount, final String externalId) {
|
||||
final HashMap<String, String> map = new HashMap<>();
|
||||
map.put("locale", "en");
|
||||
map.put("dateFormat", "dd MMMM yyyy");
|
||||
@@ -627,6 +819,9 @@ public class LoanTransactionHelper extends IntegrationTest {
|
||||
if (transactionAmount != null) {
|
||||
map.put("transactionAmount", transactionAmount);
|
||||
}
|
||||
if (externalId != null) {
|
||||
map.put("externalId", externalId);
|
||||
}
|
||||
log.info("Loan Application disburse request : {} ", map);
|
||||
return new Gson().toJson(map);
|
||||
}
|
||||
@@ -842,6 +1037,10 @@ public class LoanTransactionHelper extends IntegrationTest {
|
||||
}
|
||||
|
||||
public static String getPayChargeJSON(final String date, final String installmentNumber) {
|
||||
return getPayChargeJSON(date, installmentNumber, null);
|
||||
}
|
||||
|
||||
public static String getPayChargeJSON(final String date, final String installmentNumber, final String externalId) {
|
||||
final HashMap<String, String> map = new HashMap<>();
|
||||
map.put("locale", "en_GB");
|
||||
map.put("dateFormat", "dd MMMM yyyy");
|
||||
@@ -849,6 +1048,9 @@ public class LoanTransactionHelper extends IntegrationTest {
|
||||
if (installmentNumber != null) {
|
||||
map.put("installmentNumber", installmentNumber);
|
||||
}
|
||||
if (externalId != null) {
|
||||
map.put("externalId", externalId);
|
||||
}
|
||||
String json = new Gson().toJson(map);
|
||||
log.info("{}", json);
|
||||
return json;
|
||||
@@ -1236,7 +1438,7 @@ public class LoanTransactionHelper extends IntegrationTest {
|
||||
|
||||
final String payload = createChargebackPayload(amount, paymentTypeList.get(paymentTypeIdx).getId());
|
||||
log.info("Loan Chargeback: {}", payload);
|
||||
PostLoansLoanIdTransactionsTransactionIdResponse postLoansTransactionCommandResponse = applyLoanTransactionCommand(loanId,
|
||||
PostLoansLoanIdTransactionsResponse postLoansTransactionCommandResponse = applyLoanTransactionCommand(loanId,
|
||||
transactionId.intValue(), "chargeback", payload, responseSpec);
|
||||
assertNotNull(postLoansTransactionCommandResponse);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user