FINERACT-2190: Improve copyFrom of LoanRepaymentScheduleInstallment
This commit is contained in:
+6
-2
@@ -39,8 +39,8 @@ public final class MathUtil {
|
||||
return nullToDefault(value, 0L);
|
||||
}
|
||||
|
||||
public static Long nullToDefault(Long value, Long def) {
|
||||
return value == null ? def : value;
|
||||
public static Integer nullToZero(Integer value) {
|
||||
return nullToDefault(value, 0);
|
||||
}
|
||||
|
||||
public static Long zeroToNull(Long value) {
|
||||
@@ -505,4 +505,8 @@ public final class MathUtil {
|
||||
return notNull ? first == null ? second : second == null ? first : max(first, second, false)
|
||||
: isGreaterThan(first, second) ? first : second;
|
||||
}
|
||||
|
||||
public static boolean isEqualTo(Integer first, Integer second) {
|
||||
return nullToZero(first).equals(nullToZero(second));
|
||||
}
|
||||
}
|
||||
|
||||
+5
-28
@@ -24,6 +24,8 @@ import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import java.math.BigDecimal;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
@@ -31,6 +33,7 @@ import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanInstallmentChargeData;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@Table(name = "m_loan_installment_charge")
|
||||
public class LoanInstallmentCharge extends AbstractPersistableCustom<Long> implements Comparable<LoanInstallmentCharge> {
|
||||
|
||||
@@ -38,6 +41,7 @@ public class LoanInstallmentCharge extends AbstractPersistableCustom<Long> imple
|
||||
@JoinColumn(name = "loan_charge_id", referencedColumnName = "id", nullable = false)
|
||||
private LoanCharge loancharge;
|
||||
|
||||
@Setter
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "loan_schedule_id", nullable = false)
|
||||
private LoanRepaymentScheduleInstallment installment;
|
||||
@@ -48,6 +52,7 @@ public class LoanInstallmentCharge extends AbstractPersistableCustom<Long> imple
|
||||
@Column(name = "amount_paid_derived", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal amountPaid;
|
||||
|
||||
@Setter
|
||||
@Column(name = "amount_waived_derived", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal amountWaived;
|
||||
|
||||
@@ -140,10 +145,6 @@ public class LoanInstallmentCharge extends AbstractPersistableCustom<Long> imple
|
||||
return this.amount.subtract(totalAccountedFor);
|
||||
}
|
||||
|
||||
public BigDecimal getAmount() {
|
||||
return this.amount;
|
||||
}
|
||||
|
||||
public Money getAmount(final MonetaryCurrency currency) {
|
||||
return Money.of(currency, this.amount);
|
||||
}
|
||||
@@ -152,22 +153,10 @@ public class LoanInstallmentCharge extends AbstractPersistableCustom<Long> imple
|
||||
return Money.of(currency, this.amountPaid);
|
||||
}
|
||||
|
||||
public BigDecimal getAmountOutstanding() {
|
||||
return this.amountOutstanding;
|
||||
}
|
||||
|
||||
private BigDecimal calculateAmountOutstanding(final MonetaryCurrency currency) {
|
||||
return getAmount(currency).minus(getAmountWaived(currency)).minus(getAmountPaid(currency)).getAmount();
|
||||
}
|
||||
|
||||
public boolean isPaid() {
|
||||
return this.paid;
|
||||
}
|
||||
|
||||
public boolean isWaived() {
|
||||
return this.waived;
|
||||
}
|
||||
|
||||
public boolean isPending() {
|
||||
return !MathUtil.isZero(this.amountOutstanding);
|
||||
}
|
||||
@@ -228,10 +217,6 @@ public class LoanInstallmentCharge extends AbstractPersistableCustom<Long> imple
|
||||
this.paid = false;
|
||||
}
|
||||
|
||||
public void setAmountWaived(final BigDecimal amountWaived) {
|
||||
this.amountWaived = amountWaived;
|
||||
}
|
||||
|
||||
public void undoWaiveFlag() {
|
||||
this.waived = false;
|
||||
}
|
||||
@@ -317,14 +302,6 @@ public class LoanInstallmentCharge extends AbstractPersistableCustom<Long> imple
|
||||
return this.loancharge;
|
||||
}
|
||||
|
||||
public LoanRepaymentScheduleInstallment getInstallment() {
|
||||
return this.installment;
|
||||
}
|
||||
|
||||
public void setInstallment(LoanRepaymentScheduleInstallment installment) {
|
||||
this.installment = installment;
|
||||
}
|
||||
|
||||
public LoanInstallmentChargeData toData() {
|
||||
return LoanInstallmentChargeData.builder().installmentNumber(installment.getInstallmentNumber()).dueDate(installment.getDueDate())
|
||||
.amount(amount).amountOutstanding(amountOutstanding).amountWaived(amountWaived).paid(paid).waived(waived).build();
|
||||
|
||||
+4
-15
@@ -25,12 +25,16 @@ import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_loan_interest_recalculation_additional_details")
|
||||
@Getter
|
||||
public class LoanInterestRecalcualtionAdditionalDetails extends AbstractPersistableCustom<Long> {
|
||||
|
||||
@Setter
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "loan_repayment_schedule_id", nullable = false)
|
||||
private LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment;
|
||||
@@ -52,19 +56,4 @@ public class LoanInterestRecalcualtionAdditionalDetails extends AbstractPersista
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public LocalDate getEffectiveDate() {
|
||||
return this.effectiveDate;
|
||||
}
|
||||
|
||||
public BigDecimal getAmount() {
|
||||
return this.amount;
|
||||
}
|
||||
|
||||
public LoanRepaymentScheduleInstallment getLoanRepaymentScheduleInstallment() {
|
||||
return loanRepaymentScheduleInstallment;
|
||||
}
|
||||
|
||||
public void setLoanRepaymentScheduleInstallment(LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment) {
|
||||
this.loanRepaymentScheduleInstallment = loanRepaymentScheduleInstallment;
|
||||
}
|
||||
}
|
||||
|
||||
+125
-96
@@ -33,6 +33,7 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
||||
@@ -56,7 +57,7 @@ public class LoanRepaymentScheduleInstallment extends AbstractAuditableWithUTCDa
|
||||
@Column(name = "installment", nullable = false)
|
||||
private Integer installmentNumber;
|
||||
|
||||
@Column(name = "fromdate", nullable = true)
|
||||
@Column(name = "fromdate")
|
||||
private LocalDate fromDate;
|
||||
|
||||
@Column(name = "duedate", nullable = false)
|
||||
@@ -140,11 +141,9 @@ public class LoanRepaymentScheduleInstallment extends AbstractAuditableWithUTCDa
|
||||
// TODO: At some point in time this database column needs to be renamed to credited_principal using the following
|
||||
// approach
|
||||
// https://blog.thepete.net/blog/2023/12/05/expand/contract-making-a-breaking-change-without-a-big-bang/
|
||||
@Setter
|
||||
@Column(name = "credits_amount", scale = 6, precision = 19)
|
||||
private BigDecimal creditedPrincipal;
|
||||
|
||||
@Setter
|
||||
@Column(name = "credited_interest", scale = 6, precision = 19)
|
||||
private BigDecimal creditedInterest;
|
||||
|
||||
@@ -392,10 +391,6 @@ public class LoanRepaymentScheduleInstallment extends AbstractAuditableWithUTCDa
|
||||
return getInterestOutstanding(currency).isGreaterThanZero();
|
||||
}
|
||||
|
||||
public Money getTotalPrincipalAndInterest(final MonetaryCurrency currency) {
|
||||
return getPrincipal(currency).plus(getInterestCharged(currency));
|
||||
}
|
||||
|
||||
public Money getTotalOutstanding(final MonetaryCurrency currency) {
|
||||
return getPrincipalOutstanding(currency).plus(getInterestOutstanding(currency)).plus(getFeeChargesOutstanding(currency))
|
||||
.plus(getPenaltyChargesOutstanding(currency));
|
||||
@@ -405,10 +400,6 @@ public class LoanRepaymentScheduleInstallment extends AbstractAuditableWithUTCDa
|
||||
this.loan = loan;
|
||||
}
|
||||
|
||||
public boolean isPartlyPaid() {
|
||||
return !this.obligationsMet && (this.interestPaid != null || this.feeChargesPaid != null || this.principalCompleted != null);
|
||||
}
|
||||
|
||||
public boolean isNotFullyPaidOff() {
|
||||
return !this.obligationsMet;
|
||||
}
|
||||
@@ -734,18 +725,6 @@ public class LoanRepaymentScheduleInstallment extends AbstractAuditableWithUTCDa
|
||||
this.penaltyAccrued = MathUtil.zeroToNull(MathUtil.toBigDecimal(penalityCharges));
|
||||
}
|
||||
|
||||
public void setInterestAccrued(BigDecimal interestAccrued) {
|
||||
this.interestAccrued = interestAccrued;
|
||||
}
|
||||
|
||||
public void setFeeAccrued(BigDecimal feeAccrued) {
|
||||
this.feeAccrued = feeAccrued;
|
||||
}
|
||||
|
||||
public void setPenaltyAccrued(BigDecimal penaltyAccrued) {
|
||||
this.penaltyAccrued = penaltyAccrued;
|
||||
}
|
||||
|
||||
public void updateObligationsMet(final MonetaryCurrency currency, final LocalDate transactionDate) {
|
||||
if (!this.obligationsMet && getTotalOutstanding(currency).isZero()) {
|
||||
this.obligationsMet = true;
|
||||
@@ -802,18 +781,6 @@ public class LoanRepaymentScheduleInstallment extends AbstractAuditableWithUTCDa
|
||||
return Money.of(currency, this.totalPaidInAdvance);
|
||||
}
|
||||
|
||||
public Money getTotalPaidLate(final MonetaryCurrency currency) {
|
||||
return Money.of(currency, this.totalPaidLate);
|
||||
}
|
||||
|
||||
public boolean isRecalculatedInterestComponent() {
|
||||
return this.recalculatedInterestComponent;
|
||||
}
|
||||
|
||||
public void setRecalculatedInterestComponent(boolean recalculatedInterestComponent) {
|
||||
this.recalculatedInterestComponent = recalculatedInterestComponent;
|
||||
}
|
||||
|
||||
public void updateInstallmentNumber(final Integer installmentNumber) {
|
||||
if (installmentNumber != null) {
|
||||
this.installmentNumber = installmentNumber;
|
||||
@@ -832,10 +799,6 @@ public class LoanRepaymentScheduleInstallment extends AbstractAuditableWithUTCDa
|
||||
this.obligationsMetOnDate = obligationsMetOnDate;
|
||||
}
|
||||
|
||||
public void updateInterestWrittenOff(final BigDecimal interestWrittenOff) {
|
||||
this.interestWrittenOff = interestWrittenOff;
|
||||
}
|
||||
|
||||
public void updatePrincipal(final BigDecimal principal) {
|
||||
this.principal = principal;
|
||||
}
|
||||
@@ -1007,41 +970,15 @@ public class LoanRepaymentScheduleInstallment extends AbstractAuditableWithUTCDa
|
||||
.plus(getPenaltyChargesCharged(currency));
|
||||
}
|
||||
|
||||
public Set<LoanInterestRecalcualtionAdditionalDetails> getLoanCompoundingDetails() {
|
||||
return this.loanCompoundingDetails;
|
||||
}
|
||||
|
||||
public Money getAccruedInterestOutstanding(final MonetaryCurrency currency) {
|
||||
final Money interestAccountedFor = getInterestPaid(currency).plus(getInterestWaived(currency))
|
||||
.plus(getInterestWrittenOff(currency));
|
||||
return getInterestAccrued(currency).minus(interestAccountedFor);
|
||||
}
|
||||
|
||||
public Money getTotalPaid(final MonetaryCurrency currency) {
|
||||
return getPenaltyChargesPaid(currency).plus(getFeeChargesPaid(currency)).plus(getInterestPaid(currency))
|
||||
.plus(getPrincipalCompleted(currency));
|
||||
}
|
||||
|
||||
public void setRescheduleInterestPortion(BigDecimal rescheduleInterestPortion) {
|
||||
this.rescheduleInterestPortion = rescheduleInterestPortion;
|
||||
}
|
||||
|
||||
public void setFeeChargesWaived(final BigDecimal newFeeChargesCharged) {
|
||||
this.feeChargesWaived = newFeeChargesCharged;
|
||||
}
|
||||
|
||||
public void setPenaltyChargesWaived(final BigDecimal newPenaltyChargesCharged) {
|
||||
this.penaltyChargesWaived = newPenaltyChargesCharged;
|
||||
}
|
||||
|
||||
public void markAsAdditional() {
|
||||
this.additional = true;
|
||||
}
|
||||
|
||||
public Set<LoanTransactionToRepaymentScheduleMapping> getLoanTransactionToRepaymentScheduleMappings() {
|
||||
return this.loanTransactionToRepaymentScheduleMappings;
|
||||
}
|
||||
|
||||
public void resetBalances() {
|
||||
resetDerivedComponents();
|
||||
resetPrincipalDue();
|
||||
@@ -1071,57 +1008,149 @@ public class LoanRepaymentScheduleInstallment extends AbstractAuditableWithUTCDa
|
||||
}
|
||||
|
||||
public void copyFrom(final LoanScheduleModelPeriod period) {
|
||||
// Reset fields and relations
|
||||
resetBalances();
|
||||
updateLoanCompoundingDetails(period.getLoanCompoundingDetails());
|
||||
getInstallmentCharges().clear();
|
||||
getPostDatedChecks().clear();
|
||||
getLoanTransactionToRepaymentScheduleMappings().clear();
|
||||
// Update fields
|
||||
setFromDate(period.periodFromDate());
|
||||
setDueDate(period.periodDueDate());
|
||||
setPrincipal(period.principalDue());
|
||||
setInterestCharged(period.interestDue());
|
||||
setFeeChargesCharged(period.feeChargesDue());
|
||||
setPenaltyCharges(period.penaltyChargesDue());
|
||||
|
||||
setRecalculatedInterestComponent(period.isRecalculatedInterestComponent());
|
||||
if (getLoanCompoundingDetails() != null) {
|
||||
getLoanCompoundingDetails().clear();
|
||||
}
|
||||
if (period.getLoanCompoundingDetails() != null) {
|
||||
period.getLoanCompoundingDetails().forEach(lcd -> {
|
||||
lcd.setLoanRepaymentScheduleInstallment(this);
|
||||
getLoanCompoundingDetails().add(lcd);
|
||||
});
|
||||
}
|
||||
setRescheduleInterestPortion(period.rescheduleInterestPortion());
|
||||
setDownPayment(period.isDownPaymentPeriod());
|
||||
|
||||
setAdditional(false);
|
||||
setReAged(false);
|
||||
}
|
||||
|
||||
public void copyFrom(final LoanRepaymentScheduleInstallment installment) {
|
||||
if (getId().equals(installment.getId())) {
|
||||
return;
|
||||
}
|
||||
// Reset balances
|
||||
resetBalances();
|
||||
// Dates
|
||||
setFromDate(installment.getFromDate());
|
||||
setDueDate(installment.getDueDate());
|
||||
|
||||
setPrincipal(installment.getPrincipal());
|
||||
setInterestCharged(installment.getInterestCharged());
|
||||
setFeeChargesCharged(installment.getFeeChargesCharged());
|
||||
setPenaltyCharges(installment.getPenaltyCharges());
|
||||
setRecalculatedInterestComponent(installment.isRecalculatedInterestComponent());
|
||||
if (getLoanCompoundingDetails() != null) {
|
||||
getLoanCompoundingDetails().clear();
|
||||
}
|
||||
if (installment.getLoanCompoundingDetails() != null) {
|
||||
installment.getLoanCompoundingDetails().forEach(lcd -> {
|
||||
lcd.setLoanRepaymentScheduleInstallment(this);
|
||||
getLoanCompoundingDetails().add(lcd);
|
||||
});
|
||||
}
|
||||
|
||||
Set<LoanInstallmentCharge> installmentCharges = installment.getInstallmentCharges();
|
||||
installmentCharges.forEach(c -> c.setInstallment(this));
|
||||
getInstallmentCharges().addAll(installmentCharges);
|
||||
|
||||
setObligationsMetOnDate(installment.getObligationsMetOnDate());
|
||||
// Flags
|
||||
setObligationsMet(installment.isObligationsMet());
|
||||
setAdditional(installment.isAdditional());
|
||||
setReAged(installment.isReAged());
|
||||
setDownPayment(installment.isDownPayment());
|
||||
// Principal
|
||||
setPrincipal(installment.getPrincipal());
|
||||
setPrincipalCompleted(installment.getPrincipalCompleted());
|
||||
setPrincipalWrittenOff(installment.getPrincipalWrittenOff());
|
||||
// Interest
|
||||
setInterestCharged(installment.getInterestCharged());
|
||||
setInterestAccrued(installment.getInterestAccrued());
|
||||
setInterestPaid(installment.getInterestPaid());
|
||||
setInterestWaived(installment.getInterestWaived());
|
||||
setInterestWrittenOff(installment.getInterestWrittenOff());
|
||||
setRescheduleInterestPortion(installment.getRescheduleInterestPortion());
|
||||
setRecalculatedInterestComponent(installment.isRecalculatedInterestComponent());
|
||||
// Fee
|
||||
setFeeChargesCharged(installment.getFeeChargesCharged());
|
||||
setFeeChargesPaid(installment.getFeeChargesPaid());
|
||||
setFeeAccrued(installment.getFeeAccrued());
|
||||
setFeeChargesWaived(installment.getFeeChargesWaived());
|
||||
setFeeChargesWrittenOff(installment.getFeeChargesWrittenOff());
|
||||
// Penalty
|
||||
setPenaltyCharges(installment.getPenaltyCharges());
|
||||
setPenaltyAccrued(installment.getPenaltyAccrued());
|
||||
setPenaltyChargesWaived(installment.getPenaltyChargesWaived());
|
||||
setPenaltyChargesPaid(installment.getPenaltyChargesPaid());
|
||||
setPenaltyChargesWrittenOff(installment.getPenaltyChargesWrittenOff());
|
||||
// paid in advance / late
|
||||
setTotalPaidInAdvance(installment.getTotalPaidInAdvance());
|
||||
setTotalPaidLate(installment.getTotalPaidLate());
|
||||
// Credits (Chargeback)
|
||||
setCreditedFee(installment.getCreditedFee());
|
||||
setCreditedPenalty(installment.getCreditedPenalty());
|
||||
setCreditedInterest(installment.getCreditedInterest());
|
||||
setCreditedPrincipal(installment.getCreditedPrincipal());
|
||||
// Compounding details
|
||||
updateLoanCompoundingDetails(installment.getLoanCompoundingDetails());
|
||||
// Installment charges
|
||||
updateLoaInstallmentCharges(installment.getInstallmentCharges());
|
||||
// Post dated checks
|
||||
updatePostDatedChecks(installment.getPostDatedChecks());
|
||||
// Loan transaction repayment schedule mapping
|
||||
updateTransactionRepaymentScheduleMapping(installment.getLoanTransactionToRepaymentScheduleMappings());
|
||||
}
|
||||
|
||||
private void updateLoanCompoundingDetails(Set<LoanInterestRecalcualtionAdditionalDetails> loanCompoundingDetails) {
|
||||
Set<LoanInterestRecalcualtionAdditionalDetails> retainedLoanCompoundingDetails = new HashSet<>();
|
||||
if (loanCompoundingDetails != null) {
|
||||
loanCompoundingDetails.forEach(nlcd -> {
|
||||
nlcd.setLoanRepaymentScheduleInstallment(this);
|
||||
getLoanCompoundingDetails().stream().filter(lcd -> MathUtil.isEqualTo(lcd.getAmount(), nlcd.getAmount()) //
|
||||
&& DateUtils.isEqual(lcd.getEffectiveDate(), nlcd.getEffectiveDate())) //
|
||||
.findAny().ifPresentOrElse(retainedLoanCompoundingDetails::add, () -> retainedLoanCompoundingDetails.add(nlcd));
|
||||
});
|
||||
}
|
||||
setLoanCompoundingDetails(retainedLoanCompoundingDetails);
|
||||
}
|
||||
|
||||
private void updateLoaInstallmentCharges(Set<LoanInstallmentCharge> installmentCharges) {
|
||||
Set<LoanInstallmentCharge> retainedInstallmentCharges = new HashSet<>();
|
||||
if (installmentCharges != null) {
|
||||
installmentCharges.forEach(nic -> {
|
||||
nic.setInstallment(this);
|
||||
getInstallmentCharges().stream().filter(ic -> MathUtil.isEqualTo(ic.getAmountOutstanding(), nic.getAmountOutstanding()) //
|
||||
&& MathUtil.isEqualTo(ic.getAmountWrittenOff(), nic.getAmountWrittenOff()) //
|
||||
&& MathUtil.isEqualTo(ic.getAmountPaid(), nic.getAmountPaid()) //
|
||||
&& MathUtil.isEqualTo(ic.getAmountThroughChargePayment(), nic.getAmountThroughChargePayment()) //
|
||||
&& MathUtil.isEqualTo(ic.getAmountWaived(), nic.getAmountWaived()) //
|
||||
&& MathUtil.isEqualTo(ic.getAmount(), nic.getAmount()) //
|
||||
&& Boolean.logicalAnd(ic.isPaid(), nic.isPaid()) //
|
||||
&& Boolean.logicalAnd(ic.isWaived(), nic.isWaived()) //
|
||||
&& Boolean.logicalAnd(ic.isPending(), nic.isPending())) //
|
||||
.findAny().ifPresentOrElse(retainedInstallmentCharges::add, () -> retainedInstallmentCharges.add(nic));
|
||||
});
|
||||
}
|
||||
setInstallmentCharges(retainedInstallmentCharges);
|
||||
}
|
||||
|
||||
private void updatePostDatedChecks(Set<PostDatedChecks> postDatedChecks) {
|
||||
Set<PostDatedChecks> retainedPostDatedChecks = new HashSet<>();
|
||||
if (postDatedChecks != null) {
|
||||
postDatedChecks.forEach(npdc -> {
|
||||
npdc.setLoanRepaymentScheduleInstallment(this);
|
||||
getPostDatedChecks().stream().filter(pdc -> MathUtil.isEqualTo(pdc.getCheckNo(), npdc.getCheckNo()) //
|
||||
&& MathUtil.isEqualTo(pdc.getAccountNo(), npdc.getAccountNo()) //
|
||||
&& MathUtil.isEqualTo(pdc.getAmount(), npdc.getAmount()) //
|
||||
&& StringUtils.equals(pdc.getBankName(), npdc.getBankName()) //
|
||||
&& MathUtil.isEqualTo(pdc.getStatus(), npdc.getStatus()) //
|
||||
&& DateUtils.isEqual(pdc.getRepaymentDate(), npdc.getRepaymentDate())) //
|
||||
.findAny().ifPresentOrElse(retainedPostDatedChecks::add, () -> retainedPostDatedChecks.add(npdc));
|
||||
});
|
||||
}
|
||||
setPostDatedChecks(retainedPostDatedChecks);
|
||||
}
|
||||
|
||||
private void updateTransactionRepaymentScheduleMapping(
|
||||
Set<LoanTransactionToRepaymentScheduleMapping> transactionToRepaymentScheduleMappings) {
|
||||
Set<LoanTransactionToRepaymentScheduleMapping> retainedTransactionRepaymentScheduleMapping = new HashSet<>();
|
||||
if (transactionToRepaymentScheduleMappings != null) {
|
||||
transactionToRepaymentScheduleMappings.forEach(ntrsm -> {
|
||||
ntrsm.setInstallment(this);
|
||||
getLoanTransactionToRepaymentScheduleMappings().stream()
|
||||
.filter(trsm -> MathUtil.isEqualTo(trsm.getAmount(), ntrsm.getAmount()) //
|
||||
&& MathUtil.isEqualTo(trsm.getFeeChargesPortion(), ntrsm.getFeeChargesPortion()) //
|
||||
&& MathUtil.isEqualTo(trsm.getInterestPortion(), ntrsm.getInterestPortion()) //
|
||||
&& MathUtil.isEqualTo(trsm.getPrincipalPortion(), ntrsm.getPrincipalPortion()) //
|
||||
&& MathUtil.isEqualTo(trsm.getPenaltyChargesPortion(), ntrsm.getPenaltyChargesPortion())) //
|
||||
.findAny().ifPresentOrElse(retainedTransactionRepaymentScheduleMapping::add,
|
||||
() -> retainedTransactionRepaymentScheduleMapping.add(ntrsm));
|
||||
});
|
||||
}
|
||||
setLoanTransactionToRepaymentScheduleMappings(retainedTransactionRepaymentScheduleMapping);
|
||||
}
|
||||
}
|
||||
|
||||
+5
-33
@@ -25,20 +25,24 @@ import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import java.math.BigDecimal;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.AllocationType;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_loan_transaction_repayment_schedule_mapping")
|
||||
@Getter
|
||||
public class LoanTransactionToRepaymentScheduleMapping extends AbstractPersistableCustom<Long> {
|
||||
|
||||
@Setter
|
||||
@ManyToOne(optional = false, cascade = CascadeType.PERSIST)
|
||||
@JoinColumn(name = "loan_transaction_id", nullable = false)
|
||||
private LoanTransaction loanTransaction;
|
||||
|
||||
@Setter
|
||||
@ManyToOne(optional = false, cascade = CascadeType.PERSIST)
|
||||
@JoinColumn(name = "loan_repayment_schedule_id", nullable = false)
|
||||
private LoanRepaymentScheduleInstallment installment;
|
||||
@@ -137,36 +141,4 @@ public class LoanTransactionToRepaymentScheduleMapping extends AbstractPersistab
|
||||
return Money.of(currency, this.penaltyChargesPortion);
|
||||
}
|
||||
|
||||
public BigDecimal getPortion(AllocationType allocationType) {
|
||||
return switch (allocationType) {
|
||||
case PRINCIPAL -> getPrincipalPortion();
|
||||
case INTEREST -> getInterestPortion();
|
||||
case FEE -> getFeeChargesPortion();
|
||||
case PENALTY -> getPenaltyChargesPortion();
|
||||
};
|
||||
}
|
||||
|
||||
public LoanTransaction getLoanTransaction() {
|
||||
return loanTransaction;
|
||||
}
|
||||
|
||||
public BigDecimal getPrincipalPortion() {
|
||||
return this.principalPortion;
|
||||
}
|
||||
|
||||
public BigDecimal getInterestPortion() {
|
||||
return this.interestPortion;
|
||||
}
|
||||
|
||||
public BigDecimal getFeeChargesPortion() {
|
||||
return this.feeChargesPortion;
|
||||
}
|
||||
|
||||
public BigDecimal getPenaltyChargesPortion() {
|
||||
return this.penaltyChargesPortion;
|
||||
}
|
||||
|
||||
public void setLoanTransaction(LoanTransaction loanTransaction) {
|
||||
this.loanTransaction = loanTransaction;
|
||||
}
|
||||
}
|
||||
|
||||
+6
-41
@@ -27,6 +27,8 @@ import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
@@ -34,11 +36,14 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleIns
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_repayment_with_post_dated_checks")
|
||||
@Getter
|
||||
public class PostDatedChecks extends AbstractPersistableCustom<Long> {
|
||||
|
||||
@Setter
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "loan_id", referencedColumnName = "id", nullable = false)
|
||||
private Loan loan;
|
||||
@Setter
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "repayment_id", referencedColumnName = "id", nullable = false)
|
||||
private LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment;
|
||||
@@ -50,6 +55,7 @@ public class PostDatedChecks extends AbstractPersistableCustom<Long> {
|
||||
private BigDecimal amount;
|
||||
@Column(name = "repayment_date", nullable = false)
|
||||
private LocalDate repaymentDate;
|
||||
@Setter
|
||||
@Column(name = "status", columnDefinition = "0")
|
||||
private Integer status;
|
||||
@Column(name = "check_no", nullable = false, unique = true)
|
||||
@@ -75,14 +81,6 @@ public class PostDatedChecks extends AbstractPersistableCustom<Long> {
|
||||
loanRepaymentScheduleInstallment.getDueDate(), loan, checkNo);
|
||||
}
|
||||
|
||||
public void setLoan(Loan loan) {
|
||||
this.loan = loan;
|
||||
}
|
||||
|
||||
public void setLoanRepaymentScheduleInstallment(final LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment) {
|
||||
this.loanRepaymentScheduleInstallment = loanRepaymentScheduleInstallment;
|
||||
}
|
||||
|
||||
public Map<String, Object> updatePostDatedChecks(JsonCommand command) {
|
||||
final Map<String, Object> changes = new HashMap<>();
|
||||
|
||||
@@ -112,37 +110,4 @@ public class PostDatedChecks extends AbstractPersistableCustom<Long> {
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
public Loan getLoan() {
|
||||
return this.loan;
|
||||
}
|
||||
|
||||
public LoanRepaymentScheduleInstallment getLoanRepaymentScheduleInstallment() {
|
||||
return this.loanRepaymentScheduleInstallment;
|
||||
}
|
||||
|
||||
public void setStatus(Integer status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getBankName() {
|
||||
return this.bankName;
|
||||
}
|
||||
|
||||
public Long getCheckNo() {
|
||||
return this.checkNo;
|
||||
}
|
||||
|
||||
public Long getAccountNo() {
|
||||
return this.accountNo;
|
||||
}
|
||||
|
||||
public BigDecimal getAmount() {
|
||||
return this.amount;
|
||||
}
|
||||
|
||||
public Integer getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -425,8 +425,8 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
|
||||
loanApplicationTerms.getInterestMethod());
|
||||
final LoanLifecycleStateMachine loanLifecycleStateMachine = null;
|
||||
loan.setHelpers(loanLifecycleStateMachine);
|
||||
final LoanScheduleDTO loanScheduleDTO = loanScheduleGenerator.rescheduleNextInstallments(mathContext, loanApplicationTerms, loan,
|
||||
loanApplicationTerms.getHolidayDetailDTO(), loanRepaymentScheduleTransactionProcessor, rescheduleFromDate);
|
||||
final LoanScheduleDTO loanScheduleDTO = loanScheduleGenerator.rescheduleNextInstallments(mathContext, loanApplicationTerms,
|
||||
loan, loanApplicationTerms.getHolidayDetailDTO(), loanRepaymentScheduleTransactionProcessor, rescheduleFromDate);
|
||||
|
||||
// Either the installments got recalculated or the model
|
||||
if (loanScheduleDTO.getInstallments() != null) {
|
||||
|
||||
Reference in New Issue
Block a user