mifosx-58: loan charges at time of disbursement

This commit is contained in:
Keith Woodlock
2012-09-13 17:20:49 +01:00
parent 16da04f089
commit 384928670d
10 changed files with 169 additions and 87 deletions
@@ -0,0 +1,2 @@
ALTER TABLE `m_loan`
ADD COLUMN `total_charges_due_at_disbursement_derived` bigint(20) DEFAULT NULL AFTER `interest_rebate_amount`;
@@ -47,7 +47,7 @@ public class Charge extends AbstractAuditableCustom<AppUser, Long> {
// //
} }
public Charge(final String name, final BigDecimal amount, final String currencyCode, private Charge(final String name, final BigDecimal amount, final String currencyCode,
final ChargeAppliesTo chargeAppliesTo, final ChargeTimeType chargeTime, final ChargeAppliesTo chargeAppliesTo, final ChargeTimeType chargeTime,
final ChargeCalculationType chargeCalculationType, final boolean active) { final ChargeCalculationType chargeCalculationType, final boolean active) {
this.name = name; this.name = name;
@@ -2,10 +2,10 @@ package org.mifosng.platform.charge.domain;
public enum ChargeCalculationType { public enum ChargeCalculationType {
INVALID(0, "chargeCalculationType.invalid"), INVALID(0, "chargeCalculationType.invalid"), //
FLAT(1, "chargeCalculationType.flat"), FLAT(1, "chargeCalculationType.flat"), //
PERCENT_OF_AMOUNT(2, "chargeCalculationType.percent.of.amount"), PERCENT_OF_AMOUNT(2, "chargeCalculationType.percent.of.amount"), //
PERCENT_OF_AMOUNT_AND_INTEREST(3, "chargeCalculationType.percent.of.amount.and.interest"), PERCENT_OF_AMOUNT_AND_INTEREST(3, "chargeCalculationType.percent.of.amount.and.interest"), //
PERCENT_OF_INTEREST(4, "chargeCalculationType.percent.of.interest"); PERCENT_OF_INTEREST(4, "chargeCalculationType.percent.of.interest");
private final Integer value; private final Integer value;
@@ -156,6 +156,10 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
@Column(name = "interest_rebate_amount", scale = 6, precision = 19) @Column(name = "interest_rebate_amount", scale = 6, precision = 19)
private BigDecimal interestRebateOwed; private BigDecimal interestRebateOwed;
@SuppressWarnings("unused") // derived field used in GETs only at present
@Column(name = "total_charges_due_at_disbursement_derived", scale = 6, precision = 19)
private BigDecimal totalChargesDueAtDisbursement;
@Transient @Transient
private final InterestRebateCalculatorFactory interestRebateCalculatorFactory = new DailyEquivalentInterestRebateCalculatorFactory(); private final InterestRebateCalculatorFactory interestRebateCalculatorFactory = new DailyEquivalentInterestRebateCalculatorFactory();
@@ -164,8 +168,8 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
public static Loan createNew(final Fund fund,final Staff loanOfficer, final LoanTransactionProcessingStrategy transactionProcessingStrategy, public static Loan createNew(final Fund fund,final Staff loanOfficer, final LoanTransactionProcessingStrategy transactionProcessingStrategy,
final LoanProduct loanProduct, final Client client, final LoanProduct loanProduct, final Client client,
final LoanProductRelatedDetail loanRepaymentScheduleDetail) { final LoanProductRelatedDetail loanRepaymentScheduleDetail, final Set<LoanCharge> loanCharges) {
return new Loan(client, fund,loanOfficer, transactionProcessingStrategy, loanProduct, loanRepaymentScheduleDetail, null); return new Loan(client, fund,loanOfficer, transactionProcessingStrategy, loanProduct, loanRepaymentScheduleDetail, null, loanCharges);
} }
protected Loan() { protected Loan() {
@@ -175,9 +179,12 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
this.charges = null; this.charges = null;
} }
public Loan(final Client client, Fund fund, Staff loanOfficer, LoanTransactionProcessingStrategy transactionProcessingStrategy, final LoanProduct loanProduct, private Loan(
final Client client, Fund fund, Staff loanOfficer,
final LoanTransactionProcessingStrategy transactionProcessingStrategy,
final LoanProduct loanProduct,
final LoanProductRelatedDetail loanRepaymentScheduleDetail, final LoanProductRelatedDetail loanRepaymentScheduleDetail,
final LoanStatus loanStatus) { final LoanStatus loanStatus, final Set<LoanCharge> loanCharges) {
this.client = client; this.client = client;
this.fund = fund; this.fund = fund;
this.loanofficer = loanOfficer; this.loanofficer = loanOfficer;
@@ -189,9 +196,37 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
} else { } else {
this.loanStatus = null; this.loanStatus = null;
} }
if (loanCharges != null && !loanCharges.isEmpty()) {
this.charges = associateChargesWithThisLoan(loanCharges);
this.totalChargesDueAtDisbursement = deriveSumTotalOfChargesDueAtDisbursement();
} else {
this.charges = null;
}
this.interestRebateOwed = BigDecimal.ZERO; this.interestRebateOwed = BigDecimal.ZERO;
} }
private BigDecimal deriveSumTotalOfChargesDueAtDisbursement() {
Money chargesDue = Money.of(getCurrency(), BigDecimal.ZERO);
for (LoanCharge charge : this.charges) {
if (charge.isDueAtDisbursement()) {
chargesDue = chargesDue.plus(charge.calculateMonetaryAmount());
}
}
return chargesDue.getAmount();
}
private Set<LoanCharge> associateChargesWithThisLoan(Set<LoanCharge> loanCharges) {
for (LoanCharge loanCharge : loanCharges) {
loanCharge.update(this);
}
return loanCharges;
}
public Client client() { public Client client() {
return this.client; return this.client;
} }
@@ -266,7 +301,9 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
if (command.isChargesChanged()) { if (command.isChargesChanged()) {
this.charges.clear(); this.charges.clear();
this.charges.addAll(charges);
this.charges = associateChargesWithThisLoan(charges);
this.totalChargesDueAtDisbursement = deriveSumTotalOfChargesDueAtDisbursement();
} }
this.loanRepaymentScheduleDetail.update(command.toLoanProductCommand()); this.loanRepaymentScheduleDetail.update(command.toLoanProductCommand());
@@ -1217,4 +1254,8 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
return this.loanRepaymentScheduleDetail.getPrincipal() return this.loanRepaymentScheduleDetail.getPrincipal()
.getCurrencyCode(); .getCurrencyCode();
} }
public Money getPrincpal() {
return this.loanRepaymentScheduleDetail.getPrincipal();
}
} }
@@ -1,18 +1,27 @@
package org.mifosng.platform.loan.domain; package org.mifosng.platform.loan.domain;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.mifosng.platform.api.commands.LoanChargeCommand; import org.mifosng.platform.api.commands.LoanChargeCommand;
import org.mifosng.platform.charge.domain.Charge; import org.mifosng.platform.charge.domain.Charge;
import org.mifosng.platform.charge.domain.ChargeCalculationType;
import javax.persistence.*; import org.mifosng.platform.charge.domain.ChargeTimeType;
import java.io.Serializable;
import java.math.BigDecimal;
@Entity @Entity
@IdClass(LoanCharge.LoanChargePK.class) @IdClass(LoanCharge.LoanChargePK.class)
@Table(name = "m_loan_charge") @Table(name = "m_loan_charge")
public class LoanCharge { public class LoanCharge {
@SuppressWarnings("unused")
@Id @Id
private Loan loan; private Loan loan;
@@ -20,50 +29,55 @@ public class LoanCharge {
@Id @Id
private Charge charge; private Charge charge;
@SuppressWarnings("unused")
@Column(name = "amount", scale = 6, precision = 19, nullable = false) @Column(name = "amount", scale = 6, precision = 19, nullable = false)
private BigDecimal amount; private BigDecimal amount;
@SuppressWarnings("unused")
@Column(name = "charge_time_enum", nullable = false) @Column(name = "charge_time_enum", nullable = false)
private Integer chargeTime; private Integer chargeTime;
@SuppressWarnings("unused")
@Column(name = "charge_calculation_enum") @Column(name = "charge_calculation_enum")
private Integer chargeCalculation; private Integer chargeCalculation;
public static LoanCharge createNew(final Charge chargeDefinition, final LoanChargeCommand command) {
return new LoanCharge(null, chargeDefinition, command);
}
public static LoanCharge createNew(final Charge chargeDefinition) {
return new LoanCharge(null, chargeDefinition);
}
protected LoanCharge() { protected LoanCharge() {
// //
} }
public LoanCharge(Loan loan, Charge charge, LoanChargeCommand command) { private LoanCharge(final Loan loan, final Charge chargeDefinition, final LoanChargeCommand command) {
this.loan = loan; this.loan = loan;
this.charge = charge; this.charge = chargeDefinition;
if (command.isAmountChanged()){ if (command.isAmountChanged()){
this.amount = command.getAmount(); this.amount = command.getAmount();
} else { } else {
this.amount = charge.getAmount(); this.amount = chargeDefinition.getAmount();
} }
if (command.isChargeTimeTypeChanged()){ if (command.isChargeTimeTypeChanged()){
this.chargeTime = command.getChargeTimeType(); this.chargeTime = command.getChargeTimeType();
} else { } else {
this.chargeTime = charge.getChargeTime(); this.chargeTime = chargeDefinition.getChargeTime();
} }
if (command.isChargeCalculationTypeChanged()){ if (command.isChargeCalculationTypeChanged()){
this.chargeCalculation = command.getChargeCalculationType(); this.chargeCalculation = command.getChargeCalculationType();
} else { } else {
this.chargeCalculation = charge.getChargeCalculation(); this.chargeCalculation = chargeDefinition.getChargeCalculation();
} }
} }
public LoanCharge(final Loan loan, final Charge charge) { private LoanCharge(final Loan loan, final Charge chargeDefinition) {
this(loan, charge, charge.getAmount(), charge.getChargeTime(), charge.getChargeCalculation()); this(loan, chargeDefinition, chargeDefinition.getAmount(), chargeDefinition.getChargeTime(), chargeDefinition.getChargeCalculation());
} }
public LoanCharge(final Loan loan, final Charge charge, final BigDecimal amount, final Integer chargeTime, final Integer chargeCalculation) { private LoanCharge(final Loan loan, final Charge charge, final BigDecimal amount, final Integer chargeTime, final Integer chargeCalculation) {
this.loan = loan; this.loan = loan;
this.charge = charge; this.charge = charge;
this.amount = amount; this.amount = amount;
@@ -84,4 +98,34 @@ public class LoanCharge {
@JoinColumn(name = "charge_id", referencedColumnName = "id", nullable=false) @JoinColumn(name = "charge_id", referencedColumnName = "id", nullable=false)
private Charge charge; private Charge charge;
} }
public void update(final Loan loan) {
this.loan = loan;
}
public boolean isDueAtDisbursement() {
return ChargeTimeType.fromInt(this.chargeTime).equals(ChargeTimeType.DISBURSEMENT);
}
public BigDecimal calculateMonetaryAmount() {
BigDecimal calculatedAmount = BigDecimal.ZERO;
if (ChargeCalculationType.fromInt(chargeCalculation).equals(ChargeCalculationType.FLAT)) {
calculatedAmount = this.amount;
} else if (ChargeCalculationType.fromInt(chargeCalculation).equals(ChargeCalculationType.PERCENT_OF_AMOUNT)) {
BigDecimal amountAsPercentageFactor = BigDecimal.ZERO;
if (isGreaterThanZero(this.amount)) {
amountAsPercentageFactor = this.amount.divide(BigDecimal.valueOf(Double.valueOf("100")));
}
calculatedAmount = this.loan.getPrincpal().multiplyRetainScale(amountAsPercentageFactor, RoundingMode.HALF_EVEN).getAmount();
}
return calculatedAmount;
}
private boolean isGreaterThanZero(final BigDecimal value) {
return value.compareTo(BigDecimal.ZERO) == 1;
}
} }
@@ -52,7 +52,7 @@ public class LoanTransaction extends AbstractAuditableCustom<AppUser, Long> {
@Enumerated(EnumType.ORDINAL) @Enumerated(EnumType.ORDINAL)
@Column(name = "transaction_type_enum", nullable = false) @Column(name = "transaction_type_enum", nullable = false)
private LoanTransactionType typeOf; private Integer typeOf;
@OneToOne(optional=true, cascade={CascadeType.PERSIST}) @OneToOne(optional=true, cascade={CascadeType.PERSIST})
@JoinColumn(name="contra_id") @JoinColumn(name="contra_id")
@@ -65,32 +65,30 @@ public class LoanTransaction extends AbstractAuditableCustom<AppUser, Long> {
this.typeOf = null; this.typeOf = null;
} }
public static LoanTransaction disbursement(Money amount, LocalDate disbursementDate) { public static LoanTransaction disbursement(final Money amount, final LocalDate disbursementDate) {
return new LoanTransaction(LoanTransactionType.DISBURSEMENT, amount.getAmount(), disbursementDate); return new LoanTransaction(LoanTransactionType.DISBURSEMENT, amount.getAmount(), disbursementDate);
} }
public static LoanTransaction repayment(Money amount, LocalDate paymentDate) { public static LoanTransaction repayment(final Money amount, final LocalDate paymentDate) {
return new LoanTransaction(LoanTransactionType.REPAYMENT, amount.getAmount(), paymentDate); return new LoanTransaction(LoanTransactionType.REPAYMENT, amount.getAmount(), paymentDate);
} }
public static LoanTransaction waiver(Money waived, LocalDate waiveDate) { public static LoanTransaction waiver(final Money waived, final LocalDate waiveDate) {
return new LoanTransaction(LoanTransactionType.WAIVED, waived.getAmount(), waiveDate); return new LoanTransaction(LoanTransactionType.WAIVED, waived.getAmount(), waiveDate);
} }
private static LoanTransaction contra(LoanTransaction originalTransaction) { private static LoanTransaction contra(LoanTransaction originalTransaction) {
LoanTransaction contra = new LoanTransaction(LoanTransactionType.REVERSAL, originalTransaction.getAmount().negate(), new LocalDate(originalTransaction.getDateOf())); LoanTransaction contra = new LoanTransaction(LoanTransactionType.REVERSAL, originalTransaction.getAmount().negate(), new LocalDate(originalTransaction.getDateOf()));
contra.updateContra(originalTransaction); contra.updateContra(originalTransaction);
return contra; return contra;
} }
public void updateContra(LoanTransaction transaction) { public void updateContra(final LoanTransaction transaction) {
this.contra = transaction; this.contra = transaction;
} }
private LoanTransaction(LoanTransactionType type, final BigDecimal amount, final LocalDate date) { private LoanTransaction(final LoanTransactionType type, final BigDecimal amount, final LocalDate date) {
this.typeOf = type; this.typeOf = type.getValue();
this.amount = amount; this.amount = amount;
this.dateOf = date.toDateMidnight().toDate(); this.dateOf = date.toDateMidnight().toDate();
} }
@@ -113,11 +111,11 @@ public class LoanTransaction extends AbstractAuditableCustom<AppUser, Long> {
} }
public LoanTransactionType getTypeOf() { public LoanTransactionType getTypeOf() {
return typeOf; return LoanTransactionType.fromInt(this.typeOf);
} }
public boolean isRepayment() { public boolean isRepayment() {
return LoanTransactionType.REPAYMENT.equals(typeOf) && isNotContra(); return LoanTransactionType.REPAYMENT.equals(getTypeOf()) && isNotContra();
} }
public boolean isNotRepayment() { public boolean isNotRepayment() {
@@ -129,11 +127,11 @@ public class LoanTransaction extends AbstractAuditableCustom<AppUser, Long> {
} }
public boolean isDisbursement() { public boolean isDisbursement() {
return LoanTransactionType.DISBURSEMENT.equals(typeOf); return LoanTransactionType.DISBURSEMENT.equals(getTypeOf());
} }
public boolean isWaiver() { public boolean isWaiver() {
return LoanTransactionType.WAIVED.equals(typeOf) && isNotContra(); return LoanTransactionType.WAIVED.equals(getTypeOf()) && isNotContra();
} }
public boolean isNotWaiver() { public boolean isNotWaiver() {
@@ -1,7 +1,12 @@
package org.mifosng.platform.loan.domain; package org.mifosng.platform.loan.domain;
public enum LoanTransactionType { public enum LoanTransactionType {
INVALID(0, "loanTransactionType.invalid"), DISBURSEMENT(1, "loanTransactionType.disbursement"), REPAYMENT(2, "loanTransactionType.repayment"), REVERSAL(3, "loanTransactionType.reversal"), WAIVED(4, "loanTransactionType.waiver");
INVALID(0, "loanTransactionType.invalid"), //
DISBURSEMENT(1, "loanTransactionType.disbursement"), //
REPAYMENT(2, "loanTransactionType.repayment"), //
REVERSAL(3, "loanTransactionType.reversal"), //
WAIVED(4, "loanTransactionType.waiver");
private final Integer value; private final Integer value;
private final String code; private final String code;
@@ -6,8 +6,8 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import org.mifosng.platform.api.commands.LoanChargeCommand;
import org.mifosng.platform.api.commands.LoanApplicationCommand; import org.mifosng.platform.api.commands.LoanApplicationCommand;
import org.mifosng.platform.api.commands.LoanChargeCommand;
import org.mifosng.platform.api.data.LoanSchedule; import org.mifosng.platform.api.data.LoanSchedule;
import org.mifosng.platform.api.data.MoneyData; import org.mifosng.platform.api.data.MoneyData;
import org.mifosng.platform.api.data.ScheduledLoanInstallment; import org.mifosng.platform.api.data.ScheduledLoanInstallment;
@@ -20,7 +20,6 @@ import org.mifosng.platform.exceptions.ChargeIsNotActiveException;
import org.mifosng.platform.exceptions.ChargeNotFoundException; import org.mifosng.platform.exceptions.ChargeNotFoundException;
import org.mifosng.platform.exceptions.ClientNotFoundException; import org.mifosng.platform.exceptions.ClientNotFoundException;
import org.mifosng.platform.exceptions.FundNotFoundException; import org.mifosng.platform.exceptions.FundNotFoundException;
import org.mifosng.platform.exceptions.InvalidCurrencyException;
import org.mifosng.platform.exceptions.LoanProductNotFoundException; import org.mifosng.platform.exceptions.LoanProductNotFoundException;
import org.mifosng.platform.exceptions.LoanTransactionProcessingStrategyNotFoundException; import org.mifosng.platform.exceptions.LoanTransactionProcessingStrategyNotFoundException;
import org.mifosng.platform.exceptions.StaffNotFoundException; import org.mifosng.platform.exceptions.StaffNotFoundException;
@@ -94,9 +93,6 @@ public class LoanAssembler {
LoanProductRelatedDetail loanRepaymentScheduleDetail = assembleLoanProductRelatedDetailFrom(command, currency); LoanProductRelatedDetail loanRepaymentScheduleDetail = assembleLoanProductRelatedDetailFrom(command, currency);
LoanSchedule loanSchedule = command.getLoanSchedule();
List<ScheduledLoanInstallment> loanRepaymentSchedule = loanSchedule.getScheduledLoanInstallments();
// associating fund with loan product at creation is optional for now. // associating fund with loan product at creation is optional for now.
Fund fund = findFundByIdIfProvided(command.getFundId()); Fund fund = findFundByIdIfProvided(command.getFundId());
LoanTransactionProcessingStrategy loanTransactionProcessingStrategy = findStrategyByIdIfProvided(command.getTransactionProcessingStrategyId()); LoanTransactionProcessingStrategy loanTransactionProcessingStrategy = findStrategyByIdIfProvided(command.getTransactionProcessingStrategyId());
@@ -104,11 +100,15 @@ public class LoanAssembler {
//optionally associate a loan officer to the loan //optionally associate a loan officer to the loan
Staff loanOfficer= findLoanOfficerByIdIfProvided(command.getLoanOfficerId()); Staff loanOfficer= findLoanOfficerByIdIfProvided(command.getLoanOfficerId());
Loan loan = Loan.createNew(fund,loanOfficer, loanTransactionProcessingStrategy, loanProduct, client, loanRepaymentScheduleDetail); // optionally, see if charges are associated with loan on creation (through loan product or by being directly added)
final Set<LoanCharge> loanCharges = assembleSetOfLoanCharges(command.getCharges(), loanProduct.getCharges());
Loan loan = Loan.createNew(fund,loanOfficer, loanTransactionProcessingStrategy, loanProduct, client, loanRepaymentScheduleDetail, loanCharges);
loan.setExternalId(command.getExternalId()); loan.setExternalId(command.getExternalId());
final Set<LoanCharge> charges = this.assembleSetOfCharges(command, loan, loanProduct); // TODO - user service to calculate loan schedule at this point
loan.setCharges(charges); LoanSchedule loanSchedule = command.getLoanSchedule();
List<ScheduledLoanInstallment> loanRepaymentSchedule = loanSchedule.getScheduledLoanInstallments();
for (ScheduledLoanInstallment scheduledLoanInstallment : loanRepaymentSchedule) { for (ScheduledLoanInstallment scheduledLoanInstallment : loanRepaymentSchedule) {
@@ -130,6 +130,33 @@ public class LoanAssembler {
return loan; return loan;
} }
public Set<LoanCharge> assembleSetOfLoanCharges(LoanChargeCommand[] chargesPassedAtCreation, Set<Charge> chargesInheritedFromProduct) {
Set<LoanCharge> loanCharges = new HashSet<LoanCharge>();
if (!ObjectUtils.isEmpty(chargesPassedAtCreation)) {
for (LoanChargeCommand loanChargeCommand : chargesPassedAtCreation) {
Long chargeDefinitionId = loanChargeCommand.getId();
Charge chargeDefinition = this.chargeRepository.findOne(chargeDefinitionId);
if (chargeDefinition == null || chargeDefinition.isDeleted()) {
throw new ChargeNotFoundException(chargeDefinitionId);
}
if (!chargeDefinition.isActive()) {
throw new ChargeIsNotActiveException(chargeDefinitionId);
}
loanCharges.add(LoanCharge.createNew(chargeDefinition, loanChargeCommand));
}
} else if (chargesPassedAtCreation == null) {
for (Charge productCharge : chargesInheritedFromProduct) {
loanCharges.add(LoanCharge.createNew(productCharge));
}
}
return loanCharges;
}
public LoanProductRelatedDetail assembleLoanProductRelatedDetailFrom(final LoanApplicationCommand command, MonetaryCurrency currency) { public LoanProductRelatedDetail assembleLoanProductRelatedDetailFrom(final LoanApplicationCommand command, MonetaryCurrency currency) {
final BigDecimal defaultNominalInterestRatePerPeriod = command.getInterestRatePerPeriod(); final BigDecimal defaultNominalInterestRatePerPeriod = command.getInterestRatePerPeriod();
final PeriodFrequencyType interestPeriodFrequencyType = PeriodFrequencyType.fromInt(command.getInterestRateFrequencyType()); final PeriodFrequencyType interestPeriodFrequencyType = PeriodFrequencyType.fromInt(command.getInterestRateFrequencyType());
@@ -193,39 +220,4 @@ public class LoanAssembler {
} }
return strategy; return strategy;
} }
public Set<LoanCharge> assembleSetOfCharges(final LoanApplicationCommand command, final Loan loan,
final LoanProduct product) {
Set<LoanCharge> charges = new HashSet<LoanCharge>();
LoanChargeCommand[] loanChargesArray = command.getCharges();
String loanCurrencyCode = loan.getCurrencyCode();
if (loanCurrencyCode == null){
loanCurrencyCode = product.getCurrency().getCode();
}
if (!ObjectUtils.isEmpty(loanChargesArray)) {
for (LoanChargeCommand loanChargeCommand : loanChargesArray) {
Long id = loanChargeCommand.getId();
Charge charge = this.chargeRepository.findOne(id);
if (charge == null || charge.isDeleted()) {
throw new ChargeNotFoundException(id);
}
if (!charge.isActive()){
throw new ChargeIsNotActiveException(id);
}
if (!loanCurrencyCode.equals(charge.getCurrencyCode())){
String errorMessage = "Charge and Loan must have the same currency.";
throw new InvalidCurrencyException("charge", "attach.to.loan", errorMessage);
}
charges.add(new LoanCharge(loan, charge, loanChargeCommand));
}
} else if (loanChargesArray == null) {
for (Charge productCharge : product.getCharges()){
charges.add(new LoanCharge(loan, productCharge));
}
}
return charges;
}
} }
@@ -145,7 +145,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
Fund fund = this.loanAssembler.findFundByIdIfProvided(command.getFundId()); Fund fund = this.loanAssembler.findFundByIdIfProvided(command.getFundId());
Staff loanOfficer = this.loanAssembler.findLoanOfficerByIdIfProvided(command.getLoanOfficerId()); Staff loanOfficer = this.loanAssembler.findLoanOfficerByIdIfProvided(command.getLoanOfficerId());
LoanTransactionProcessingStrategy strategy = this.loanAssembler.findStrategyByIdIfProvided(command.getTransactionProcessingStrategyId()); LoanTransactionProcessingStrategy strategy = this.loanAssembler.findStrategyByIdIfProvided(command.getTransactionProcessingStrategyId());
Set<LoanCharge> charges = this.loanAssembler.assembleSetOfCharges(command, loan, loanProduct) ; Set<LoanCharge> charges = this.loanAssembler.assembleSetOfLoanCharges(command.getCharges(), loanProduct.getCharges()) ;
LoanSchedule loanSchedule = this.calculationPlatformService.calculateLoanSchedule(command.toCalculateLoanScheduleCommand()); LoanSchedule loanSchedule = this.calculationPlatformService.calculateLoanSchedule(command.toCalculateLoanScheduleCommand());
loan.modifyLoanApplication(command, client, loanProduct, fund, strategy, loanSchedule, charges, loanOfficer); loan.modifyLoanApplication(command, client, loanProduct, fund, strategy, loanSchedule, charges, loanOfficer);