FINERACT-1724: Fee's are not included in total balance amount, when we have multiple disbursements on first day
This commit is contained in:
+64
-3
@@ -26,6 +26,7 @@ import io.restassured.builder.ResponseSpecBuilder;
|
||||
import io.restassured.http.ContentType;
|
||||
import io.restassured.specification.RequestSpecification;
|
||||
import io.restassured.specification.ResponseSpecification;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -37,6 +38,7 @@ import org.apache.fineract.client.models.JournalEntryTransactionItem;
|
||||
import org.apache.fineract.client.models.PostChargesResponse;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdChargesChargeIdResponse;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdChargesResponse;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdRequest;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
|
||||
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
|
||||
import org.apache.fineract.integrationtests.common.BusinessDateHelper;
|
||||
@@ -505,6 +507,64 @@ public class LoanChargeSpecificDueDateTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApplyLoanSpecificDueDatePenaltyWithDisbursementDateWithMultipleDisbursement() {
|
||||
|
||||
final LocalDate todaysDate = Utils.getLocalDateOfTenant();
|
||||
|
||||
// Client and Loan account creation
|
||||
final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2012");
|
||||
final GetLoanProductsProductIdResponse getLoanProductsProductResponse = createLoanProductWithPeriodicAccrual(loanTransactionHelper,
|
||||
null);
|
||||
assertNotNull(getLoanProductsProductResponse);
|
||||
|
||||
// Older date to have more than one overdue installment
|
||||
LocalDate transactionDate = todaysDate;
|
||||
String operationDate = Utils.dateFormatter.format(transactionDate);
|
||||
log.info("Operation date {}", transactionDate);
|
||||
|
||||
// Create Loan Account
|
||||
final Integer loanId = createLoanAccount(loanTransactionHelper, clientId.toString(),
|
||||
getLoanProductsProductResponse.getId().toString(), operationDate, "12", "0");
|
||||
|
||||
// Get loan details
|
||||
GetLoansLoanIdResponse getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
|
||||
validateLoanAccount(getLoansLoanIdResponse, Double.valueOf(principalAmount), Double.valueOf("0.00"), true);
|
||||
|
||||
// Apply Loan Charge with specific due date
|
||||
|
||||
final String feeAmount = "10.00";
|
||||
String payloadJSON = ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, feeAmount, true);
|
||||
final PostChargesResponse postChargesResponse = ChargesHelper.createLoanCharge(requestSpec, responseSpec, payloadJSON);
|
||||
assertNotNull(postChargesResponse);
|
||||
final Long loanChargeId = postChargesResponse.getResourceId();
|
||||
assertNotNull(loanChargeId);
|
||||
|
||||
payloadJSON = LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(loanChargeId.toString(), operationDate, feeAmount);
|
||||
PostLoansLoanIdChargesResponse postLoansLoanIdChargesResponse = loanTransactionHelper.addChargeForLoan(loanId, payloadJSON,
|
||||
responseSpec);
|
||||
assertNotNull(postLoansLoanIdChargesResponse);
|
||||
|
||||
// Get loan details expecting to have a delinquency classification
|
||||
getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
|
||||
validateLoanAccount(getLoansLoanIdResponse, Double.valueOf(principalAmount), Double.valueOf("10.00"), true);
|
||||
|
||||
loanTransactionHelper.disburseLoan((long) loanId, new PostLoansLoanIdRequest().actualDisbursementDate(operationDate)
|
||||
.transactionAmount(new BigDecimal("1000")).locale("en").dateFormat("dd MMMM yyyy"));
|
||||
|
||||
// Get loan details expecting to have a delinquency classification
|
||||
getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
|
||||
validateLoanAccount(getLoansLoanIdResponse, Double.parseDouble(principalAmount) * 2, Double.valueOf("10.00"), true);
|
||||
|
||||
operationDate = Utils.dateFormatter.format(transactionDate.plusMonths(1));
|
||||
payloadJSON = LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(loanChargeId.toString(), operationDate, feeAmount);
|
||||
postLoansLoanIdChargesResponse = loanTransactionHelper.addChargeForLoan(loanId, payloadJSON, responseSpec);
|
||||
|
||||
// Get loan details expecting to have a delinquency classification
|
||||
getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
|
||||
validateLoanAccount(getLoansLoanIdResponse, Double.parseDouble(principalAmount) * 2, Double.valueOf("20.00"), true);
|
||||
}
|
||||
|
||||
private GetLoanProductsProductIdResponse createLoanProduct(final LoanTransactionHelper loanTransactionHelper,
|
||||
final Integer delinquencyBucketId) {
|
||||
final HashMap<String, Object> loanProductMap = new LoanProductTestBuilder().build(null, delinquencyBucketId);
|
||||
@@ -515,13 +575,14 @@ public class LoanChargeSpecificDueDateTest {
|
||||
private GetLoanProductsProductIdResponse createLoanProductWithPeriodicAccrual(final LoanTransactionHelper loanTransactionHelper,
|
||||
final Integer delinquencyBucketId) {
|
||||
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();
|
||||
|
||||
final HashMap<String, Object> loanProductMap = new LoanProductTestBuilder()
|
||||
final HashMap<String, Object> loanProductMap = new LoanProductTestBuilder().withMultiDisburse()
|
||||
.withInterestCalculationPeriodTypeAsRepaymentPeriod(true).withInterestTypeAsDecliningBalance()
|
||||
.withAccountingRulePeriodicAccrual(new Account[] { assetAccount, incomeAccount, expenseAccount, overpaymentAccount })
|
||||
.withDisallowExpectedDisbursements(true) //
|
||||
.build(null, delinquencyBucketId);
|
||||
final Integer loanProductId = loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap));
|
||||
return loanTransactionHelper.getLoanProduct(loanProductId);
|
||||
@@ -539,7 +600,7 @@ public class LoanChargeSpecificDueDateTest {
|
||||
.build(clientId, loanProductId, null);
|
||||
final Integer loanId = loanTransactionHelper.getLoanId(loanApplicationJSON);
|
||||
loanTransactionHelper.approveLoan(operationDate, principalAmount, loanId, null);
|
||||
loanTransactionHelper.disburseLoanWithNetDisbursalAmount(operationDate, loanId, principalAmount);
|
||||
loanTransactionHelper.disburseLoanWithTransactionAmount(operationDate, loanId, principalAmount);
|
||||
return loanId;
|
||||
}
|
||||
|
||||
|
||||
-61
@@ -95,53 +95,6 @@ public class LoanSpecificDueDateChargeAfterMaturityTest {
|
||||
this.periodicAccrualAccountingHelper = new PeriodicAccrualAccountingHelper(requestSpec, responseSpec);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onlyNonInterestBearingLoanCanAcceptChargeAfterMaturity() {
|
||||
final Account assetAccount = this.accountHelper.createAssetAccount();
|
||||
final Account incomeAccount = this.accountHelper.createIncomeAccount();
|
||||
final Account expenseAccount = this.accountHelper.createExpenseAccount();
|
||||
final Account overpaymentAccount = this.accountHelper.createLiabilityAccount();
|
||||
|
||||
final Integer loanProductID = createLoanProductWithPeriodicAccrualAccountingWithInterestRecalculationEnabled(assetAccount,
|
||||
incomeAccount, expenseAccount, overpaymentAccount);
|
||||
|
||||
final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec, DATE_OF_JOINING);
|
||||
|
||||
final Integer loanID = applyForLoanApplication(clientID, loanProductID, "1");
|
||||
|
||||
final float PENALTY_PORTION = 100.0f;
|
||||
|
||||
Integer flatSpecifiedDueDate = ChargesHelper.createCharges(requestSpec, responseSpec, ChargesHelper
|
||||
.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, String.valueOf(PENALTY_PORTION), true));
|
||||
|
||||
HashMap<String, Object> loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID);
|
||||
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
|
||||
|
||||
loanStatusHashMap = this.loanTransactionHelper.approveLoan(EXPECTED_DISBURSAL_DATE, loanID);
|
||||
LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
|
||||
LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
|
||||
|
||||
LocalDate targetDate = LocalDate.of(2011, 3, 4);
|
||||
final String loanDisbursementDate = dateFormatter.format(targetDate);
|
||||
|
||||
String loanDetails = this.loanTransactionHelper.getLoanDetails(requestSpec, responseSpec, loanID);
|
||||
loanStatusHashMap = this.loanTransactionHelper.disburseLoanWithNetDisbursalAmount(loanDisbursementDate, loanID,
|
||||
JsonPath.from(loanDetails).get("netDisbursalAmount").toString());
|
||||
LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
|
||||
|
||||
targetDate = LocalDate.of(2011, 4, 5);
|
||||
final String penaltyCharge1AddedDate = dateFormatter.format(targetDate);
|
||||
|
||||
final String ADD_CHARGES_URL = "/fineract-provider/api/v1/loans/" + loanID + "/charges?" + Utils.TENANT_IDENTIFIER;
|
||||
ResponseSpecification response403Spec = new ResponseSpecBuilder().expectStatusCode(403).build();
|
||||
final HashMap response = Utils.performServerPost(requestSpec, response403Spec, ADD_CHARGES_URL,
|
||||
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(flatSpecifiedDueDate), penaltyCharge1AddedDate,
|
||||
String.valueOf(PENALTY_PORTION)),
|
||||
"");
|
||||
assertEquals("validation.msg.domain.rule.violation", response.get("userMessageGlobalisationCode"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkPeriodicAccrualAccountingAPIFlow() {
|
||||
final Account assetAccount = this.accountHelper.createAssetAccount();
|
||||
@@ -458,20 +411,6 @@ public class LoanSpecificDueDateChargeAfterMaturityTest {
|
||||
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
|
||||
}
|
||||
|
||||
private Integer createLoanProductWithPeriodicAccrualAccountingWithInterestRecalculationEnabled(final Account... accounts) {
|
||||
LOG.info("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------");
|
||||
final String loanProductJSON = new LoanProductTestBuilder().withPrincipal("10000.0").withNumberOfRepayments("1")
|
||||
.withinterestRatePerPeriod("1").withInterestRateFrequencyTypeAsYear().withInterestTypeAsDecliningBalance()
|
||||
.withInterestCalculationPeriodTypeAsDays()
|
||||
.withInterestRecalculationDetails(LoanProductTestBuilder.RECALCULATION_COMPOUNDING_METHOD_NONE,
|
||||
LoanProductTestBuilder.RECALCULATION_STRATEGY_REDUCE_NUMBER_OF_INSTALLMENTS,
|
||||
LoanProductTestBuilder.INTEREST_APPLICABLE_STRATEGY_ON_PRE_CLOSE_DATE)
|
||||
.withInterestRecalculationRestFrequencyDetails(LoanProductTestBuilder.RECALCULATION_FREQUENCY_TYPE_DAILY, "0", null, null)
|
||||
.withInterestRecalculationCompoundingFrequencyDetails(null, null, null, null).withMoratorium("0", "0")
|
||||
.withInterestCalculationPeriodTypeAsRepaymentPeriod(true).withAccountingRulePeriodicAccrual(accounts).build(null);
|
||||
return this.loanTransactionHelper.getLoanProductId(loanProductJSON);
|
||||
}
|
||||
|
||||
private Integer createLoanProductWithPeriodicAccrualAccountingNoInterest(final Account... accounts) {
|
||||
LOG.info("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------");
|
||||
final String loanProductJSON = new LoanProductTestBuilder().withPrincipal(LP_PRINCIPAL.toString()).withRepaymentTypeAsMonth()
|
||||
|
||||
Reference in New Issue
Block a user