MIFOSX-1727
This commit is contained in:
@@ -13353,6 +13353,7 @@ Request Body:
|
||||
<li><b>allow-transactions-on-holiday</b> - defaults to false - if true allows transactions on <a href="#holidays">holidays</a></li>
|
||||
<li><b>savings-interest-posting-current-period-end</b> - Set it at the database level before any savings interest is posted. When set as false(default), interest will be posted on the first date of next period. If set as true, interest will be posted on last date of current period. There is no difference in the interest amount posted.</li>
|
||||
<li><b>financial-year-beginning-month</b> - Set it at the database level before any savings interest is posted. Allowed values 1 - 12 (January - December). Interest posting periods are evaluated based on this configuration.</li>
|
||||
<li><b>meetings-mandatory-for-jlg-loans</b> - if set to true, enforces all JLG loans to follow a meeting schedule belonging to either the parent group or Center.</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+2
@@ -43,4 +43,6 @@ public interface ConfigurationDomainService {
|
||||
|
||||
public Integer retrieveMaxAllowedClientsInGroup();
|
||||
|
||||
boolean isMeetingMandatoryForJLGLoans();
|
||||
|
||||
}
|
||||
+7
@@ -166,4 +166,11 @@ public class ConfigurationDomainServiceJpa implements ConfigurationDomainService
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMeetingMandatoryForJLGLoans() {
|
||||
final String propertyName = "meetings-mandatory-for-jlg-loans";
|
||||
final GlobalConfigurationProperty property = this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
|
||||
return property.isEnabled();
|
||||
}
|
||||
|
||||
}
|
||||
+39
-40
@@ -19,11 +19,11 @@ import org.mifosplatform.organisation.monetary.domain.ApplicationCurrency;
|
||||
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.mifosplatform.organisation.monetary.domain.Money;
|
||||
import org.mifosplatform.portfolio.calendar.domain.CalendarInstance;
|
||||
import org.mifosplatform.portfolio.common.domain.DayOfWeekType;
|
||||
import org.mifosplatform.portfolio.common.domain.DaysInMonthType;
|
||||
import org.mifosplatform.portfolio.common.domain.DaysInYearType;
|
||||
import org.mifosplatform.portfolio.common.domain.NthDayType;
|
||||
import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.mifosplatform.portfolio.common.domain.DayOfWeekType;
|
||||
import org.mifosplatform.portfolio.loanaccount.data.DisbursementData;
|
||||
import org.mifosplatform.portfolio.loanaccount.data.LoanTermVariationsData;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.LoanInterestRecalculationDetails;
|
||||
@@ -44,8 +44,8 @@ public final class LoanApplicationTerms {
|
||||
private final Integer repaymentEvery;
|
||||
private final PeriodFrequencyType repaymentPeriodFrequencyType;
|
||||
private final Integer nthDay;
|
||||
|
||||
private final DayOfWeekType weekDayType;
|
||||
|
||||
private final DayOfWeekType weekDayType;
|
||||
private final AmortizationMethod amortizationMethod;
|
||||
|
||||
private final InterestMethod interestMethod;
|
||||
@@ -106,15 +106,15 @@ public final class LoanApplicationTerms {
|
||||
// added
|
||||
private LocalDate loanEndDate;
|
||||
|
||||
private List<DisbursementData> disbursementDatas;
|
||||
private final List<DisbursementData> disbursementDatas;
|
||||
|
||||
private boolean multiDisburseLoan;
|
||||
private final boolean multiDisburseLoan;
|
||||
|
||||
private BigDecimal fixedEmiAmount;
|
||||
|
||||
private BigDecimal maxOutstandingBalance;
|
||||
private final BigDecimal maxOutstandingBalance;
|
||||
|
||||
private List<LoanTermVariationsData> emiAmountVariations;
|
||||
private final List<LoanTermVariationsData> emiAmountVariations;
|
||||
|
||||
private Money totalInterestDue;
|
||||
|
||||
@@ -134,38 +134,39 @@ public final class LoanApplicationTerms {
|
||||
|
||||
public static LoanApplicationTerms assembleFrom(final ApplicationCurrency currency, final Integer loanTermFrequency,
|
||||
final PeriodFrequencyType loanTermPeriodFrequencyType, final Integer numberOfRepayments, final Integer repaymentEvery,
|
||||
final PeriodFrequencyType repaymentPeriodFrequencyType, Integer nthDay,
|
||||
DayOfWeekType weekDayType, final AmortizationMethod amortizationMethod,
|
||||
final InterestMethod interestMethod, final BigDecimal interestRatePerPeriod,
|
||||
final PeriodFrequencyType repaymentPeriodFrequencyType, Integer nthDay, DayOfWeekType weekDayType,
|
||||
final AmortizationMethod amortizationMethod, final InterestMethod interestMethod, final BigDecimal interestRatePerPeriod,
|
||||
final PeriodFrequencyType interestRatePeriodFrequencyType, final BigDecimal annualNominalInterestRate,
|
||||
final InterestCalculationPeriodMethod interestCalculationPeriodMethod, final Money principalMoney,
|
||||
final LocalDate expectedDisbursementDate, final LocalDate repaymentsStartingFromDate,
|
||||
final LocalDate calculatedRepaymentsStartingFromDate, final Integer graceOnPrincipalPayment, final Integer graceOnInterestPayment,
|
||||
final Integer graceOnInterestCharged, final LocalDate interestChargedFromDate, final Money inArrearsTolerance,
|
||||
final boolean multiDisburseLoan, final BigDecimal emiAmount,
|
||||
final LocalDate calculatedRepaymentsStartingFromDate, final Integer graceOnPrincipalPayment,
|
||||
final Integer graceOnInterestPayment, final Integer graceOnInterestCharged, final LocalDate interestChargedFromDate,
|
||||
final Money inArrearsTolerance, final boolean multiDisburseLoan, final BigDecimal emiAmount,
|
||||
final List<DisbursementData> disbursementDatas, final BigDecimal maxOutstandingBalance,
|
||||
final List<LoanTermVariationsData> emiAmountVariations, final Integer graceOnArrearsAgeing, final DaysInMonthType daysInMonthType, final DaysInYearType daysInYearType, final boolean isInterestRecalculationEnabled) {
|
||||
final List<LoanTermVariationsData> emiAmountVariations, final Integer graceOnArrearsAgeing,
|
||||
final DaysInMonthType daysInMonthType, final DaysInYearType daysInYearType, final boolean isInterestRecalculationEnabled) {
|
||||
|
||||
final LoanRescheduleStrategyMethod rescheduleStrategyMethod = null;
|
||||
final InterestRecalculationCompoundingMethod interestRecalculationCompoundingMethod = null;
|
||||
final CalendarInstance restCalendarInstance = null;
|
||||
final RecalculationFrequencyType recalculationFrequencyType = null;
|
||||
return new LoanApplicationTerms(currency, loanTermFrequency, loanTermPeriodFrequencyType, numberOfRepayments, repaymentEvery,
|
||||
repaymentPeriodFrequencyType,nthDay, weekDayType, amortizationMethod, interestMethod, interestRatePerPeriod, interestRatePeriodFrequencyType,
|
||||
annualNominalInterestRate, interestCalculationPeriodMethod, principalMoney, expectedDisbursementDate,
|
||||
repaymentsStartingFromDate, calculatedRepaymentsStartingFromDate, graceOnPrincipalPayment, graceOnInterestPayment,
|
||||
graceOnInterestCharged, interestChargedFromDate, inArrearsTolerance, multiDisburseLoan, emiAmount, disbursementDatas,
|
||||
maxOutstandingBalance, emiAmountVariations, graceOnArrearsAgeing, daysInMonthType, daysInYearType,
|
||||
repaymentPeriodFrequencyType, nthDay, weekDayType, amortizationMethod, interestMethod, interestRatePerPeriod,
|
||||
interestRatePeriodFrequencyType, annualNominalInterestRate, interestCalculationPeriodMethod, principalMoney,
|
||||
expectedDisbursementDate, repaymentsStartingFromDate, calculatedRepaymentsStartingFromDate, graceOnPrincipalPayment,
|
||||
graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, inArrearsTolerance, multiDisburseLoan, emiAmount,
|
||||
disbursementDatas, maxOutstandingBalance, emiAmountVariations, graceOnArrearsAgeing, daysInMonthType, daysInYearType,
|
||||
isInterestRecalculationEnabled, rescheduleStrategyMethod, interestRecalculationCompoundingMethod, restCalendarInstance,
|
||||
recalculationFrequencyType);
|
||||
}
|
||||
|
||||
public static LoanApplicationTerms assembleFrom(final ApplicationCurrency applicationCurrency, final Integer loanTermFrequency,
|
||||
final PeriodFrequencyType loanTermPeriodFrequencyType, NthDayType nthDay,
|
||||
DayOfWeekType dayOfWeek, final LocalDate expectedDisbursementDate,
|
||||
final LocalDate repaymentsStartingFromDate, final LocalDate calculatedRepaymentsStartingFromDate, final Money inArrearsTolerance,
|
||||
final PeriodFrequencyType loanTermPeriodFrequencyType, NthDayType nthDay, DayOfWeekType dayOfWeek,
|
||||
final LocalDate expectedDisbursementDate, final LocalDate repaymentsStartingFromDate,
|
||||
final LocalDate calculatedRepaymentsStartingFromDate, final Money inArrearsTolerance,
|
||||
final LoanProductRelatedDetail loanProductRelatedDetail, final boolean multiDisburseLoan, final BigDecimal emiAmount,
|
||||
final List<DisbursementData> disbursementDatas, final BigDecimal maxOutstandingBalance, final List<LoanTermVariationsData> emiAmountVariations, final LocalDate interestChargedFromDate) {
|
||||
final List<DisbursementData> disbursementDatas, final BigDecimal maxOutstandingBalance,
|
||||
final List<LoanTermVariationsData> emiAmountVariations, final LocalDate interestChargedFromDate) {
|
||||
|
||||
final Integer numberOfRepayments = loanProductRelatedDetail.getNumberOfRepayments();
|
||||
final Integer repaymentEvery = loanProductRelatedDetail.getRepayEvery();
|
||||
@@ -194,13 +195,13 @@ public final class LoanApplicationTerms {
|
||||
final RecalculationFrequencyType recalculationFrequencyType = null;
|
||||
|
||||
return new LoanApplicationTerms(applicationCurrency, loanTermFrequency, loanTermPeriodFrequencyType, numberOfRepayments,
|
||||
repaymentEvery, repaymentPeriodFrequencyType, nthDay.getValue(), dayOfWeek, amortizationMethod, interestMethod, interestRatePerPeriod,
|
||||
interestRatePeriodFrequencyType, annualNominalInterestRate, interestCalculationPeriodMethod, principalMoney,
|
||||
expectedDisbursementDate, repaymentsStartingFromDate, calculatedRepaymentsStartingFromDate, graceOnPrincipalPayment,
|
||||
graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, inArrearsTolerance, multiDisburseLoan, emiAmount,
|
||||
disbursementDatas, maxOutstandingBalance, emiAmountVariations, loanProductRelatedDetail.getGraceOnDueDate(),
|
||||
daysInMonthType, daysInYearType, isInterestRecalculationEnabled, rescheduleStrategyMethod,
|
||||
interestRecalculationCompoundingMethod, restCalendarInstance, recalculationFrequencyType);
|
||||
repaymentEvery, repaymentPeriodFrequencyType, nthDay.getValue(), dayOfWeek, amortizationMethod, interestMethod,
|
||||
interestRatePerPeriod, interestRatePeriodFrequencyType, annualNominalInterestRate, interestCalculationPeriodMethod,
|
||||
principalMoney, expectedDisbursementDate, repaymentsStartingFromDate, calculatedRepaymentsStartingFromDate,
|
||||
graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, inArrearsTolerance,
|
||||
multiDisburseLoan, emiAmount, disbursementDatas, maxOutstandingBalance, emiAmountVariations,
|
||||
loanProductRelatedDetail.getGraceOnDueDate(), daysInMonthType, daysInYearType, isInterestRecalculationEnabled,
|
||||
rescheduleStrategyMethod, interestRecalculationCompoundingMethod, restCalendarInstance, recalculationFrequencyType);
|
||||
}
|
||||
|
||||
public static LoanApplicationTerms assembleFrom(final ApplicationCurrency applicationCurrency, final Integer loanTermFrequency,
|
||||
@@ -270,9 +271,8 @@ public final class LoanApplicationTerms {
|
||||
|
||||
private LoanApplicationTerms(final ApplicationCurrency currency, final Integer loanTermFrequency,
|
||||
final PeriodFrequencyType loanTermPeriodFrequencyType, final Integer numberOfRepayments, final Integer repaymentEvery,
|
||||
final PeriodFrequencyType repaymentPeriodFrequencyType, final Integer nthDay,
|
||||
final DayOfWeekType weekDayType, final AmortizationMethod amortizationMethod,
|
||||
final InterestMethod interestMethod, final BigDecimal interestRatePerPeriod,
|
||||
final PeriodFrequencyType repaymentPeriodFrequencyType, final Integer nthDay, final DayOfWeekType weekDayType,
|
||||
final AmortizationMethod amortizationMethod, final InterestMethod interestMethod, final BigDecimal interestRatePerPeriod,
|
||||
final PeriodFrequencyType interestRatePeriodFrequencyType, final BigDecimal annualNominalInterestRate,
|
||||
final InterestCalculationPeriodMethod interestCalculationPeriodMethod, final Money principal,
|
||||
final LocalDate expectedDisbursementDate, final LocalDate repaymentsStartingFromDate,
|
||||
@@ -990,15 +990,14 @@ public final class LoanApplicationTerms {
|
||||
public BigDecimal getFixedEmiAmount() {
|
||||
return this.fixedEmiAmount;
|
||||
}
|
||||
|
||||
|
||||
public Integer getNthDay() {
|
||||
return this.nthDay;
|
||||
}
|
||||
|
||||
public DayOfWeekType getWeekDayType() {
|
||||
return this.weekDayType;
|
||||
}
|
||||
return this.nthDay;
|
||||
}
|
||||
|
||||
public DayOfWeekType getWeekDayType() {
|
||||
return this.weekDayType;
|
||||
}
|
||||
|
||||
public void setFixedEmiAmountForPeriod(LocalDate periodDate) {
|
||||
LocalDate startDate = expectedDisbursementDate;
|
||||
|
||||
+27
-61
@@ -164,7 +164,7 @@ public class LoanScheduleAssembler {
|
||||
|
||||
final LocalDate expectedDisbursementDate = this.fromApiJsonHelper.extractLocalDateNamed("expectedDisbursementDate", element);
|
||||
final LocalDate repaymentsStartingFromDate = this.fromApiJsonHelper.extractLocalDateNamed("repaymentsStartingFromDate", element);
|
||||
LocalDate calculatedRepaymentsStartingFromDate = null;
|
||||
LocalDate calculatedRepaymentsStartingFromDate = repaymentsStartingFromDate;
|
||||
|
||||
final Boolean synchDisbursement = this.fromApiJsonHelper.extractBooleanNamed("syncDisbursementWithMeeting", element);
|
||||
final Long calendarId = this.fromApiJsonHelper.extractLongNamed("calendarId", element);
|
||||
@@ -190,67 +190,31 @@ public class LoanScheduleAssembler {
|
||||
}
|
||||
|
||||
/*
|
||||
* If user has not passed the first repayments date then only system
|
||||
* will derive it based on loan is individual/group loan or JLG loan.
|
||||
* If user has not passed the first repayments date then then derive the
|
||||
* same based on loan type.
|
||||
*/
|
||||
Boolean isRepaymentsStartingFromDateDerived = false;
|
||||
if (repaymentsStartingFromDate == null) {
|
||||
if (calculatedRepaymentsStartingFromDate == null) {
|
||||
calculatedRepaymentsStartingFromDate = deriveFirstRepaymentDate(loanType, repaymentEvery, expectedDisbursementDate,
|
||||
repaymentPeriodFrequencyType, loanProduct.getMinimumDaysBetweenDisbursalAndFirstRepayment(), calendar);
|
||||
isRepaymentsStartingFromDateDerived = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* If it is JLG loan, then make sure first repayment falls on meeting
|
||||
* date
|
||||
* If it is JLG loan synched with a meeting, then make sure first
|
||||
* repayment falls on meeting date
|
||||
*/
|
||||
if (loanType.isJLGAccount()) {
|
||||
if (isRepaymentsStartingFromDateDerived) {
|
||||
validateRepaymentsStartDateWithMeetingDates(calculatedRepaymentsStartingFromDate, calendar);
|
||||
} else {
|
||||
validateRepaymentsStartDateWithMeetingDates(repaymentsStartingFromDate, calendar);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If it is JLG loan and disbursement is synced on meeting, make sure
|
||||
* disbursement date on meeting date
|
||||
*/
|
||||
if (loanType.isJLGAccount()) {
|
||||
if (loanType.isJLGAccount() && calendar != null) {
|
||||
validateRepaymentsStartDateWithMeetingDates(calculatedRepaymentsStartingFromDate, calendar);
|
||||
/*
|
||||
* If disbursement is synced on meeting, make sure disbursement date
|
||||
* is on a meeting date
|
||||
*/
|
||||
if (synchDisbursement != null && synchDisbursement.booleanValue()) {
|
||||
validateDisbursementDateWithMeetingDates(expectedDisbursementDate, calendar);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If minimum days between disbursal and first repayment is set, then
|
||||
* validate the rule
|
||||
*/
|
||||
if (isRepaymentsStartingFromDateDerived) {
|
||||
validateMinimumDaysBetweenDisbursalAndFirstRepayment(expectedDisbursementDate, calculatedRepaymentsStartingFromDate,
|
||||
loanProduct.getMinimumDaysBetweenDisbursalAndFirstRepayment());
|
||||
} else {
|
||||
validateMinimumDaysBetweenDisbursalAndFirstRepayment(expectedDisbursementDate, repaymentsStartingFromDate,
|
||||
loanProduct.getMinimumDaysBetweenDisbursalAndFirstRepayment());
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* If first repayment is not derived and instead directly taken from
|
||||
* input then copy the value of repaymentsStartingFromDate to
|
||||
* calculatedRepaymentsStartingFromDate
|
||||
*
|
||||
* TODO: The reason for this bad code is,
|
||||
* LoanApplicationTerms.assembleFrom takes both
|
||||
* repaymentsStartingFromDate and calculatedRepaymentsStartingFromDate
|
||||
* and derived data has precedence over input date,
|
||||
*
|
||||
* FIXME:LoanApplicationTerms.assembleFrom should take only one
|
||||
* "first repayment date" than taking two dates with same purpose.
|
||||
*/
|
||||
if (!isRepaymentsStartingFromDateDerived) {
|
||||
calculatedRepaymentsStartingFromDate = repaymentsStartingFromDate;
|
||||
}
|
||||
validateMinimumDaysBetweenDisbursalAndFirstRepayment(expectedDisbursementDate, calculatedRepaymentsStartingFromDate,
|
||||
loanProduct.getMinimumDaysBetweenDisbursalAndFirstRepayment());
|
||||
|
||||
// grace details
|
||||
final Integer graceOnPrincipalPayment = this.fromApiJsonHelper.extractIntegerWithLocaleNamed("graceOnPrincipalPayment", element);
|
||||
@@ -469,17 +433,25 @@ public class LoanScheduleAssembler {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("null")
|
||||
private LocalDate deriveFirstRepaymentDate(final AccountType loanType, final Integer repaymentEvery,
|
||||
final LocalDate expectedDisbursementDate, final PeriodFrequencyType repaymentPeriodFrequencyType,
|
||||
final Integer minimumDaysBetweenDisbursalAndFirstRepayment, final Calendar calendar) {
|
||||
|
||||
LocalDate derivedFirstRepayment = null;
|
||||
LocalDate dateBasedOnRepaymentFrequency = null;
|
||||
|
||||
final LocalDate dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment = expectedDisbursementDate
|
||||
.plusDays(minimumDaysBetweenDisbursalAndFirstRepayment);
|
||||
|
||||
if (loanType.isIndividualAccount() || loanType.isGroupAccount()) {
|
||||
if (loanType.isJLGAccount() && calendar != null) {
|
||||
|
||||
final LocalDate refernceDateForCalculatingFirstRepaymentDate = expectedDisbursementDate;
|
||||
derivedFirstRepayment = deriveFirstRepaymentDateForJLGLoans(repaymentEvery, expectedDisbursementDate,
|
||||
refernceDateForCalculatingFirstRepaymentDate, repaymentPeriodFrequencyType,
|
||||
minimumDaysBetweenDisbursalAndFirstRepayment, calendar);
|
||||
|
||||
}/*** Individual or group account, or JLG not linked to a meeting ***/
|
||||
else {
|
||||
LocalDate dateBasedOnRepaymentFrequency;
|
||||
// Derive the first repayment date as greater date among
|
||||
// (disbursement date + plus frequency) or
|
||||
// (disbursement date + minimum between disbursal and first
|
||||
@@ -490,18 +462,12 @@ public class LoanScheduleAssembler {
|
||||
dateBasedOnRepaymentFrequency = expectedDisbursementDate.plusWeeks(repaymentEvery);
|
||||
} else if (repaymentPeriodFrequencyType.isMonthly()) {
|
||||
dateBasedOnRepaymentFrequency = expectedDisbursementDate.plusMonths(repaymentEvery);
|
||||
} else if (repaymentPeriodFrequencyType.isYearly()) {
|
||||
}/** yearly loan **/
|
||||
else {
|
||||
dateBasedOnRepaymentFrequency = expectedDisbursementDate.plusYears(repaymentEvery);
|
||||
}
|
||||
derivedFirstRepayment = dateBasedOnRepaymentFrequency.isAfter(dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment) ? dateBasedOnRepaymentFrequency
|
||||
: dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment;
|
||||
} else if (loanType.isJLGAccount()) {
|
||||
|
||||
final LocalDate refernceDateForCalculatingFirstRepaymentDate = expectedDisbursementDate;
|
||||
derivedFirstRepayment = deriveFirstRepaymentDateForJLGLoans(repaymentEvery, expectedDisbursementDate,
|
||||
refernceDateForCalculatingFirstRepaymentDate, repaymentPeriodFrequencyType,
|
||||
minimumDaysBetweenDisbursalAndFirstRepayment, calendar);
|
||||
|
||||
}
|
||||
|
||||
return derivedFirstRepayment;
|
||||
|
||||
+12
-3
@@ -11,6 +11,7 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonQuery;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||
@@ -61,6 +62,7 @@ public class LoanScheduleCalculationPlatformServiceImpl implements LoanScheduleC
|
||||
private final LoanAccountDomainService accountDomainService;
|
||||
private final CalendarInstanceRepository calendarInstanceRepository;
|
||||
private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
|
||||
@Autowired
|
||||
public LoanScheduleCalculationPlatformServiceImpl(final CalculateLoanScheduleQueryFromApiJsonHelper fromApiJsonDeserializer,
|
||||
@@ -69,7 +71,8 @@ public class LoanScheduleCalculationPlatformServiceImpl implements LoanScheduleC
|
||||
final LoanReadPlatformService loanReadPlatformService, final LoanApplicationCommandFromApiJsonHelper loanApiJsonDeserializer,
|
||||
final LoanAssembler loanAssembler, final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepository,
|
||||
final LoanAccountDomainService accountDomainService, final CalendarInstanceRepository calendarInstanceRepository,
|
||||
final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory) {
|
||||
final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory,
|
||||
final ConfigurationDomainService configurationDomainService) {
|
||||
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
|
||||
this.loanScheduleAssembler = loanScheduleAssembler;
|
||||
this.fromJsonHelper = fromJsonHelper;
|
||||
@@ -82,13 +85,19 @@ public class LoanScheduleCalculationPlatformServiceImpl implements LoanScheduleC
|
||||
this.accountDomainService = accountDomainService;
|
||||
this.calendarInstanceRepository = calendarInstanceRepository;
|
||||
this.loanRepaymentScheduleTransactionProcessorFactory = loanRepaymentScheduleTransactionProcessorFactory;
|
||||
this.configurationDomainService = configurationDomainService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoanScheduleModel calculateLoanSchedule(final JsonQuery query, Boolean validateParams) {
|
||||
|
||||
/***
|
||||
* TODO: Vishwas, this is probably not required, test and remove the
|
||||
* same
|
||||
**/
|
||||
if (validateParams) {
|
||||
this.loanApiJsonDeserializer.validateForCreate(query.json());
|
||||
boolean isMeetingMandatoryForJLGLoans = configurationDomainService.isMeetingMandatoryForJLGLoans();
|
||||
this.loanApiJsonDeserializer.validateForCreate(query.json(), isMeetingMandatoryForJLGLoans);
|
||||
}
|
||||
this.fromApiJsonDeserializer.validate(query.json());
|
||||
|
||||
@@ -171,7 +180,7 @@ public class LoanScheduleCalculationPlatformServiceImpl implements LoanScheduleC
|
||||
}
|
||||
if (isNewPaymentRequired) {
|
||||
LoanTransaction ondayPaymentTransaction = LoanTransaction.repayment(null, totalAmount, null, LocalDate.now(), null,
|
||||
DateUtils.getLocalDateTimeOfTenant(), null);
|
||||
DateUtils.getLocalDateTimeOfTenant(), null);
|
||||
modifiedTransactions.add(ondayPaymentTransaction);
|
||||
}
|
||||
|
||||
|
||||
+27
-35
@@ -46,9 +46,9 @@ public final class LoanApplicationCommandFromApiJsonHelper {
|
||||
*/
|
||||
final Set<String> supportedParameters = new HashSet<>(Arrays.asList("dateFormat", "locale", "id", "clientId", "groupId", "loanType",
|
||||
"productId", "principal", "loanTermFrequency", "loanTermFrequencyType", "numberOfRepayments", "repaymentEvery",
|
||||
"repaymentFrequencyType","repaymentFrequencyNthDayType", "repaymentFrequencyDayOfWeekType", "interestRatePerPeriod", "amortizationType", "interestType", "interestCalculationPeriodType",
|
||||
"expectedDisbursementDate", "repaymentsStartingFromDate", "graceOnPrincipalPayment",
|
||||
"graceOnInterestPayment",
|
||||
"repaymentFrequencyType", "repaymentFrequencyNthDayType", "repaymentFrequencyDayOfWeekType", "interestRatePerPeriod",
|
||||
"amortizationType", "interestType", "interestCalculationPeriodType", "expectedDisbursementDate", "repaymentsStartingFromDate",
|
||||
"graceOnPrincipalPayment", "graceOnInterestPayment",
|
||||
"graceOnInterestCharged",
|
||||
"interestChargedFromDate", //
|
||||
"submittedOnDate",
|
||||
@@ -78,7 +78,7 @@ public final class LoanApplicationCommandFromApiJsonHelper {
|
||||
this.apiJsonHelper = apiJsonHelper;
|
||||
}
|
||||
|
||||
public void validateForCreate(final String json) {
|
||||
public void validateForCreate(final String json, final boolean isMeetingMandatoryForJLGLoans) {
|
||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
@@ -112,32 +112,24 @@ public final class LoanApplicationCommandFromApiJsonHelper {
|
||||
if (loanType.isJLGAccount()) {
|
||||
baseDataValidator.reset().parameter("clientId").value(clientId).notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter("groupId").value(groupId).notNull().longGreaterThanZero();
|
||||
/**
|
||||
* these validations should be carried out based on Global
|
||||
* configurations, commenting them for now
|
||||
**/
|
||||
|
||||
/**
|
||||
* // if it is JLG loan then must have a meeting details
|
||||
* (calendar) final String calendarIdParameterName =
|
||||
* "calendarId"; final Long calendarId =
|
||||
* this.fromApiJsonHelper.extractLongNamed
|
||||
* (calendarIdParameterName, element);
|
||||
* baseDataValidator.reset().
|
||||
* parameter(calendarIdParameterName).value
|
||||
* (calendarId).notNull().integerGreaterThanZero();
|
||||
*
|
||||
* // if it is JLG loan then must have a syncDisbursement final
|
||||
* String syncDisbursementParameterName =
|
||||
* "syncDisbursementWithMeeting"; final Boolean syncDisbursement
|
||||
* = this.fromApiJsonHelper.extractBooleanNamed(
|
||||
* syncDisbursementParameterName, element);
|
||||
*
|
||||
* if (syncDisbursement == null) {
|
||||
* baseDataValidator.reset().parameter
|
||||
* (syncDisbursementParameterName
|
||||
* ).value(syncDisbursement).trueOrFalseRequired(false); }
|
||||
**/
|
||||
// if it is JLG loan that must have meeting details
|
||||
if (isMeetingMandatoryForJLGLoans) {
|
||||
final String calendarIdParameterName = "calendarId";
|
||||
final Long calendarId = this.fromApiJsonHelper.extractLongNamed(calendarIdParameterName, element);
|
||||
baseDataValidator.reset().parameter(calendarIdParameterName).value(calendarId).notNull().integerGreaterThanZero();
|
||||
|
||||
// if it is JLG loan then must have a value for
|
||||
// syncDisbursement passed in
|
||||
String syncDisbursementParameterName = "syncDisbursementWithMeeting";
|
||||
final Boolean syncDisbursement = this.fromApiJsonHelper.extractBooleanNamed(syncDisbursementParameterName, element);
|
||||
|
||||
if (syncDisbursement == null) {
|
||||
baseDataValidator.reset().parameter(syncDisbursementParameterName).value(syncDisbursement)
|
||||
.trueOrFalseRequired(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -289,14 +281,14 @@ 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);
|
||||
if (this.fromApiJsonHelper.parameterExists(createSiAtDisbursementParameterName, element)) {
|
||||
final Boolean createStandingInstructionAtDisbursement = this.fromApiJsonHelper.extractBooleanNamed(
|
||||
createSiAtDisbursementParameterName, element);
|
||||
final Long linkAccountId = this.fromApiJsonHelper.extractLongNamed(linkAccountIdParameterName, element);
|
||||
|
||||
if(createStandingInstructionAtDisbursement) {
|
||||
|
||||
if (createStandingInstructionAtDisbursement) {
|
||||
baseDataValidator.reset().parameter(linkAccountIdParameterName).value(linkAccountId).notNull().longGreaterThanZero();
|
||||
}
|
||||
}
|
||||
|
||||
+6
-2
@@ -18,6 +18,7 @@ import org.mifosplatform.infrastructure.accountnumberformat.domain.AccountNumber
|
||||
import org.mifosplatform.infrastructure.accountnumberformat.domain.AccountNumberFormatRepositoryWrapper;
|
||||
import org.mifosplatform.infrastructure.accountnumberformat.domain.EntityAccountType;
|
||||
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
|
||||
import org.mifosplatform.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonQuery;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
@@ -131,6 +132,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
private final LoanAccountDomainService loanAccountDomainService;
|
||||
private final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository;
|
||||
private final BusinessEventNotifierService businessEventNotifierService;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
|
||||
@Autowired
|
||||
public LoanApplicationWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final FromJsonHelper fromJsonHelper,
|
||||
@@ -148,7 +150,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository,
|
||||
final LoanReadPlatformService loanReadPlatformService, final LoanAccountDomainService loanAccountDomainService,
|
||||
final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository,
|
||||
final BusinessEventNotifierService businessEventNotifierService) {
|
||||
final BusinessEventNotifierService businessEventNotifierService, final ConfigurationDomainService configurationDomainService) {
|
||||
this.context = context;
|
||||
this.fromJsonHelper = fromJsonHelper;
|
||||
this.loanApplicationTransitionApiJsonValidator = loanApplicationTransitionApiJsonValidator;
|
||||
@@ -176,6 +178,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
this.loanAccountDomainService = loanAccountDomainService;
|
||||
this.accountNumberFormatRepository = accountNumberFormatRepository;
|
||||
this.businessEventNotifierService = businessEventNotifierService;
|
||||
this.configurationDomainService = configurationDomainService;
|
||||
}
|
||||
|
||||
private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() {
|
||||
@@ -189,8 +192,9 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
|
||||
try {
|
||||
final AppUser currentUser = getAppUserIfPresent();
|
||||
boolean isMeetingMandatoryForJLGLoans = configurationDomainService.isMeetingMandatoryForJLGLoans();
|
||||
|
||||
this.fromApiJsonDeserializer.validateForCreate(command.json());
|
||||
this.fromApiJsonDeserializer.validateForCreate(command.json(), isMeetingMandatoryForJLGLoans);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan");
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
INSERT INTO c_configuration (`name`, `description`) VALUES ('meetings-mandatory-for-jlg-loans', 'Enforces all JLG loans to follow a meeting schedule belonging to parent group or Center');
|
||||
Reference in New Issue
Block a user