Merge pull request #1055 from pramodn02/develop
MIFOSX-1419 : moved capturing of rest frequency to product
This commit is contained in:
+9
@@ -0,0 +1,9 @@
|
||||
ALTER TABLE `m_product_loan_recalculation_details`
|
||||
ADD COLUMN `rest_frequency_type_enum` SMALLINT(1) NOT NULL AFTER `reschedule_strategy_enum`,
|
||||
ADD COLUMN `rest_frequency_interval` SMALLINT(3) NOT NULL DEFAULT '0' AFTER `rest_frequency_type_enum`,
|
||||
ADD COLUMN `rest_freqency_date` DATE NULL DEFAULT NULL AFTER `rest_frequency_interval`;
|
||||
|
||||
ALTER TABLE `m_loan_recalculation_details`
|
||||
ADD COLUMN `rest_frequency_type_enum` SMALLINT(1) NOT NULL AFTER `reschedule_strategy_enum`,
|
||||
ADD COLUMN `rest_frequency_interval` SMALLINT(3) NOT NULL DEFAULT '0' AFTER `rest_frequency_type_enum`,
|
||||
ADD COLUMN `rest_freqency_date` DATE NULL DEFAULT NULL AFTER `rest_frequency_interval`;
|
||||
-2
@@ -42,7 +42,6 @@ public class LoanApplicationTestBuilder {
|
||||
private String loanType = "individual";
|
||||
private String fixedEmiAmount = "10000";
|
||||
private String maxOutstandingLoanBalance = "36000";
|
||||
private String recalculationFrequencyType = "1";
|
||||
private String graceOnPrincipalPayment = null;
|
||||
private List<HashMap> disbursementData = null;
|
||||
private List<HashMap> charges = new ArrayList<HashMap>();
|
||||
@@ -72,7 +71,6 @@ public class LoanApplicationTestBuilder {
|
||||
map.put("expectedDisbursementDate", this.expectedDisbursmentDate);
|
||||
map.put("submittedOnDate", this.submittedOnDate);
|
||||
map.put("loanType", this.loanType);
|
||||
map.put("recalculationFrequencyType", this.recalculationFrequencyType);
|
||||
if (charges != null) {
|
||||
map.put("charges", charges);
|
||||
}
|
||||
|
||||
+18
@@ -821,5 +821,23 @@ public class DataValidatorBuilder {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public DataValidatorBuilder validateDateBeforeOrEqual(final LocalDate date) {
|
||||
if (this.value == null && this.ignoreNullValue) { return this; }
|
||||
|
||||
if (this.value != null && date != null) {
|
||||
final LocalDate dateVal = (LocalDate) this.value;
|
||||
if (!date.isAfter(dateVal)) {
|
||||
final StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(this.resource).append(".")
|
||||
.append(this.parameter).append(".is.greater.than.date");
|
||||
final StringBuilder defaultEnglishMessage = new StringBuilder("The ").append(this.parameter)
|
||||
.append(" must be less than or equal to provided date").append(date);
|
||||
final ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(),
|
||||
defaultEnglishMessage.toString(), this.parameter, dateVal, date);
|
||||
this.dataValidationErrors.add(error);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
-1
@@ -33,7 +33,6 @@ public interface LoanApiConstants {
|
||||
public static final String isInterestRecalculationEnabledParameterName = "isInterestRecalculationEnabled";
|
||||
public static final String daysInYearTypeParameterName = "daysInYearType";
|
||||
public static final String daysInMonthTypeParameterName = "daysInMonthType";
|
||||
public static final String recalculationFrequencyTypeParameterName = "recalculationFrequencyType";
|
||||
public static final String interestRecalculationCompoundingMethodParameterName = "interestRecalculationCompoundingMethod";
|
||||
public static final String rescheduleStrategyMethodParameterName = "rescheduleStrategyMethod";
|
||||
|
||||
|
||||
+1
-5
@@ -410,7 +410,6 @@ public class LoansApiResource {
|
||||
Collection<CodeValueData> loanCollateralOptions = null;
|
||||
Collection<CalendarData> calendarOptions = null;
|
||||
Collection<PortfolioAccountData> accountLinkingOptions = null;
|
||||
List<EnumOptionData> interestRecalculationFrequencyTypeOptions = null;
|
||||
|
||||
final boolean template = ApiParameterHelper.template(uriInfo.getQueryParameters());
|
||||
if (template) {
|
||||
@@ -452,9 +451,6 @@ public class LoansApiResource {
|
||||
calendarOptions = this.loanReadPlatformService.retrieveCalendars(loanBasicDetails.groupId());
|
||||
}
|
||||
|
||||
interestRecalculationFrequencyTypeOptions = this.dropdownReadPlatformService
|
||||
.retrieveInterestRecalculationFrequencyTypeOptions();
|
||||
|
||||
}
|
||||
|
||||
Collection<ChargeData> overdueCharges = this.chargeReadPlatformService.retrieveLoanProductCharges(loanBasicDetails.loanProductId(),
|
||||
@@ -465,7 +461,7 @@ public class LoansApiResource {
|
||||
repaymentStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions,
|
||||
interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, allowedLoanOfficers, loanPurposeOptions,
|
||||
loanCollateralOptions, calendarOptions, notes, accountLinkingOptions, linkedAccount, disbursementData, emiAmountVariations,
|
||||
overdueCharges, interestRecalculationFrequencyTypeOptions);
|
||||
overdueCharges);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters(),
|
||||
mandatoryResponseParameters);
|
||||
|
||||
+16
-39
@@ -130,7 +130,6 @@ public class LoanAccountData {
|
||||
private final Collection<ChargeData> chargeOptions;
|
||||
private final Collection<CodeValueData> loanCollateralOptions;
|
||||
private final Collection<CalendarData> calendarOptions;
|
||||
private final List<EnumOptionData> interestRecalculationFrequencyTypeOptions;
|
||||
|
||||
@Transient
|
||||
private final BigDecimal feeChargesAtDisbursementCharged;
|
||||
@@ -261,7 +260,6 @@ public class LoanAccountData {
|
||||
final EnumOptionData daysInYearType = null;
|
||||
final boolean isInterestRecalculationEnabled = false;
|
||||
final LoanInterestRecalculationData interestRecalculationData = null;
|
||||
final List<EnumOptionData> interestRecalculationFrequencyTypeOptions = null;
|
||||
|
||||
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, loanProductId,
|
||||
loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName,
|
||||
@@ -277,7 +275,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, interestRecalculationFrequencyTypeOptions);
|
||||
isInterestRecalculationEnabled, interestRecalculationData);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -371,7 +369,6 @@ public class LoanAccountData {
|
||||
final EnumOptionData daysInYearType = null;
|
||||
final boolean isInterestRecalculationEnabled = false;
|
||||
final LoanInterestRecalculationData interestRecalculationData = null;
|
||||
final List<EnumOptionData> interestRecalculationFrequencyTypeOptions = null;
|
||||
|
||||
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, loanProductId,
|
||||
loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName,
|
||||
@@ -386,8 +383,7 @@ public class LoanAccountData {
|
||||
loanPurposeOptions, loanCollateralOptions, calendarOptions, syncDisbursementWithMeeting, loancounter, loanProductCounter,
|
||||
notes, accountLinkingOptions, linkedAccount, disbursementData, multiDisburseLoan, fixedEmiAmount,
|
||||
maxOutstandingLoanBalance, emiAmountVariations, memberVariations, product, inArrears, graceOnArrearsAgeing, overdueCharges,
|
||||
isNPA, daysInMonthType, daysInYearType, isInterestRecalculationEnabled, interestRecalculationData,
|
||||
interestRecalculationFrequencyTypeOptions);
|
||||
isNPA, daysInMonthType, daysInYearType, isInterestRecalculationEnabled, interestRecalculationData);
|
||||
}
|
||||
|
||||
public static LoanAccountData populateClientDefaults(final LoanAccountData acc, final LoanAccountData clientAcc) {
|
||||
@@ -409,8 +405,7 @@ public class LoanAccountData {
|
||||
acc.syncDisbursementWithMeeting, acc.loanCounter, acc.loanProductCounter, acc.notes, acc.accountLinkingOptions,
|
||||
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.interestRecalculationFrequencyTypeOptions);
|
||||
acc.isNPA, acc.daysInMonthType, acc.daysInYearType, acc.isInterestRecalculationEnabled, acc.interestRecalculationData);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -505,7 +500,6 @@ public class LoanAccountData {
|
||||
final EnumOptionData daysInYearType = null;
|
||||
final boolean isInterestRecalculationEnabled = false;
|
||||
final LoanInterestRecalculationData interestRecalculationData = null;
|
||||
final List<EnumOptionData> interestRecalculationFrequencyTypeOptions = null;
|
||||
|
||||
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, loanProductId,
|
||||
loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName,
|
||||
@@ -520,7 +514,7 @@ public class LoanAccountData {
|
||||
loanPurposeOptions, loanCollateralOptions, calendarOptions, syncDisbursementWithMeeting, loancounter, loanProductCounter,
|
||||
notes, accountLinkingOptions, linkedAccount, disbursementData, multiDisburseLoan, fixedEmiAmount, maxOutstandingBalance,
|
||||
emiAmountVariations, memberVariations, product, inArrears, graceOnArrearsAgeing, overdueCharges, isNPA, daysInMonthType,
|
||||
daysInYearType, isInterestRecalculationEnabled, interestRecalculationData, interestRecalculationFrequencyTypeOptions);
|
||||
daysInYearType, isInterestRecalculationEnabled, interestRecalculationData);
|
||||
}
|
||||
|
||||
public static LoanAccountData populateGroupDefaults(final LoanAccountData acc, final LoanAccountData groupAcc) {
|
||||
@@ -541,8 +535,7 @@ public class LoanAccountData {
|
||||
acc.syncDisbursementWithMeeting, acc.loanCounter, acc.loanProductCounter, acc.notes, acc.accountLinkingOptions,
|
||||
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.interestRecalculationFrequencyTypeOptions);
|
||||
acc.isNPA, acc.daysInMonthType, acc.daysInYearType, acc.isInterestRecalculationEnabled, acc.interestRecalculationData);
|
||||
}
|
||||
|
||||
public static LoanAccountData loanProductWithTemplateDefaults(final LoanProductData product,
|
||||
@@ -552,7 +545,7 @@ public class LoanAccountData {
|
||||
final Collection<EnumOptionData> interestTypeOptions, final Collection<EnumOptionData> interestCalculationPeriodTypeOptions,
|
||||
final Collection<FundData> fundOptions, final Collection<ChargeData> chargeOptions,
|
||||
final Collection<CodeValueData> loanPurposeOptions, final Collection<CodeValueData> loanCollateralOptions,
|
||||
final Integer loanCycleNumber, final List<EnumOptionData> interestRecalculationFrequencyTypeOptions) {
|
||||
final Integer loanCycleNumber) {
|
||||
|
||||
final Long id = null;
|
||||
final String accountNo = null;
|
||||
@@ -667,8 +660,7 @@ public class LoanAccountData {
|
||||
notes, accountLinkingOptions, linkedAccount, disbursementData, product.getMultiDisburseLoan(), fixedEmi,
|
||||
product.getOutstandingLoanBalance(), emiAmountVariations, memberVariations, product, inArrears,
|
||||
product.getGraceOnArrearsAgeing(), product.overdueFeeCharges(), isNPA, product.getDaysInMonthType(),
|
||||
product.getDaysInYearType(), product.isInterestRecalculationEnabled(), product.toLoanInterestRecalculationData(),
|
||||
interestRecalculationFrequencyTypeOptions);
|
||||
product.getDaysInYearType(), product.isInterestRecalculationEnabled(), product.toLoanInterestRecalculationData());
|
||||
}
|
||||
|
||||
public static LoanAccountData populateLoanProductDefaults(final LoanAccountData acc, final LoanProductData product) {
|
||||
@@ -721,8 +713,7 @@ public class LoanAccountData {
|
||||
acc.linkedAccount, acc.disbursementDetails, product.getMultiDisburseLoan(), acc.fixedEmiAmount,
|
||||
product.getOutstandingLoanBalance(), acc.emiAmountVariations, acc.memberVariations, product, acc.inArrears,
|
||||
product.getGraceOnArrearsAgeing(), product.overdueFeeCharges(), acc.isNPA, product.getDaysInMonthType(),
|
||||
product.getDaysInYearType(), product.isInterestRecalculationEnabled(), product.toLoanInterestRecalculationData(),
|
||||
acc.interestRecalculationFrequencyTypeOptions);
|
||||
product.getDaysInYearType(), product.isInterestRecalculationEnabled(), product.toLoanInterestRecalculationData());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -777,7 +768,6 @@ public class LoanAccountData {
|
||||
final Map<Long, LoanBorrowerCycleData> memberVariations = null;
|
||||
final LoanProductData product = null;
|
||||
final Collection<ChargeData> overdueCharges = null;
|
||||
final List<EnumOptionData> interestRecalculationFrequencyTypeOptions = null;
|
||||
|
||||
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, loanProductId,
|
||||
loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName,
|
||||
@@ -792,7 +782,7 @@ public class LoanAccountData {
|
||||
loanPurposeOptions, loanCollateralOptions, calendarOptions, syncDisbursementWithMeeting, loancounter, loanProductCounter,
|
||||
notes, accountLinkingOptions, linkedAccount, disbursementData, multiDisburseLoan, fixedEmiAmont, outstandingLoanBalance,
|
||||
emiAmountVariations, memberVariations, product, inArrears, graceOnArrearsAgeing, overdueCharges, isNPA, daysInMonthType,
|
||||
daysInYearType, isInterestRecalculationEnabled, interestRecalculationData, interestRecalculationFrequencyTypeOptions);
|
||||
daysInYearType, isInterestRecalculationEnabled, interestRecalculationData);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -812,8 +802,7 @@ public class LoanAccountData {
|
||||
final Collection<CodeValueData> loanCollateralOptions, final Collection<CalendarData> calendarOptions,
|
||||
final Collection<NoteData> notes, final Collection<PortfolioAccountData> accountLinkingOptions,
|
||||
final PortfolioAccountData linkedAccount, final Collection<DisbursementData> disbursementDetails,
|
||||
final Collection<LoanTermVariationsData> emiAmountVariations, final Collection<ChargeData> overdueCharges,
|
||||
final List<EnumOptionData> interestRecalculationFrequencyTypeOptions) {
|
||||
final Collection<LoanTermVariationsData> emiAmountVariations, final Collection<ChargeData> overdueCharges) {
|
||||
|
||||
return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientName, acc.clientOfficeId,
|
||||
acc.group, acc.loanType, acc.loanProductId, acc.loanProductName, acc.loanProductDescription, acc.fundId, acc.fundName,
|
||||
@@ -831,7 +820,7 @@ public class LoanAccountData {
|
||||
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, interestRecalculationFrequencyTypeOptions);
|
||||
acc.isInterestRecalculationEnabled, acc.interestRecalculationData);
|
||||
}
|
||||
|
||||
public static LoanAccountData associationsAndTemplate(final LoanAccountData acc, final Collection<LoanProductData> productOptions,
|
||||
@@ -842,8 +831,7 @@ public class LoanAccountData {
|
||||
acc.transactionProcessingStrategyOptions, acc.interestRateFrequencyTypeOptions, acc.amortizationTypeOptions,
|
||||
acc.interestTypeOptions, acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, null,
|
||||
allowedLoanOfficers, acc.loanPurposeOptions, acc.loanCollateralOptions, calendarOptions, acc.notes, accountLinkingOptions,
|
||||
acc.linkedAccount, acc.disbursementDetails, acc.emiAmountVariations, acc.overdueCharges,
|
||||
acc.interestRecalculationFrequencyTypeOptions);
|
||||
acc.linkedAccount, acc.disbursementDetails, acc.emiAmountVariations, acc.overdueCharges);
|
||||
}
|
||||
|
||||
public static LoanAccountData associateGroup(final LoanAccountData acc, final GroupGeneralData group) {
|
||||
@@ -863,8 +851,7 @@ public class LoanAccountData {
|
||||
acc.syncDisbursementWithMeeting, acc.loanCounter, acc.loanProductCounter, acc.notes, acc.accountLinkingOptions,
|
||||
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.interestRecalculationFrequencyTypeOptions);
|
||||
acc.isNPA, acc.daysInMonthType, acc.daysInYearType, acc.isInterestRecalculationEnabled, acc.interestRecalculationData);
|
||||
}
|
||||
|
||||
public static LoanAccountData associateMemberVariations(final LoanAccountData acc, final Map<Long, Integer> memberLoanCycle) {
|
||||
@@ -921,8 +908,7 @@ public class LoanAccountData {
|
||||
acc.syncDisbursementWithMeeting, acc.loanCounter, acc.loanProductCounter, acc.notes, acc.accountLinkingOptions,
|
||||
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.interestRecalculationFrequencyTypeOptions);
|
||||
acc.isNPA, acc.daysInMonthType, acc.daysInYearType, acc.isInterestRecalculationEnabled, acc.interestRecalculationData);
|
||||
}
|
||||
|
||||
public static LoanAccountData withInterestRecalculationCalendarData(final LoanAccountData acc, final CalendarData calendarData) {
|
||||
@@ -945,8 +931,7 @@ public class LoanAccountData {
|
||||
acc.syncDisbursementWithMeeting, acc.loanCounter, acc.loanProductCounter, acc.notes, acc.accountLinkingOptions,
|
||||
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.interestRecalculationFrequencyTypeOptions);
|
||||
acc.isNPA, acc.daysInMonthType, acc.daysInYearType, acc.isInterestRecalculationEnabled, interestRecalculationData);
|
||||
}
|
||||
|
||||
private LoanAccountData(
|
||||
@@ -1002,8 +987,7 @@ 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 List<EnumOptionData> interestRecalculationFrequencyTypeOptions) {
|
||||
final LoanInterestRecalculationData interestRecalculationData) {
|
||||
this.id = id;
|
||||
this.accountNo = accountNo;
|
||||
this.status = status;
|
||||
@@ -1147,13 +1131,6 @@ public class LoanAccountData {
|
||||
this.daysInYearType = daysInYearType;
|
||||
this.isInterestRecalculationEnabled = isInterestRecalculationEnabled;
|
||||
this.interestRecalculationData = interestRecalculationData;
|
||||
|
||||
if (CollectionUtils.isEmpty(interestRecalculationFrequencyTypeOptions)) {
|
||||
this.interestRecalculationFrequencyTypeOptions = null;
|
||||
} else {
|
||||
this.interestRecalculationFrequencyTypeOptions = interestRecalculationFrequencyTypeOptions;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public RepaymentScheduleRelatedLoanData repaymentScheduleRelatedData() {
|
||||
|
||||
+13
-2
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
package org.mifosplatform.portfolio.loanaccount.data;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.portfolio.calendar.data.CalendarData;
|
||||
|
||||
@@ -16,20 +17,30 @@ public class LoanInterestRecalculationData {
|
||||
private final EnumOptionData rescheduleStrategyType;
|
||||
@SuppressWarnings("unused")
|
||||
private final CalendarData calendarData;
|
||||
private final EnumOptionData recalculationRestFrequencyType;
|
||||
private final Integer recalculationRestFrequencyInterval;
|
||||
private final LocalDate recalculationRestFrequencyDate;
|
||||
|
||||
public LoanInterestRecalculationData(final Long id, final Long loanId, final EnumOptionData interestRecalculationCompoundingType,
|
||||
final EnumOptionData rescheduleStrategyType, final CalendarData calendarData) {
|
||||
final EnumOptionData rescheduleStrategyType, final CalendarData calendarData,
|
||||
final EnumOptionData recalculationRestFrequencyType, final Integer recalculationRestFrequencyInterval,
|
||||
final LocalDate recalculationRestFrequencyDate) {
|
||||
this.id = id;
|
||||
this.loanId = loanId;
|
||||
this.interestRecalculationCompoundingType = interestRecalculationCompoundingType;
|
||||
this.rescheduleStrategyType = rescheduleStrategyType;
|
||||
this.calendarData = calendarData;
|
||||
this.recalculationRestFrequencyType = recalculationRestFrequencyType;
|
||||
this.recalculationRestFrequencyInterval = recalculationRestFrequencyInterval;
|
||||
this.recalculationRestFrequencyDate = recalculationRestFrequencyDate;
|
||||
}
|
||||
|
||||
public static LoanInterestRecalculationData withCalendarData(final LoanInterestRecalculationData recalculationData,
|
||||
final CalendarData calendarData) {
|
||||
return new LoanInterestRecalculationData(recalculationData.id, recalculationData.loanId,
|
||||
recalculationData.interestRecalculationCompoundingType, recalculationData.rescheduleStrategyType, calendarData);
|
||||
recalculationData.interestRecalculationCompoundingType, recalculationData.rescheduleStrategyType, calendarData,
|
||||
recalculationData.recalculationRestFrequencyType, recalculationData.recalculationRestFrequencyInterval,
|
||||
recalculationData.recalculationRestFrequencyDate);
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
|
||||
+31
-7
@@ -90,10 +90,12 @@ import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanScheduleG
|
||||
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanScheduleGeneratorFactory;
|
||||
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel;
|
||||
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanScheduleModelPeriod;
|
||||
import org.mifosplatform.portfolio.loanproduct.LoanProductConstants;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.InterestMethod;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanProduct;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanTransactionProcessingStrategy;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.RecalculationFrequencyType;
|
||||
import org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations;
|
||||
import org.mifosplatform.useradministration.domain.AppUser;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
@@ -1057,6 +1059,9 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
|
||||
final String dateFormatAsInput = command.dateFormat();
|
||||
final String localeAsInput = command.locale();
|
||||
final LocalDate recalculationRestFrequencyDate = command
|
||||
.localDateValueOfParameterNamed(LoanProductConstants.recalculationRestFrequencyDateParamName);
|
||||
updateLoanInterestRecalculationSettings(recalculationRestFrequencyDate, command, actualChanges);
|
||||
|
||||
final String accountNoParamName = "accountNo";
|
||||
if (command.isChangeInStringParameterNamed(accountNoParamName, this.accountNumber)) {
|
||||
@@ -1299,15 +1304,24 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
/**
|
||||
* Update interest recalculation settings if product configuration changes
|
||||
*/
|
||||
public void updateLoanInterestRecalculationSettings() {
|
||||
public void updateLoanInterestRecalculationSettings(final LocalDate recalculationRestFrequencyDate, final JsonCommand command,
|
||||
final Map<String, Object> actualChanges) {
|
||||
|
||||
if (isInterestRecalculationEnabledForProduct()) {
|
||||
Date restFrequencyDate = null;
|
||||
if (recalculationRestFrequencyDate != null) {
|
||||
restFrequencyDate = recalculationRestFrequencyDate.toDate();
|
||||
}
|
||||
if (this.loanInterestRecalculationDetails == null) {
|
||||
this.loanInterestRecalculationDetails = this.loanProduct.copyInterestRecalculationSettings();
|
||||
this.loanInterestRecalculationDetails = LoanInterestRecalculationDetails.createFrom(this.loanProduct
|
||||
.getProductInterestRecalculationDetails().getInterestRecalculationCompoundingMethod(), this.loanProduct
|
||||
.getProductInterestRecalculationDetails().getRescheduleStrategyMethod(), this.loanProduct
|
||||
.getProductInterestRecalculationDetails().getRestFrequencyType().getValue(), this.loanProduct
|
||||
.getProductInterestRecalculationDetails().getRestInterval(), restFrequencyDate);
|
||||
this.loanInterestRecalculationDetails.updateLoan(this);
|
||||
} else {
|
||||
this.loanInterestRecalculationDetails = this.loanProduct
|
||||
.updateLoanInterestRecalculationDetails(this.loanInterestRecalculationDetails);
|
||||
|
||||
this.loanInterestRecalculationDetails.update(command, actualChanges);
|
||||
}
|
||||
} else {
|
||||
this.loanInterestRecalculationDetails = null;
|
||||
@@ -1479,7 +1493,7 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
public void loanApplicationSubmittal(final AppUser currentUser, final LoanScheduleModel loanSchedule,
|
||||
final LoanApplicationTerms loanApplicationTerms, final LoanLifecycleStateMachine lifecycleStateMachine,
|
||||
final LocalDate submittedOn, final String externalId, final boolean allowTransactionsOnHoliday, final List<Holiday> holidays,
|
||||
final WorkingDays workingDays, final boolean allowTransactionsOnNonWorkingDay) {
|
||||
final WorkingDays workingDays, final boolean allowTransactionsOnNonWorkingDay, final LocalDate recalculationRestFrequencyDate) {
|
||||
|
||||
updateLoanSchedule(loanSchedule);
|
||||
|
||||
@@ -1542,7 +1556,15 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
* enabled
|
||||
*/
|
||||
if (this.loanRepaymentScheduleDetail.isInterestRecalculationEnabled()) {
|
||||
this.loanInterestRecalculationDetails = this.loanProduct.copyInterestRecalculationSettings();
|
||||
Date restFrequencyDate = null;
|
||||
if (recalculationRestFrequencyDate != null) {
|
||||
restFrequencyDate = recalculationRestFrequencyDate.toDate();
|
||||
}
|
||||
this.loanInterestRecalculationDetails = LoanInterestRecalculationDetails.createFrom(this.loanProduct
|
||||
.getProductInterestRecalculationDetails().getInterestRecalculationCompoundingMethod(), this.loanProduct
|
||||
.getProductInterestRecalculationDetails().getRescheduleStrategyMethod(), this.loanProduct
|
||||
.getProductInterestRecalculationDetails().getRestFrequencyType().getValue(), this.loanProduct
|
||||
.getProductInterestRecalculationDetails().getRestInterval(), restFrequencyDate);
|
||||
this.loanInterestRecalculationDetails.updateLoan(this);
|
||||
}
|
||||
|
||||
@@ -4106,12 +4128,14 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
loanVariationTermsData.add(data);
|
||||
}
|
||||
|
||||
RecalculationFrequencyType recalculationFrequencyType = this.loanInterestRecalculationDetails().getRestFrequencyType();
|
||||
|
||||
final LoanApplicationTerms loanApplicationTerms = LoanApplicationTerms.assembleFrom(applicationCurrency, loanTermFrequency,
|
||||
loanTermPeriodFrequencyType, getDisbursementDate(), getExpectedFirstRepaymentOnDate(),
|
||||
calculatedRepaymentsStartingFromDate, getInArrearsTolerance(), this.loanRepaymentScheduleDetail,
|
||||
this.loanProduct.isMultiDisburseLoan(), this.fixedEmiAmount, disbursementData, this.maxOutstandingLoanBalance,
|
||||
loanVariationTermsData, getInterestChargedFromDate(), this.loanInterestRecalculationDetails,
|
||||
calendarInstanceForInterestRecalculation);
|
||||
calendarInstanceForInterestRecalculation, recalculationFrequencyType);
|
||||
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategy);
|
||||
|
||||
+57
-6
@@ -5,14 +5,23 @@
|
||||
*/
|
||||
package org.mifosplatform.portfolio.loanaccount.domain;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.portfolio.loanproduct.LoanProductConstants;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.InterestRecalculationCompoundingMethod;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanRescheduleStrategyMethod;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.RecalculationFrequencyType;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
/**
|
||||
@@ -43,27 +52,53 @@ public class LoanInterestRecalculationDetails extends AbstractPersistable<Long>
|
||||
@Column(name = "reschedule_strategy_enum", nullable = false)
|
||||
private Integer rescheduleStrategyMethod;
|
||||
|
||||
@Column(name = "rest_frequency_type_enum", nullable = false)
|
||||
private Integer restFrequencyType;
|
||||
|
||||
@Column(name = "rest_frequency_interval", nullable = false)
|
||||
private Integer restInterval;
|
||||
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "rest_freqency_date")
|
||||
private Date restFrequencyDate;
|
||||
|
||||
protected LoanInterestRecalculationDetails() {
|
||||
// Default constructor for jpa repository
|
||||
}
|
||||
|
||||
private LoanInterestRecalculationDetails(final Integer interestRecalculationCompoundingMethod, final Integer rescheduleStrategyMethod) {
|
||||
private LoanInterestRecalculationDetails(final Integer interestRecalculationCompoundingMethod, final Integer rescheduleStrategyMethod,
|
||||
final Integer restFrequencyType, final Integer restInterval, final Date restFrequencyDate) {
|
||||
this.interestRecalculationCompoundingMethod = interestRecalculationCompoundingMethod;
|
||||
this.rescheduleStrategyMethod = rescheduleStrategyMethod;
|
||||
this.restFrequencyDate = restFrequencyDate;
|
||||
this.restFrequencyType = restFrequencyType;
|
||||
this.restInterval = restInterval;
|
||||
}
|
||||
|
||||
public static LoanInterestRecalculationDetails createFrom(final Integer interestRecalculationCompoundingMethod,
|
||||
final Integer rescheduleStrategyMethod) {
|
||||
return new LoanInterestRecalculationDetails(interestRecalculationCompoundingMethod, rescheduleStrategyMethod);
|
||||
final Integer rescheduleStrategyMethod, final Integer restFrequencyType, final Integer restInterval,
|
||||
final Date restFrequencyDate) {
|
||||
return new LoanInterestRecalculationDetails(interestRecalculationCompoundingMethod, rescheduleStrategyMethod, restFrequencyType,
|
||||
restInterval, restFrequencyDate);
|
||||
}
|
||||
|
||||
public void updateLoan(final Loan loan) {
|
||||
this.loan = loan;
|
||||
}
|
||||
|
||||
public void update(final Integer interestRecalculationCompoundingMethod, final Integer rescheduleStrategyMethod) {
|
||||
this.interestRecalculationCompoundingMethod = interestRecalculationCompoundingMethod;
|
||||
this.rescheduleStrategyMethod = rescheduleStrategyMethod;
|
||||
public void update(final JsonCommand command, final Map<String, Object> actualChanges) {
|
||||
if (command.isChangeInLocalDateParameterNamed(LoanProductConstants.recalculationRestFrequencyDateParamName,
|
||||
getRestFrequencyLocalDate())) {
|
||||
final String dateFormatAsInput = command.dateFormat();
|
||||
final String localeAsInput = command.locale();
|
||||
final String valueAsInput = command.stringValueOfParameterNamed(LoanProductConstants.recalculationRestFrequencyDateParamName);
|
||||
actualChanges.put(LoanProductConstants.recalculationRestFrequencyDateParamName, valueAsInput);
|
||||
actualChanges.put("dateFormat", dateFormatAsInput);
|
||||
actualChanges.put("locale", localeAsInput);
|
||||
|
||||
final LocalDate newValue = command.localDateValueOfParameterNamed(LoanProductConstants.recalculationRestFrequencyDateParamName);
|
||||
this.restFrequencyDate = newValue.toDate();
|
||||
}
|
||||
}
|
||||
|
||||
public InterestRecalculationCompoundingMethod getInterestRecalculationCompoundingMethod() {
|
||||
@@ -74,4 +109,20 @@ public class LoanInterestRecalculationDetails extends AbstractPersistable<Long>
|
||||
return LoanRescheduleStrategyMethod.fromInt(this.rescheduleStrategyMethod);
|
||||
}
|
||||
|
||||
public LocalDate getRestFrequencyLocalDate() {
|
||||
LocalDate recurrenceOnLocalDate = null;
|
||||
if (this.restFrequencyDate != null) {
|
||||
recurrenceOnLocalDate = new LocalDate(this.restFrequencyDate);
|
||||
}
|
||||
return recurrenceOnLocalDate;
|
||||
}
|
||||
|
||||
public RecalculationFrequencyType getRestFrequencyType() {
|
||||
return RecalculationFrequencyType.fromInt(this.restFrequencyType);
|
||||
}
|
||||
|
||||
|
||||
public Integer getRestInterval() {
|
||||
return this.restInterval;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-6
@@ -1022,16 +1022,15 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
|
||||
recalculationDates, preCloseTransaction);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private LocalDate getNextRestScheduleDate(LocalDate startDate, LoanApplicationTerms loanApplicationTerms,
|
||||
final boolean isHolidayEnabled, final List<Holiday> holidays, final WorkingDays workingDays) {
|
||||
CalendarInstance calendarInstance = loanApplicationTerms.getRestCalendarInstance();
|
||||
LocalDate nextScheduleDate = CalendarUtils.getNextScheduleDate(calendarInstance.getCalendar(), startDate);
|
||||
/*
|
||||
* nextScheduleDate =
|
||||
* this.scheduledDateGenerator.adjustRepaymentDate(nextScheduleDate,
|
||||
* loanApplicationTerms, isHolidayEnabled, holidays, workingDays);
|
||||
*/
|
||||
if (loanApplicationTerms.getRecalculationFrequencyType().isSameAsRepayment()) {
|
||||
nextScheduleDate = this.scheduledDateGenerator.adjustRepaymentDate(nextScheduleDate, loanApplicationTerms, isHolidayEnabled,
|
||||
holidays, workingDays);
|
||||
}
|
||||
|
||||
return nextScheduleDate;
|
||||
}
|
||||
|
||||
|
||||
+21
-6
@@ -31,6 +31,7 @@ import org.mifosplatform.portfolio.loanproduct.domain.InterestMethod;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.InterestRecalculationCompoundingMethod;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanRescheduleStrategyMethod;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.RecalculationFrequencyType;
|
||||
|
||||
public final class LoanApplicationTerms {
|
||||
|
||||
@@ -122,6 +123,8 @@ public final class LoanApplicationTerms {
|
||||
|
||||
private final CalendarInstance restCalendarInstance;
|
||||
|
||||
private final RecalculationFrequencyType recalculationFrequencyType;
|
||||
|
||||
public static LoanApplicationTerms assembleFrom(final ApplicationCurrency currency, final Integer loanTermFrequency,
|
||||
final PeriodFrequencyType loanTermPeriodFrequencyType, final Integer numberOfRepayments, final Integer repaymentEvery,
|
||||
final PeriodFrequencyType repaymentPeriodFrequencyType, final AmortizationMethod amortizationMethod,
|
||||
@@ -139,13 +142,15 @@ public final class LoanApplicationTerms {
|
||||
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, 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);
|
||||
isInterestRecalculationEnabled, rescheduleStrategyMethod, interestRecalculationCompoundingMethod, restCalendarInstance,
|
||||
recalculationFrequencyType);
|
||||
}
|
||||
|
||||
public static LoanApplicationTerms assembleFrom(final ApplicationCurrency applicationCurrency, final Integer loanTermFrequency,
|
||||
@@ -179,6 +184,7 @@ public final class LoanApplicationTerms {
|
||||
final LoanRescheduleStrategyMethod rescheduleStrategyMethod = null;
|
||||
final InterestRecalculationCompoundingMethod interestRecalculationCompoundingMethod = null;
|
||||
final CalendarInstance restCalendarInstance = null;
|
||||
final RecalculationFrequencyType recalculationFrequencyType = null;
|
||||
|
||||
return new LoanApplicationTerms(applicationCurrency, loanTermFrequency, loanTermPeriodFrequencyType, numberOfRepayments,
|
||||
repaymentEvery, repaymentPeriodFrequencyType, amortizationMethod, interestMethod, interestRatePerPeriod,
|
||||
@@ -187,7 +193,7 @@ public final class LoanApplicationTerms {
|
||||
graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, inArrearsTolerance, multiDisburseLoan, emiAmount,
|
||||
disbursementDatas, maxOutstandingBalance, emiAmountVariations, loanProductRelatedDetail.getGraceOnDueDate(),
|
||||
daysInMonthType, daysInYearType, isInterestRecalculationEnabled, rescheduleStrategyMethod,
|
||||
interestRecalculationCompoundingMethod, restCalendarInstance);
|
||||
interestRecalculationCompoundingMethod, restCalendarInstance, recalculationFrequencyType);
|
||||
}
|
||||
|
||||
public static LoanApplicationTerms assembleFrom(final ApplicationCurrency applicationCurrency, final Integer loanTermFrequency,
|
||||
@@ -196,7 +202,8 @@ public final class LoanApplicationTerms {
|
||||
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 LoanInterestRecalculationDetails interestRecalculationDetails, final CalendarInstance restCalendarInstance) {
|
||||
final LoanInterestRecalculationDetails interestRecalculationDetails, final CalendarInstance restCalendarInstance,
|
||||
final RecalculationFrequencyType recalculationFrequencyType) {
|
||||
|
||||
final Integer numberOfRepayments = loanProductRelatedDetail.getNumberOfRepayments();
|
||||
final Integer repaymentEvery = loanProductRelatedDetail.getRepayEvery();
|
||||
@@ -233,7 +240,7 @@ public final class LoanApplicationTerms {
|
||||
graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, inArrearsTolerance, multiDisburseLoan, emiAmount,
|
||||
disbursementDatas, maxOutstandingBalance, emiAmountVariations, loanProductRelatedDetail.getGraceOnDueDate(),
|
||||
daysInMonthType, daysInYearType, isInterestRecalculationEnabled, rescheduleStrategyMethod,
|
||||
interestRecalculationCompoundingMethod, restCalendarInstance);
|
||||
interestRecalculationCompoundingMethod, restCalendarInstance, recalculationFrequencyType);
|
||||
}
|
||||
|
||||
public static LoanApplicationTerms assembleFrom(final Integer repaymentEvery, final PeriodFrequencyType repaymentPeriodFrequencyType,
|
||||
@@ -250,7 +257,8 @@ public final class LoanApplicationTerms {
|
||||
applicationTerms.disbursementDatas, applicationTerms.maxOutstandingBalance, applicationTerms.emiAmountVariations,
|
||||
applicationTerms.graceOnArrearsAgeing, applicationTerms.daysInMonthType, applicationTerms.daysInYearType,
|
||||
applicationTerms.interestRecalculationEnabled, applicationTerms.rescheduleStrategyMethod,
|
||||
applicationTerms.interestRecalculationCompoundingMethod, applicationTerms.restCalendarInstance);
|
||||
applicationTerms.interestRecalculationCompoundingMethod, applicationTerms.restCalendarInstance,
|
||||
applicationTerms.recalculationFrequencyType);
|
||||
}
|
||||
|
||||
private LoanApplicationTerms(final ApplicationCurrency currency, final Integer loanTermFrequency,
|
||||
@@ -266,7 +274,8 @@ public final class LoanApplicationTerms {
|
||||
final BigDecimal maxOutstandingBalance, final List<LoanTermVariationsData> emiAmountVariations,
|
||||
final Integer graceOnArrearsAgeing, final DaysInMonthType daysInMonthType, final DaysInYearType daysInYearType,
|
||||
final boolean isInterestRecalculationEnabled, final LoanRescheduleStrategyMethod rescheduleStrategyMethod,
|
||||
final InterestRecalculationCompoundingMethod interestRecalculationCompoundingMethod, final CalendarInstance restCalendarInstance) {
|
||||
final InterestRecalculationCompoundingMethod interestRecalculationCompoundingMethod,
|
||||
final CalendarInstance restCalendarInstance, final RecalculationFrequencyType recalculationFrequencyType) {
|
||||
this.currency = currency;
|
||||
this.loanTermFrequency = loanTermFrequency;
|
||||
this.loanTermPeriodFrequencyType = loanTermPeriodFrequencyType;
|
||||
@@ -304,6 +313,7 @@ public final class LoanApplicationTerms {
|
||||
this.rescheduleStrategyMethod = rescheduleStrategyMethod;
|
||||
this.interestRecalculationCompoundingMethod = interestRecalculationCompoundingMethod;
|
||||
this.restCalendarInstance = restCalendarInstance;
|
||||
this.recalculationFrequencyType = recalculationFrequencyType;
|
||||
}
|
||||
|
||||
public Money adjustPrincipalIfLastRepaymentPeriod(final Money principalForPeriod, final Money totalCumulativePrincipalToDate,
|
||||
@@ -1052,4 +1062,9 @@ public final class LoanApplicationTerms {
|
||||
}
|
||||
return numberOfPeriods;
|
||||
}
|
||||
|
||||
|
||||
public RecalculationFrequencyType getRecalculationFrequencyType() {
|
||||
return this.recalculationFrequencyType;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -41,7 +41,7 @@ public final class CalculateLoanScheduleQueryFromApiJsonHelper {
|
||||
"graceOnInterestCharged", "interestChargedFromDate", "submittedOnDate", "submittedOnNote", "locale", "dateFormat", "charges",
|
||||
"collateral", "syncDisbursementWithMeeting", "linkAccountId", LoanApiConstants.disbursementDataParameterName,
|
||||
LoanApiConstants.emiAmountParameterName, LoanApiConstants.maxOutstandingBalanceParameterName,
|
||||
LoanProductConstants.graceOnArrearsAgeingParameterName, LoanApiConstants.recalculationFrequencyTypeParameterName));
|
||||
LoanProductConstants.graceOnArrearsAgeingParameterName, LoanProductConstants.recalculationRestFrequencyDateParamName));
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
|
||||
+14
-17
@@ -5,8 +5,6 @@
|
||||
*/
|
||||
package org.mifosplatform.portfolio.loanaccount.serialization;
|
||||
|
||||
import static org.mifosplatform.portfolio.loanaccount.api.LoanApiConstants.recalculationFrequencyTypeParameterName;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
@@ -48,21 +46,26 @@ 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", "interestRatePerPeriod", "amortizationType", "interestType", "interestCalculationPeriodType",
|
||||
"expectedDisbursementDate", "repaymentsStartingFromDate", "graceOnPrincipalPayment", "graceOnInterestPayment",
|
||||
"expectedDisbursementDate", "repaymentsStartingFromDate", "graceOnPrincipalPayment",
|
||||
"graceOnInterestPayment",
|
||||
"graceOnInterestCharged",
|
||||
"interestChargedFromDate", //
|
||||
"submittedOnDate",
|
||||
"submittedOnNote", //
|
||||
"accountNo", "externalId", "fundId",
|
||||
"accountNo",
|
||||
"externalId",
|
||||
"fundId",
|
||||
"loanOfficerId", // optional
|
||||
"loanPurposeId", "inArrearsTolerance", "charges",
|
||||
"loanPurposeId",
|
||||
"inArrearsTolerance",
|
||||
"charges",
|
||||
"collateral", // optional
|
||||
"transactionProcessingStrategyId", // settings
|
||||
"calendarId", // optional
|
||||
"syncDisbursementWithMeeting",// optional
|
||||
"linkAccountId", LoanApiConstants.disbursementDataParameterName, LoanApiConstants.emiAmountParameterName,
|
||||
LoanApiConstants.maxOutstandingBalanceParameterName, LoanProductConstants.graceOnArrearsAgeingParameterName,
|
||||
LoanApiConstants.recalculationFrequencyTypeParameterName));
|
||||
LoanProductConstants.recalculationRestFrequencyDateParamName));
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
private final CalculateLoanScheduleQueryFromApiJsonHelper apiJsonHelper;
|
||||
@@ -360,13 +363,6 @@ public final class LoanApplicationCommandFromApiJsonHelper {
|
||||
}
|
||||
validateLoanMultiDisbursementdate(element, baseDataValidator, expectedDisbursementDate, principal);
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.recalculationFrequencyTypeParameterName, element)) {
|
||||
final Integer recalculationFrequencyType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(
|
||||
LoanApiConstants.recalculationFrequencyTypeParameterName, element);
|
||||
baseDataValidator.reset().parameter(LoanApiConstants.recalculationFrequencyTypeParameterName).value(recalculationFrequencyType)
|
||||
.notNull().inMinMaxRange(1, 5);
|
||||
}
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
}
|
||||
|
||||
@@ -452,7 +448,8 @@ public final class LoanApplicationCommandFromApiJsonHelper {
|
||||
atLeastOneParameterPassedForUpdate = true;
|
||||
final BigDecimal inArrearsTolerance = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(inArrearsToleranceParameterName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(inArrearsToleranceParameterName).value(inArrearsTolerance).ignoreIfNull().zeroOrPositiveAmount();
|
||||
baseDataValidator.reset().parameter(inArrearsToleranceParameterName).value(inArrearsTolerance).ignoreIfNull()
|
||||
.zeroOrPositiveAmount();
|
||||
}
|
||||
|
||||
final String loanTermFrequencyParameterName = "loanTermFrequency";
|
||||
@@ -839,11 +836,11 @@ public final class LoanApplicationCommandFromApiJsonHelper {
|
||||
|
||||
}
|
||||
|
||||
public void validateRecalcuationFrequencyType(final Integer recalculationFrequencyTypeValue) {
|
||||
public void validateRecalcuationFrequency(final LocalDate recalculationFrequencyDate, final LocalDate expectedDisbursementDate) {
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan");
|
||||
baseDataValidator.reset().parameter(recalculationFrequencyTypeParameterName).value(recalculationFrequencyTypeValue).notNull()
|
||||
.inMinMaxRange(1, 5);
|
||||
baseDataValidator.reset().parameter(LoanProductConstants.recalculationRestFrequencyDateParamName).value(recalculationFrequencyDate)
|
||||
.notNull().validateDateBeforeOrEqual(expectedDisbursementDate);
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
}
|
||||
|
||||
|
||||
+37
-39
@@ -5,8 +5,6 @@
|
||||
*/
|
||||
package org.mifosplatform.portfolio.loanaccount.service;
|
||||
|
||||
import static org.mifosplatform.portfolio.loanaccount.api.LoanApiConstants.recalculationFrequencyTypeParameterName;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@@ -70,6 +68,7 @@ import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanScheduleM
|
||||
import org.mifosplatform.portfolio.loanaccount.loanschedule.service.LoanScheduleCalculationPlatformService;
|
||||
import org.mifosplatform.portfolio.loanaccount.serialization.LoanApplicationCommandFromApiJsonHelper;
|
||||
import org.mifosplatform.portfolio.loanaccount.serialization.LoanApplicationTransitionApiJsonValidator;
|
||||
import org.mifosplatform.portfolio.loanproduct.LoanProductConstants;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanProduct;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRepository;
|
||||
@@ -214,11 +213,13 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
|
||||
if (loanProduct.isInterestRecalculationEnabled()) {
|
||||
|
||||
final Integer recalculationFrequencyTypeValue = command
|
||||
.integerValueOfParameterNamed(recalculationFrequencyTypeParameterName);
|
||||
this.fromApiJsonDeserializer.validateRecalcuationFrequencyType(recalculationFrequencyTypeValue);
|
||||
|
||||
createAndPersistCalendarInstanceForInterestRecalculation(newLoanApplication, recalculationFrequencyTypeValue);
|
||||
final LocalDate recalculationFrequencyDate = this.fromJsonHelper.extractLocalDateNamed(
|
||||
LoanProductConstants.recalculationRestFrequencyDateParamName, command.parsedJson());
|
||||
if (!newLoanApplication.loanInterestRecalculationDetails().getRestFrequencyType().isSameAsRepayment()) {
|
||||
this.fromApiJsonDeserializer.validateRecalcuationFrequency(recalculationFrequencyDate,
|
||||
newLoanApplication.getExpectedDisbursedOnLocalDate());
|
||||
}
|
||||
createAndPersistCalendarInstanceForInterestRecalculation(newLoanApplication);
|
||||
}
|
||||
|
||||
if (newLoanApplication.isAccountNumberRequiresAutoGeneration()) {
|
||||
@@ -271,33 +272,30 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
}
|
||||
}
|
||||
|
||||
private void createAndPersistCalendarInstanceForInterestRecalculation(final Loan loan, final Integer recalculationFrequencyTypeValue) {
|
||||
private void createAndPersistCalendarInstanceForInterestRecalculation(final Loan loan) {
|
||||
|
||||
final LocalDate calendarStartDate = loan.getDisbursementDate();
|
||||
LocalDate calendarStartDate = loan.loanInterestRecalculationDetails().getRestFrequencyLocalDate();
|
||||
if (calendarStartDate == null) {
|
||||
calendarStartDate = loan.getExpectedDisbursedOnLocalDate();
|
||||
}
|
||||
final Integer repeatsOnDay = calendarStartDate.getDayOfWeek();
|
||||
final RecalculationFrequencyType recalculationFrequencyType = RecalculationFrequencyType.fromInt(recalculationFrequencyTypeValue);
|
||||
final RecalculationFrequencyType recalculationFrequencyType = loan.loanInterestRecalculationDetails().getRestFrequencyType();
|
||||
|
||||
Integer frequency = 1;
|
||||
Integer frequency = loan.loanInterestRecalculationDetails().getRestInterval();
|
||||
CalendarFrequencyType calendarFrequencyType = CalendarFrequencyType.INVALID;
|
||||
switch (recalculationFrequencyType) {
|
||||
case DAILY:
|
||||
frequency = 1;
|
||||
calendarFrequencyType = CalendarFrequencyType.DAILY;
|
||||
break;
|
||||
case FORTNIGHTLY:
|
||||
frequency = 2;
|
||||
calendarFrequencyType = CalendarFrequencyType.WEEKLY;
|
||||
break;
|
||||
case MONTHLY:
|
||||
frequency = 1;
|
||||
calendarFrequencyType = CalendarFrequencyType.MONTHLY;
|
||||
break;
|
||||
case SAME_AS_REPAYMENT_PERIOD:
|
||||
frequency = loan.repaymentScheduleDetail().getRepayEvery();
|
||||
calendarFrequencyType = CalendarFrequencyType.from(loan.repaymentScheduleDetail().getRepaymentPeriodFrequencyType());
|
||||
calendarStartDate = loan.getExpectedDisbursedOnLocalDate();
|
||||
break;
|
||||
case WEEKLY:
|
||||
frequency = 1;
|
||||
calendarFrequencyType = CalendarFrequencyType.WEEKLY;
|
||||
break;
|
||||
default:
|
||||
@@ -313,35 +311,32 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
|
||||
}
|
||||
|
||||
private void updateCalendarDetailsForInterestRecalculation(final CalendarInstance calendarInstance, final Loan loan,
|
||||
final Integer recalculationFrequencyTypeValue) {
|
||||
private void updateCalendarDetailsForInterestRecalculation(final CalendarInstance calendarInstance, final Loan loan) {
|
||||
|
||||
Calendar interestRecalculationRecurrings = calendarInstance.getCalendar();
|
||||
final LocalDate calendarStartDate = loan.getDisbursementDate();
|
||||
LocalDate calendarStartDate = loan.loanInterestRecalculationDetails().getRestFrequencyLocalDate();
|
||||
if (calendarStartDate == null) {
|
||||
calendarStartDate = loan.getExpectedDisbursedOnLocalDate();
|
||||
}
|
||||
final Integer repeatsOnDay = calendarStartDate.getDayOfWeek();
|
||||
final RecalculationFrequencyType recalculationFrequencyType = RecalculationFrequencyType.fromInt(recalculationFrequencyTypeValue);
|
||||
final RecalculationFrequencyType recalculationFrequencyType = loan.loanInterestRecalculationDetails().getRestFrequencyType();
|
||||
|
||||
Integer frequency = 1;
|
||||
Integer frequency = loan.loanInterestRecalculationDetails().getRestInterval();
|
||||
CalendarFrequencyType calendarFrequencyType = CalendarFrequencyType.INVALID;
|
||||
switch (recalculationFrequencyType) {
|
||||
case DAILY:
|
||||
frequency = 1;
|
||||
calendarFrequencyType = CalendarFrequencyType.DAILY;
|
||||
break;
|
||||
case FORTNIGHTLY:
|
||||
frequency = 2;
|
||||
calendarFrequencyType = CalendarFrequencyType.WEEKLY;
|
||||
break;
|
||||
|
||||
case MONTHLY:
|
||||
frequency = 1;
|
||||
calendarFrequencyType = CalendarFrequencyType.MONTHLY;
|
||||
break;
|
||||
case SAME_AS_REPAYMENT_PERIOD:
|
||||
calendarStartDate = loan.getExpectedDisbursedOnLocalDate();
|
||||
frequency = loan.repaymentScheduleDetail().getRepayEvery();
|
||||
calendarFrequencyType = CalendarFrequencyType.from(loan.repaymentScheduleDetail().getRepaymentPeriodFrequencyType());
|
||||
break;
|
||||
case WEEKLY:
|
||||
frequency = 1;
|
||||
calendarFrequencyType = CalendarFrequencyType.WEEKLY;
|
||||
break;
|
||||
default:
|
||||
@@ -616,26 +611,29 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
// updating loan interest recalculation details throwing null
|
||||
// pointer exception after saveAndFlush
|
||||
// http://stackoverflow.com/questions/17151757/hibernate-cascade-update-gives-null-pointer/17334374#17334374
|
||||
existingLoanApplication.updateLoanInterestRecalculationSettings();
|
||||
this.loanRepository.save(existingLoanApplication);
|
||||
|
||||
if (productRelatedDetail.isInterestRecalculationEnabled()) {
|
||||
|
||||
final Integer recalculationFrequencyTypeValue = command
|
||||
.integerValueOfParameterNamed(recalculationFrequencyTypeParameterName);
|
||||
|
||||
this.fromApiJsonDeserializer.validateRecalcuationFrequencyType(recalculationFrequencyTypeValue);
|
||||
LocalDate recalculationFrequencyDate = existingLoanApplication.loanProduct().getProductInterestRecalculationDetails()
|
||||
.getRestFrequencyLocalDate();
|
||||
if (this.fromJsonHelper.parameterExists(LoanProductConstants.recalculationRestFrequencyDateParamName, command.parsedJson())) {
|
||||
recalculationFrequencyDate = this.fromJsonHelper.extractLocalDateNamed(
|
||||
LoanProductConstants.recalculationRestFrequencyDateParamName, command.parsedJson());
|
||||
if (!existingLoanApplication.loanInterestRecalculationDetails().getRestFrequencyType().isSameAsRepayment()) {
|
||||
this.fromApiJsonDeserializer.validateRecalcuationFrequency(recalculationFrequencyDate,
|
||||
existingLoanApplication.getExpectedDisbursedOnLocalDate());
|
||||
}
|
||||
}
|
||||
|
||||
CalendarInstance calendarInstance = this.calendarInstanceRepository.findByEntityIdAndEntityTypeIdAndCalendarTypeId(
|
||||
existingLoanApplication.loanInterestRecalculationDetailId(),
|
||||
CalendarEntityType.LOAN_RECALCULATION_DETAIL.getValue(), CalendarType.COLLECTION.getValue());
|
||||
|
||||
if (calendarInstance == null) {
|
||||
createAndPersistCalendarInstanceForInterestRecalculation(existingLoanApplication, recalculationFrequencyTypeValue);
|
||||
createAndPersistCalendarInstanceForInterestRecalculation(existingLoanApplication);
|
||||
|
||||
} else {
|
||||
updateCalendarDetailsForInterestRecalculation(calendarInstance, existingLoanApplication,
|
||||
recalculationFrequencyTypeValue);
|
||||
updateCalendarDetailsForInterestRecalculation(calendarInstance, existingLoanApplication);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-1
@@ -61,6 +61,7 @@ import org.mifosplatform.portfolio.loanaccount.exception.MultiDisbursementDataRe
|
||||
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
|
||||
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel;
|
||||
import org.mifosplatform.portfolio.loanaccount.loanschedule.service.LoanScheduleAssembler;
|
||||
import org.mifosplatform.portfolio.loanproduct.LoanProductConstants;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanProduct;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRepository;
|
||||
@@ -260,6 +261,8 @@ public class LoanAssembler {
|
||||
loanDisbursementDetails.updateLoan(loanApplication);
|
||||
}
|
||||
}
|
||||
|
||||
final LocalDate recalculationRestFrequencyDate = this.fromApiJsonHelper.extractLocalDateNamed(LoanProductConstants.recalculationRestFrequencyDateParamName, element);
|
||||
|
||||
final LoanApplicationTerms loanApplicationTerms = this.loanScheduleAssembler.assembleLoanTerms(element);
|
||||
final boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled();
|
||||
@@ -271,7 +274,8 @@ public class LoanAssembler {
|
||||
final LoanScheduleModel loanScheduleModel = this.loanScheduleAssembler.assembleLoanScheduleFrom(loanApplicationTerms,
|
||||
isHolidayEnabled, holidays, workingDays, element);
|
||||
loanApplication.loanApplicationSubmittal(currentUser, loanScheduleModel, loanApplicationTerms, defaultLoanLifecycleStateMachine(),
|
||||
submittedOnDate, externalId, allowTransactionsOnHoliday, holidays, workingDays, allowTransactionsOnNonWorkingDay);
|
||||
submittedOnDate, externalId, allowTransactionsOnHoliday, holidays, workingDays, allowTransactionsOnNonWorkingDay,
|
||||
recalculationRestFrequencyDate);
|
||||
|
||||
return loanApplication;
|
||||
}
|
||||
|
||||
+9
-6
@@ -533,7 +533,9 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
+ " l.loan_counter as loanCounter, l.loan_product_counter as loanProductCounter,"
|
||||
+ " l.is_npa as isNPA, l.days_in_month_enum as daysInMonth, l.days_in_year_enum as daysInYear, "
|
||||
+ " 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.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 "
|
||||
+ " 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 "
|
||||
@@ -775,9 +777,13 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
final int rescheduleStrategyEnumValue = JdbcSupport.getInteger(rs, "rescheduleStrategy");
|
||||
final EnumOptionData rescheduleStrategyType = LoanEnumerations.rescheduleStrategyType(rescheduleStrategyEnumValue);
|
||||
final CalendarData calendarData = null;
|
||||
final int restFrequencyEnumValue = JdbcSupport.getInteger(rs, "restFrequencyEnum");
|
||||
final EnumOptionData restFrequencyType = LoanEnumerations.interestRecalculationFrequencyType(restFrequencyEnumValue);
|
||||
final int restFrequencyInterval = JdbcSupport.getInteger(rs, "restFrequencyInterval");
|
||||
final LocalDate restFrequencyDate = JdbcSupport.getLocalDate(rs, "restFrequencyDate");
|
||||
|
||||
interestRecalculationData = new LoanInterestRecalculationData(lprId, productId, interestRecalculationCompoundingType,
|
||||
rescheduleStrategyType, calendarData);
|
||||
rescheduleStrategyType, calendarData, restFrequencyType, restFrequencyInterval, restFrequencyDate);
|
||||
}
|
||||
|
||||
return LoanAccountData.basicLoanDetails(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, groupData,
|
||||
@@ -1220,13 +1226,10 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
}
|
||||
}
|
||||
|
||||
final List<EnumOptionData> interestRecalculationFrequencyTypeOptions = this.loanDropdownReadPlatformService
|
||||
.retrieveInterestRecalculationFrequencyTypeOptions();
|
||||
|
||||
return LoanAccountData.loanProductWithTemplateDefaults(loanProduct, loanTermFrequencyTypeOptions, repaymentFrequencyTypeOptions,
|
||||
repaymentStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions,
|
||||
interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, loanPurposeOptions, loanCollateralOptions,
|
||||
loanCycleCounter, interestRecalculationFrequencyTypeOptions);
|
||||
loanCycleCounter);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
@@ -68,5 +68,8 @@ public interface LoanProductConstants {
|
||||
public static final String daysInMonthTypeParameterName = "daysInMonthType";
|
||||
public static final String interestRecalculationCompoundingMethodParameterName = "interestRecalculationCompoundingMethod";
|
||||
public static final String rescheduleStrategyMethodParameterName = "rescheduleStrategyMethod";
|
||||
public static final String recalculationRestFrequencyTypeParameterName = "recalculationRestFrequencyType";
|
||||
public static final String recalculationRestFrequencyIntervalParameterName = "recalculationRestFrequencyInterval";
|
||||
public static final String recalculationRestFrequencyDateParamName = "recalculationRestFrequencyDate";
|
||||
|
||||
}
|
||||
|
||||
+5
-3
@@ -76,8 +76,8 @@ public class LoanProductsApiResource {
|
||||
"transactionProcessingStrategyOptions", "chargeOptions", "accountingOptions", "accountingRuleOptions",
|
||||
"accountingMappingOptions"));
|
||||
|
||||
private final Set<String> PRODUCT_MIX_DATA_PARAMETERS = new HashSet<>(Arrays.asList("productId", "productName",
|
||||
"restrictedProducts", "allowedProducts", "productOptions"));
|
||||
private final Set<String> PRODUCT_MIX_DATA_PARAMETERS = new HashSet<>(Arrays.asList("productId", "productName", "restrictedProducts",
|
||||
"allowedProducts", "productOptions"));
|
||||
|
||||
private final String resourceNameForPermissions = "LOANPRODUCT";
|
||||
|
||||
@@ -277,12 +277,14 @@ public class LoanProductsApiResource {
|
||||
final List<EnumOptionData> interestRecalculationCompoundingTypeOptions = dropdownReadPlatformService
|
||||
.retrieveInterestRecalculationCompoundingTypeOptions();
|
||||
final List<EnumOptionData> rescheduleStrategyTypeOptions = dropdownReadPlatformService.retrieveRescheduleStrategyTypeOptions();
|
||||
final List<EnumOptionData> interestRecalculationFrequencyTypeOptions = dropdownReadPlatformService
|
||||
.retrieveInterestRecalculationFrequencyTypeOptions();
|
||||
|
||||
return new LoanProductData(productData, chargeOptions, penaltyOptions, paymentTypeOptions, currencyOptions,
|
||||
amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, repaymentFrequencyTypeOptions,
|
||||
interestRateFrequencyTypeOptions, fundOptions, transactionProcessingStrategyOptions, accountOptions,
|
||||
accountingRuleTypeOptions, loanCycleValueConditionTypeOptions, daysInMonthTypeOptions, daysInYearTypeOptions,
|
||||
interestRecalculationCompoundingTypeOptions, rescheduleStrategyTypeOptions);
|
||||
interestRecalculationCompoundingTypeOptions, rescheduleStrategyTypeOptions, interestRecalculationFrequencyTypeOptions);
|
||||
}
|
||||
|
||||
}
|
||||
+28
-2
@@ -32,6 +32,7 @@ import org.mifosplatform.portfolio.loanproduct.domain.AmortizationMethod;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.InterestMethod;
|
||||
import org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Immutable data object to represent loan products.
|
||||
@@ -126,6 +127,8 @@ public class LoanProductData {
|
||||
@SuppressWarnings("unused")
|
||||
private final List<EnumOptionData> rescheduleStrategyTypeOptions;
|
||||
|
||||
private final List<EnumOptionData> interestRecalculationFrequencyTypeOptions;
|
||||
|
||||
private final Boolean multiDisburseLoan;
|
||||
private final Integer maxTrancheCount;
|
||||
private final BigDecimal outstandingLoanBalance;
|
||||
@@ -427,6 +430,7 @@ public class LoanProductData {
|
||||
this.daysInYearTypeOptions = null;
|
||||
this.interestRecalculationCompoundingTypeOptions = null;
|
||||
this.rescheduleStrategyTypeOptions = null;
|
||||
this.interestRecalculationFrequencyTypeOptions = null;
|
||||
}
|
||||
|
||||
public LoanProductData(final LoanProductData productData, final Collection<ChargeData> chargeOptions,
|
||||
@@ -438,7 +442,7 @@ public class LoanProductData {
|
||||
final Map<String, List<GLAccountData>> accountingMappingOptions, final List<EnumOptionData> accountingRuleOptions,
|
||||
final List<EnumOptionData> valueConditionTypeOptions, final List<EnumOptionData> daysInMonthTypeOptions,
|
||||
final List<EnumOptionData> daysInYearTypeOptions, final List<EnumOptionData> interestRecalculationCompoundingTypeOptions,
|
||||
final List<EnumOptionData> rescheduleStrategyTypeOptions) {
|
||||
final List<EnumOptionData> rescheduleStrategyTypeOptions, final List<EnumOptionData> interestRecalculationFrequencyTypeOptions) {
|
||||
this.id = productData.id;
|
||||
this.name = productData.name;
|
||||
this.shortName = productData.shortName;
|
||||
@@ -526,6 +530,12 @@ public class LoanProductData {
|
||||
this.interestRecalculationCompoundingTypeOptions = interestRecalculationCompoundingTypeOptions;
|
||||
this.rescheduleStrategyTypeOptions = rescheduleStrategyTypeOptions;
|
||||
|
||||
if (CollectionUtils.isEmpty(interestRecalculationFrequencyTypeOptions)) {
|
||||
this.interestRecalculationFrequencyTypeOptions = null;
|
||||
} else {
|
||||
this.interestRecalculationFrequencyTypeOptions = interestRecalculationFrequencyTypeOptions;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Collection<ChargeData> nullIfEmpty(final Collection<ChargeData> charges) {
|
||||
@@ -747,7 +757,8 @@ public class LoanProductData {
|
||||
final Long loanId = null;
|
||||
final CalendarData calendarData = null;
|
||||
return new LoanInterestRecalculationData(id, loanId, getInterestRecalculationCompoundingType(), getRescheduleStrategyType(),
|
||||
calendarData);
|
||||
calendarData, getRecalculationRestFrequencyType(), getRecalculationRestFrequencyInterval(),
|
||||
getRecalculationRestFrequencyDate());
|
||||
}
|
||||
|
||||
private EnumOptionData getRescheduleStrategyType() {
|
||||
@@ -759,4 +770,19 @@ public class LoanProductData {
|
||||
if (isInterestRecalculationEnabled()) { return this.interestRecalculationData.getInterestRecalculationCompoundingType(); }
|
||||
return null;
|
||||
}
|
||||
|
||||
private LocalDate getRecalculationRestFrequencyDate() {
|
||||
if (isInterestRecalculationEnabled()) { return this.interestRecalculationData.getRecalculationRestFrequencyDate(); }
|
||||
return null;
|
||||
}
|
||||
|
||||
public EnumOptionData getRecalculationRestFrequencyType() {
|
||||
if (isInterestRecalculationEnabled()) { return this.interestRecalculationData.getRecalculationRestFrequencyType(); }
|
||||
return null;
|
||||
}
|
||||
|
||||
public Integer getRecalculationRestFrequencyInterval() {
|
||||
if (isInterestRecalculationEnabled()) { return this.interestRecalculationData.getRecalculationRestFrequencyInterval(); }
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+27
-2
@@ -8,6 +8,7 @@ package org.mifosplatform.portfolio.loanproduct.data;
|
||||
import static org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations.interestRecalculationCompoundingType;
|
||||
import static org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations.rescheduleStrategyType;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.InterestRecalculationCompoundingMethod;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanRescheduleStrategyMethod;
|
||||
@@ -20,13 +21,21 @@ public class LoanProductInterestRecalculationData {
|
||||
private final Long productId;
|
||||
private final EnumOptionData interestRecalculationCompoundingType;
|
||||
private final EnumOptionData rescheduleStrategyType;
|
||||
private final EnumOptionData recalculationRestFrequencyType;
|
||||
private final Integer recalculationRestFrequencyInterval;
|
||||
private final LocalDate recalculationRestFrequencyDate;
|
||||
|
||||
public LoanProductInterestRecalculationData(final Long id, final Long productId,
|
||||
final EnumOptionData interestRecalculationCompoundingType, final EnumOptionData rescheduleStrategyType) {
|
||||
final EnumOptionData interestRecalculationCompoundingType, final EnumOptionData rescheduleStrategyType,
|
||||
final EnumOptionData recalculationRestFrequencyType, final Integer recalculationRestFrequencyInterval,
|
||||
final LocalDate recalculationRestFrequencyDate) {
|
||||
this.id = id;
|
||||
this.productId = productId;
|
||||
this.interestRecalculationCompoundingType = interestRecalculationCompoundingType;
|
||||
this.rescheduleStrategyType = rescheduleStrategyType;
|
||||
this.recalculationRestFrequencyType = recalculationRestFrequencyType;
|
||||
this.recalculationRestFrequencyInterval = recalculationRestFrequencyInterval;
|
||||
this.recalculationRestFrequencyDate = recalculationRestFrequencyDate;
|
||||
}
|
||||
|
||||
public static LoanProductInterestRecalculationData sensibleDefaultsForNewLoanProductCreation() {
|
||||
@@ -34,7 +43,11 @@ public class LoanProductInterestRecalculationData {
|
||||
final Long productId = null;
|
||||
final EnumOptionData interestRecalculationCompoundingType = interestRecalculationCompoundingType(InterestRecalculationCompoundingMethod.NONE);
|
||||
final EnumOptionData rescheduleStrategyType = rescheduleStrategyType(LoanRescheduleStrategyMethod.REDUCE_EMI_AMOUNT);
|
||||
return new LoanProductInterestRecalculationData(id, productId, interestRecalculationCompoundingType, rescheduleStrategyType);
|
||||
final EnumOptionData recalculationRestFrequencyType = null;
|
||||
final Integer recalculationRestFrequencyInterval = null;
|
||||
final LocalDate recalculationRestFrequencyDate = null;
|
||||
return new LoanProductInterestRecalculationData(id, productId, interestRecalculationCompoundingType, rescheduleStrategyType,
|
||||
recalculationRestFrequencyType, recalculationRestFrequencyInterval, recalculationRestFrequencyDate);
|
||||
}
|
||||
|
||||
public EnumOptionData getInterestRecalculationCompoundingType() {
|
||||
@@ -45,4 +58,16 @@ public class LoanProductInterestRecalculationData {
|
||||
return this.rescheduleStrategyType;
|
||||
}
|
||||
|
||||
public LocalDate getRecalculationRestFrequencyDate() {
|
||||
return this.recalculationRestFrequencyDate;
|
||||
}
|
||||
|
||||
public EnumOptionData getRecalculationRestFrequencyType() {
|
||||
return this.recalculationRestFrequencyType;
|
||||
}
|
||||
|
||||
public Integer getRecalculationRestFrequencyInterval() {
|
||||
return this.recalculationRestFrequencyInterval;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-17
@@ -43,7 +43,6 @@ import org.mifosplatform.portfolio.common.domain.DaysInMonthType;
|
||||
import org.mifosplatform.portfolio.common.domain.DaysInYearType;
|
||||
import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.mifosplatform.portfolio.fund.domain.Fund;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.LoanInterestRecalculationDetails;
|
||||
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.AprCalculator;
|
||||
import org.mifosplatform.portfolio.loanproduct.LoanProductConstants;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
@@ -906,21 +905,7 @@ public class LoanProduct extends AbstractPersistable<Long> {
|
||||
return this.loanProductRelatedDetail.fetchDaysInYearType();
|
||||
}
|
||||
|
||||
public LoanInterestRecalculationDetails copyInterestRecalculationSettings() {
|
||||
LoanInterestRecalculationDetails loanInterestRecalculationDetails = null;
|
||||
if (this.isInterestRecalculationEnabled()) {
|
||||
loanInterestRecalculationDetails = LoanInterestRecalculationDetails.createFrom(
|
||||
this.productInterestRecalculationDetails.getInterestRecalculationCompoundingMethod(),
|
||||
this.productInterestRecalculationDetails.getRescheduleStrategyMethod());
|
||||
}
|
||||
return loanInterestRecalculationDetails;
|
||||
}
|
||||
|
||||
public LoanInterestRecalculationDetails updateLoanInterestRecalculationDetails(
|
||||
LoanInterestRecalculationDetails loanInterestRecalculationDetails) {
|
||||
|
||||
loanInterestRecalculationDetails.update(this.productInterestRecalculationDetails.getInterestRecalculationCompoundingMethod(),
|
||||
this.productInterestRecalculationDetails.getRescheduleStrategyMethod());
|
||||
return loanInterestRecalculationDetails;
|
||||
public LoanProductInterestRecalculationDetails getProductInterestRecalculationDetails() {
|
||||
return this.productInterestRecalculationDetails;
|
||||
}
|
||||
}
|
||||
+93
-2
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
package org.mifosplatform.portfolio.loanproduct.domain;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.Column;
|
||||
@@ -12,7 +13,10 @@ import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.portfolio.loanproduct.LoanProductConstants;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
@@ -27,6 +31,7 @@ import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
@Table(name = "m_product_loan_recalculation_details")
|
||||
public class LoanProductInterestRecalculationDetails extends AbstractPersistable<Long> {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@OneToOne
|
||||
@JoinColumn(name = "product_id", nullable = false)
|
||||
private LoanProduct loanProduct;
|
||||
@@ -43,6 +48,16 @@ public class LoanProductInterestRecalculationDetails extends AbstractPersistable
|
||||
@Column(name = "reschedule_strategy_enum", nullable = false)
|
||||
private Integer rescheduleStrategyMethod;
|
||||
|
||||
@Column(name = "rest_frequency_type_enum", nullable = false)
|
||||
private Integer restFrequencyType;
|
||||
|
||||
@Column(name = "rest_frequency_interval", nullable = false)
|
||||
private Integer restInterval;
|
||||
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "rest_freqency_date")
|
||||
private Date restFrequencyDate;
|
||||
|
||||
protected LoanProductInterestRecalculationDetails() {
|
||||
//
|
||||
}
|
||||
@@ -55,13 +70,34 @@ public class LoanProductInterestRecalculationDetails extends AbstractPersistable
|
||||
final Integer loanRescheduleStrategyMethod = LoanRescheduleStrategyMethod.fromInt(
|
||||
command.integerValueOfParameterNamed(LoanProductConstants.rescheduleStrategyMethodParameterName)).getValue();
|
||||
|
||||
return new LoanProductInterestRecalculationDetails(interestRecalculationCompoundingMethod, loanRescheduleStrategyMethod);
|
||||
final Integer recurrenceFrequency = command
|
||||
.integerValueOfParameterNamed(LoanProductConstants.recalculationRestFrequencyTypeParameterName);
|
||||
final LocalDate recurrenceOnLocalDate = command
|
||||
.localDateValueOfParameterNamed(LoanProductConstants.recalculationRestFrequencyDateParamName);
|
||||
Integer recurrenceInterval = command
|
||||
.integerValueOfParameterNamed(LoanProductConstants.recalculationRestFrequencyIntervalParameterName);
|
||||
RecalculationFrequencyType frequencyType = RecalculationFrequencyType.fromInt(recurrenceFrequency);
|
||||
Date recurrenceOnDate = null;
|
||||
if (recurrenceOnLocalDate != null) {
|
||||
if (frequencyType.isSameAsRepayment()) {
|
||||
recurrenceInterval = 0;
|
||||
} else {
|
||||
recurrenceOnDate = recurrenceOnLocalDate.toDate();
|
||||
}
|
||||
}
|
||||
|
||||
return new LoanProductInterestRecalculationDetails(interestRecalculationCompoundingMethod, loanRescheduleStrategyMethod,
|
||||
recurrenceFrequency, recurrenceInterval, recurrenceOnDate);
|
||||
}
|
||||
|
||||
private LoanProductInterestRecalculationDetails(final Integer interestRecalculationCompoundingMethod,
|
||||
final Integer rescheduleStrategyMethod) {
|
||||
final Integer rescheduleStrategyMethod, final Integer restFrequencyType, final Integer restInterval,
|
||||
final Date restFrequencyDate) {
|
||||
this.interestRecalculationCompoundingMethod = interestRecalculationCompoundingMethod;
|
||||
this.rescheduleStrategyMethod = rescheduleStrategyMethod;
|
||||
this.restFrequencyType = restFrequencyType;
|
||||
this.restInterval = restInterval;
|
||||
this.restFrequencyDate = restFrequencyDate;
|
||||
}
|
||||
|
||||
public void updateProduct(final LoanProduct loanProduct) {
|
||||
@@ -94,5 +130,60 @@ public class LoanProductInterestRecalculationDetails extends AbstractPersistable
|
||||
actualChanges.put("locale", localeAsInput);
|
||||
this.rescheduleStrategyMethod = LoanRescheduleStrategyMethod.fromInt(newValue).getValue();
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(LoanProductConstants.recalculationRestFrequencyTypeParameterName,
|
||||
this.restFrequencyType)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(LoanProductConstants.recalculationRestFrequencyTypeParameterName);
|
||||
actualChanges.put(LoanProductConstants.recalculationRestFrequencyTypeParameterName, newValue);
|
||||
actualChanges.put("locale", localeAsInput);
|
||||
this.restFrequencyType = RecalculationFrequencyType.fromInt(newValue).getValue();
|
||||
}
|
||||
RecalculationFrequencyType frequencyType = RecalculationFrequencyType.fromInt(this.restFrequencyType);
|
||||
if (frequencyType.isSameAsRepayment()) {
|
||||
this.restInterval = 0;
|
||||
this.restFrequencyDate = null;
|
||||
} else {
|
||||
if (command.isChangeInIntegerParameterNamed(LoanProductConstants.recalculationRestFrequencyIntervalParameterName,
|
||||
this.restInterval)) {
|
||||
Integer newValue = command
|
||||
.integerValueOfParameterNamed(LoanProductConstants.recalculationRestFrequencyIntervalParameterName);
|
||||
if (frequencyType.isSameAsRepayment()) {
|
||||
newValue = 0;
|
||||
}
|
||||
actualChanges.put(LoanProductConstants.recalculationRestFrequencyIntervalParameterName, newValue);
|
||||
actualChanges.put("locale", localeAsInput);
|
||||
this.restInterval = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInLocalDateParameterNamed(LoanProductConstants.recalculationRestFrequencyDateParamName,
|
||||
getRestFrequencyLocalDate())) {
|
||||
final LocalDate newValue = command
|
||||
.localDateValueOfParameterNamed(LoanProductConstants.recalculationRestFrequencyDateParamName);
|
||||
Date recurrenceOnDate = null;
|
||||
if (newValue != null) {
|
||||
if (!frequencyType.isSameAsRepayment()) {
|
||||
recurrenceOnDate = newValue.toDate();
|
||||
}
|
||||
}
|
||||
actualChanges.put(LoanProductConstants.recalculationRestFrequencyDateParamName, newValue);
|
||||
this.restFrequencyDate = recurrenceOnDate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public LocalDate getRestFrequencyLocalDate() {
|
||||
LocalDate recurrenceOnLocalDate = null;
|
||||
if (this.restFrequencyDate != null) {
|
||||
recurrenceOnLocalDate = new LocalDate(this.restFrequencyDate);
|
||||
}
|
||||
return recurrenceOnLocalDate;
|
||||
}
|
||||
|
||||
public RecalculationFrequencyType getRestFrequencyType() {
|
||||
return RecalculationFrequencyType.fromInt(this.restFrequencyType);
|
||||
}
|
||||
|
||||
public Integer getRestInterval() {
|
||||
return this.restInterval;
|
||||
}
|
||||
}
|
||||
|
||||
+19
-2
@@ -8,13 +8,14 @@ package org.mifosplatform.portfolio.loanproduct.domain;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType;
|
||||
|
||||
public enum RecalculationFrequencyType {
|
||||
INVALID(0, "interestRecalculationFrequencyType.invalid"), //
|
||||
SAME_AS_REPAYMENT_PERIOD(1, "interestRecalculationFrequencyType.same.as.repayment.period"), //
|
||||
DAILY(2, "interestRecalculationFrequencyType.daily"), //
|
||||
WEEKLY(3, "interestRecalculationFrequencyType.weekly"), //
|
||||
FORTNIGHTLY(4, "interestRecalculationFrequencyType.fortnightly"), //
|
||||
MONTHLY(5, "interestRecalculationFrequencyType.monthly");
|
||||
MONTHLY(4, "interestRecalculationFrequencyType.monthly");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
@@ -44,4 +45,20 @@ public enum RecalculationFrequencyType {
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public boolean isSameAsRepayment() {
|
||||
return this.value.equals(RecalculationFrequencyType.SAME_AS_REPAYMENT_PERIOD.getValue());
|
||||
}
|
||||
|
||||
public boolean isDaily() {
|
||||
return this.value.equals(RecalculationFrequencyType.DAILY.getValue());
|
||||
}
|
||||
|
||||
public boolean isWeekly() {
|
||||
return this.value.equals(RecalculationFrequencyType.WEEKLY.getValue());
|
||||
}
|
||||
|
||||
public boolean isMonthly() {
|
||||
return this.value.equals(RecalculationFrequencyType.MONTHLY.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
+74
-24
@@ -16,6 +16,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.accounting.common.AccountingConstants.LOAN_PRODUCT_ACCOUNTING_PARAMS;
|
||||
import org.mifosplatform.accounting.common.AccountingRuleType;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
@@ -27,6 +28,7 @@ import org.mifosplatform.portfolio.loanproduct.LoanProductConstants;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.InterestMethod;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanProduct;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductValueConditionType;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.RecalculationFrequencyType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -41,8 +43,8 @@ public final class LoanProductDataValidator {
|
||||
/**
|
||||
* The parameters supported for this command.
|
||||
*/
|
||||
private final Set<String> supportedParameters = new HashSet<>(Arrays.asList("locale", "dateFormat", "name", "description",
|
||||
"fundId", "currencyCode", "digitsAfterDecimal", "inMultiplesOf", "principal", "minPrincipal", "maxPrincipal", "repaymentEvery",
|
||||
private final Set<String> supportedParameters = new HashSet<>(Arrays.asList("locale", "dateFormat", "name", "description", "fundId",
|
||||
"currencyCode", "digitsAfterDecimal", "inMultiplesOf", "principal", "minPrincipal", "maxPrincipal", "repaymentEvery",
|
||||
"numberOfRepayments", "minNumberOfRepayments", "maxNumberOfRepayments", "repaymentFrequencyType", "interestRatePerPeriod",
|
||||
"minInterestRatePerPeriod", "maxInterestRatePerPeriod", "interestRateFrequencyType", "amortizationType", "interestType",
|
||||
"interestCalculationPeriodType", "inArrearsTolerance", "transactionProcessingStrategyId", "graceOnPrincipalPayment",
|
||||
@@ -54,7 +56,8 @@ public final class LoanProductDataValidator {
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.OVERPAYMENT.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.TRANSFERS_SUSPENSE.getValue(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.PENALTIES_RECEIVABLE.getValue(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.PAYMENT_CHANNEL_FUND_SOURCE_MAPPING.getValue(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.FEE_INCOME_ACCOUNT_MAPPING.getValue(),LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_RECOVERY.getValue(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.FEE_INCOME_ACCOUNT_MAPPING.getValue(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_RECOVERY.getValue(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.PENALTY_INCOME_ACCOUNT_MAPPING.getValue(), LoanProductConstants.useBorrowerCycleParameterName,
|
||||
LoanProductConstants.principalVariationsForBorrowerCycleParameterName,
|
||||
LoanProductConstants.interestRateVariationsForBorrowerCycleParameterName,
|
||||
@@ -64,7 +67,10 @@ public final class LoanProductDataValidator {
|
||||
LoanProductConstants.overdueDaysForNPAParameterName, LoanProductConstants.isInterestRecalculationEnabledParameterName,
|
||||
LoanProductConstants.daysInYearTypeParameterName, LoanProductConstants.daysInMonthTypeParameterName,
|
||||
LoanProductConstants.rescheduleStrategyMethodParameterName,
|
||||
LoanProductConstants.interestRecalculationCompoundingMethodParameterName));
|
||||
LoanProductConstants.interestRecalculationCompoundingMethodParameterName,
|
||||
LoanProductConstants.recalculationRestFrequencyDateParamName,
|
||||
LoanProductConstants.recalculationRestFrequencyIntervalParameterName,
|
||||
LoanProductConstants.recalculationRestFrequencyTypeParameterName));
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
@@ -129,18 +135,18 @@ public final class LoanProductDataValidator {
|
||||
baseDataValidator.reset().parameter(maxPrincipalParameterName).value(maxPrincipalAmount).ignoreIfNull().positiveAmount();
|
||||
}
|
||||
|
||||
if (maxPrincipalAmount != null && maxPrincipalAmount.compareTo(BigDecimal.ZERO) != -1 ) {
|
||||
if (maxPrincipalAmount != null && maxPrincipalAmount.compareTo(BigDecimal.ZERO) != -1) {
|
||||
|
||||
if (minPrincipalAmount != null && minPrincipalAmount.compareTo(BigDecimal.ZERO) != -1) {
|
||||
baseDataValidator.reset().parameter(maxPrincipalParameterName).value(maxPrincipalAmount).notLessThanMin(minPrincipalAmount);
|
||||
if (minPrincipalAmount.compareTo(maxPrincipalAmount) <= 0 && principal != null ) {
|
||||
if (minPrincipalAmount.compareTo(maxPrincipalAmount) <= 0 && principal != null) {
|
||||
baseDataValidator.reset().parameter("principal").value(principal)
|
||||
.inMinAndMaxAmountRange(minPrincipalAmount, maxPrincipalAmount);
|
||||
}
|
||||
} else if(principal != null) {
|
||||
} else if (principal != null) {
|
||||
baseDataValidator.reset().parameter("principal").value(principal).notGreaterThanMax(maxPrincipalAmount);
|
||||
}
|
||||
} else if (minPrincipalAmount != null && minPrincipalAmount.compareTo(BigDecimal.ZERO) != -1 && principal !=null) {
|
||||
} else if (minPrincipalAmount != null && minPrincipalAmount.compareTo(BigDecimal.ZERO) != -1 && principal != null) {
|
||||
baseDataValidator.reset().parameter("principal").value(principal).notLessThanMin(minPrincipalAmount);
|
||||
}
|
||||
|
||||
@@ -291,7 +297,7 @@ public final class LoanProductDataValidator {
|
||||
|
||||
if (isInterestRecalculationEnabled != null) {
|
||||
if (isInterestRecalculationEnabled.booleanValue()) {
|
||||
validateInterestRecalculationParams(element, baseDataValidator);
|
||||
validateInterestRecalculationParams(element, baseDataValidator, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,8 +339,8 @@ public final class LoanProductDataValidator {
|
||||
|
||||
final Long incomeFromRecoveryAccountId = this.fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_RECOVERY.getValue(), element);
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_RECOVERY.getValue()).value(incomeFromRecoveryAccountId)
|
||||
.notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_RECOVERY.getValue())
|
||||
.value(incomeFromRecoveryAccountId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long writeOffAccountId = this.fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(), element);
|
||||
@@ -411,23 +417,67 @@ public final class LoanProductDataValidator {
|
||||
}
|
||||
}
|
||||
|
||||
private void validateInterestRecalculationParams(final JsonElement element, final DataValidatorBuilder baseDataValidator) {
|
||||
private void validateInterestRecalculationParams(final JsonElement element, final DataValidatorBuilder baseDataValidator,
|
||||
final LoanProduct loanProduct) {
|
||||
|
||||
/**
|
||||
* { @link InterestRecalculationCompoundingMethod }
|
||||
*/
|
||||
final Integer interestRecalculationCompoundingMethod = this.fromApiJsonHelper.extractIntegerNamed(
|
||||
LoanProductConstants.interestRecalculationCompoundingMethodParameterName, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(LoanProductConstants.interestRecalculationCompoundingMethodParameterName)
|
||||
.value(interestRecalculationCompoundingMethod).notNull().inMinMaxRange(0, 3);
|
||||
|
||||
if (loanProduct == null
|
||||
|| this.fromApiJsonHelper
|
||||
.parameterExists(LoanProductConstants.interestRecalculationCompoundingMethodParameterName, element)) {
|
||||
final Integer interestRecalculationCompoundingMethod = this.fromApiJsonHelper.extractIntegerNamed(
|
||||
LoanProductConstants.interestRecalculationCompoundingMethodParameterName, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(LoanProductConstants.interestRecalculationCompoundingMethodParameterName)
|
||||
.value(interestRecalculationCompoundingMethod).notNull().inMinMaxRange(0, 3);
|
||||
}
|
||||
/**
|
||||
* { @link LoanRescheduleStrategyMethod }
|
||||
*/
|
||||
final Integer rescheduleStrategyMethod = this.fromApiJsonHelper.extractIntegerNamed(
|
||||
LoanProductConstants.rescheduleStrategyMethodParameterName, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(LoanProductConstants.rescheduleStrategyMethodParameterName).value(rescheduleStrategyMethod)
|
||||
.notNull().inMinMaxRange(1, 3);
|
||||
if (loanProduct == null
|
||||
|| this.fromApiJsonHelper.parameterExists(LoanProductConstants.rescheduleStrategyMethodParameterName, element)) {
|
||||
final Integer rescheduleStrategyMethod = this.fromApiJsonHelper.extractIntegerNamed(
|
||||
LoanProductConstants.rescheduleStrategyMethodParameterName, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(LoanProductConstants.rescheduleStrategyMethodParameterName).value(rescheduleStrategyMethod)
|
||||
.notNull().inMinMaxRange(1, 3);
|
||||
}
|
||||
|
||||
RecalculationFrequencyType frequencyType = null;
|
||||
|
||||
if (loanProduct == null
|
||||
|| this.fromApiJsonHelper.parameterExists(LoanProductConstants.recalculationRestFrequencyTypeParameterName, element)) {
|
||||
final Integer recalculationRestFrequencyType = this.fromApiJsonHelper.extractIntegerNamed(
|
||||
LoanProductConstants.recalculationRestFrequencyTypeParameterName, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(LoanProductConstants.recalculationRestFrequencyTypeParameterName)
|
||||
.value(recalculationRestFrequencyType).notNull().inMinMaxRange(1, 4);
|
||||
frequencyType = RecalculationFrequencyType.fromInt(recalculationRestFrequencyType);
|
||||
}
|
||||
|
||||
if (frequencyType == null) {
|
||||
if (loanProduct == null) {
|
||||
frequencyType = RecalculationFrequencyType.INVALID;
|
||||
} else {
|
||||
frequencyType = loanProduct.getProductInterestRecalculationDetails().getRestFrequencyType();
|
||||
}
|
||||
}
|
||||
|
||||
if (!frequencyType.isSameAsRepayment()) {
|
||||
if (loanProduct == null
|
||||
|| this.fromApiJsonHelper.parameterExists(LoanProductConstants.recalculationRestFrequencyDateParamName, element)) {
|
||||
final LocalDate recurrenceOnLocalDate = this.fromApiJsonHelper.extractLocalDateNamed(
|
||||
LoanProductConstants.recalculationRestFrequencyDateParamName, element);
|
||||
baseDataValidator.reset().parameter(LoanProductConstants.recalculationRestFrequencyDateParamName)
|
||||
.value(recurrenceOnLocalDate).notNull();
|
||||
}
|
||||
if (loanProduct == null
|
||||
|| this.fromApiJsonHelper
|
||||
.parameterExists(LoanProductConstants.recalculationRestFrequencyIntervalParameterName, element)) {
|
||||
final Integer recurrenceInterval = this.fromApiJsonHelper.extractIntegerNamed(
|
||||
LoanProductConstants.recalculationRestFrequencyIntervalParameterName, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(LoanProductConstants.recalculationRestFrequencyIntervalParameterName)
|
||||
.value(recurrenceInterval).notNull();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -654,7 +704,7 @@ public final class LoanProductDataValidator {
|
||||
|
||||
if (isInterestRecalculationEnabled != null) {
|
||||
if (isInterestRecalculationEnabled.booleanValue()) {
|
||||
validateInterestRecalculationParams(element, baseDataValidator);
|
||||
validateInterestRecalculationParams(element, baseDataValidator, loanProduct);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -693,8 +743,8 @@ public final class LoanProductDataValidator {
|
||||
|
||||
final Long incomeFromRecoveryAccountId = this.fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_RECOVERY.getValue(), element);
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_RECOVERY.getValue()).value(incomeFromRecoveryAccountId)
|
||||
.ignoreIfNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter(LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_RECOVERY.getValue())
|
||||
.value(incomeFromRecoveryAccountId).ignoreIfNull().integerGreaterThanZero();
|
||||
|
||||
final Long writeOffAccountId = this.fromApiJsonHelper.extractLongNamed(
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(), element);
|
||||
|
||||
+1
-2
@@ -141,12 +141,11 @@ public class LoanDropdownReadPlatformServiceImpl implements LoanDropdownReadPlat
|
||||
|
||||
@Override
|
||||
public List<EnumOptionData> retrieveInterestRecalculationFrequencyTypeOptions() {
|
||||
|
||||
|
||||
final List<EnumOptionData> interestRecalculationFrequencyTypeOptions = Arrays.asList(
|
||||
interestRecalculationFrequencyType(RecalculationFrequencyType.SAME_AS_REPAYMENT_PERIOD),
|
||||
interestRecalculationFrequencyType(RecalculationFrequencyType.DAILY),
|
||||
interestRecalculationFrequencyType(RecalculationFrequencyType.WEEKLY),
|
||||
interestRecalculationFrequencyType(RecalculationFrequencyType.FORTNIGHTLY),
|
||||
interestRecalculationFrequencyType(RecalculationFrequencyType.MONTHLY));
|
||||
return interestRecalculationFrequencyTypeOptions;
|
||||
}
|
||||
|
||||
-4
@@ -526,10 +526,6 @@ public class LoanEnumerations {
|
||||
optionData = new EnumOptionData(RecalculationFrequencyType.DAILY.getValue().longValue(),
|
||||
RecalculationFrequencyType.DAILY.getCode(), "Daily");
|
||||
break;
|
||||
case FORTNIGHTLY:
|
||||
optionData = new EnumOptionData(RecalculationFrequencyType.FORTNIGHTLY.getValue().longValue(),
|
||||
RecalculationFrequencyType.FORTNIGHTLY.getCode(), "Fortnightly");
|
||||
break;
|
||||
case MONTHLY:
|
||||
optionData = new EnumOptionData(RecalculationFrequencyType.MONTHLY.getValue().longValue(),
|
||||
RecalculationFrequencyType.MONTHLY.getCode(), "Monthly");
|
||||
|
||||
+8
-1
@@ -125,6 +125,8 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
||||
+ "lp.allow_multiple_disbursals as multiDisburseLoan, lp.max_disbursals as maxTrancheCount, lp.max_outstanding_loan_balance as outstandingLoanBalance, "
|
||||
+ "lp.days_in_month_enum as daysInMonth, lp.days_in_year_enum as daysInYear, lp.interest_recalculation_enabled as isInterestRecalculationEnabled, "
|
||||
+ "lpr.id as lprId, lpr.product_id as productId, lpr.compound_type_enum as compoundType, lpr.reschedule_strategy_enum as rescheduleStrategy, "
|
||||
+ "lpr.rest_frequency_type_enum as restFrequencyEnum, lpr.rest_frequency_interval as restFrequencyInterval, "
|
||||
+ "lpr.rest_freqency_date as restFrequencyDate, "
|
||||
+ "curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, curr.display_symbol as currencyDisplaySymbol, lp.external_id as externalId "
|
||||
+ " from m_product_loan lp "
|
||||
+ " left join m_fund f on f.id = lp.fund_id "
|
||||
@@ -242,9 +244,14 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
||||
.interestRecalculationCompoundingType(compoundTypeEnumValue);
|
||||
final int rescheduleStrategyEnumValue = JdbcSupport.getInteger(rs, "rescheduleStrategy");
|
||||
final EnumOptionData rescheduleStrategyType = LoanEnumerations.rescheduleStrategyType(rescheduleStrategyEnumValue);
|
||||
final int restFrequencyEnumValue = JdbcSupport.getInteger(rs, "restFrequencyEnum");
|
||||
final EnumOptionData restFrequencyType = LoanEnumerations.interestRecalculationFrequencyType(restFrequencyEnumValue);
|
||||
final int restFrequencyInterval = JdbcSupport.getInteger(rs, "restFrequencyInterval");
|
||||
final LocalDate restFrequencyDate = JdbcSupport.getLocalDate(rs, "restFrequencyDate");
|
||||
|
||||
interestRecalculationData = new LoanProductInterestRecalculationData(lprId, productId,
|
||||
interestRecalculationCompoundingType, rescheduleStrategyType);
|
||||
interestRecalculationCompoundingType, rescheduleStrategyType, restFrequencyType, restFrequencyInterval,
|
||||
restFrequencyDate);
|
||||
}
|
||||
|
||||
return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
|
||||
|
||||
Reference in New Issue
Block a user