cleaning up MIFOSX-1584

This commit is contained in:
Vishwas Babu A J
2014-11-05 23:58:03 +05:30
parent a8c733100b
commit f1e9c2800b
7 changed files with 115 additions and 104 deletions
@@ -0,0 +1,26 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.loanaccount.exception;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
/**
* {@link AbstractPlatformDomainRuleException} thrown when a number of days
* between disbursal date and firstRepayment is less than
* minimumDaysBetweenDisbursalAndFirstRepayment
*
*/
public class MinDaysBetweenDisbursalAndFirstRepaymentViolationException extends AbstractPlatformDomainRuleException {
public MinDaysBetweenDisbursalAndFirstRepaymentViolationException(final LocalDate disbursalDate, final LocalDate firstRepaymentDate,
Integer minimumDaysBetweenDisbursalAndFirstRepayment) {
super("error.msg.loan.days.between.first.repayment.and.disbursal.are.less.than.minimum.allowed.numbers",
"Number of days between loan disbursal (" + disbursalDate + ") and first repayment (" + firstRepaymentDate
+ ") can't be less than (" + minimumDaysBetweenDisbursalAndFirstRepayment + ").", disbursalDate,
firstRepaymentDate, minimumDaysBetweenDisbursalAndFirstRepayment);
}
}
@@ -1,22 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.loanaccount.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
/**
* {@link AbstractPlatformDomainRuleException} thrown when a number of days between disbursal date and firstRepayment is less than
* minimumDaysBetweenDisbursalAndFirstRepayment
*
*/
public class MinimumDaysBetweenDisbursalAndFirstRepaymentRuleException extends AbstractPlatformDomainRuleException {
public MinimumDaysBetweenDisbursalAndFirstRepaymentRuleException(final String defaultUserMessage,
final Object... defaultUserMessageArgs) {
super("validation.msg.loan.days.between.first.repayment.and.disbursal.are.less than.minimum.number.of.days.required",
defaultUserMessage, defaultUserMessageArgs);
}
}
@@ -51,7 +51,7 @@ import org.mifosplatform.portfolio.loanaccount.domain.LoanTermVariationType;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction; import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
import org.mifosplatform.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor; import org.mifosplatform.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
import org.mifosplatform.portfolio.loanaccount.exception.LoanApplicationDateException; import org.mifosplatform.portfolio.loanaccount.exception.LoanApplicationDateException;
import org.mifosplatform.portfolio.loanaccount.exception.MinimumDaysBetweenDisbursalAndFirstRepaymentRuleException; import org.mifosplatform.portfolio.loanaccount.exception.MinDaysBetweenDisbursalAndFirstRepaymentViolationException;
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.AprCalculator; import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.AprCalculator;
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms; import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanScheduleGenerator; import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanScheduleGenerator;
@@ -171,7 +171,6 @@ public class LoanScheduleAssembler {
final AccountType loanType = AccountType.fromName(loanTypeStr); final AccountType loanType = AccountType.fromName(loanTypeStr);
/* /*
* If it is JLG loan then make sure loan frequency is same as * If it is JLG loan then make sure loan frequency is same as
* Group/Center meeting frequency or multiple of it. TODO: Check should * Group/Center meeting frequency or multiple of it. TODO: Check should
@@ -239,13 +238,13 @@ public class LoanScheduleAssembler {
* input then copy the value of repaymentsStartingFromDate to * input then copy the value of repaymentsStartingFromDate to
* calculatedRepaymentsStartingFromDate * calculatedRepaymentsStartingFromDate
* *
* TODO: The reason for this bad code is, LoanApplicationTerms.assembleFrom * TODO: The reason for this bad code is,
* takes both repaymentsStartingFromDate and calculatedRepaymentsStartingFromDate * LoanApplicationTerms.assembleFrom takes both
* repaymentsStartingFromDate and calculatedRepaymentsStartingFromDate
* and derived data has precedence over input date, * and derived data has precedence over input date,
* *
* FIXME:LoanApplicationTerms.assembleFrom should take only one * FIXME:LoanApplicationTerms.assembleFrom should take only one
* "first repayment date" than taking two dates with same purpose. * "first repayment date" than taking two dates with same purpose.
*
*/ */
if (!isRepaymentsStartingFromDateDerived) { if (!isRepaymentsStartingFromDateDerived) {
calculatedRepaymentsStartingFromDate = repaymentsStartingFromDate; calculatedRepaymentsStartingFromDate = repaymentsStartingFromDate;
@@ -470,63 +469,59 @@ public class LoanScheduleAssembler {
private LocalDate deriveFirstRepaymentDate(final AccountType loanType, final Integer repaymentEvery, private LocalDate deriveFirstRepaymentDate(final AccountType loanType, final Integer repaymentEvery,
final LocalDate expectedDisbursementDate, final PeriodFrequencyType repaymentPeriodFrequencyType, final LocalDate expectedDisbursementDate, final PeriodFrequencyType repaymentPeriodFrequencyType,
final Integer minimumDaysBetweenDisbursalAndFirstRepayment, final Calendar calendar){ final Integer minimumDaysBetweenDisbursalAndFirstRepayment, final Calendar calendar) {
LocalDate derivedFirstRepayment = null; LocalDate derivedFirstRepayment = null;
LocalDate dateBasedOnRepaymentFrequency = null; LocalDate dateBasedOnRepaymentFrequency;
final LocalDate dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment = expectedDisbursementDate.plusDays(minimumDaysBetweenDisbursalAndFirstRepayment); final LocalDate dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment = expectedDisbursementDate
.plusDays(minimumDaysBetweenDisbursalAndFirstRepayment);
if (loanType.isIndividualAccount() || loanType.isGroupAccount()) { if (loanType.isIndividualAccount() || loanType.isGroupAccount()) {
// Derive the first repayment date as greater date among (disbursement date + plus frequency) or // Derive the first repayment date as greater date among
// (disbursement date + minimum between disbursal and first repayment ) // (disbursement date + plus frequency) or
// (disbursement date + minimum between disbursal and first
// repayment )
if (repaymentPeriodFrequencyType.isDaily()) { if (repaymentPeriodFrequencyType.isDaily()) {
dateBasedOnRepaymentFrequency = expectedDisbursementDate.plusDays(repaymentEvery); dateBasedOnRepaymentFrequency = expectedDisbursementDate.plusDays(repaymentEvery);
} } else if (repaymentPeriodFrequencyType.isWeekly()) {
else if(repaymentPeriodFrequencyType.isWeekly()){
dateBasedOnRepaymentFrequency = expectedDisbursementDate.plusWeeks(repaymentEvery); dateBasedOnRepaymentFrequency = expectedDisbursementDate.plusWeeks(repaymentEvery);
} } else if (repaymentPeriodFrequencyType.isMonthly()) {
else if (repaymentPeriodFrequencyType.isMonthly()) {
dateBasedOnRepaymentFrequency = expectedDisbursementDate.plusMonths(repaymentEvery); dateBasedOnRepaymentFrequency = expectedDisbursementDate.plusMonths(repaymentEvery);
} } else if (repaymentPeriodFrequencyType.isYearly()) {
else if (repaymentPeriodFrequencyType.isYearly()){
dateBasedOnRepaymentFrequency = expectedDisbursementDate.plusYears(repaymentEvery); dateBasedOnRepaymentFrequency = expectedDisbursementDate.plusYears(repaymentEvery);
} }
derivedFirstRepayment = dateBasedOnRepaymentFrequency.isAfter(dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment)?dateBasedOnRepaymentFrequency:dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment; derivedFirstRepayment = dateBasedOnRepaymentFrequency.isAfter(dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment) ? dateBasedOnRepaymentFrequency
} : dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment;
else if(loanType.isJLGAccount()){ } else if (loanType.isJLGAccount()) {
final LocalDate refernceDateForCalculatingFirstRepaymentDate = expectedDisbursementDate; final LocalDate refernceDateForCalculatingFirstRepaymentDate = expectedDisbursementDate;
derivedFirstRepayment = deriveFirstRepaymentDateForJLGLoans(repaymentEvery, expectedDisbursementDate,refernceDateForCalculatingFirstRepaymentDate, derivedFirstRepayment = deriveFirstRepaymentDateForJLGLoans(repaymentEvery, expectedDisbursementDate,
repaymentPeriodFrequencyType,minimumDaysBetweenDisbursalAndFirstRepayment, calendar); refernceDateForCalculatingFirstRepaymentDate, repaymentPeriodFrequencyType,
minimumDaysBetweenDisbursalAndFirstRepayment, calendar);
} }
return derivedFirstRepayment; return derivedFirstRepayment;
} }
private LocalDate deriveFirstRepaymentDateForJLGLoans(final Integer repaymentEvery, private LocalDate deriveFirstRepaymentDateForJLGLoans(final Integer repaymentEvery, final LocalDate expectedDisbursementDate,
final LocalDate expectedDisbursementDate, final LocalDate refernceDateForCalculatingFirstRepaymentDate, final LocalDate refernceDateForCalculatingFirstRepaymentDate, final PeriodFrequencyType repaymentPeriodFrequencyType,
final PeriodFrequencyType repaymentPeriodFrequencyType,final Integer minimumDaysBetweenDisbursalAndFirstRepayment, final Integer minimumDaysBetweenDisbursalAndFirstRepayment, final Calendar calendar) {
final Calendar calendar){
final String frequency = CalendarUtils.getMeetingFrequencyFromPeriodFrequencyType(repaymentPeriodFrequencyType); final String frequency = CalendarUtils.getMeetingFrequencyFromPeriodFrequencyType(repaymentPeriodFrequencyType);
final LocalDate derivedFirstRepayment = CalendarUtils.getFirstRepaymentMeetingDate(calendar, refernceDateForCalculatingFirstRepaymentDate, final LocalDate derivedFirstRepayment = CalendarUtils.getFirstRepaymentMeetingDate(calendar,
repaymentEvery, frequency); refernceDateForCalculatingFirstRepaymentDate, repaymentEvery, frequency);
final LocalDate minimumFirstRepaymentDate = expectedDisbursementDate.plusDays(minimumDaysBetweenDisbursalAndFirstRepayment); final LocalDate minimumFirstRepaymentDate = expectedDisbursementDate.plusDays(minimumDaysBetweenDisbursalAndFirstRepayment);
return minimumFirstRepaymentDate.isBefore(derivedFirstRepayment) ? derivedFirstRepayment return minimumFirstRepaymentDate.isBefore(derivedFirstRepayment) ? derivedFirstRepayment : deriveFirstRepaymentDateForJLGLoans(
:deriveFirstRepaymentDateForJLGLoans(repaymentEvery, expectedDisbursementDate,derivedFirstRepayment, repaymentPeriodFrequencyType, repaymentEvery, expectedDisbursementDate, derivedFirstRepayment, repaymentPeriodFrequencyType,
minimumDaysBetweenDisbursalAndFirstRepayment, calendar); minimumDaysBetweenDisbursalAndFirstRepayment, calendar);
} }
private void validateMinimumDaysBetweenDisbursalAndFirstRepayment(final LocalDate disbursalDate, private void validateMinimumDaysBetweenDisbursalAndFirstRepayment(final LocalDate disbursalDate, final LocalDate firstRepaymentDate,
final LocalDate firstRepaymentDate, final Integer minimumDaysBetweenDisbursalAndFirstRepayment){ final Integer minimumDaysBetweenDisbursalAndFirstRepayment) {
final LocalDate minimumFirstRepaymentDate = disbursalDate.plusDays(minimumDaysBetweenDisbursalAndFirstRepayment); final LocalDate minimumFirstRepaymentDate = disbursalDate.plusDays(minimumDaysBetweenDisbursalAndFirstRepayment);
if(firstRepaymentDate.isBefore(minimumFirstRepaymentDate)){ if (firstRepaymentDate.isBefore(minimumFirstRepaymentDate)) { throw new MinDaysBetweenDisbursalAndFirstRepaymentViolationException(
final String errorMessage = "Number of days between disbursal date (" + disbursalDate + ") and first repayment date (" disbursalDate, firstRepaymentDate, minimumDaysBetweenDisbursalAndFirstRepayment); }
+ firstRepaymentDate + ") can't be less than minimumDaysBetweenDisbursalAndFirstRepayment ("
+ minimumDaysBetweenDisbursalAndFirstRepayment + ")." ;
throw new MinimumDaysBetweenDisbursalAndFirstRepaymentRuleException(errorMessage);
}
} }
} }
@@ -112,19 +112,32 @@ public final class LoanApplicationCommandFromApiJsonHelper {
if (loanType.isJLGAccount()) { if (loanType.isJLGAccount()) {
baseDataValidator.reset().parameter("clientId").value(clientId).notNull().integerGreaterThanZero(); baseDataValidator.reset().parameter("clientId").value(clientId).notNull().integerGreaterThanZero();
baseDataValidator.reset().parameter("groupId").value(groupId).notNull().longGreaterThanZero(); baseDataValidator.reset().parameter("groupId").value(groupId).notNull().longGreaterThanZero();
/**
* these validations should be carried out based on Global
* configurations, commenting them for now
**/
// if it is JLG loan then must have a meeting details (calendar) /**
final String calendarIdParameterName = "calendarId"; * // if it is JLG loan then must have a meeting details
final Long calendarId = this.fromApiJsonHelper.extractLongNamed(calendarIdParameterName, element); * (calendar) final String calendarIdParameterName =
baseDataValidator.reset().parameter(calendarIdParameterName).value(calendarId).notNull().integerGreaterThanZero(); * "calendarId"; final Long calendarId =
* this.fromApiJsonHelper.extractLongNamed
// if it is JLG loan then must have a syncDisbursement * (calendarIdParameterName, element);
final String syncDisbursementParameterName = "syncDisbursementWithMeeting"; * baseDataValidator.reset().
final Boolean syncDisbursement = this.fromApiJsonHelper.extractBooleanNamed(syncDisbursementParameterName, element); * parameter(calendarIdParameterName).value
* (calendarId).notNull().integerGreaterThanZero();
if (syncDisbursement == null) { *
baseDataValidator.reset().parameter(syncDisbursementParameterName).value(syncDisbursement).trueOrFalseRequired(false); * // if it is JLG loan then must have a syncDisbursement final
} * String syncDisbursementParameterName =
* "syncDisbursementWithMeeting"; final Boolean syncDisbursement
* = this.fromApiJsonHelper.extractBooleanNamed(
* syncDisbursementParameterName, element);
*
* if (syncDisbursement == null) {
* baseDataValidator.reset().parameter
* (syncDisbursementParameterName
* ).value(syncDisbursement).trueOrFalseRequired(false); }
**/
} }
} }
@@ -168,7 +168,7 @@ public class LoanProduct extends AbstractPersistable<Long> {
final Integer graceOnInterestPayment = command.integerValueOfParameterNamed("graceOnInterestPayment"); final Integer graceOnInterestPayment = command.integerValueOfParameterNamed("graceOnInterestPayment");
final Integer graceOnInterestCharged = command.integerValueOfParameterNamed("graceOnInterestCharged"); final Integer graceOnInterestCharged = command.integerValueOfParameterNamed("graceOnInterestCharged");
final Integer minimumDaysBetweenDisbursalAndFirstRepayment = command final Integer minimumDaysBetweenDisbursalAndFirstRepayment = command
.integerValueOfParameterNamed("minimumDaysBetweenDisbursalAndFirstRepayment"); .integerValueOfParameterNamed(LoanProductConstants.minimumDaysBetweenDisbursalAndFirstRepayment);
final AccountingRuleType accountingRuleType = AccountingRuleType.fromInt(command.integerValueOfParameterNamed("accountingRule")); final AccountingRuleType accountingRuleType = AccountingRuleType.fromInt(command.integerValueOfParameterNamed("accountingRule"));
final boolean includeInBorrowerCycle = command.booleanPrimitiveValueOfParameterNamed("includeInBorrowerCycle"); final boolean includeInBorrowerCycle = command.booleanPrimitiveValueOfParameterNamed("includeInBorrowerCycle");
@@ -435,7 +435,8 @@ public class LoanProduct extends AbstractPersistable<Long> {
final Set<LoanProductBorrowerCycleVariations> loanProductBorrowerCycleVariations, final boolean multiDisburseLoan, final Set<LoanProductBorrowerCycleVariations> loanProductBorrowerCycleVariations, final boolean multiDisburseLoan,
final Integer maxTrancheCount, final BigDecimal outstandingLoanBalance, final Integer graceOnArrearsAgeing, final Integer maxTrancheCount, final BigDecimal outstandingLoanBalance, final Integer graceOnArrearsAgeing,
final Integer overdueDaysForNPA, final DaysInMonthType daysInMonthType, final DaysInYearType daysInYearType, final Integer overdueDaysForNPA, final DaysInMonthType daysInMonthType, final DaysInYearType daysInYearType,
final boolean isInterestRecalculationEnabled, final LoanProductInterestRecalculationDetails productInterestRecalculationDetails, final boolean isInterestRecalculationEnabled,
final LoanProductInterestRecalculationDetails productInterestRecalculationDetails,
final Integer minimumDaysBetweenDisbursalAndFirstRepayment) { final Integer minimumDaysBetweenDisbursalAndFirstRepayment) {
this.fund = fund; this.fund = fund;
this.transactionProcessingStrategy = transactionProcessingStrategy; this.transactionProcessingStrategy = transactionProcessingStrategy;
@@ -809,8 +810,8 @@ public class LoanProduct extends AbstractPersistable<Long> {
return this.loanProductRelatedDetail.isInterestRecalculationEnabled(); return this.loanProductRelatedDetail.isInterestRecalculationEnabled();
} }
public Integer getMinimumDaysBetweenDisbursalAndFirstRepayment(){ public Integer getMinimumDaysBetweenDisbursalAndFirstRepayment() {
return this.minimumDaysBetweenDisbursalAndFirstRepayment == null?0:this.minimumDaysBetweenDisbursalAndFirstRepayment; return this.minimumDaysBetweenDisbursalAndFirstRepayment == null ? 0 : this.minimumDaysBetweenDisbursalAndFirstRepayment;
} }
public LoanProductBorrowerCycleVariations fetchLoanProductBorrowerCycleVariationById(Long id) { public LoanProductBorrowerCycleVariations fetchLoanProductBorrowerCycleVariationById(Long id) {
@@ -105,10 +105,10 @@ public final class LoanProductDataValidator {
baseDataValidator.reset().parameter("fundId").value(fundId).ignoreIfNull().integerGreaterThanZero(); baseDataValidator.reset().parameter("fundId").value(fundId).ignoreIfNull().integerGreaterThanZero();
} }
if (this.fromApiJsonHelper.parameterExists("minimumDaysBetweenDisbursalAndFirstRepayment", element)) { if (this.fromApiJsonHelper.parameterExists(LoanProductConstants.minimumDaysBetweenDisbursalAndFirstRepayment, element)) {
final Long minimumDaysBetweenDisbursalAndFirstRepayment = this.fromApiJsonHelper.extractLongNamed( final Long minimumDaysBetweenDisbursalAndFirstRepayment = this.fromApiJsonHelper.extractLongNamed(
"minimumDaysBetweenDisbursalAndFirstRepayment", element); LoanProductConstants.minimumDaysBetweenDisbursalAndFirstRepayment, element);
baseDataValidator.reset().parameter("minimumDaysBetweenDisbursalAndFirstRepayment") baseDataValidator.reset().parameter(LoanProductConstants.minimumDaysBetweenDisbursalAndFirstRepayment)
.value(minimumDaysBetweenDisbursalAndFirstRepayment).ignoreIfNull().integerGreaterThanZero(); .value(minimumDaysBetweenDisbursalAndFirstRepayment).ignoreIfNull().integerGreaterThanZero();
} }
@@ -1,2 +0,0 @@
ALTER TABLE `m_product_loan`
ADD COLUMN `min_days_between_disbursal_and_first_repayment` INT(3) NULL AFTER `interest_recalculation_enabled`;