diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm index fb03182f2..0cf171e4e 100644 --- a/api-docs/apiLive.htm +++ b/api-docs/apiLive.htm @@ -7961,7 +7961,7 @@ Request Body: graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, linkAccountId, - fixedEmiAmount, maxOutstandingLoanBalance, disbursementData, graceOnArrearsAgeing + fixedEmiAmount, maxOutstandingLoanBalance, disbursementData, graceOnArrearsAgeing, createStandingInstructionAtDisbursement (requires linkedAccountId if set to true) diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java index 2aef03c45..4d8af4bd5 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java @@ -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 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 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 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 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() { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java index c0925d525..d6ea11603 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java @@ -338,18 +338,21 @@ public class Loan extends AbstractPersistable { @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 loanCharges, final Set collateral, final BigDecimal fixedEmiAmount, final Set 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 { final LoanTransactionProcessingStrategy transactionProcessingStrategy, final LoanProductRelatedDetail loanRepaymentScheduleDetail, final Set loanCharges, final Set collateral, final Boolean syncDisbursementWithMeeting, final BigDecimal fixedEmiAmount, - final Set disbursementDetails, final BigDecimal maxOutstandingLoanBalance) { + final Set 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 { final LoanTransactionProcessingStrategy transactionProcessingStrategy, final LoanProductRelatedDetail loanRepaymentScheduleDetail, final Set loanCharges, final Set collateral, final Boolean syncDisbursementWithMeeting, final BigDecimal fixedEmiAmount, - final Set disbursementDetails, final BigDecimal maxOutstandingLoanBalance) { + final Set 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 { final LoanProduct loanProduct, final LoanProductRelatedDetail loanRepaymentScheduleDetail, final LoanStatus loanStatus, final Set loanCharges, final Set collateral, final Boolean syncDisbursementWithMeeting, final BigDecimal fixedEmiAmount, final Set 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 { 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 { this.repaymentFrequencyDayOfWeekType = repaymentFrequencyDayOfWeekType; } + public String getAccountNumber() { + return this.accountNumber; + } + + public Client getClient() { + return this.client; + } + + public Boolean shouldCreateStandingInstructionAtDisbursement() { + return (this.createStandingInstructionAtDisbursement != null) && this.createStandingInstructionAtDisbursement; + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java index 8300bbabc..e31b2177b 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java @@ -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"; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanAssembler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanAssembler.java index 1d89bbdd2..05b1b3652 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanAssembler.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanAssembler.java @@ -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); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java index 3278384d7..e27188a3c 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java @@ -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); } } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index dd2550cee..e4e2607f8 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -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) { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccount.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccount.java index 0676eebf0..9ae26d358 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccount.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccount.java @@ -2430,4 +2430,8 @@ public class SavingsAccount extends AbstractPersistable { } return savingsAccountCharge; } + + public String getAccountNumber() { + return this.accountNumber; + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/resources/sql/migrations/core_db/V214__alter_table_add_create_SI_at_disbursement.sql b/mifosng-provider/src/main/resources/sql/migrations/core_db/V214__alter_table_add_create_SI_at_disbursement.sql new file mode 100644 index 000000000..c33a946ce --- /dev/null +++ b/mifosng-provider/src/main/resources/sql/migrations/core_db/V214__alter_table_add_create_SI_at_disbursement.sql @@ -0,0 +1 @@ +alter table `m_loan` add `create_standing_instruction_at_disbursement` tinyint(1) null;