FINERACT-2421: Disbursement charge amount incorrect calculation
This commit is contained in:
committed by
Adam Saghy
parent
2620c61afa
commit
1d1876edfd
+1
-1
@@ -962,7 +962,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService {
|
||||
|
||||
for (LoanDisbursementDetails loanDisbursementDetails : loan.getDisbursementDetails()) {
|
||||
if (loanDisbursementDetails.actualDisbursementDate() == null) {
|
||||
totalPrincipal = Money.of(currency, totalPrincipal.getAmount().subtract(loanDisbursementDetails.principal()));
|
||||
totalPrincipal = Money.of(currency, totalPrincipal.getAmount().subtract(loanDisbursementDetails.getPrincipal()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -175,8 +175,8 @@ public class LoanScheduleCalculationPlatformServiceImpl implements LoanScheduleC
|
||||
for (LoanRepaymentScheduleInstallment installment : installments) {
|
||||
if (loanDisbursementDetails != null
|
||||
&& !DateUtils.isAfter(loanDisbursementDetails.expectedDisbursementDateAsLocalDate(), installment.getDueDate())) {
|
||||
outstanding = outstanding.plus(loanDisbursementDetails.principal());
|
||||
principal = principal.plus(loanDisbursementDetails.principal());
|
||||
outstanding = outstanding.plus(loanDisbursementDetails.getPrincipal());
|
||||
principal = principal.plus(loanDisbursementDetails.getPrincipal());
|
||||
if (disbursementItr.hasNext()) {
|
||||
loanDisbursementDetails = disbursementItr.next();
|
||||
} else {
|
||||
|
||||
+2
-2
@@ -97,7 +97,7 @@ public final class LoanApprovedAmountValidatorImpl implements LoanApprovedAmount
|
||||
|
||||
BigDecimal totalPrincipalOnLoan = loan.getSummary().getTotalPrincipal();
|
||||
BigDecimal totalExpectedPrincipal = loan.getDisbursementDetails().stream().filter(t -> t.actualDisbursementDate() == null)
|
||||
.map(LoanDisbursementDetails::principal).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
.map(LoanDisbursementDetails::getPrincipal).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
if (MathUtil.isLessThan(newApprovedAmount, totalPrincipalOnLoan.add(totalExpectedPrincipal))) {
|
||||
baseDataValidator.reset().parameter(LoanApiConstants.amountParameterName)
|
||||
.failWithCode("less.than.disbursed.principal.and.capitalized.income");
|
||||
@@ -145,7 +145,7 @@ public final class LoanApprovedAmountValidatorImpl implements LoanApprovedAmount
|
||||
}
|
||||
|
||||
BigDecimal expectedDisbursementAmount = loan.getDisbursementDetails().stream().filter(t -> t.actualDisbursementDate() == null)
|
||||
.map(LoanDisbursementDetails::principal).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
.map(LoanDisbursementDetails::getPrincipal).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
|
||||
BigDecimal maximumAvailableDisbursementThreshold = maximumThresholdForApprovedAmount
|
||||
.subtract(loan.getSummary().getTotalPrincipal()).subtract(expectedDisbursementAmount);
|
||||
|
||||
+4
-4
@@ -174,7 +174,7 @@ public class LoanChargeAssembler {
|
||||
} else {
|
||||
if (disbursementDetail.expectedDisbursementDateAsLocalDate().equals(expectedDisbursementDate)) {
|
||||
final LoanCharge loanCharge = createNewWithoutLoan(chargeDefinition,
|
||||
disbursementDetail.principal(), amount, chargeTime, chargeCalculation,
|
||||
disbursementDetail.getPrincipal(), amount, chargeTime, chargeCalculation,
|
||||
disbursementDetail.expectedDisbursementDateAsLocalDate(), chargePaymentModeEnum,
|
||||
numberOfRepayments, externalId);
|
||||
loanCharges.add(loanCharge);
|
||||
@@ -191,8 +191,8 @@ public class LoanChargeAssembler {
|
||||
LoanTrancheDisbursementCharge loanTrancheDisbursementCharge = null;
|
||||
for (LoanDisbursementDetails disbursementDetail : disbursementDetails) {
|
||||
if (ChargeTimeType.TRANCHE_DISBURSEMENT.getValue().equals(chargeDefinition.getChargeTimeType())) {
|
||||
final LoanCharge loanCharge = createNewWithoutLoan(chargeDefinition, disbursementDetail.principal(),
|
||||
amount, chargeTime, chargeCalculation,
|
||||
final LoanCharge loanCharge = createNewWithoutLoan(chargeDefinition,
|
||||
disbursementDetail.getPrincipal(), amount, chargeTime, chargeCalculation,
|
||||
disbursementDetail.expectedDisbursementDateAsLocalDate(), chargePaymentModeEnum,
|
||||
numberOfRepayments, externalId);
|
||||
loanCharges.add(loanCharge);
|
||||
@@ -309,7 +309,7 @@ public class LoanChargeAssembler {
|
||||
amountPercentageAppliedTo = BigDecimal.ZERO;
|
||||
for (final LoanDisbursementDetails loanDisbursementDetails : loan.getDisbursementDetails()) {
|
||||
if (!DateUtils.isAfter(loanDisbursementDetails.expectedDisbursementDate(), dueDate)) {
|
||||
amountPercentageAppliedTo = amountPercentageAppliedTo.add(loanDisbursementDetails.principal());
|
||||
amountPercentageAppliedTo = amountPercentageAppliedTo.add(loanDisbursementDetails.getPrincipal());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-3
@@ -105,7 +105,6 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachin
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanOverdueInstallmentCharge;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleProcessingWrapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTrancheDisbursementCharge;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||
@@ -159,7 +158,6 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
private final AccountAssociationsReadPlatformService accountAssociationsReadPlatformService;
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory;
|
||||
private final ExternalIdFactory externalIdFactory;
|
||||
private final AccountTransferDetailRepository accountTransferDetailRepository;
|
||||
private final LoanChargeAssembler loanChargeAssembler;
|
||||
@@ -216,7 +214,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo
|
||||
externalId = externalIdFactory.create();
|
||||
}
|
||||
LocalDate dueDate = disbursementDetail.expectedDisbursementDateAsLocalDate();
|
||||
loanCharge = loanChargeAssembler.createNewWithoutLoan(chargeDefinition, disbursementDetail.principal(), null, null,
|
||||
loanCharge = loanChargeAssembler.createNewWithoutLoan(chargeDefinition, disbursementDetail.getPrincipal(), null, null,
|
||||
null, dueDate, null, null, externalId);
|
||||
loanTrancheDisbursementCharge = new LoanTrancheDisbursementCharge(loanCharge, disbursementDetail);
|
||||
loanCharge.updateLoanTrancheDisbursementCharge(loanTrancheDisbursementCharge);
|
||||
|
||||
+7
-6
@@ -138,7 +138,7 @@ public class LoanDisbursementService {
|
||||
disburseAmount = disburseAmount.zero();
|
||||
for (LoanDisbursementDetails disbursementDetails : details) {
|
||||
disbursementDetails.updateActualDisbursementDate(actualDisbursementDate);
|
||||
disburseAmount = disburseAmount.plus(disbursementDetails.principal());
|
||||
disburseAmount = disburseAmount.plus(disbursementDetails.getPrincipal());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -162,7 +162,7 @@ public class LoanDisbursementService {
|
||||
// First try to find a tranche that exactly matches the requested disbursement amount
|
||||
for (LoanDisbursementDetails disbursementDetails : details) {
|
||||
if (disbursementDetails.actualDisbursementDate() == null
|
||||
&& disbursementDetails.principal().compareTo(principalDisbursed) == 0) {
|
||||
&& disbursementDetails.getPrincipal().compareTo(principalDisbursed) == 0) {
|
||||
selectedTranche = disbursementDetails;
|
||||
break;
|
||||
}
|
||||
@@ -198,9 +198,9 @@ public class LoanDisbursementService {
|
||||
BigDecimal setPrincipalAmount = BigDecimal.ZERO;
|
||||
for (LoanDisbursementDetails disbursementDetails : loanDisburseDetails) {
|
||||
if (disbursementDetails.actualDisbursementDate() != null) {
|
||||
setPrincipalAmount = setPrincipalAmount.add(disbursementDetails.principal());
|
||||
setPrincipalAmount = setPrincipalAmount.add(disbursementDetails.getPrincipal());
|
||||
}
|
||||
totalAmount = totalAmount.add(disbursementDetails.principal());
|
||||
totalAmount = totalAmount.add(disbursementDetails.getPrincipal());
|
||||
}
|
||||
loan.getLoanRepaymentScheduleDetail().setPrincipal(setPrincipalAmount);
|
||||
} else {
|
||||
@@ -435,7 +435,7 @@ public class LoanDisbursementService {
|
||||
LoanDisbursementDetails singleDetail = undisbursedDetails.iterator().next();
|
||||
BigDecimal loanPrincipal = loan.getLoanRepaymentScheduleDetail().getPrincipal().getAmount();
|
||||
|
||||
if (singleDetail.principal().compareTo(loanPrincipal) == 0) {
|
||||
if (singleDetail.getPrincipal().compareTo(loanPrincipal) == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -452,7 +452,8 @@ public class LoanDisbursementService {
|
||||
|
||||
return disbursementDetails.stream()
|
||||
.sorted(Comparator.comparing(LoanDisbursementDetails::expectedDisbursementDate)
|
||||
.thenComparing((LoanDisbursementDetails d1, LoanDisbursementDetails d2) -> d2.principal().compareTo(d1.principal()))
|
||||
.thenComparing(
|
||||
(LoanDisbursementDetails d1, LoanDisbursementDetails d2) -> d2.getPrincipal().compareTo(d1.getPrincipal()))
|
||||
.thenComparing(LoanDisbursementDetails::getId))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
+10
-5
@@ -1666,10 +1666,14 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
return "dd.id as id, dd.loan_id as loanId, dd.expected_disburse_date as expectedDisbursementdate, dd.disbursedon_date as actualDisbursementdate,dd.principal as principal,dd.net_disbursal_amount as netDisbursalAmount,sum(lc.amount) chargeAmount, lc.amount_waived_derived waivedAmount, "
|
||||
+ sqlGenerator.groupConcat("lc.id") + " loanChargeId "
|
||||
+ "from m_loan l inner join m_loan_disbursement_detail dd on dd.loan_id = l.id left join m_loan_tranche_disbursement_charge tdc on tdc.disbursement_detail_id=dd.id "
|
||||
+ "left join m_loan_charge lc on lc.id=tdc.loan_charge_id and lc.is_active=true";
|
||||
return "dd.id as id, dd.loan_id as loanId, dd.expected_disburse_date as expectedDisbursementdate, dd.disbursedon_date as actualDisbursementdate, "
|
||||
+ "dd.principal as principal,dd.net_disbursal_amount as netDisbursalAmount, sum(lc.amount) as chargeAmount, coalesce(sum(cad.amount), 0) as disburseChargeAmount, "
|
||||
+ "lc.amount_waived_derived waivedAmount, coalesce(" + sqlGenerator.groupConcat("lc.id") + ", "
|
||||
+ sqlGenerator.groupConcat("cad.id") + ") loanChargeId "
|
||||
+ "from m_loan l inner join m_loan_disbursement_detail dd on dd.loan_id = l.id "
|
||||
+ "left join m_loan_tranche_disbursement_charge tdc on tdc.disbursement_detail_id = dd.id "
|
||||
+ "left join m_loan_charge lc on lc.id = tdc.loan_charge_id and lc.is_active = true "
|
||||
+ "left join (select lch.id, lch.loan_id, lch.amount from m_loan_charge lch inner join m_charge ch on ch.id = lch.charge_id and ch.charge_time_enum = 1) cad on cad.loan_id = l.id";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1686,8 +1690,9 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
||||
if (chargeAmount != null && waivedAmount != null) {
|
||||
chargeAmount = chargeAmount.subtract(waivedAmount);
|
||||
}
|
||||
BigDecimal disburseChargeAmount = rs.getBigDecimal("disburseChargeAmount");
|
||||
return new DisbursementData(id, loanId, expectedDisbursementdate, actualDisbursementdate, principal, netDisbursalAmount,
|
||||
loanChargeId, chargeAmount, waivedAmount);
|
||||
loanChargeId, chargeAmount, waivedAmount).setDisburseChargeAmount(disburseChargeAmount);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-1
@@ -365,7 +365,12 @@ public class LoanRepaymentScheduleService {
|
||||
if (dataItem.isDisbursement()) {
|
||||
// Process disbursement data
|
||||
DisbursementData data = (DisbursementData) dataItem.getData();
|
||||
periodData = createLoanSchedulePeriodData(data, disbursementChargeAmount, waivedChargeAmount);
|
||||
if (periods.isEmpty()) {
|
||||
periodData = createLoanSchedulePeriodData(data, disbursementChargeAmount, waivedChargeAmount);
|
||||
} else {
|
||||
periodData = createLoanSchedulePeriodData(data, disbursementChargeAmount.subtract(data.getDisburseChargeAmount()),
|
||||
waivedChargeAmount);
|
||||
}
|
||||
} else {
|
||||
// Process capitalized income data
|
||||
LoanTransactionRepaymentPeriodData data = (LoanTransactionRepaymentPeriodData) dataItem.getData();
|
||||
|
||||
+1
-1
@@ -2209,7 +2209,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
Collection<LoanDisbursementDetails> loanDisburseDetails = loan.getDisbursementDetails();
|
||||
for (LoanDisbursementDetails disbursementDetails : loanDisburseDetails) {
|
||||
if (disbursementDetails.actualDisbursementDate() != null) {
|
||||
totalDisbursedAmount = totalDisbursedAmount.add(disbursementDetails.principal());
|
||||
totalDisbursedAmount = totalDisbursedAmount.add(disbursementDetails.getPrincipal());
|
||||
}
|
||||
}
|
||||
if (totalDisbursedAmount.compareTo(loan.getApprovedPrincipal()) == 0) {
|
||||
|
||||
+7
-9
@@ -314,11 +314,10 @@ public class LoanAccountConfiguration {
|
||||
LoanWritePlatformService loanWritePlatformService, LoanUtilService loanUtilService,
|
||||
LoanChargeReadPlatformService loanChargeReadPlatformService, LoanLifecycleStateMachine loanLifecycleStateMachine,
|
||||
AccountAssociationsReadPlatformService accountAssociationsReadPlatformService, FromJsonHelper fromApiJsonHelper,
|
||||
ConfigurationDomainService configurationDomainService,
|
||||
LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory,
|
||||
ExternalIdFactory externalIdFactory, AccountTransferDetailRepository accountTransferDetailRepository,
|
||||
LoanChargeAssembler loanChargeAssembler, PaymentDetailWritePlatformService paymentDetailWritePlatformService,
|
||||
NoteRepository noteRepository, LoanAccrualsProcessingService loanAccrualsProcessingService,
|
||||
ConfigurationDomainService configurationDomainService, ExternalIdFactory externalIdFactory,
|
||||
AccountTransferDetailRepository accountTransferDetailRepository, LoanChargeAssembler loanChargeAssembler,
|
||||
PaymentDetailWritePlatformService paymentDetailWritePlatformService, NoteRepository noteRepository,
|
||||
LoanAccrualsProcessingService loanAccrualsProcessingService,
|
||||
LoanDownPaymentTransactionValidator loanDownPaymentTransactionValidator, LoanChargeValidator loanChargeValidator,
|
||||
LoanScheduleService loanScheduleService, ReprocessLoanTransactionsService reprocessLoanTransactionsService,
|
||||
LoanAccountService loanAccountService, LoanAdjustmentService loanAdjustmentService, LoanChargeService loanChargeService,
|
||||
@@ -327,10 +326,9 @@ public class LoanAccountConfiguration {
|
||||
businessEventNotifierService, loanTransactionRepository, accountTransfersWritePlatformService, loanRepositoryWrapper,
|
||||
loanAccountDomainService, loanChargeRepository, loanWritePlatformService, loanUtilService, loanChargeReadPlatformService,
|
||||
loanLifecycleStateMachine, accountAssociationsReadPlatformService, fromApiJsonHelper, configurationDomainService,
|
||||
loanRepaymentScheduleTransactionProcessorFactory, externalIdFactory, accountTransferDetailRepository, loanChargeAssembler,
|
||||
paymentDetailWritePlatformService, noteRepository, loanAccrualsProcessingService, loanDownPaymentTransactionValidator,
|
||||
loanChargeValidator, loanScheduleService, reprocessLoanTransactionsService, loanAccountService, loanAdjustmentService,
|
||||
loanChargeService, loanJournalEntryPoster);
|
||||
externalIdFactory, accountTransferDetailRepository, loanChargeAssembler, paymentDetailWritePlatformService, noteRepository,
|
||||
loanAccrualsProcessingService, loanDownPaymentTransactionValidator, loanChargeValidator, loanScheduleService,
|
||||
reprocessLoanTransactionsService, loanAccountService, loanAdjustmentService, loanChargeService, loanJournalEntryPoster);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
Reference in New Issue
Block a user