Allow externalId to be provided when creating loan charges
This commit is contained in:
committed by
Aleksandar Vidakovic
parent
b387a92b13
commit
b0e37c24eb
+10
-1
@@ -81,6 +81,8 @@ public class LoanChargeData {
|
|||||||
|
|
||||||
private BigDecimal amountUnrecognized;
|
private BigDecimal amountUnrecognized;
|
||||||
|
|
||||||
|
private String externalId;
|
||||||
|
|
||||||
public static LoanChargeData template(final Collection<ChargeData> chargeOptions) {
|
public static LoanChargeData template(final Collection<ChargeData> chargeOptions) {
|
||||||
return new LoanChargeData(null, null, null, null, null, null, null, null, chargeOptions, false, null, false, false, null, null,
|
return new LoanChargeData(null, null, null, null, null, null, null, null, chargeOptions, false, null, false, false, null, null,
|
||||||
null, null, null);
|
null, null, null);
|
||||||
@@ -103,7 +105,7 @@ public class LoanChargeData {
|
|||||||
final EnumOptionData chargeCalculationType, final BigDecimal percentage, final BigDecimal amountPercentageAppliedTo,
|
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 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 minCap, final BigDecimal maxCap, final BigDecimal amountOrPercentage,
|
||||||
Collection<LoanInstallmentChargeData> installmentChargeData) {
|
Collection<LoanInstallmentChargeData> installmentChargeData, final String externalId) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.chargeId = chargeId;
|
this.chargeId = chargeId;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@@ -140,6 +142,7 @@ public class LoanChargeData {
|
|||||||
this.installmentChargeData = installmentChargeData;
|
this.installmentChargeData = installmentChargeData;
|
||||||
this.amountAccrued = null;
|
this.amountAccrued = null;
|
||||||
this.amountUnrecognized = null;
|
this.amountUnrecognized = null;
|
||||||
|
this.externalId = externalId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private LoanChargeData(final Long id, final Long chargeId, final String name, final CurrencyData currency, final BigDecimal amount,
|
private LoanChargeData(final Long id, final Long chargeId, final String name, final CurrencyData currency, final BigDecimal amount,
|
||||||
@@ -306,6 +309,7 @@ public class LoanChargeData {
|
|||||||
this.installmentChargeData = installmentChargeData;
|
this.installmentChargeData = installmentChargeData;
|
||||||
this.amountAccrued = chargeData.amountAccrued;
|
this.amountAccrued = chargeData.amountAccrued;
|
||||||
this.amountUnrecognized = chargeData.amountUnrecognized;
|
this.amountUnrecognized = chargeData.amountUnrecognized;
|
||||||
|
this.externalId = chargeData.externalId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoanChargeData(final Long id, final LocalDate dueAsOfDate, final BigDecimal amount, final EnumOptionData chargeCalculationType,
|
public LoanChargeData(final Long id, final LocalDate dueAsOfDate, final BigDecimal amount, final EnumOptionData chargeCalculationType,
|
||||||
@@ -440,4 +444,9 @@ public class LoanChargeData {
|
|||||||
public BigDecimal getAmountUnrecognized() {
|
public BigDecimal getAmountUnrecognized() {
|
||||||
return this.amountUnrecognized;
|
return this.amountUnrecognized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getExternalId() {
|
||||||
|
return externalId;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-3
@@ -42,6 +42,7 @@ import javax.persistence.OneToOne;
|
|||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
import javax.persistence.Temporal;
|
import javax.persistence.Temporal;
|
||||||
import javax.persistence.TemporalType;
|
import javax.persistence.TemporalType;
|
||||||
|
import javax.persistence.UniqueConstraint;
|
||||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
@@ -57,7 +58,7 @@ import org.apache.fineract.portfolio.loanaccount.command.LoanChargeCommand;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.data.LoanChargePaidDetail;
|
import org.apache.fineract.portfolio.loanaccount.data.LoanChargePaidDetail;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "m_loan_charge")
|
@Table(name = "m_loan_charge", uniqueConstraints = { @UniqueConstraint(columnNames = { "external_id" }, name = "external_id") })
|
||||||
public class LoanCharge extends AbstractPersistableCustom {
|
public class LoanCharge extends AbstractPersistableCustom {
|
||||||
|
|
||||||
@ManyToOne(optional = false)
|
@ManyToOne(optional = false)
|
||||||
@@ -126,6 +127,9 @@ public class LoanCharge extends AbstractPersistableCustom {
|
|||||||
@Column(name = "is_active", nullable = false)
|
@Column(name = "is_active", nullable = false)
|
||||||
private boolean active = true;
|
private boolean active = true;
|
||||||
|
|
||||||
|
@Column(name = "external_id")
|
||||||
|
private String externalId;
|
||||||
|
|
||||||
@OneToOne(mappedBy = "loancharge", cascade = CascadeType.ALL, optional = true, orphanRemoval = true, fetch = FetchType.EAGER)
|
@OneToOne(mappedBy = "loancharge", cascade = CascadeType.ALL, optional = true, orphanRemoval = true, fetch = FetchType.EAGER)
|
||||||
private LoanOverdueInstallmentCharge overdueInstallmentCharge;
|
private LoanOverdueInstallmentCharge overdueInstallmentCharge;
|
||||||
|
|
||||||
@@ -204,8 +208,11 @@ public class LoanCharge extends AbstractPersistableCustom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LoanCharge(loan, chargeDefinition, amountPercentageAppliedTo, amount, chargeTime, chargeCalculation, dueDate,
|
LoanCharge newLoanCharge = new LoanCharge(loan, chargeDefinition, amountPercentageAppliedTo, amount, chargeTime, chargeCalculation,
|
||||||
chargePaymentMode, null, loanCharge);
|
dueDate, chargePaymentMode, null, loanCharge);
|
||||||
|
final String externalId = command.stringValueOfParameterNamedAllowingNull("externalId");
|
||||||
|
newLoanCharge.setExternalId(externalId);
|
||||||
|
return newLoanCharge;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -264,6 +271,7 @@ public class LoanCharge extends AbstractPersistableCustom {
|
|||||||
if (chargePaymentMode != null) {
|
if (chargePaymentMode != null) {
|
||||||
this.chargePaymentMode = chargePaymentMode.getValue();
|
this.chargePaymentMode = chargePaymentMode.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
populateDerivedFields(loanPrincipal, chargeAmount, numberOfRepayments, loanCharge);
|
populateDerivedFields(loanPrincipal, chargeAmount, numberOfRepayments, loanCharge);
|
||||||
this.paid = determineIfFullyPaid();
|
this.paid = determineIfFullyPaid();
|
||||||
}
|
}
|
||||||
@@ -1070,4 +1078,13 @@ public class LoanCharge extends AbstractPersistableCustom {
|
|||||||
public void undoWaived() {
|
public void undoWaived() {
|
||||||
this.waived = false;
|
this.waived = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getExternalId() {
|
||||||
|
return externalId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExternalId(String externalId) {
|
||||||
|
this.externalId = externalId;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+32
-2
@@ -22,8 +22,13 @@ import org.apache.fineract.commands.annotation.CommandType;
|
|||||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||||
|
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanWritePlatformService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanWritePlatformService;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.dao.DataIntegrityViolationException;
|
||||||
|
import org.springframework.orm.jpa.JpaSystemException;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
@@ -31,6 +36,8 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
@CommandType(entity = "LOANCHARGE", action = "CREATE")
|
@CommandType(entity = "LOANCHARGE", action = "CREATE")
|
||||||
public class AddLoanChargeCommandHandler implements NewCommandSourceHandler {
|
public class AddLoanChargeCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(AddLoanChargeCommandHandler.class);
|
||||||
|
|
||||||
private final LoanWritePlatformService writePlatformService;
|
private final LoanWritePlatformService writePlatformService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@@ -41,7 +48,30 @@ public class AddLoanChargeCommandHandler implements NewCommandSourceHandler {
|
|||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
|
try {
|
||||||
return this.writePlatformService.addLoanCharge(command.getLoanId(), command);
|
return this.writePlatformService.addLoanCharge(command.getLoanId(), command);
|
||||||
|
} catch (final JpaSystemException | DataIntegrityViolationException dve) {
|
||||||
|
handleDataIntegrityIssues(command, dve.getMostSpecificCause(), dve);
|
||||||
|
return CommandProcessingResult.empty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleDataIntegrityIssues(final JsonCommand command, final Throwable realCause, final Exception dve) {
|
||||||
|
|
||||||
|
if (realCause.getMessage().contains("external_id")) {
|
||||||
|
|
||||||
|
final String externalId = command.stringValueOfParameterNamed("externalId");
|
||||||
|
throw new PlatformDataIntegrityException("error.msg.loan.charge.duplicate.externalId",
|
||||||
|
"Loan Charge with externalId `" + externalId + "` already exists", "externalId", externalId);
|
||||||
|
}
|
||||||
|
|
||||||
|
logAsErrorUnexpectedDataIntegrityException(dve);
|
||||||
|
throw new PlatformDataIntegrityException("error.msg.loan.charge.unknown.data.integrity.issue",
|
||||||
|
"Unknown data integrity issue with resource.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void logAsErrorUnexpectedDataIntegrityException(final Exception dve) {
|
||||||
|
LOG.error("Error occured.", dve);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -304,7 +304,8 @@ public final class LoanEventApiJsonValidator {
|
|||||||
throw new InvalidJsonException();
|
throw new InvalidJsonException();
|
||||||
}
|
}
|
||||||
|
|
||||||
final Set<String> disbursementParameters = new HashSet<>(Arrays.asList("chargeId", "amount", "dueDate", "locale", "dateFormat"));
|
final Set<String> disbursementParameters = new HashSet<>(
|
||||||
|
Arrays.asList("chargeId", "amount", "dueDate", "locale", "dateFormat", "externalId"));
|
||||||
|
|
||||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, disbursementParameters);
|
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, disbursementParameters);
|
||||||
|
|||||||
+5
-4
@@ -68,9 +68,9 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform
|
|||||||
private static final class LoanChargeMapper implements RowMapper<LoanChargeData> {
|
private static final class LoanChargeMapper implements RowMapper<LoanChargeData> {
|
||||||
|
|
||||||
public String schema() {
|
public String schema() {
|
||||||
return "lc.id as id, c.id as chargeId, c.name as name, " + "lc.amount as amountDue, " + "lc.amount_paid_derived as amountPaid, "
|
return "lc.id as id, lc.external_id as externalId, c.id as chargeId, c.name as name, " + "lc.amount as amountDue, "
|
||||||
+ "lc.amount_waived_derived as amountWaived, " + "lc.amount_writtenoff_derived as amountWrittenOff, "
|
+ "lc.amount_paid_derived as amountPaid, " + "lc.amount_waived_derived as amountWaived, "
|
||||||
+ "lc.amount_outstanding_derived as amountOutstanding, "
|
+ "lc.amount_writtenoff_derived as amountWrittenOff, " + "lc.amount_outstanding_derived as amountOutstanding, "
|
||||||
+ "lc.calculation_percentage as percentageOf, lc.calculation_on_amount as amountPercentageAppliedTo, "
|
+ "lc.calculation_percentage as percentageOf, lc.calculation_on_amount as amountPercentageAppliedTo, "
|
||||||
+ "lc.charge_time_enum as chargeTime, " + "lc.is_penalty as penalty, "
|
+ "lc.charge_time_enum as chargeTime, " + "lc.is_penalty as penalty, "
|
||||||
+ "lc.due_for_collection_as_of_date as dueAsOfDate, " + "lc.charge_calculation_enum as chargeCalculation, "
|
+ "lc.due_for_collection_as_of_date as dueAsOfDate, " + "lc.charge_calculation_enum as chargeCalculation, "
|
||||||
@@ -130,10 +130,11 @@ public class LoanChargeReadPlatformServiceImpl implements LoanChargeReadPlatform
|
|||||||
if (disbursementDate != null) {
|
if (disbursementDate != null) {
|
||||||
dueAsOfDate = disbursementDate;
|
dueAsOfDate = disbursementDate;
|
||||||
}
|
}
|
||||||
|
final String externalId = rs.getString("externalId");
|
||||||
|
|
||||||
return new LoanChargeData(id, chargeId, name, currency, amount, amountPaid, amountWaived, amountWrittenOff, amountOutstanding,
|
return new LoanChargeData(id, chargeId, name, currency, amount, amountPaid, amountWaived, amountWrittenOff, amountOutstanding,
|
||||||
chargeTimeType, dueAsOfDate, chargeCalculationType, percentageOf, amountPercentageAppliedTo, penalty, paymentMode, paid,
|
chargeTimeType, dueAsOfDate, chargeCalculationType, percentageOf, amountPercentageAppliedTo, penalty, paymentMode, paid,
|
||||||
waived, null, minCap, maxCap, amountOrPercentage, null);
|
waived, null, minCap, maxCap, amountOrPercentage, null, externalId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,4 +27,5 @@
|
|||||||
<include file="parts/0005_savings_transaction_reversal.xml" relativeToChangelogFile="true"/>
|
<include file="parts/0005_savings_transaction_reversal.xml" relativeToChangelogFile="true"/>
|
||||||
<include file="parts/0006_product_loan_disallow_expected_disbursements.xml" relativeToChangelogFile="true"/>
|
<include file="parts/0006_product_loan_disallow_expected_disbursements.xml" relativeToChangelogFile="true"/>
|
||||||
<include file="parts/0007_product_loan_higher_than_applied_loan_amount_management.xml" relativeToChangelogFile="true"/>
|
<include file="parts/0007_product_loan_higher_than_applied_loan_amount_management.xml" relativeToChangelogFile="true"/>
|
||||||
|
<include file="parts/0008_loan_charge_add_external_id.xml" relativeToChangelogFile="true"/>
|
||||||
</databaseChangeLog>
|
</databaseChangeLog>
|
||||||
|
|||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
<?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="external_id" type="VARCHAR(100)">
|
||||||
|
<constraints unique="true"/>
|
||||||
|
</column>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
</databaseChangeLog>
|
||||||
+181
@@ -0,0 +1,181 @@
|
|||||||
|
/**
|
||||||
|
* 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 com.google.gson.Gson;
|
||||||
|
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.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import org.apache.fineract.integrationtests.common.ClientHelper;
|
||||||
|
import org.apache.fineract.integrationtests.common.Utils;
|
||||||
|
import org.apache.fineract.integrationtests.common.accounting.Account;
|
||||||
|
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.LoanStatusChecker;
|
||||||
|
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
|
public class ClientLoanChargeExternalIntegrationTest {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(ClientLoanChargeExternalIntegrationTest.class);
|
||||||
|
|
||||||
|
public static final String MINIMUM_OPENING_BALANCE = "1000.0";
|
||||||
|
public static final String ACCOUNT_TYPE_INDIVIDUAL = "INDIVIDUAL";
|
||||||
|
private static final String NONE = "1";
|
||||||
|
|
||||||
|
private ResponseSpecification responseSpec;
|
||||||
|
private RequestSpecification requestSpec;
|
||||||
|
private LoanTransactionHelper loanTransactionHelper;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setup() {
|
||||||
|
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.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void checkNewClientLoanChargeSavesExternalId() {
|
||||||
|
|
||||||
|
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
|
||||||
|
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
|
||||||
|
|
||||||
|
final Integer loanProductID = createLoanProduct(false, NONE);
|
||||||
|
|
||||||
|
List<HashMap> collaterals = new ArrayList<>();
|
||||||
|
final Integer loanID = applyForLoanApplication(clientID, loanProductID, null, null, "12,000.00", collaterals);
|
||||||
|
HashMap loanStatusHashMap = this.loanTransactionHelper.approveLoan("20 September 2011", loanID);
|
||||||
|
LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
|
||||||
|
loanStatusHashMap = this.loanTransactionHelper.disburseLoan("20 September 2011", loanID, "12,000.00");
|
||||||
|
LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
|
||||||
|
|
||||||
|
final Integer charge = ChargesHelper.createCharges(requestSpec, responseSpec, ChargesHelper
|
||||||
|
.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_AMOUNT_AND_INTEREST, "1", false));
|
||||||
|
|
||||||
|
final float amount = 1.0f;
|
||||||
|
final String externalId = "extId" + loanID.toString();
|
||||||
|
final Integer chargeID = this.loanTransactionHelper.addChargesForLoan(loanID,
|
||||||
|
getLoanChargeAsJSON(String.valueOf(charge), "22 September 2011", String.valueOf(amount), externalId));
|
||||||
|
Assertions.assertNotNull(chargeID);
|
||||||
|
|
||||||
|
HashMap loanChargeMap = this.loanTransactionHelper.getLoanCharge(loanID, chargeID);
|
||||||
|
Assertions.assertNotNull(loanChargeMap.get("externalId"));
|
||||||
|
Assertions.assertEquals(loanChargeMap.get("externalId"), externalId, "Incorrect External Id Saved");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void checkNewClientLoanChargeFindsDuplicateExternalId() {
|
||||||
|
|
||||||
|
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
|
||||||
|
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
|
||||||
|
|
||||||
|
final Integer loanProductID = createLoanProduct(false, NONE);
|
||||||
|
|
||||||
|
List<HashMap> collaterals = new ArrayList<>();
|
||||||
|
final Integer loanID = applyForLoanApplication(clientID, loanProductID, null, null, "12,000.00", collaterals);
|
||||||
|
HashMap loanStatusHashMap = this.loanTransactionHelper.approveLoan("20 September 2011", loanID);
|
||||||
|
LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
|
||||||
|
loanStatusHashMap = this.loanTransactionHelper.disburseLoan("20 September 2011", loanID, "12,000.00");
|
||||||
|
LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
|
||||||
|
|
||||||
|
final Integer charge = ChargesHelper.createCharges(requestSpec, responseSpec, ChargesHelper
|
||||||
|
.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_AMOUNT_AND_INTEREST, "1", false));
|
||||||
|
|
||||||
|
final String externalId = "extId" + loanID.toString();
|
||||||
|
final float amount = 1.0f;
|
||||||
|
final Integer chargeID = this.loanTransactionHelper.addChargesForLoan(loanID,
|
||||||
|
getLoanChargeAsJSON(String.valueOf(charge), "22 September 2011", String.valueOf(amount), externalId));
|
||||||
|
Assertions.assertNotNull(chargeID);
|
||||||
|
|
||||||
|
final float amount2 = 2.0f;
|
||||||
|
ResponseSpecification responseSpec403 = new ResponseSpecBuilder().expectStatusCode(403).build();
|
||||||
|
final Integer chargeID2 = this.loanTransactionHelper.addChargesForLoan(loanID,
|
||||||
|
getLoanChargeAsJSON(String.valueOf(charge), "23 September 2011", String.valueOf(amount2), externalId), responseSpec403);
|
||||||
|
|
||||||
|
Assertions.assertNull(chargeID2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getLoanChargeAsJSON(final String chargeId, final String dueDate, final String amount, final String externalId) {
|
||||||
|
final HashMap<String, String> map = new HashMap<>();
|
||||||
|
map.put("locale", "en_GB");
|
||||||
|
map.put("dateFormat", "dd MMMM yyyy");
|
||||||
|
map.put("amount", amount);
|
||||||
|
map.put("dueDate", dueDate);
|
||||||
|
map.put("chargeId", chargeId);
|
||||||
|
map.put("externalId", externalId);
|
||||||
|
String json = new Gson().toJson(map);
|
||||||
|
LOG.info("{}", json);
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer createLoanProduct(final boolean multiDisburseLoan, final String accountingRule, final Account... accounts) {
|
||||||
|
LOG.info("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------");
|
||||||
|
LoanProductTestBuilder builder = new LoanProductTestBuilder() //
|
||||||
|
.withPrincipal("12,000.00") //
|
||||||
|
.withNumberOfRepayments("4") //
|
||||||
|
.withRepaymentAfterEvery("1") //
|
||||||
|
.withRepaymentTypeAsMonth() //
|
||||||
|
.withinterestRatePerPeriod("1") //
|
||||||
|
.withInterestRateFrequencyTypeAsMonths() //
|
||||||
|
.withAmortizationTypeAsEqualInstallments() //
|
||||||
|
.withInterestTypeAsDecliningBalance() //
|
||||||
|
.withTranches(multiDisburseLoan) //
|
||||||
|
.withAccounting(accountingRule, accounts);
|
||||||
|
if (multiDisburseLoan) {
|
||||||
|
builder = builder.withInterestCalculationPeriodTypeAsRepaymentPeriod(true);
|
||||||
|
}
|
||||||
|
final String loanProductJSON = builder.build(null);
|
||||||
|
return this.loanTransactionHelper.getLoanProductId(loanProductJSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, List<HashMap> charges,
|
||||||
|
final String savingsId, String principal, List<HashMap> collaterals) {
|
||||||
|
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
|
||||||
|
final String loanApplicationJSON = new LoanApplicationTestBuilder() //
|
||||||
|
.withPrincipal(principal) //
|
||||||
|
.withLoanTermFrequency("4") //
|
||||||
|
.withLoanTermFrequencyAsMonths() //
|
||||||
|
.withNumberOfRepayments("4") //
|
||||||
|
.withRepaymentEveryAfter("1") //
|
||||||
|
.withRepaymentFrequencyTypeAsMonths() //
|
||||||
|
.withInterestRatePerPeriod("2") //
|
||||||
|
.withAmortizationTypeAsEqualInstallments() //
|
||||||
|
.withInterestTypeAsDecliningBalance() //
|
||||||
|
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
|
||||||
|
.withExpectedDisbursementDate("20 September 2011") //
|
||||||
|
.withSubmittedOnDate("20 September 2011") //
|
||||||
|
.withCollaterals(collaterals).withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId);
|
||||||
|
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+8
-1
@@ -341,11 +341,18 @@ public class LoanTransactionHelper {
|
|||||||
|
|
||||||
public Integer addChargesForLoan(final Integer loanId, final String request) {
|
public Integer addChargesForLoan(final Integer loanId, final String request) {
|
||||||
LOG.info("--------------------------------- ADD CHARGES FOR LOAN --------------------------------");
|
LOG.info("--------------------------------- ADD CHARGES FOR LOAN --------------------------------");
|
||||||
final String ADD_CHARGES_URL = "/fineract-provider/api/v1/loans/" + loanId + "/charges?" + Utils.TENANT_IDENTIFIER;
|
final String ADD_CHARGES_URL = LOAN_ACCOUNT_URL + "/" + loanId + "/charges?" + Utils.TENANT_IDENTIFIER;
|
||||||
final HashMap response = Utils.performServerPost(requestSpec, responseSpec, ADD_CHARGES_URL, request, "");
|
final HashMap response = Utils.performServerPost(requestSpec, responseSpec, ADD_CHARGES_URL, request, "");
|
||||||
return (Integer) response.get("resourceId");
|
return (Integer) response.get("resourceId");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer addChargesForLoan(final Integer loanId, final String request, final ResponseSpecification responseSpecParam) {
|
||||||
|
LOG.info("--------------------------------- ADD CHARGES FOR LOAN --------------------------------");
|
||||||
|
final String ADD_CHARGES_URL = LOAN_ACCOUNT_URL + "/" + loanId + "/charges?" + Utils.TENANT_IDENTIFIER;
|
||||||
|
final HashMap response = Utils.performServerPost(requestSpec, responseSpecParam, ADD_CHARGES_URL, request, "");
|
||||||
|
return (Integer) response.get("resourceId");
|
||||||
|
}
|
||||||
|
|
||||||
public Object addChargesForAllreadyDisursedLoan(final Integer loanId, final String request,
|
public Object addChargesForAllreadyDisursedLoan(final Integer loanId, final String request,
|
||||||
final ResponseSpecification responseSpecification) {
|
final ResponseSpecification responseSpecification) {
|
||||||
final String ADD_CHARGES_URL = "/fineract-provider/api/v1/loans/" + loanId + "/charges?" + Utils.TENANT_IDENTIFIER;
|
final String ADD_CHARGES_URL = "/fineract-provider/api/v1/loans/" + loanId + "/charges?" + Utils.TENANT_IDENTIFIER;
|
||||||
|
|||||||
Reference in New Issue
Block a user