mifosx-58: handle charges at disbursement for loan creation.

This commit is contained in:
Keith Woodlock
2012-09-27 11:24:30 +01:00
parent d5f697962c
commit f737336dc3
11 changed files with 293 additions and 70 deletions
@@ -0,0 +1,10 @@
ALTER TABLE `m_loan_charge`
ADD COLUMN `calculation_percentage` decimal(19,6) DEFAULT NULL AFTER `charge_calculation_enum`;
ALTER TABLE `m_loan_charge`
ADD COLUMN `calculation_on_amount` decimal(19,6) DEFAULT NULL AFTER `calculation_percentage`;
ALTER TABLE `m_loan_charge`
ADD COLUMN `amount_paid_derived` decimal(19,6) DEFAULT NULL AFTER `amount`;
ALTER TABLE `m_loan_charge`
ADD COLUMN `amount_outstanding_derived` decimal(19,6) NOT NULL default 0 AFTER `amount_paid_derived`;
ALTER TABLE `m_loan_charge`
ADD COLUMN `is_paid_derived` tinyint(1) NOT NULL default 0 AFTER `amount_outstanding_derived`;
@@ -214,9 +214,11 @@ public class LoansApiResource {
convenienceDataRequired = true;
}
charges = this.chargeReadPlatformService.retrieveLoanCharges(loanId);
if (CollectionUtils.isEmpty(charges)) {
charges = null;
if (responseParameters.contains("charges")) {
charges = this.chargeReadPlatformService.retrieveLoanCharges(loanId);
if (CollectionUtils.isEmpty(charges)) {
charges = null; // set back to null so doesnt appear in JSON is no charges exist.
}
}
}
@@ -67,8 +67,9 @@ public class LoanBasicDetailsData {
final Integer termFrequency = product.getNumberOfRepayments() * product.getRepaymentEvery();
final EnumOptionData termPeriodFrequencyType = product.getRepaymentFrequencyType();
final Collection<LoanChargeData> charges = new ArrayList<LoanChargeData>();
for (ChargeData charge : product.getCharges()){
charges.add(new LoanChargeData(null, charge.getId(), charge.getName(), charge.getCurrency(),
for (ChargeData charge : product.getCharges()) {
charges.add(LoanChargeData.newChargeDetails(charge.getId(), charge.getName(), charge.getCurrency(),
charge.getAmount(), charge.getChargeTimeType(), charge.getChargeCalculationType()));
}
@@ -15,20 +15,41 @@ public class LoanChargeData {
@SuppressWarnings("unused")
private final String name;
@SuppressWarnings("unused")
private final EnumOptionData chargeTimeType;
@SuppressWarnings("unused")
private final EnumOptionData chargeCalculationType;
@SuppressWarnings("unused")
private final BigDecimal percentage;
@SuppressWarnings("unused")
private final BigDecimal amountPercentageAppliedTo;
@SuppressWarnings("unused")
private final CurrencyData currency;
@SuppressWarnings("unused")
private final BigDecimal amount;
@SuppressWarnings("unused")
private final EnumOptionData chargeTimeType;
private final BigDecimal amountPaid;
@SuppressWarnings("unused")
private final EnumOptionData chargeCalculationType;
private final BigDecimal amountOutstanding;
@SuppressWarnings("unused")
private final Collection<ChargeData> chargeOptions;
public static LoanChargeData template(final Collection<ChargeData> chargeOptions){
return new LoanChargeData(null,null,null,null,null,null,null, chargeOptions);
}
/**
* used when populating with details from charge definition (for crud on charges)
*/
public static LoanChargeData newChargeDetails(
final Long chargeId,
final String name,
final CurrencyData currency,
final BigDecimal value,
final EnumOptionData chargeTimeType,
final EnumOptionData chargeCalculationType) {
return new LoanChargeData(null, chargeId, name, currency, value, chargeTimeType, chargeCalculationType, null);
}
public LoanChargeData(
final Long id,
@@ -36,15 +57,23 @@ public class LoanChargeData {
final String name,
final CurrencyData currency,
final BigDecimal amount,
final BigDecimal amountPaid,
final BigDecimal amountOutstanding,
final EnumOptionData chargeTimeType,
final EnumOptionData chargeCalculationType) {
final EnumOptionData chargeCalculationType,
final BigDecimal percentage,
final BigDecimal amountPercentageAppliedTo) {
this.id = id;
this.chargeId = chargeId;
this.name = name;
this.currency = currency;
this.amount = amount;
this.amountPaid = amountPaid;
this.amountOutstanding = amountOutstanding;
this.chargeTimeType = chargeTimeType;
this.chargeCalculationType = chargeCalculationType;
this.percentage = percentage;
this.amountPercentageAppliedTo = amountPercentageAppliedTo;
this.chargeOptions = null;
}
@@ -63,8 +92,12 @@ public class LoanChargeData {
this.name = name;
this.currency = currency;
this.amount = amount;
this.amountPaid = BigDecimal.ZERO;
this.amountOutstanding = amount;
this.chargeTimeType = chargeTimeType;
this.chargeCalculationType = chargeCalculationType;
this.percentage = null;
this.amountPercentageAppliedTo = null;
this.chargeOptions = chargeOptions;
}
}
@@ -195,9 +195,12 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
private static final class LoanChargeMapper implements RowMapper<LoanChargeData> {
public String loanChargeSchema(){
return "lc.id as id, c.id as chargeId, c.name as name, lc.amount as amount, c.currency_code as currencyCode, " +
"lc.charge_time_enum as chargeTime, " +
"lc.charge_calculation_enum as chargeCalculation, oc.name as currencyName, " +
return "lc.id as id, c.id as chargeId, c.name as name, " +
"lc.amount as amountDue, lc.amount_paid_derived as amountPaid, lc.amount_outstanding_derived as amountOutstanding, " +
"lc.calculation_percentage as percentageOf, lc.calculation_on_amount as amountPercentageAppliedTo, " +
"lc.charge_time_enum as chargeTime, " +
"lc.charge_calculation_enum as chargeCalculation, " +
"c.currency_code as currencyCode, oc.name as currencyName, " +
"oc.decimal_places as currencyDecimalPlaces, oc.display_symbol as currencyDisplaySymbol, " +
"oc.internationalized_name_code as currencyNameCode from m_charge c " +
"join m_organisation_currency oc on c.currency_code = oc.code " +
@@ -205,28 +208,37 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
}
@Override
public LoanChargeData mapRow(ResultSet rs, @SuppressWarnings("unused") int rowNum) throws SQLException {
Long id = rs.getLong("id");
Long chargeId = rs.getLong("chargeId");
String name = rs.getString("name");
BigDecimal amount = rs.getBigDecimal("amount");
public LoanChargeData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
final Long id = rs.getLong("id");
final Long chargeId = rs.getLong("chargeId");
final String name = rs.getString("name");
final BigDecimal amount = rs.getBigDecimal("amountDue");
BigDecimal amountPaid = rs.getBigDecimal("amountPaid");
if (amountPaid == null) {
amountPaid = BigDecimal.ZERO;
}
final BigDecimal amountOutstanding = rs.getBigDecimal("amountOutstanding");
final BigDecimal percentageOf = rs.getBigDecimal("percentageOf");
final BigDecimal amountPercentageAppliedTo = rs.getBigDecimal("amountPercentageAppliedTo");
String currencyCode = rs.getString("currencyCode");
String currencyName = rs.getString("currencyName");
String currencyNameCode = rs.getString("currencyNameCode");
String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
Integer currencyDecimalPlaces = JdbcSupport.getInteger(rs, "currencyDecimalPlaces");
final String currencyCode = rs.getString("currencyCode");
final String currencyName = rs.getString("currencyName");
final String currencyNameCode = rs.getString("currencyNameCode");
final String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
final Integer currencyDecimalPlaces = JdbcSupport.getInteger(rs, "currencyDecimalPlaces");
CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDecimalPlaces,
final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDecimalPlaces,
currencyDisplaySymbol, currencyNameCode);
int chargeTime = rs.getInt("chargeTime");
EnumOptionData chargeTimeType = ChargeEnumerations.chargeTimeType(chargeTime);
final int chargeTime = rs.getInt("chargeTime");
final EnumOptionData chargeTimeType = ChargeEnumerations.chargeTimeType(chargeTime);
int chargeCalculation = rs.getInt("chargeCalculation");
EnumOptionData chargeCalculationType = ChargeEnumerations.chargeCalculationType(chargeCalculation);
final int chargeCalculation = rs.getInt("chargeCalculation");
final EnumOptionData chargeCalculationType = ChargeEnumerations.chargeCalculationType(chargeCalculation);
return new LoanChargeData(id, chargeId, name, currency, amount, chargeTimeType, chargeCalculationType);
return new LoanChargeData(id, chargeId, name, currency, amount, amountPaid, amountOutstanding, chargeTimeType, chargeCalculationType, percentageOf, amountPercentageAppliedTo);
}
}
}
@@ -491,14 +491,17 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
// add repayment transaction to track incoming money from client to mfi for (charges due at time of disbursement)
if (getTotalChargesDueAtDisbursement().isGreaterThanZero()) {
// FIXME - add charges component to 'transactions'
LoanTransaction chargesPayment = LoanTransaction.repaymentAtDisbursement(getTotalChargesDueAtDisbursement(), disbursedOn);
Money zero = Money.zero(getCurrency());
chargesPayment.updateComponents(zero, zero, zero, getTotalChargesDueAtDisbursement());
chargesPayment.updateLoan(this);
this.loanTransactions.add(chargesPayment);
// should also pay-off the time-of-disbursement charges
for (LoanCharge charge : this.charges) {
if (charge.isDueAtDisbursement()) {
charge.markAsFullyPaid();
}
}
}
if (disbursedOn.isBefore(getApprovedOnDate())) {
@@ -515,8 +518,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
"cannot.be.a.future.date", errorMessage, disbursedOn);
}
LocalDate firstRepaymentDueDate = this.repaymentScheduleInstallments
.get(0).getDueDate();
LocalDate firstRepaymentDueDate = this.repaymentScheduleInstallments.get(0).getDueDate();
if (disbursedOn.isAfter(firstRepaymentDueDate)) {
final String errorMessage = "The date on which a loan is disbursed cannot be after the first expected repayment date: "
+ firstRepaymentDueDate.toString();
@@ -526,14 +528,19 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
}
}
public void undoDisbursal(
LoanLifecycleStateMachine loanLifecycleStateMachine) {
public void undoDisbursal(final LoanLifecycleStateMachine loanLifecycleStateMachine) {
LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_DISBURSAL_UNDO, LoanStatus.fromInt(this.loanStatus));
final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_DISBURSAL_UNDO, LoanStatus.fromInt(this.loanStatus));
this.loanStatus = statusEnum.getValue();
this.loanTransactions.clear();
this.disbursedOnDate = null;
for (LoanCharge charge : this.charges) {
if (charge.isDueAtDisbursement()) {
charge.resetToOriginal();
}
}
}
public void waive(final LoanTransaction loanTransaction, final LoanLifecycleStateMachine loanLifecycleStateMachine) {
@@ -1,6 +1,7 @@
package org.mifosng.platform.loan.domain;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.HashSet;
import java.util.Set;
@@ -30,21 +31,41 @@ public class LoanCharge extends AbstractPersistable<Long> {
@JoinColumn(name = "charge_id", referencedColumnName = "id", nullable=false)
private Charge charge;
@Column(name = "amount", scale = 6, precision = 19, nullable = false)
private BigDecimal amount;
@Column(name = "charge_time_enum", nullable = false)
private Integer chargeTime;
@Column(name = "charge_calculation_enum")
private Integer chargeCalculation;
@Column(name = "calculation_percentage", scale = 6, precision = 19, nullable = true)
private BigDecimal percentage;
@Column(name = "calculation_on_amount", scale = 6, precision = 19, nullable = true)
private BigDecimal amountPercentageAppliedTo;
@Column(name = "amount", scale = 6, precision = 19, nullable = false)
private BigDecimal amount;
@Column(name = "amount_paid_derived", scale = 6, precision = 19, nullable = true)
private BigDecimal amountPaid;
@SuppressWarnings("unused")
@Column(name = "amount_outstanding_derived", scale = 6, precision = 19, nullable = false)
private BigDecimal amountOutstanding;
@SuppressWarnings("unused")
@Column(name = "is_paid_derived", nullable=false)
private boolean paid = false;
public static LoanCharge createNew(final Loan loan, final Charge chargeDefinition, final LoanChargeCommand command) {
return new LoanCharge(loan, chargeDefinition, command);
}
public static LoanCharge createNew(final Charge chargeDefinition, final LoanChargeCommand command) {
return new LoanCharge(null, chargeDefinition, command);
/*
* loanPrincipal is required for charges that are percentage based
*/
public static LoanCharge createNewWithoutLoan(final Charge chargeDefinition, final LoanChargeCommand command, final BigDecimal loanPrincipal) {
return new LoanCharge(chargeDefinition, command, loanPrincipal);
}
public static LoanCharge createNew(final Charge chargeDefinition) {
@@ -55,16 +76,36 @@ public class LoanCharge extends AbstractPersistable<Long> {
//
}
public LoanCharge(final Charge chargeDefinition, final LoanChargeCommand command, final BigDecimal loanPrincipal) {
this.loan = null;
this.charge = chargeDefinition;
if (command.isChargeTimeTypeChanged()){
this.chargeTime = command.getChargeTimeType();
} else {
this.chargeTime = chargeDefinition.getChargeTime();
}
if (command.isChargeCalculationTypeChanged()){
this.chargeCalculation = command.getChargeCalculationType();
} else {
this.chargeCalculation = chargeDefinition.getChargeCalculation();
}
BigDecimal chargeAmount = chargeDefinition.getAmount();
if (command.isAmountChanged()){
chargeAmount = command.getAmount();
}
populateDerivedFields(loanPrincipal, chargeAmount);
this.paid = determineIfFullyPaid();
}
private LoanCharge(final Loan loan, final Charge chargeDefinition, final LoanChargeCommand command) {
this.loan = loan;
this.charge = chargeDefinition;
if (command.isAmountChanged()){
this.amount = command.getAmount();
} else {
this.amount = chargeDefinition.getAmount();
}
if (command.isChargeTimeTypeChanged()){
this.chargeTime = command.getChargeTimeType();
} else {
@@ -76,9 +117,58 @@ public class LoanCharge extends AbstractPersistable<Long> {
} else {
this.chargeCalculation = chargeDefinition.getChargeCalculation();
}
BigDecimal chargeAmount = chargeDefinition.getAmount();
if (command.isAmountChanged()){
chargeAmount = command.getAmount();
}
populateDerivedFields(loan.getPrincpal().getAmount(), chargeAmount);
this.paid = determineIfFullyPaid();
}
private LoanCharge(final Loan loan, final Charge chargeDefinition) {
private void populateDerivedFields(final BigDecimal loanPrincipal, final BigDecimal chargeAmount) {
switch (ChargeCalculationType.fromInt(this.chargeCalculation)) {
case INVALID:
this.percentage = null;
this.amount = null;
this.amountPercentageAppliedTo = null;
this.amountPaid = null;
this.amountOutstanding = null;
break;
case FLAT:
this.percentage = null;
this.amount = chargeAmount;
this.amountPercentageAppliedTo = null;
this.amountPaid = null;
this.amountOutstanding = chargeAmount;
break;
case PERCENT_OF_AMOUNT:
this.percentage = chargeAmount;
this.amountPercentageAppliedTo = loanPrincipal;
this.amount = percentageOf(this.amountPercentageAppliedTo, this.percentage);
this.amountPaid = null;
this.amountOutstanding = calculateOutstanding();
break;
case PERCENT_OF_AMOUNT_AND_INTEREST:
this.percentage = null;
this.amount = null;
this.amountPercentageAppliedTo = null;
this.amountPaid = null;
this.amountOutstanding = null;
break;
case PERCENT_OF_INTEREST:
this.percentage = null;
this.amount = null;
this.amountPercentageAppliedTo = null;
this.amountPaid = null;
this.amountOutstanding = null;
break;
}
}
private LoanCharge(final Loan loan, final Charge chargeDefinition) {
this(loan, chargeDefinition, chargeDefinition.getAmount(), chargeDefinition.getChargeTime(), chargeDefinition.getChargeCalculation());
}
@@ -107,7 +197,6 @@ public class LoanCharge extends AbstractPersistable<Long> {
if (command.isChargeCalculationTypeChanged()){
this.chargeCalculation = ChargeCalculationType.fromInt(command.getChargeCalculationType()).getValue();
}
}
public boolean isDueAtDisbursement() {
@@ -117,17 +206,35 @@ public class LoanCharge extends AbstractPersistable<Long> {
public BigDecimal calculateMonetaryAmount(final Money principalDisbursed) {
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")));
switch (ChargeCalculationType.fromInt(this.chargeCalculation)) {
case INVALID:
calculatedAmount = this.amount;
break;
case FLAT:
calculatedAmount = this.amount;
break;
case PERCENT_OF_AMOUNT:
this.amountPercentageAppliedTo = principalDisbursed.getAmount();
this.amount = percentageOf(this.amountPercentageAppliedTo, this.percentage);
this.amountPaid = null;
this.amountOutstanding = calculateOutstanding();
calculatedAmount = this.amount;
break;
case PERCENT_OF_AMOUNT_AND_INTEREST:
this.percentage = null;
this.amount = null;
this.amountPercentageAppliedTo = null;
this.amountPaid = null;
this.amountOutstanding = null;
break;
case PERCENT_OF_INTEREST:
this.percentage = null;
this.amount = null;
this.amountPercentageAppliedTo = null;
this.amountPaid = null;
this.amountOutstanding = null;
break;
}
calculatedAmount = principalDisbursed.multiplyRetainScale(amountAsPercentageFactor, RoundingMode.HALF_EVEN).getAmount();
}
return calculatedAmount;
}
@@ -145,4 +252,43 @@ public class LoanCharge extends AbstractPersistable<Long> {
return new LoanChargeCommand(modifiedParameters, this.getId(), this.loan.getId(), this.charge.getId(),
this.amount, this.chargeTime, this.chargeCalculation);
}
private boolean determineIfFullyPaid() {
return BigDecimal.ZERO.compareTo(calculateOutstanding()) == 0;
}
private BigDecimal calculateOutstanding() {
BigDecimal amountPaidLocal = BigDecimal.ZERO;
if (this.amountPaid != null) {
amountPaidLocal = this.amountPaid;
}
return this.amount.subtract(amountPaidLocal);
}
private BigDecimal percentageOf(final BigDecimal value, final BigDecimal percentage) {
BigDecimal percentageOf = BigDecimal.ZERO;
if (isGreaterThanZero(value)) {
final MathContext mc = new MathContext(8, RoundingMode.HALF_EVEN);
BigDecimal multiplicand = percentage.divide(BigDecimal.valueOf(100l), mc);
percentageOf = value.multiply(multiplicand, mc);
}
return percentageOf;
}
public void markAsFullyPaid() {
this.amountPaid = this.amount;
this.amountOutstanding = BigDecimal.ZERO;
this.paid = true;
}
public void resetToOriginal() {
this.amountPaid = BigDecimal.ZERO;
this.amountOutstanding = this.amount;
this.paid = false;
}
}
@@ -68,7 +68,7 @@ public class CalculationPlatformServiceImpl implements CalculationPlatformServic
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneByCode(loanScheduleRelatedDetails.getCurrency().getCode());
final Set<LoanCharge> loanCharges = this.loanChargeAssembler.assembleFrom(command.getCharges());
final Set<LoanCharge> loanCharges = this.loanChargeAssembler.assembleFrom(command.getCharges(), loanScheduleRelatedDetails.getPrincipal().getAmount());
return loanScheduleGenerator.generate(applicationCurrency,
loanScheduleRelatedDetails, loanTermFrequency,
@@ -104,7 +104,7 @@ public class LoanAssembler {
Staff loanOfficer= findLoanOfficerByIdIfProvided(command.getLoanOfficerId());
// 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(), loanProduct.getCurrency().getCode());
final Set<LoanCharge> loanCharges = assembleSetOfLoanCharges(command.getCharges(), loanProduct.getCharges(), loanProduct.getCurrency().getCode(), command.getPrincipal());
Loan loan = Loan.createNew(fund,loanOfficer, loanTransactionProcessingStrategy, loanProduct, client, loanRepaymentScheduleDetail, loanCharges);
loan.setExternalId(command.getExternalId());
@@ -130,8 +130,11 @@ public class LoanAssembler {
return loan;
}
public Set<LoanCharge> assembleSetOfLoanCharges(LoanChargeCommand[] chargesPassedAtCreation,
Set<Charge> chargesInheritedFromProduct, String loanCurrencyCode) {
public Set<LoanCharge> assembleSetOfLoanCharges(final LoanChargeCommand[] chargesPassedAtCreation,
final Set<Charge> chargesInheritedFromProduct,
final String loanCurrencyCode,
final BigDecimal loanPrincipal) {
Set<LoanCharge> loanCharges = new HashSet<LoanCharge>();
if (!ObjectUtils.isEmpty(chargesPassedAtCreation)) {
@@ -152,7 +155,7 @@ public class LoanAssembler {
throw new InvalidCurrencyException("charge", "attach.to.loan", errorMessage);
}
loanCharges.add(LoanCharge.createNew(chargeDefinition, loanChargeCommand));
loanCharges.add(LoanCharge.createNewWithoutLoan(chargeDefinition, loanChargeCommand, loanPrincipal));
}
} else if (chargesPassedAtCreation == null) {
for (Charge productCharge : chargesInheritedFromProduct) {
@@ -1,5 +1,6 @@
package org.mifosng.platform.loan.service;
import java.math.BigDecimal;
import java.util.HashSet;
import java.util.Set;
@@ -7,6 +8,7 @@ import org.mifosng.platform.api.commands.LoanChargeCommand;
import org.mifosng.platform.charge.domain.Charge;
import org.mifosng.platform.charge.domain.ChargeRepository;
import org.mifosng.platform.loan.domain.LoanCharge;
import org.mifosng.platform.loan.domain.LoanChargeRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -14,22 +16,29 @@ import org.springframework.stereotype.Service;
public class LoanChargeAssembler {
private ChargeRepository chargeRepository;
private final LoanChargeRepository loanChargeRepository;
@Autowired
public LoanChargeAssembler(final ChargeRepository chargeRepository) {
public LoanChargeAssembler(final ChargeRepository chargeRepository, final LoanChargeRepository loanChargeRepository) {
this.chargeRepository = chargeRepository;
this.loanChargeRepository = loanChargeRepository;
}
public Set<LoanCharge> assembleFrom(final LoanChargeCommand[] charges) {
public Set<LoanCharge> assembleFrom(final LoanChargeCommand[] charges, final BigDecimal loanPrincipal) {
final Set<LoanCharge> loanCharges = new HashSet<LoanCharge>();
// FIXME - KW - what if loanChargeCommands contains the actual loanCharge id, use loanChargeRepository to fetch it then.
if (charges != null) {
for (LoanChargeCommand loanChargeCommand : charges) {
Charge chargeDefinition = this.chargeRepository.findOne(loanChargeCommand.getChargeId());
LoanCharge loanCharge = LoanCharge.createNew(chargeDefinition, loanChargeCommand);
loanCharges.add(loanCharge);
if (loanChargeCommand.getId() == null) {
final Charge chargeDefinition = this.chargeRepository.findOne(loanChargeCommand.getChargeId());
final LoanCharge loanCharge = LoanCharge.createNewWithoutLoan(chargeDefinition, loanChargeCommand, loanPrincipal);
loanCharges.add(loanCharge);
} else {
final LoanCharge loanCharge = this.loanChargeRepository.findOne(loanChargeCommand.getId());
loanCharges.add(loanCharge);
}
}
}
@@ -156,7 +156,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
Fund fund = this.loanAssembler.findFundByIdIfProvided(command.getFundId());
Staff loanOfficer = this.loanAssembler.findLoanOfficerByIdIfProvided(command.getLoanOfficerId());
LoanTransactionProcessingStrategy strategy = this.loanAssembler.findStrategyByIdIfProvided(command.getTransactionProcessingStrategyId());
Set<LoanCharge> charges = this.loanAssembler.assembleSetOfLoanCharges(command.getCharges(), loanProduct.getCharges(), loan.getCurrency().getCode());
Set<LoanCharge> charges = this.loanAssembler.assembleSetOfLoanCharges(command.getCharges(), loanProduct.getCharges(), loan.getCurrency().getCode(), loan.getPrincpal().getAmount());
final LoanScheduleNewData loanSchedule = this.calculationPlatformService.calculateLoanScheduleNew(command.toCalculateLoanScheduleCommand());
loan.modifyLoanApplication(command, client, loanProduct, fund, strategy, loanSchedule, charges, loanOfficer);