Merge branch 'MIFOSX-1639' of git://github.com/emmanuelnnaa/mifosx into emmanuelnnaa-MIFOSX-1639

Conflicts:
	mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java
	mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java
	mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java
This commit is contained in:
Vishwas Babu A J
2014-11-13 20:20:00 +05:30
9 changed files with 137 additions and 31 deletions
+1 -1
View File
@@ -7961,7 +7961,7 @@ Request Body:
</tr>
<tr class=alt>
<td>graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, linkAccountId,
fixedEmiAmount, maxOutstandingLoanBalance, disbursementData, graceOnArrearsAgeing
fixedEmiAmount, maxOutstandingLoanBalance, disbursementData, graceOnArrearsAgeing, createStandingInstructionAtDisbursement (requires linkedAccountId if set to true)
</td>
</tr>
</table>
@@ -173,6 +173,7 @@ public class LoanAccountData {
private final boolean isInterestRecalculationEnabled;
private final LoanInterestRecalculationData interestRecalculationData;
private final Boolean createStandingInstructionAtDisbursement;
/**
* Used to produce a {@link LoanAccountData} with only collateral options
@@ -270,6 +271,7 @@ public class LoanAccountData {
final boolean isInterestRecalculationEnabled = false;
final LoanInterestRecalculationData interestRecalculationData = null;
final LoanScheduleData originalSchedule = null;
final Boolean createStandingInstructionAtDisbursement = null;
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, loanProductId,
loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName,
@@ -286,7 +288,7 @@ public class LoanAccountData {
syncDisbursementWithMeeting, loancounter, loanProductCounter, notes, accountLinkingOptions, linkedAccount,
disbursementData, multiDisburseLoan, fixedEmiAmount, maxOutstandingLoanBalance, emiAmountVariations, memberVariations,
product, inArrears, graceOnArrearsAgeing, overdueCharges, isNPA, daysInMonthType, daysInYearType,
isInterestRecalculationEnabled, interestRecalculationData, originalSchedule);
isInterestRecalculationEnabled, interestRecalculationData, originalSchedule, createStandingInstructionAtDisbursement);
}
/**
@@ -385,6 +387,7 @@ public class LoanAccountData {
final boolean isInterestRecalculationEnabled = false;
final LoanInterestRecalculationData interestRecalculationData = null;
final LoanScheduleData originalSchedule = null;
final Boolean createStandingInstructionAtDisbursement = null;
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, loanProductId,
loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName,
@@ -401,7 +404,8 @@ public class LoanAccountData {
syncDisbursementWithMeeting, loancounter, loanProductCounter, notes, accountLinkingOptions, linkedAccount,
disbursementData, multiDisburseLoan, fixedEmiAmount, maxOutstandingLoanBalance, emiAmountVariations, memberVariations,
product, inArrears, graceOnArrearsAgeing, overdueCharges, isNPA, daysInMonthType, daysInYearType,
isInterestRecalculationEnabled, interestRecalculationData, originalSchedule);
isInterestRecalculationEnabled, interestRecalculationData, originalSchedule, createStandingInstructionAtDisbursement);
}
public static LoanAccountData populateClientDefaults(final LoanAccountData acc, final LoanAccountData clientAcc) {
@@ -425,7 +429,7 @@ public class LoanAccountData {
acc.linkedAccount, acc.disbursementDetails, acc.multiDisburseLoan, acc.fixedEmiAmount, acc.maxOutstandingLoanBalance,
acc.emiAmountVariations, acc.memberVariations, acc.product, acc.inArrears, acc.graceOnArrearsAgeing, acc.overdueCharges,
acc.isNPA, acc.daysInMonthType, acc.daysInYearType, acc.isInterestRecalculationEnabled, acc.interestRecalculationData,
acc.originalSchedule);
acc.originalSchedule, acc.createStandingInstructionAtDisbursement);
}
/**
@@ -525,6 +529,7 @@ public class LoanAccountData {
final boolean isInterestRecalculationEnabled = false;
final LoanInterestRecalculationData interestRecalculationData = null;
final LoanScheduleData originalSchedule = null;
final Boolean createStandingInstructionAtDisbursement = null;
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, loanProductId,
loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName,
@@ -541,7 +546,7 @@ public class LoanAccountData {
syncDisbursementWithMeeting, loancounter, loanProductCounter, notes, accountLinkingOptions, linkedAccount,
disbursementData, multiDisburseLoan, fixedEmiAmount, maxOutstandingBalance, emiAmountVariations, memberVariations, product,
inArrears, graceOnArrearsAgeing, overdueCharges, isNPA, daysInMonthType, daysInYearType, isInterestRecalculationEnabled,
interestRecalculationData, originalSchedule);
interestRecalculationData, originalSchedule, createStandingInstructionAtDisbursement);
}
public static LoanAccountData populateGroupDefaults(final LoanAccountData acc, final LoanAccountData groupAcc) {
@@ -565,7 +570,7 @@ public class LoanAccountData {
acc.linkedAccount, acc.disbursementDetails, acc.multiDisburseLoan, acc.fixedEmiAmount, acc.maxOutstandingLoanBalance,
acc.emiAmountVariations, acc.memberVariations, acc.product, acc.inArrears, acc.graceOnArrearsAgeing, acc.overdueCharges,
acc.isNPA, acc.daysInMonthType, acc.daysInYearType, acc.isInterestRecalculationEnabled, acc.interestRecalculationData,
acc.originalSchedule);
acc.originalSchedule, acc.createStandingInstructionAtDisbursement);
}
public static LoanAccountData loanProductWithTemplateDefaults(final LoanProductData product,
@@ -676,6 +681,7 @@ public class LoanAccountData {
final Boolean inArrears = null;
final Boolean isNPA = null;
final LoanScheduleData originalSchedule = null;
final Boolean createStandingInstructionAtDisbursement = null;
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType,
product.getId(), product.getName(), product.getDescription(), product.getFundId(), product.getFundName(), loanPurposeId,
@@ -695,7 +701,7 @@ public class LoanAccountData {
disbursementData, product.getMultiDisburseLoan(), fixedEmi, product.getOutstandingLoanBalance(), emiAmountVariations,
memberVariations, product, inArrears, product.getGraceOnArrearsAgeing(), product.overdueFeeCharges(), isNPA,
product.getDaysInMonthType(), product.getDaysInYearType(), product.isInterestRecalculationEnabled(),
product.toLoanInterestRecalculationData(), originalSchedule);
product.toLoanInterestRecalculationData(), originalSchedule, createStandingInstructionAtDisbursement);
}
public static LoanAccountData populateLoanProductDefaults(final LoanAccountData acc, final LoanProductData product) {
@@ -749,7 +755,7 @@ public class LoanAccountData {
product.getOutstandingLoanBalance(), acc.emiAmountVariations, acc.memberVariations, product, acc.inArrears,
product.getGraceOnArrearsAgeing(), product.overdueFeeCharges(), acc.isNPA, product.getDaysInMonthType(),
product.getDaysInYearType(), product.isInterestRecalculationEnabled(), product.toLoanInterestRecalculationData(),
acc.originalSchedule);
acc.originalSchedule, acc.createStandingInstructionAtDisbursement);
}
/*
@@ -774,7 +780,7 @@ public class LoanAccountData {
final Boolean multiDisburseLoan, final BigDecimal fixedEmiAmont, final BigDecimal outstandingLoanBalance,
final Boolean inArrears, final Integer graceOnArrearsAgeing, final Boolean isNPA, final EnumOptionData daysInMonthType,
final EnumOptionData daysInYearType, final boolean isInterestRecalculationEnabled,
final LoanInterestRecalculationData interestRecalculationData) {
final LoanInterestRecalculationData interestRecalculationData, final Boolean createStandingInstructionAtDisbursement) {
final LoanScheduleData repaymentSchedule = null;
final Collection<LoanTransactionData> transactions = null;
@@ -824,7 +830,7 @@ public class LoanAccountData {
syncDisbursementWithMeeting, loancounter, loanProductCounter, notes, accountLinkingOptions, linkedAccount,
disbursementData, multiDisburseLoan, fixedEmiAmont, outstandingLoanBalance, emiAmountVariations, memberVariations, product,
inArrears, graceOnArrearsAgeing, overdueCharges, isNPA, daysInMonthType, daysInYearType, isInterestRecalculationEnabled,
interestRecalculationData, originalSchedule);
interestRecalculationData, originalSchedule, createStandingInstructionAtDisbursement);
}
/*
@@ -865,7 +871,8 @@ public class LoanAccountData {
acc.syncDisbursementWithMeeting, acc.loanCounter, acc.loanProductCounter, notes, accountLinkingOptions, linkedAccount,
disbursementDetails, acc.multiDisburseLoan, acc.fixedEmiAmount, acc.maxOutstandingLoanBalance, emiAmountVariations,
acc.memberVariations, acc.product, acc.inArrears, acc.graceOnArrearsAgeing, overdueCharges, acc.isNPA, acc.daysInMonthType,
acc.daysInYearType, acc.isInterestRecalculationEnabled, acc.interestRecalculationData, acc.originalSchedule);
acc.daysInYearType, acc.isInterestRecalculationEnabled, acc.interestRecalculationData, acc.originalSchedule,
acc.createStandingInstructionAtDisbursement);
}
public static LoanAccountData associationsAndTemplate(final LoanAccountData acc, final Collection<LoanProductData> productOptions,
@@ -900,7 +907,7 @@ public class LoanAccountData {
acc.linkedAccount, acc.disbursementDetails, acc.multiDisburseLoan, acc.fixedEmiAmount, acc.maxOutstandingLoanBalance,
acc.emiAmountVariations, acc.memberVariations, acc.product, acc.inArrears, acc.graceOnArrearsAgeing, acc.overdueCharges,
acc.isNPA, acc.daysInMonthType, acc.daysInYearType, acc.isInterestRecalculationEnabled, acc.interestRecalculationData,
acc.originalSchedule);
acc.originalSchedule, acc.createStandingInstructionAtDisbursement);
}
public static LoanAccountData associateMemberVariations(final LoanAccountData acc, final Map<Long, Integer> memberLoanCycle) {
@@ -960,7 +967,7 @@ public class LoanAccountData {
acc.linkedAccount, acc.disbursementDetails, acc.multiDisburseLoan, acc.fixedEmiAmount, acc.maxOutstandingLoanBalance,
acc.emiAmountVariations, memberVariations, acc.product, acc.inArrears, acc.graceOnArrearsAgeing, acc.overdueCharges,
acc.isNPA, acc.daysInMonthType, acc.daysInYearType, acc.isInterestRecalculationEnabled, acc.interestRecalculationData,
acc.originalSchedule);
acc.originalSchedule, acc.createStandingInstructionAtDisbursement);
}
public static LoanAccountData withInterestRecalculationCalendarData(final LoanAccountData acc, final CalendarData calendarData) {
@@ -986,7 +993,7 @@ public class LoanAccountData {
acc.linkedAccount, acc.disbursementDetails, acc.multiDisburseLoan, acc.fixedEmiAmount, acc.maxOutstandingLoanBalance,
acc.emiAmountVariations, acc.memberVariations, acc.product, acc.inArrears, acc.graceOnArrearsAgeing, acc.overdueCharges,
acc.isNPA, acc.daysInMonthType, acc.daysInYearType, acc.isInterestRecalculationEnabled, interestRecalculationData,
acc.originalSchedule);
acc.originalSchedule, acc.createStandingInstructionAtDisbursement);
}
public static LoanAccountData withOriginalSchedule(final LoanAccountData acc, final LoanScheduleData originalSchedule) {
@@ -1010,7 +1017,7 @@ public class LoanAccountData {
acc.linkedAccount, acc.disbursementDetails, acc.multiDisburseLoan, acc.fixedEmiAmount, acc.maxOutstandingLoanBalance,
acc.emiAmountVariations, acc.memberVariations, acc.product, acc.inArrears, acc.graceOnArrearsAgeing, acc.overdueCharges,
acc.isNPA, acc.daysInMonthType, acc.daysInYearType, acc.isInterestRecalculationEnabled, acc.interestRecalculationData,
originalSchedule);
originalSchedule, acc.createStandingInstructionAtDisbursement);
}
private LoanAccountData(
@@ -1069,7 +1076,8 @@ public class LoanAccountData {
final LoanProductData product, final Boolean inArrears, final Integer graceOnArrearsAgeing,
final Collection<ChargeData> overdueCharges, final Boolean isNPA, final EnumOptionData daysInMonthType,
final EnumOptionData daysInYearType, final boolean isInterestRecalculationEnabled,
final LoanInterestRecalculationData interestRecalculationData, final LoanScheduleData originalSchedule) {
final LoanInterestRecalculationData interestRecalculationData, final LoanScheduleData originalSchedule,
final Boolean createStandingInstructionAtDisbursement) {
this.id = id;
this.accountNo = accountNo;
this.status = status;
@@ -1218,6 +1226,7 @@ public class LoanAccountData {
this.isInterestRecalculationEnabled = isInterestRecalculationEnabled;
this.interestRecalculationData = interestRecalculationData;
this.originalSchedule = originalSchedule;
this.createStandingInstructionAtDisbursement = createStandingInstructionAtDisbursement;
}
public RepaymentScheduleRelatedLoanData repaymentScheduleRelatedData() {
@@ -338,18 +338,21 @@ public class Loan extends AbstractPersistable<Long> {
@Column(name = "accrued_till")
private Date accruedTill;
@Column(name = "create_standing_instruction_at_disbursement", nullable = true)
private Boolean createStandingInstructionAtDisbursement;
public static Loan newIndividualLoanApplication(final String accountNo, final Client client, final Integer loanType,
final LoanProduct loanProduct, final Fund fund, final Staff officer, final CodeValue loanPurpose,
final LoanTransactionProcessingStrategy transactionProcessingStrategy,
final LoanProductRelatedDetail loanRepaymentScheduleDetail, final Set<LoanCharge> loanCharges,
final Set<LoanCollateral> collateral, final BigDecimal fixedEmiAmount, final Set<LoanDisbursementDetails> disbursementDetails,
final BigDecimal maxOutstandingLoanBalance) {
final BigDecimal maxOutstandingLoanBalance, final Boolean createStandingInstructionAtDisbursement) {
final LoanStatus status = null;
final Group group = null;
final Boolean syncDisbursementWithMeeting = null;
return new Loan(accountNo, client, group, loanType, fund, officer, loanPurpose, transactionProcessingStrategy, loanProduct,
loanRepaymentScheduleDetail, status, loanCharges, collateral, syncDisbursementWithMeeting, fixedEmiAmount,
disbursementDetails, maxOutstandingLoanBalance);
disbursementDetails, maxOutstandingLoanBalance, createStandingInstructionAtDisbursement);
}
public static Loan newGroupLoanApplication(final String accountNo, final Group group, final Integer loanType,
@@ -357,12 +360,13 @@ public class Loan extends AbstractPersistable<Long> {
final LoanTransactionProcessingStrategy transactionProcessingStrategy,
final LoanProductRelatedDetail loanRepaymentScheduleDetail, final Set<LoanCharge> loanCharges,
final Set<LoanCollateral> collateral, final Boolean syncDisbursementWithMeeting, final BigDecimal fixedEmiAmount,
final Set<LoanDisbursementDetails> disbursementDetails, final BigDecimal maxOutstandingLoanBalance) {
final Set<LoanDisbursementDetails> disbursementDetails, final BigDecimal maxOutstandingLoanBalance,
final Boolean createStandingInstructionAtDisbursement) {
final LoanStatus status = null;
final Client client = null;
return new Loan(accountNo, client, group, loanType, fund, officer, loanPurpose, transactionProcessingStrategy, loanProduct,
loanRepaymentScheduleDetail, status, loanCharges, collateral, syncDisbursementWithMeeting, fixedEmiAmount,
disbursementDetails, maxOutstandingLoanBalance);
disbursementDetails, maxOutstandingLoanBalance, createStandingInstructionAtDisbursement);
}
public static Loan newIndividualLoanApplicationFromGroup(final String accountNo, final Client client, final Group group,
@@ -370,11 +374,12 @@ public class Loan extends AbstractPersistable<Long> {
final LoanTransactionProcessingStrategy transactionProcessingStrategy,
final LoanProductRelatedDetail loanRepaymentScheduleDetail, final Set<LoanCharge> loanCharges,
final Set<LoanCollateral> collateral, final Boolean syncDisbursementWithMeeting, final BigDecimal fixedEmiAmount,
final Set<LoanDisbursementDetails> disbursementDetails, final BigDecimal maxOutstandingLoanBalance) {
final Set<LoanDisbursementDetails> disbursementDetails, final BigDecimal maxOutstandingLoanBalance,
final Boolean createStandingInstructionAtDisbursement) {
final LoanStatus status = null;
return new Loan(accountNo, client, group, loanType, fund, officer, loanPurpose, transactionProcessingStrategy, loanProduct,
loanRepaymentScheduleDetail, status, loanCharges, collateral, syncDisbursementWithMeeting, fixedEmiAmount,
disbursementDetails, maxOutstandingLoanBalance);
disbursementDetails, maxOutstandingLoanBalance, createStandingInstructionAtDisbursement);
}
protected Loan() {
@@ -386,7 +391,7 @@ public class Loan extends AbstractPersistable<Long> {
final LoanProduct loanProduct, final LoanProductRelatedDetail loanRepaymentScheduleDetail, final LoanStatus loanStatus,
final Set<LoanCharge> loanCharges, final Set<LoanCollateral> collateral, final Boolean syncDisbursementWithMeeting,
final BigDecimal fixedEmiAmount, final Set<LoanDisbursementDetails> disbursementDetails,
final BigDecimal maxOutstandingLoanBalance) {
final BigDecimal maxOutstandingLoanBalance, final Boolean createStandingInstructionAtDisbursement) {
this.loanRepaymentScheduleDetail = loanRepaymentScheduleDetail;
this.loanRepaymentScheduleDetail.validateRepaymentPeriodWithGraceSettings();
@@ -430,6 +435,7 @@ public class Loan extends AbstractPersistable<Long> {
this.maxOutstandingLoanBalance = maxOutstandingLoanBalance;
this.disbursementDetails = disbursementDetails;
this.approvedPrincipal = this.loanRepaymentScheduleDetail.getPrincipal().getAmount();
this.createStandingInstructionAtDisbursement = createStandingInstructionAtDisbursement;
}
private LoanSummary updateSummaryWithTotalFeeChargesDueAtDisbursement(final BigDecimal feeChargesDueAtDisbursement) {
@@ -4766,4 +4772,15 @@ public class Loan extends AbstractPersistable<Long> {
this.repaymentFrequencyDayOfWeekType = repaymentFrequencyDayOfWeekType;
}
public String getAccountNumber() {
return this.accountNumber;
}
public Client getClient() {
return this.client;
}
public Boolean shouldCreateStandingInstructionAtDisbursement() {
return (this.createStandingInstructionAtDisbursement != null) && this.createStandingInstructionAtDisbursement;
}
}
@@ -66,7 +66,7 @@ public final class LoanApplicationCommandFromApiJsonHelper {
"syncDisbursementWithMeeting",// optional
"linkAccountId", LoanApiConstants.disbursementDataParameterName, LoanApiConstants.emiAmountParameterName,
LoanApiConstants.maxOutstandingBalanceParameterName, LoanProductConstants.graceOnArrearsAgeingParameterName,
LoanProductConstants.recalculationRestFrequencyDateParamName));
LoanProductConstants.recalculationRestFrequencyDateParamName, "createStandingInstructionAtDisbursement"));
private final FromJsonHelper fromApiJsonHelper;
private final CalculateLoanScheduleQueryFromApiJsonHelper apiJsonHelper;
@@ -289,6 +289,17 @@ public final class LoanApplicationCommandFromApiJsonHelper {
final Long linkAccountId = this.fromApiJsonHelper.extractLongNamed(linkAccountIdParameterName, element);
baseDataValidator.reset().parameter(linkAccountIdParameterName).value(linkAccountId).ignoreIfNull().longGreaterThanZero();
}
final String createSiAtDisbursementParameterName = "createStandingInstructionAtDisbursement";
if(this.fromApiJsonHelper.parameterExists(createSiAtDisbursementParameterName, element)) {
final Boolean createStandingInstructionAtDisbursement = this.fromApiJsonHelper
.extractBooleanNamed(createSiAtDisbursementParameterName, element);
final Long linkAccountId = this.fromApiJsonHelper.extractLongNamed(linkAccountIdParameterName, element);
if(createStandingInstructionAtDisbursement) {
baseDataValidator.reset().parameter(linkAccountIdParameterName).value(linkAccountId).notNull().longGreaterThanZero();
}
}
// charges
final String chargesParameterName = "charges";
@@ -159,7 +159,8 @@ public class LoanAssembler {
final Long transactionProcessingStrategyId = this.fromApiJsonHelper.extractLongNamed("transactionProcessingStrategyId", element);
final Long loanPurposeId = this.fromApiJsonHelper.extractLongNamed("loanPurposeId", element);
final Boolean syncDisbursementWithMeeting = this.fromApiJsonHelper.extractBooleanNamed("syncDisbursementWithMeeting", element);
final Boolean createStandingInstructionAtDisbursement = this.fromApiJsonHelper.extractBooleanNamed("createStandingInstructionAtDisbursement", element);
final LoanProduct loanProduct = this.loanProductRepository.findOne(productId);
if (loanProduct == null) { throw new LoanProductNotFoundException(productId); }
@@ -233,19 +234,21 @@ public class LoanAssembler {
loanApplication = Loan.newIndividualLoanApplicationFromGroup(accountNo, client, group, loanType.getId().intValue(),
loanProduct, fund, loanOfficer, loanPurpose, loanTransactionProcessingStrategy, loanProductRelatedDetail, loanCharges,
collateral, syncDisbursementWithMeeting, fixedEmiAmount, disbursementDetails, maxOutstandingLoanBalance);
collateral, syncDisbursementWithMeeting, fixedEmiAmount, disbursementDetails, maxOutstandingLoanBalance,
createStandingInstructionAtDisbursement);
} else if (group != null) {
loanApplication = Loan.newGroupLoanApplication(accountNo, group, loanType.getId().intValue(), loanProduct, fund, loanOfficer,
loanPurpose, loanTransactionProcessingStrategy, loanProductRelatedDetail, loanCharges, collateral,
syncDisbursementWithMeeting, fixedEmiAmount, disbursementDetails, maxOutstandingLoanBalance);
syncDisbursementWithMeeting, fixedEmiAmount, disbursementDetails, maxOutstandingLoanBalance,
createStandingInstructionAtDisbursement);
} else if (client != null) {
loanApplication = Loan.newIndividualLoanApplication(accountNo, client, loanType.getId().intValue(), loanProduct, fund,
loanOfficer, loanPurpose, loanTransactionProcessingStrategy, loanProductRelatedDetail, loanCharges, collateral,
fixedEmiAmount, disbursementDetails, maxOutstandingLoanBalance);
fixedEmiAmount, disbursementDetails, maxOutstandingLoanBalance, createStandingInstructionAtDisbursement);
}
@@ -550,7 +550,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
+ " l.interest_recalculation_enabled as isInterestRecalculationEnabled, "
+ " lir.id as lirId, lir.loan_id as loanId, lir.compound_type_enum as compoundType, lir.reschedule_strategy_enum as rescheduleStrategy, "
+ " lir.rest_frequency_type_enum as restFrequencyEnum, lir.rest_frequency_interval as restFrequencyInterval, "
+ " lir.rest_freqency_date as restFrequencyDate "
+ " lir.rest_freqency_date as restFrequencyDate, "
+ " l.create_standing_instruction_at_disbursement as createStandingInstructionAtDisbursement "
+ " from m_loan l" //
+ " join m_product_loan lp on lp.id = l.product_id" //
+ " left join m_loan_recalculation_details lir on lir.loan_id = l.id "
@@ -788,6 +789,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
final int daysInYear = JdbcSupport.getInteger(rs, "daysInYear");
final EnumOptionData daysInYearType = CommonEnumerations.daysInYearType(daysInYear);
final boolean isInterestRecalculationEnabled = rs.getBoolean("isInterestRecalculationEnabled");
final Boolean createStandingInstructionAtDisbursement = rs.getBoolean("createStandingInstructionAtDisbursement");
LoanInterestRecalculationData interestRecalculationData = null;
if (isInterestRecalculationEnabled) {
@@ -819,7 +821,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
graceOnInterestCharged, interestChargedFromDate, timeline, loanSummary, feeChargesDueAtDisbursementCharged,
syncDisbursementWithMeeting, loanCounter, loanProductCounter, multiDisburseLoan, fixedEmiAmount,
outstandingLoanBalance, inArrears, graceOnArrearsAgeing, isNPA, daysInMonthType, daysInYearType,
isInterestRecalculationEnabled, interestRecalculationData);
isInterestRecalculationEnabled, interestRecalculationData, createStandingInstructionAtDisbursement);
}
}
@@ -49,9 +49,18 @@ import org.mifosplatform.organisation.workingdays.domain.WorkingDaysRepositoryWr
import org.mifosplatform.portfolio.account.PortfolioAccountType;
import org.mifosplatform.portfolio.account.data.AccountTransferDTO;
import org.mifosplatform.portfolio.account.data.PortfolioAccountData;
import org.mifosplatform.portfolio.account.domain.AccountAssociations;
import org.mifosplatform.portfolio.account.domain.AccountAssociationsRepository;
import org.mifosplatform.portfolio.account.domain.AccountTransferDetailRepository;
import org.mifosplatform.portfolio.account.domain.AccountTransferDetails;
import org.mifosplatform.portfolio.account.domain.AccountTransferRecurrenceType;
import org.mifosplatform.portfolio.account.domain.AccountTransferRepository;
import org.mifosplatform.portfolio.account.domain.AccountTransferStandingInstruction;
import org.mifosplatform.portfolio.account.domain.AccountTransferTransaction;
import org.mifosplatform.portfolio.account.domain.AccountTransferType;
import org.mifosplatform.portfolio.account.domain.StandingInstructionPriority;
import org.mifosplatform.portfolio.account.domain.StandingInstructionStatus;
import org.mifosplatform.portfolio.account.domain.StandingInstructionType;
import org.mifosplatform.portfolio.account.service.AccountAssociationsReadPlatformService;
import org.mifosplatform.portfolio.account.service.AccountTransfersReadPlatformService;
import org.mifosplatform.portfolio.account.service.AccountTransfersWritePlatformService;
@@ -181,6 +190,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
private final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository;
private final LoanScheduleHistoryWritePlatformService loanScheduleHistoryWritePlatformService;
private final LoanApplicationCommandFromApiJsonHelper loanApplicationCommandFromApiJsonHelper;
private final AccountAssociationsRepository accountAssociationRepository;
private final AccountTransferDetailRepository accountTransferDetailRepository;
@Autowired
public LoanWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
@@ -203,7 +214,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final CalendarRepository calendarRepository,
final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository,
final LoanScheduleHistoryWritePlatformService loanScheduleHistoryWritePlatformService,
final LoanApplicationCommandFromApiJsonHelper loanApplicationCommandFromApiJsonHelper) {
final LoanApplicationCommandFromApiJsonHelper loanApplicationCommandFromApiJsonHelper,
final AccountAssociationsRepository accountAssociationRepository,
final AccountTransferDetailRepository accountTransferDetailRepository) {
this.context = context;
this.loanEventApiJsonValidator = loanEventApiJsonValidator;
this.loanAssembler = loanAssembler;
@@ -234,6 +247,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
this.repaymentScheduleInstallmentRepository = repaymentScheduleInstallmentRepository;
this.loanScheduleHistoryWritePlatformService = loanScheduleHistoryWritePlatformService;
this.loanApplicationCommandFromApiJsonHelper = loanApplicationCommandFromApiJsonHelper;
this.accountAssociationRepository = accountAssociationRepository;
this.accountTransferDetailRepository = accountTransferDetailRepository;
}
private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() {
@@ -344,6 +359,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
this.accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(), mapEntry.getValue());
}
}
// auto create standing instruction
createStandingInstruction(loan);
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
@@ -383,6 +401,47 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
.with(changes) //
.build();
}
/**
* create standing instruction for disbursed loan
*
* @param loan the disbursed loan
* @return void
**/
private void createStandingInstruction(Loan loan) {
if(loan.shouldCreateStandingInstructionAtDisbursement()) {
AccountAssociations accountAssociations = this.accountAssociationRepository.findByLoanId(loan.getId());
if(accountAssociations != null) {
SavingsAccount linkedSavingsAccount = accountAssociations.linkedSavingsAccount();
// name is auto-generated
final String name = "To loan " + loan.getAccountNumber() + " from savings " + linkedSavingsAccount.getAccountNumber();
final Office fromOffice = loan.getOffice();
final Client fromClient = loan.getClient();
final Office toOffice = loan.getOffice();
final Client toClient = loan.getClient();
final Integer priority = StandingInstructionPriority.MEDIUM.getValue();
final Integer transferType = AccountTransferType.LOAN_REPAYMENT.getValue();
final Integer instructionType = StandingInstructionType.DUES.getValue();
final Integer status = StandingInstructionStatus.ACTIVE.getValue();
final Integer recurrenceType = AccountTransferRecurrenceType.AS_PER_DUES.getValue();
final LocalDate validFrom = new LocalDate();
AccountTransferDetails accountTransferDetails = AccountTransferDetails.savingsToLoanTransfer(fromOffice,
fromClient, linkedSavingsAccount, toOffice, toClient, loan, transferType);
AccountTransferStandingInstruction accountTransferStandingInstruction = AccountTransferStandingInstruction.create(
accountTransferDetails, name, priority, instructionType, status, null, validFrom, null,
recurrenceType, null, null, null);
accountTransferDetails.updateAccountTransferStandingInstruction(accountTransferStandingInstruction);
this.accountTransferDetailRepository.save(accountTransferDetails);
}
}
}
private void updateRecurringCalendarDatesForInterestRecalculation(final Loan loan) {
@@ -2430,4 +2430,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
}
return savingsAccountCharge;
}
public String getAccountNumber() {
return this.accountNumber;
}
}
@@ -0,0 +1 @@
alter table `m_loan` add `create_standing_instruction_at_disbursement` tinyint(1) null;