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