FINERACT-1724

Added batch support for the Get Charge by Id call.
Added externalId field to PostLoansLoanIdChargesRequest.
Added submittedOnDate column to m_loan_charge table.
Updated logic to return new submittedOnDate field in GetLoansLoanIdChargesChargeIdResponse.
This commit is contained in:
Arnold Galovics
2022-10-14 17:57:29 +02:00
committed by Arnold Gálovics
parent b33e3ac892
commit 388612b1ae
14 changed files with 410 additions and 13 deletions
@@ -91,6 +91,8 @@ public class CommandStrategyProvider {
this.commandStrategies.put(CommandContext.resource("loans\\/\\d+\\/charges").method("POST").build(), "createChargeCommandStrategy");
this.commandStrategies.put(CommandContext.resource("loans\\/\\d+\\/charges").method("GET").build(),
"collectChargesCommandStrategy");
this.commandStrategies.put(CommandContext.resource("loans\\/\\d+\\/charges\\/\\d+").method("GET").build(),
"getChargeByIdCommandStrategy");
this.commandStrategies.put(CommandContext.resource("loans\\/\\d+\\/transactions\\?command=repayment").method("POST").build(),
"createTransactionLoanCommandStrategy");
this.commandStrategies.put(
@@ -0,0 +1,87 @@
/**
* 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.batch.command.internal;
import com.google.common.base.Splitter;
import java.util.List;
import java.util.Map;
import javax.ws.rs.core.UriInfo;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.batch.command.CommandStrategy;
import org.apache.fineract.batch.command.CommandStrategyUtils;
import org.apache.fineract.batch.domain.BatchRequest;
import org.apache.fineract.batch.domain.BatchResponse;
import org.apache.fineract.infrastructure.core.api.MutableUriInfo;
import org.apache.fineract.portfolio.loanaccount.api.LoanChargesApiResource;
import org.apache.http.HttpStatus;
import org.springframework.stereotype.Component;
/**
* Implements {@link CommandStrategy} to retrieve a charge by id. It passes the contents of the body from the
* BatchRequest to {@link LoanChargesApiResource} and gets back the response. This class will also catch any errors
* raised by {@link LoanChargesApiResource} and map those errors to appropriate status codes in BatchResponse.
*
* @see CommandStrategy
* @see BatchRequest
* @see BatchResponse
*/
@Component
@RequiredArgsConstructor
public class GetChargeByIdCommandStrategy implements CommandStrategy {
private final LoanChargesApiResource loanChargesApiResource;
@Override
public BatchResponse execute(final BatchRequest request, UriInfo uriInfo) {
final MutableUriInfo parameterizedUriInfo = new MutableUriInfo(uriInfo);
final BatchResponse response = new BatchResponse();
final String responseBody;
response.setRequestId(request.getRequestId());
response.setHeaders(request.getHeaders());
final String relativeUrl = request.getRelativeUrl();
// Get the loan and charge ids for use in loanChargesApiResource
final List<String> pathParameters = Splitter.on('/').splitToList(relativeUrl);
final Long loanId = Long.parseLong(pathParameters.get(1));
Long chargeId;
if (relativeUrl.indexOf('?') > 0) {
chargeId = Long.parseLong(StringUtils.substringBeforeLast(pathParameters.get(3), "?"));
} else {
chargeId = Long.parseLong(pathParameters.get(3));
}
Map<String, String> queryParameters;
if (relativeUrl.indexOf('?') > 0) {
queryParameters = CommandStrategyUtils.getQueryParameters(relativeUrl);
// Add the query parameters sent in the relative URL to UriInfo
CommandStrategyUtils.addQueryParametersToUriInfo(parameterizedUriInfo, queryParameters);
}
responseBody = loanChargesApiResource.retrieveLoanCharge(loanId, chargeId, parameterizedUriInfo);
response.setStatusCode(HttpStatus.SC_OK);
response.setBody(responseBody);
return response;
}
}
@@ -19,6 +19,7 @@
package org.apache.fineract.portfolio.loanaccount.api;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDate;
import java.util.Set;
/**
@@ -102,6 +103,8 @@ final class LoanChargesApiResourceSwagger {
public Double amountOrPercentage;
@Schema(example = "false")
public Boolean penalty;
@Schema(example = "27 March 2013")
public LocalDate submittedOnDate;
}
@Schema(description = "GetLoansLoanIdChargesTemplateResponse")
@@ -179,6 +182,8 @@ final class LoanChargesApiResourceSwagger {
public String dateFormat;
@Schema(example = "29 April 2013")
public String dueDate;
@Schema(example = "786444UUUYYH7")
public String externalId;
}
@Schema(description = " PostLoansLoanIdChargesResponse")
@@ -39,6 +39,8 @@ public class LoanChargeData {
private final String name;
private final EnumOptionData chargeTimeType;
private final LocalDate submittedOnDate;
private final LocalDate dueDate;
private final EnumOptionData chargeCalculationType;
@@ -103,10 +105,10 @@ public class LoanChargeData {
public LoanChargeData(final Long id, final Long chargeId, final String name, final CurrencyData currency, final BigDecimal amount,
final BigDecimal amountPaid, final BigDecimal amountWaived, final BigDecimal amountWrittenOff,
final BigDecimal amountOutstanding, final EnumOptionData chargeTimeType, final LocalDate dueDate,
final EnumOptionData chargeCalculationType, final BigDecimal percentage, final BigDecimal amountPercentageAppliedTo,
final boolean penalty, final EnumOptionData chargePaymentMode, final boolean paid, final boolean waived, final Long loanId,
final BigDecimal minCap, final BigDecimal maxCap, final BigDecimal amountOrPercentage,
final BigDecimal amountOutstanding, final EnumOptionData chargeTimeType, final LocalDate submittedOnDate,
final LocalDate dueDate, final EnumOptionData chargeCalculationType, final BigDecimal percentage,
final BigDecimal amountPercentageAppliedTo, final boolean penalty, final EnumOptionData chargePaymentMode, final boolean paid,
final boolean waived, final Long loanId, final BigDecimal minCap, final BigDecimal maxCap, final BigDecimal amountOrPercentage,
Collection<LoanInstallmentChargeData> installmentChargeData, final String externalId) {
this.id = id;
this.chargeId = chargeId;
@@ -118,6 +120,7 @@ public class LoanChargeData {
this.amountWrittenOff = amountWrittenOff;
this.amountOutstanding = amountOutstanding;
this.chargeTimeType = chargeTimeType;
this.submittedOnDate = submittedOnDate;
this.dueDate = dueDate;
this.chargeCalculationType = chargeCalculationType;
this.percentage = percentage;
@@ -162,6 +165,7 @@ public class LoanChargeData {
this.amountWrittenOff = BigDecimal.ZERO;
this.amountOutstanding = amount;
this.chargeTimeType = chargeTimeType;
this.submittedOnDate = null;
this.dueDate = null;
this.chargeCalculationType = chargeCalculationType;
this.percentage = percentage;
@@ -203,6 +207,7 @@ public class LoanChargeData {
this.amountWrittenOff = null;
this.amountOutstanding = amountOutstanding;
this.chargeTimeType = chargeTimeType;
this.submittedOnDate = null;
this.dueDate = dueAsOfDate;
this.chargeCalculationType = null;
this.percentage = null;
@@ -234,6 +239,7 @@ public class LoanChargeData {
this.amountWrittenOff = null;
this.amountOutstanding = null;
this.chargeTimeType = chargeTimeType;
this.submittedOnDate = null;
this.dueDate = dueAsOfDate;
this.chargeCalculationType = null;
this.percentage = null;
@@ -264,6 +270,7 @@ public class LoanChargeData {
this.amountWrittenOff = null;
this.amountOutstanding = null;
this.chargeTimeType = chargeData.chargeTimeType;
this.submittedOnDate = chargeData.submittedOnDate;
this.dueDate = chargeData.dueDate;
this.chargeCalculationType = null;
this.percentage = null;
@@ -294,6 +301,7 @@ public class LoanChargeData {
this.amountWrittenOff = chargeData.amountWrittenOff;
this.amountOutstanding = chargeData.amountOutstanding;
this.chargeTimeType = chargeData.chargeTimeType;
this.submittedOnDate = chargeData.submittedOnDate;
this.dueDate = chargeData.dueDate;
this.chargeCalculationType = chargeData.chargeCalculationType;
this.percentage = chargeData.percentage;
@@ -326,6 +334,7 @@ public class LoanChargeData {
this.amountWrittenOff = null;
this.amountOutstanding = null;
this.chargeTimeType = chargeTimeType;
this.submittedOnDate = null;
this.dueDate = dueAsOfDate;
this.chargeCalculationType = chargeCalculationType;
this.percentage = null;
@@ -356,6 +365,7 @@ public class LoanChargeData {
this.amountWrittenOff = null;
this.amountOutstanding = null;
this.chargeTimeType = null;
this.submittedOnDate = null;
this.dueDate = dueAsOfDate;
this.chargeCalculationType = null;
this.percentage = null;
@@ -42,6 +42,7 @@ import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
import org.apache.fineract.organisation.monetary.domain.Money;
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
@@ -68,6 +69,9 @@ public class LoanCharge extends AbstractPersistableCustom {
@Column(name = "charge_time_enum", nullable = false)
private Integer chargeTime;
@Column(name = "submitted_on_date", nullable = true)
private LocalDate submittedOnDate;
@Column(name = "due_for_collection_as_of_date")
private LocalDate dueDate;
@@ -229,6 +233,7 @@ public class LoanCharge extends AbstractPersistableCustom {
final ChargePaymentMode chargePaymentMode, final Integer numberOfRepayments, final BigDecimal loanCharge) {
this.loan = loan;
this.charge = chargeDefinition;
this.submittedOnDate = DateUtils.getBusinessLocalDate();
this.penaltyCharge = chargeDefinition.isPenalty();
this.minCap = chargeDefinition.getMinCap();
this.maxCap = chargeDefinition.getMaxCap();
@@ -597,6 +602,10 @@ public class LoanCharge extends AbstractPersistableCustom {
return this.dueDate;
}
public LocalDate getSubmittedOnDate() {
return submittedOnDate;
}
private boolean determineIfFullyPaid() {
if (this.amount == null) {
return true;
@@ -59,8 +59,8 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform
private static final class LoanChargeMapper implements RowMapper<LoanChargeData> {
public String schema() {
return "lc.id as id, lc.external_id as externalId, c.id as chargeId, c.name as name, " + "lc.amount as amountDue, "
+ "lc.amount_paid_derived as amountPaid, " + "lc.amount_waived_derived as amountWaived, "
return "lc.id as id, lc.external_id as externalId, c.id as chargeId, c.name as name, lc.submitted_on_date as submittedOnDate, "
+ "lc.amount as amountDue, " + "lc.amount_paid_derived as amountPaid, " + "lc.amount_waived_derived as amountWaived, "
+ "lc.amount_writtenoff_derived as amountWrittenOff, " + "lc.amount_outstanding_derived as amountOutstanding, "
+ "lc.calculation_percentage as percentageOf, lc.calculation_on_amount as amountPercentageAppliedTo, "
+ "lc.charge_time_enum as chargeTime, " + "lc.is_penalty as penalty, "
@@ -116,6 +116,7 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform
final BigDecimal maxCap = rs.getBigDecimal("maxCap");
final BigDecimal amountOrPercentage = rs.getBigDecimal("amountOrPercentage");
final LocalDate disbursementDate = JdbcSupport.getLocalDate(rs, "disbursementDate");
final LocalDate submittedOnDate = JdbcSupport.getLocalDate(rs, "submittedOnDate");
if (disbursementDate != null) {
dueAsOfDate = disbursementDate;
@@ -123,8 +124,8 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform
final String externalId = rs.getString("externalId");
return new LoanChargeData(id, chargeId, name, currency, amount, amountPaid, amountWaived, amountWrittenOff, amountOutstanding,
chargeTimeType, dueAsOfDate, chargeCalculationType, percentageOf, amountPercentageAppliedTo, penalty, paymentMode, paid,
waived, null, minCap, maxCap, amountOrPercentage, null, externalId);
chargeTimeType, submittedOnDate, dueAsOfDate, chargeCalculationType, percentageOf, amountPercentageAppliedTo, penalty,
paymentMode, paid, waived, null, minCap, maxCap, amountOrPercentage, null, externalId);
}
}
@@ -526,7 +526,8 @@ public final class LoanProductDataValidator {
baseDataValidator.reset().parameter(LoanProductConstants.fixedPrincipalPercentagePerInstallmentParamName)
.value(fixedPrincipalPercentagePerInstallment).notLessThanMin(BigDecimal.ONE).notGreaterThanMax(BigDecimal.valueOf(100));
if (!amortizationType.equals(AmortizationMethod.EQUAL_PRINCIPAL.getValue()) && fixedPrincipalPercentagePerInstallment != null) {
if (amortizationType != null && !amortizationType.equals(AmortizationMethod.EQUAL_PRINCIPAL.getValue())
&& fixedPrincipalPercentagePerInstallment != null) {
baseDataValidator.reset().parameter(LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName).failWithCode(
"not.supported.principal.fixing.not.allowed.with.equal.installments",
"Principal fixing cannot be done with equal installment amortization");
@@ -74,4 +74,5 @@
<include file="parts/0052_loan_transaction_chargeback.xml" relativeToChangelogFile="true"/>
<include file="parts/0053_add_external_events_purge_job.xml" relativeToChangelogFile="true"/>
<include file="parts/0054_additional_fields_loan_repayment_schedule.xml" relativeToChangelogFile="true"/>
<include file="parts/0055_add_submitted_on_date_to_loan_charge.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>
@@ -0,0 +1,30 @@
<?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.1.xsd">
<changeSet author="fineract" id="1">
<addColumn tableName="m_loan_charge">
<column name="submitted_on_date" type="date">
<constraints nullable="true"/>
</column>
</addColumn>
</changeSet>
</databaseChangeLog>