MIFOSX-282:added min and max constraints for Interest rate and number of repayments
This commit is contained in:
+37
@@ -0,0 +1,37 @@
|
||||
ALTER TABLE `m_product_loan`
|
||||
ADD COLUMN `min_nominal_interest_rate_per_period` DECIMAL(19,6) NOT NULL AFTER `nominal_interest_rate_per_period`,
|
||||
ADD COLUMN `max_nominal_interest_rate_per_period` DECIMAL(19,6) NOT NULL AFTER `min_nominal_interest_rate_per_period`,
|
||||
ADD COLUMN `min_number_of_repayments` SMALLINT(5) NOT NULL AFTER `number_of_repayments`,
|
||||
ADD COLUMN `max_number_of_repayments` SMALLINT(5) NOT NULL AFTER `min_number_of_repayments`;
|
||||
|
||||
ALTER TABLE `m_loan`
|
||||
ADD COLUMN `min_nominal_interest_rate_per_period` DECIMAL(19,6) NOT NULL AFTER `nominal_interest_rate_per_period`,
|
||||
ADD COLUMN `max_nominal_interest_rate_per_period` DECIMAL(19,6) NOT NULL AFTER `min_nominal_interest_rate_per_period`,
|
||||
ADD COLUMN `min_number_of_repayments` SMALLINT(5) NOT NULL AFTER `number_of_repayments`,
|
||||
ADD COLUMN `max_number_of_repayments` SMALLINT(5) NOT NULL AFTER `min_number_of_repayments`;
|
||||
|
||||
ALTER TABLE `m_loan`
|
||||
ALTER `min_principal_amount` DROP DEFAULT,
|
||||
ALTER `max_principal_amount` DROP DEFAULT;
|
||||
ALTER TABLE `m_loan`
|
||||
CHANGE COLUMN `min_principal_amount` `min_principal_amount` DECIMAL(19,6) NULL AFTER `principal_amount`,
|
||||
CHANGE COLUMN `max_principal_amount` `max_principal_amount` DECIMAL(19,6) NULL AFTER `min_principal_amount`,
|
||||
CHANGE COLUMN `min_nominal_interest_rate_per_period` `min_nominal_interest_rate_per_period` DECIMAL(19,6) NULL AFTER `nominal_interest_rate_per_period`,
|
||||
CHANGE COLUMN `max_nominal_interest_rate_per_period` `max_nominal_interest_rate_per_period` DECIMAL(19,6) NULL AFTER `min_nominal_interest_rate_per_period`,
|
||||
CHANGE COLUMN `min_number_of_repayments` `min_number_of_repayments` SMALLINT(5) NULL AFTER `number_of_repayments`,
|
||||
CHANGE COLUMN `max_number_of_repayments` `max_number_of_repayments` SMALLINT(5) NULL AFTER `min_number_of_repayments`;
|
||||
|
||||
ALTER TABLE `m_product_loan`
|
||||
ALTER `min_principal_amount` DROP DEFAULT,
|
||||
ALTER `max_principal_amount` DROP DEFAULT,
|
||||
ALTER `min_nominal_interest_rate_per_period` DROP DEFAULT,
|
||||
ALTER `max_nominal_interest_rate_per_period` DROP DEFAULT,
|
||||
ALTER `min_number_of_repayments` DROP DEFAULT,
|
||||
ALTER `max_number_of_repayments` DROP DEFAULT;
|
||||
ALTER TABLE `m_product_loan`
|
||||
CHANGE COLUMN `min_principal_amount` `min_principal_amount` DECIMAL(19,6) NULL AFTER `principal_amount`,
|
||||
CHANGE COLUMN `max_principal_amount` `max_principal_amount` DECIMAL(19,6) NULL AFTER `min_principal_amount`,
|
||||
CHANGE COLUMN `min_nominal_interest_rate_per_period` `min_nominal_interest_rate_per_period` DECIMAL(19,6) NULL AFTER `nominal_interest_rate_per_period`,
|
||||
CHANGE COLUMN `max_nominal_interest_rate_per_period` `max_nominal_interest_rate_per_period` DECIMAL(19,6) NULL AFTER `min_nominal_interest_rate_per_period`,
|
||||
CHANGE COLUMN `min_number_of_repayments` `min_number_of_repayments` SMALLINT(5) NULL AFTER `number_of_repayments`,
|
||||
CHANGE COLUMN `max_number_of_repayments` `max_number_of_repayments` SMALLINT(5) NULL AFTER `min_number_of_repayments`;
|
||||
+26
@@ -289,6 +289,19 @@ public final class JsonCommand {
|
||||
}
|
||||
return isChanged;
|
||||
}
|
||||
|
||||
public boolean isChangeInBigDecimalParameterNamedWithNullCheck(final String parameterName, final BigDecimal existingValue) {
|
||||
boolean isChanged = false;
|
||||
if (parameterExists(parameterName)) {
|
||||
final BigDecimal workingValue = bigDecimalValueOfParameterNamed(parameterName);
|
||||
if(workingValue == null && existingValue != null){
|
||||
isChanged = true;
|
||||
}else{
|
||||
isChanged = differenceExists(existingValue, workingValue);
|
||||
}
|
||||
}
|
||||
return isChanged;
|
||||
}
|
||||
|
||||
public BigDecimal bigDecimalValueOfParameterNamed(final String parameterName) {
|
||||
return this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(parameterName, parsedCommand);
|
||||
@@ -303,6 +316,19 @@ public final class JsonCommand {
|
||||
return isChanged;
|
||||
}
|
||||
|
||||
public boolean isChangeInIntegerParameterNamedWithNullCheck(final String parameterName, final Integer existingValue) {
|
||||
boolean isChanged = false;
|
||||
if (parameterExists(parameterName)) {
|
||||
final Integer workingValue = integerValueOfParameterNamed(parameterName);
|
||||
if(workingValue == null && existingValue != null){
|
||||
isChanged = true;
|
||||
}else{
|
||||
isChanged = differenceExists(existingValue, workingValue);
|
||||
}
|
||||
}
|
||||
return isChanged;
|
||||
}
|
||||
|
||||
public Integer integerValueOfParameterNamed(final String parameterName) {
|
||||
return this.fromApiJsonHelper.extractIntegerWithLocaleNamed(parameterName, parsedCommand);
|
||||
}
|
||||
|
||||
+70
@@ -388,6 +388,40 @@ public class DataValidatorBuilder {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public DataValidatorBuilder notLessThanMin(final BigDecimal min) {
|
||||
if (min != null && value != null){
|
||||
BigDecimal amount = BigDecimal.valueOf(Double.valueOf(value.toString()));
|
||||
if (amount.compareTo(min) == -1) {
|
||||
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
||||
.append(".is.less.than.min");
|
||||
StringBuilder defaultEnglishMessage = new StringBuilder("The ").append(parameter) .append(" value ").append(amount)
|
||||
.append(" must not be less than minimum value ").append(min);
|
||||
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(),
|
||||
defaultEnglishMessage.toString(), parameter, amount, min);
|
||||
dataValidationErrors.add(error);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public DataValidatorBuilder notGreaterThanMax(final BigDecimal max) {
|
||||
if (max != null && value != null){
|
||||
BigDecimal amount = BigDecimal.valueOf(Double.valueOf(value.toString()));
|
||||
if (amount.compareTo(max) == 1) {
|
||||
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
||||
.append(".is.greater.than.max");
|
||||
StringBuilder defaultEnglishMessage = new StringBuilder("The ").append(parameter) .append(" value ").append(amount)
|
||||
.append(" must not be more than maximum value ").append(max);
|
||||
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(),
|
||||
defaultEnglishMessage.toString(), parameter, amount, max);
|
||||
dataValidationErrors.add(error);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public DataValidatorBuilder comapareMinAndMaxOfTwoBigDecmimalNos(final BigDecimal min, final BigDecimal max) {
|
||||
if (min != null && max != null)
|
||||
@@ -423,4 +457,40 @@ public class DataValidatorBuilder {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public DataValidatorBuilder notLessThanMin(final Integer min) {
|
||||
if (value == null && ignoreNullValue) { return this; }
|
||||
|
||||
if (value != null && min != null) {
|
||||
Integer number = Integer.valueOf(value.toString());
|
||||
if (number < min) {
|
||||
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
||||
.append(".is.less.than.min");
|
||||
StringBuilder defaultEnglishMessage = new StringBuilder("The ").append(parameter)
|
||||
.append(" must be greater than minimum value ").append(min);
|
||||
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(),
|
||||
defaultEnglishMessage.toString(), parameter, number, min);
|
||||
dataValidationErrors.add(error);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public DataValidatorBuilder notGreaterThanMax(final Integer max) {
|
||||
if (value == null && ignoreNullValue) { return this; }
|
||||
|
||||
if (value != null && max != null) {
|
||||
Integer number = Integer.valueOf(value.toString());
|
||||
if (number > max) {
|
||||
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(resource).append(".").append(parameter)
|
||||
.append(".is.greater.than.max");
|
||||
StringBuilder defaultEnglishMessage = new StringBuilder("The ").append(parameter)
|
||||
.append(" must be less than maximum value ").append(max);
|
||||
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(),
|
||||
defaultEnglishMessage.toString(), parameter, number, max);
|
||||
dataValidationErrors.add(error);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
+7
-2
@@ -1321,6 +1321,8 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
final BigDecimal maxPrincipal = this.loanRepaymentScheduleDetail.getMaxPrincipal().getAmount();
|
||||
final BigDecimal inArrearsTolerance = this.loanRepaymentScheduleDetail.getInArrearsTolerance().getAmount();
|
||||
final BigDecimal interestRatePerPeriod = this.loanRepaymentScheduleDetail.getNominalInterestRatePerPeriod();
|
||||
final BigDecimal minInterestRatePerPeriod = this.loanRepaymentScheduleDetail.getMinNominalInterestRatePerPeriod();
|
||||
final BigDecimal maxInterestRatePerPeriod = this.loanRepaymentScheduleDetail.getMaxNominalInterestRatePerPeriod();
|
||||
final PeriodFrequencyType interestRatePeriodFrequencyType = this.loanRepaymentScheduleDetail.getInterestPeriodFrequencyType();
|
||||
final BigDecimal defaultAnnualNominalInterestRate = this.loanRepaymentScheduleDetail.getAnnualNominalInterestRate();
|
||||
|
||||
@@ -1329,13 +1331,16 @@ public class Loan extends AbstractPersistable<Long> {
|
||||
final Integer repaymentEvery = this.loanRepaymentScheduleDetail.getRepayEvery();
|
||||
final PeriodFrequencyType repaymentPeriodFrequencyType = this.loanRepaymentScheduleDetail.getRepaymentPeriodFrequencyType();
|
||||
final Integer numberOfRepayments = this.loanRepaymentScheduleDetail.getNumberOfRepayments();
|
||||
final Integer minNumberOfRepayments = this.loanRepaymentScheduleDetail.getMinNumberOfRepayments();
|
||||
final Integer maxNumberOfRepayments = this.loanRepaymentScheduleDetail.getMaxNumberOfRepayments();
|
||||
final AmortizationMethod amortizationMethod = this.loanRepaymentScheduleDetail.getAmortizationMethod();
|
||||
final Integer loanTermFrequency = this.termFrequency;
|
||||
final PeriodFrequencyType loanTermPeriodFrequencyType = PeriodFrequencyType.fromInt(this.termPeriodFrequencyType);
|
||||
|
||||
final LoanSchedule loanSchedule = new LoanSchedule(loanScheduleGenerator, applicationCurrency, principal, minPrincipal,
|
||||
maxPrincipal, interestRatePerPeriod, interestRatePeriodFrequencyType, defaultAnnualNominalInterestRate, interestMethod,
|
||||
interestCalculationPeriodMethod, repaymentEvery, repaymentPeriodFrequencyType, numberOfRepayments, amortizationMethod,
|
||||
maxPrincipal, interestRatePerPeriod, minInterestRatePerPeriod, maxInterestRatePerPeriod, interestRatePeriodFrequencyType,
|
||||
defaultAnnualNominalInterestRate, interestMethod, interestCalculationPeriodMethod, repaymentEvery,
|
||||
repaymentPeriodFrequencyType, numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, amortizationMethod,
|
||||
loanTermFrequency, loanTermPeriodFrequencyType, setOfLoanCharges(), this.getDisbursementDate(),
|
||||
this.getExpectedFirstRepaymentOnDate(), this.getInterestChargedFromDate(), inArrearsTolerance);
|
||||
|
||||
|
||||
+12
-4
@@ -30,6 +30,8 @@ public final class LoanSchedule {
|
||||
private final BigDecimal minPrincipal;
|
||||
private final BigDecimal maxPrincipal;
|
||||
private final BigDecimal nominalInterestRatePerPeriod;
|
||||
private final BigDecimal minNominalInterestRatePerPeriod;
|
||||
private final BigDecimal maxNominalInterestRatePerPeriod;
|
||||
private final PeriodFrequencyType interestRatePeriodFrequencyType;
|
||||
private final BigDecimal nominalAnnualInterestRate;
|
||||
private final InterestMethod interestMethod;
|
||||
@@ -37,6 +39,8 @@ public final class LoanSchedule {
|
||||
private final Integer repaymentEvery;
|
||||
private final PeriodFrequencyType repaymentPeriodFrequencyType;
|
||||
private final Integer numberOfRepayments;
|
||||
private final Integer minNumberOfRepayments;
|
||||
private final Integer maxNumberOfRepayments;
|
||||
private final AmortizationMethod amortizationMethod;
|
||||
private final Integer loanTermFrequency;
|
||||
private final PeriodFrequencyType loanTermPeriodFrequencyType;
|
||||
@@ -49,10 +53,10 @@ public final class LoanSchedule {
|
||||
|
||||
public LoanSchedule(final LoanScheduleGenerator loanScheduleGenerator, final ApplicationCurrency applicationCurrency,
|
||||
final BigDecimal principal, final BigDecimal minPrincipal, final BigDecimal maxPrincipal,
|
||||
final BigDecimal nominalInterestRatePerPeriod, final PeriodFrequencyType interestRatePeriodFrequencyType,
|
||||
final BigDecimal nominalInterestRatePerPeriod, final BigDecimal minNominalInterestRatePerPeriod, final BigDecimal maxNominalInterestRatePerPeriod, final PeriodFrequencyType interestRatePeriodFrequencyType,
|
||||
final BigDecimal nominalAnnualInterestRate, final InterestMethod interestMethod,
|
||||
final InterestCalculationPeriodMethod interestCalculationPeriodMethod, final Integer repaymentEvery,
|
||||
final PeriodFrequencyType repaymentPeriodFrequencyType, final Integer numberOfRepayments,
|
||||
final PeriodFrequencyType repaymentPeriodFrequencyType, final Integer numberOfRepayments, final Integer minNumberOfRepayments, final Integer maxNumberOfRepayments,
|
||||
final AmortizationMethod amortizationMethod, final Integer loanTermFrequency,
|
||||
final PeriodFrequencyType loanTermPeriodFrequencyType, final Set<LoanCharge> loanCharges, final LocalDate disbursementDate,
|
||||
final LocalDate repaymentStartFromDate, final LocalDate interestChargedFromDate, final BigDecimal inArrearsTolerance) {
|
||||
@@ -62,6 +66,8 @@ public final class LoanSchedule {
|
||||
this.minPrincipal = minPrincipal;
|
||||
this.maxPrincipal = maxPrincipal;
|
||||
this.nominalInterestRatePerPeriod = nominalInterestRatePerPeriod;
|
||||
this.minNominalInterestRatePerPeriod = minNominalInterestRatePerPeriod;
|
||||
this.maxNominalInterestRatePerPeriod = maxNominalInterestRatePerPeriod;
|
||||
this.interestRatePeriodFrequencyType = interestRatePeriodFrequencyType;
|
||||
this.nominalAnnualInterestRate = nominalAnnualInterestRate;
|
||||
this.interestMethod = interestMethod;
|
||||
@@ -69,6 +75,8 @@ public final class LoanSchedule {
|
||||
this.repaymentEvery = repaymentEvery;
|
||||
this.repaymentPeriodFrequencyType = repaymentPeriodFrequencyType;
|
||||
this.numberOfRepayments = numberOfRepayments;
|
||||
this.minNumberOfRepayments = minNumberOfRepayments;
|
||||
this.maxNumberOfRepayments = maxNumberOfRepayments;
|
||||
this.amortizationMethod = amortizationMethod;
|
||||
this.loanTermFrequency = loanTermFrequency;
|
||||
this.loanTermPeriodFrequencyType = loanTermPeriodFrequencyType;
|
||||
@@ -87,9 +95,9 @@ public final class LoanSchedule {
|
||||
public LoanProductRelatedDetail loanProductRelatedDetail() {
|
||||
final MonetaryCurrency currency = new MonetaryCurrency(applicationCurrency.getCode(), applicationCurrency.getDecimalPlaces());
|
||||
|
||||
return LoanProductRelatedDetail.createFrom(currency, principal, minPrincipal, maxPrincipal, nominalInterestRatePerPeriod,
|
||||
return LoanProductRelatedDetail.createFrom(currency, principal, minPrincipal, maxPrincipal, nominalInterestRatePerPeriod, minNominalInterestRatePerPeriod, maxNominalInterestRatePerPeriod,
|
||||
interestRatePeriodFrequencyType, nominalAnnualInterestRate, interestMethod, interestCalculationPeriodMethod,
|
||||
repaymentEvery, repaymentPeriodFrequencyType, numberOfRepayments, amortizationMethod, this.inArrearsTolerance);
|
||||
repaymentEvery, repaymentPeriodFrequencyType, numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, amortizationMethod, this.inArrearsTolerance);
|
||||
}
|
||||
|
||||
public Integer getLoanTermFrequency() {
|
||||
|
||||
+6
-2
@@ -75,6 +75,8 @@ public class LoanScheduleAssembler {
|
||||
final BigDecimal minPrincipal = loanProduct.getMinPrincipalAmount().getAmount();//Copy minPrincipal from loan product to loan
|
||||
final BigDecimal maxPrincipal = loanProduct.getMaxPrincipalAmount().getAmount();//Copy maxPrincipal from loan product to loan
|
||||
final BigDecimal interestRatePerPeriod = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("interestRatePerPeriod", element);
|
||||
final BigDecimal minInterestRatePerPeriod = loanProduct.getMinNominalInterestRatePerPeriod();//Copy from Loan product to Loan
|
||||
final BigDecimal maxInterestRatePerPeriod = loanProduct.getMaxNominalInterestRatePerPeriod();//Copy from Loan product to Loan
|
||||
final Integer interestRateFrequencyType = fromApiJsonHelper.extractIntegerWithLocaleNamed("interestRateFrequencyType", element);
|
||||
final Integer interestType = fromApiJsonHelper.extractIntegerWithLocaleNamed("interestType", element);
|
||||
final Integer interestCalculationPeriodType = fromApiJsonHelper.extractIntegerWithLocaleNamed("interestCalculationPeriodType",
|
||||
@@ -91,6 +93,8 @@ public class LoanScheduleAssembler {
|
||||
final Integer repaymentEvery = fromApiJsonHelper.extractIntegerWithLocaleNamed("repaymentEvery", element);
|
||||
final Integer repaymentFrequencyType = fromApiJsonHelper.extractIntegerWithLocaleNamed("repaymentFrequencyType", element);
|
||||
final Integer numberOfRepayments = fromApiJsonHelper.extractIntegerWithLocaleNamed("numberOfRepayments", element);
|
||||
final Integer minNumberOfRepayments = loanProduct.getMinNumberOfRepayments();//Copy from Loan product to Loan
|
||||
final Integer maxNumberOfRepayments = loanProduct.getMaxNumberOfRepayments();//Copy from Loan product to Loan
|
||||
final Integer amortizationType = fromApiJsonHelper.extractIntegerWithLocaleNamed("amortizationType", element);
|
||||
final PeriodFrequencyType repaymentPeriodFrequencyType = PeriodFrequencyType.fromInt(repaymentFrequencyType);
|
||||
final AmortizationMethod amortizationMethod = AmortizationMethod.fromInt(amortizationType);
|
||||
@@ -107,9 +111,9 @@ public class LoanScheduleAssembler {
|
||||
|
||||
final LoanScheduleGenerator loanScheduleGenerator = this.loanScheduleFactory.create(interestMethod);
|
||||
|
||||
return new LoanSchedule(loanScheduleGenerator, applicationCurrency, principal, minPrincipal, maxPrincipal, interestRatePerPeriod,
|
||||
return new LoanSchedule(loanScheduleGenerator, applicationCurrency, principal, minPrincipal, maxPrincipal, interestRatePerPeriod, minInterestRatePerPeriod, maxInterestRatePerPeriod,
|
||||
interestRatePeriodFrequencyType, defaultAnnualNominalInterestRate, interestMethod, interestCalculationPeriodMethod,
|
||||
repaymentEvery, repaymentPeriodFrequencyType, numberOfRepayments, amortizationMethod, loanTermFrequency,
|
||||
repaymentEvery, repaymentPeriodFrequencyType, numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, amortizationMethod, loanTermFrequency,
|
||||
loanTermPeriodFrequencyType, loanCharges, expectedDisbursementDate, repaymentsStartingFromDate, interestChargedFromDate, inArrearsTolerance);
|
||||
}
|
||||
}
|
||||
+11
-6
@@ -57,6 +57,7 @@ import org.mifosplatform.portfolio.loanproduct.domain.LoanProduct;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRepository;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanTransactionProcessingStrategy;
|
||||
import org.mifosplatform.portfolio.loanproduct.exception.LoanProductNotFoundException;
|
||||
import org.mifosplatform.portfolio.loanproduct.serialization.LoanProductCommandFromApiJsonDeserializer;
|
||||
import org.mifosplatform.portfolio.note.domain.Note;
|
||||
import org.mifosplatform.portfolio.note.domain.NoteRepository;
|
||||
import org.mifosplatform.useradministration.domain.AppUser;
|
||||
@@ -92,19 +93,21 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory;
|
||||
private final CalendarRepository calendarRepository;
|
||||
private final CalendarInstanceRepository calendarInstanceRepository;
|
||||
private final LoanProductCommandFromApiJsonDeserializer loanProductCommandFromApiJsonDeserializer;
|
||||
|
||||
@Autowired
|
||||
public LoanApplicationWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final FromJsonHelper fromJsonHelper,
|
||||
final LoanApplicationTransitionApiJsonValidator loanApplicationTransitionApiJsonValidator,
|
||||
final LoanApplicationCommandFromApiJsonHelper fromApiJsonDeserializer, final AprCalculator aprCalculator,
|
||||
final LoanAssembler loanAssembler, final LoanChargeAssembler loanChargeAssembler,
|
||||
final CollateralAssembler loanCollateralAssembler, final LoanRepository loanRepository,
|
||||
final NoteRepository noteRepository, final LoanScheduleCalculationPlatformService calculationPlatformService,
|
||||
final ClientRepository clientRepository, final LoanProductRepository loanProductRepository,
|
||||
final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory, final LoanSummaryWrapper loanSummaryWrapper,
|
||||
final CollateralAssembler loanCollateralAssembler, final LoanRepository loanRepository, final NoteRepository noteRepository,
|
||||
final LoanScheduleCalculationPlatformService calculationPlatformService, final ClientRepository clientRepository,
|
||||
final LoanProductRepository loanProductRepository, final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory,
|
||||
final LoanSummaryWrapper loanSummaryWrapper,
|
||||
final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory,
|
||||
final CalendarRepository calendarRepository, final CalendarInstanceRepository calendarInstanceRepository) {
|
||||
this.context = context;
|
||||
final CalendarRepository calendarRepository, final CalendarInstanceRepository calendarInstanceRepository,
|
||||
final LoanProductCommandFromApiJsonDeserializer loanProductCommandFromApiJsonDeserializer) {
|
||||
this.context = context;
|
||||
this.fromJsonHelper = fromJsonHelper;
|
||||
this.loanApplicationTransitionApiJsonValidator = loanApplicationTransitionApiJsonValidator;
|
||||
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
|
||||
@@ -122,6 +125,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
this.loanRepaymentScheduleTransactionProcessorFactory = loanRepaymentScheduleTransactionProcessorFactory;
|
||||
this.calendarRepository = calendarRepository;
|
||||
this.calendarInstanceRepository = calendarInstanceRepository;
|
||||
this.loanProductCommandFromApiJsonDeserializer = loanProductCommandFromApiJsonDeserializer;
|
||||
}
|
||||
|
||||
private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() {
|
||||
@@ -199,6 +203,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
||||
}
|
||||
|
||||
final Loan existingLoanApplication = retrieveLoanBy(loanId);
|
||||
this.loanProductCommandFromApiJsonDeserializer.validateMinMaxConstraints(command.parsedJson(), existingLoanApplication.repaymentScheduleDetail(), "loan");
|
||||
|
||||
if (!existingLoanApplication.isSubmittedAndPendingApproval()) { throw new LoanApplicationNotInSubmittedAndPendingApprovalStateCannotBeModified(
|
||||
loanId); }
|
||||
|
||||
+5
-5
@@ -42,11 +42,11 @@ import org.mifosplatform.portfolio.loanaccount.domain.LoanTransactionProcessingS
|
||||
import org.mifosplatform.portfolio.loanaccount.exception.LoanTransactionProcessingStrategyNotFoundException;
|
||||
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanSchedule;
|
||||
import org.mifosplatform.portfolio.loanaccount.loanschedule.service.LoanScheduleAssembler;
|
||||
import org.mifosplatform.portfolio.loanaccount.serialization.LoanApplicationCommandFromApiJsonHelper;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanProduct;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRepository;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanTransactionProcessingStrategy;
|
||||
import org.mifosplatform.portfolio.loanproduct.exception.LoanProductNotFoundException;
|
||||
import org.mifosplatform.portfolio.loanproduct.serialization.LoanProductCommandFromApiJsonDeserializer;
|
||||
import org.mifosplatform.useradministration.domain.AppUser;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -69,7 +69,7 @@ public class LoanAssembler {
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
private final LoanSummaryWrapper loanSummaryWrapper;
|
||||
private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory;
|
||||
private final LoanApplicationCommandFromApiJsonHelper fromApiJsonDeserializer;
|
||||
private final LoanProductCommandFromApiJsonDeserializer loanProductCommandFromApiJsonDeserializer;
|
||||
|
||||
@Autowired
|
||||
public LoanAssembler(final FromJsonHelper fromApiJsonHelper, final LoanProductRepository loanProductRepository,
|
||||
@@ -79,7 +79,7 @@ public class LoanAssembler {
|
||||
final LoanScheduleAssembler loanScheduleAssembler, final LoanChargeAssembler loanChargeAssembler,
|
||||
final CollateralAssembler loanCollateralAssembler, final LoanSummaryWrapper loanSummaryWrapper,
|
||||
final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory,
|
||||
final LoanApplicationCommandFromApiJsonHelper fromApiJsonDeserializer) {
|
||||
final LoanProductCommandFromApiJsonDeserializer loanProductCommandFromApiJsonDeserializer) {
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
this.loanProductRepository = loanProductRepository;
|
||||
this.clientRepository = clientRepository;
|
||||
@@ -93,7 +93,7 @@ public class LoanAssembler {
|
||||
this.loanCollateralAssembler = loanCollateralAssembler;
|
||||
this.loanSummaryWrapper = loanSummaryWrapper;
|
||||
this.loanRepaymentScheduleTransactionProcessorFactory = loanRepaymentScheduleTransactionProcessorFactory;
|
||||
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
|
||||
this.loanProductCommandFromApiJsonDeserializer = loanProductCommandFromApiJsonDeserializer;
|
||||
}
|
||||
|
||||
public Loan assembleFrom(final JsonCommand command, final AppUser currentUser) {
|
||||
@@ -118,7 +118,7 @@ public class LoanAssembler {
|
||||
if (loanProduct == null) { throw new LoanProductNotFoundException(productId); }
|
||||
|
||||
//validate min and max constraint parameters
|
||||
this.fromApiJsonDeserializer.validateMinMaxConstraintValues(element, loanProduct);
|
||||
this.loanProductCommandFromApiJsonDeserializer.validateMinMaxConstraints(element, loanProduct.loanProductRelatedDetail(), "loan");
|
||||
|
||||
final Fund fund = findFundByIdIfProvided(fundId);
|
||||
final Staff loanOfficer = findLoanOfficerByIdIfProvided(loanOfficerId);
|
||||
|
||||
+6
-5
@@ -57,11 +57,12 @@ import org.springframework.stereotype.Component;
|
||||
public class LoanProductsApiResource {
|
||||
|
||||
private final Set<String> LOAN_PRODUCT_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("id", "name", "description", "fundId",
|
||||
"fundName", "currency", "principal", "numberOfRepayments", "repaymentEvery", "repaymentFrequencyType", "interestRatePerPeriod",
|
||||
"interestRateFrequencyType", "annualInterestRate", "amortizationType", "interestType", "interestCalculationPeriodType",
|
||||
"inArrearsTolerance", "transactionProcessingStrategyId", "transactionProcessingStrategyName", "charges", "accountingRule",
|
||||
"accountingMappings", "fundOptions", "currencyOptions", "repaymentFrequencyTypeOptions", "interestRateFrequencyTypeOptions",
|
||||
"amortizationTypeOptions", "interestTypeOptions", "interestCalculationPeriodTypeOptions",
|
||||
"fundName", "currency", "principal", "minPrincipal", "maxPrincipal", "numberOfRepayments", "minNumberOfRepayments",
|
||||
"maxNumberOfRepayments", "repaymentEvery", "repaymentFrequencyType", "interestRatePerPeriod", "minInterestRatePerPeriod",
|
||||
"maxInterestRatePerPeriod", "interestRateFrequencyType", "annualInterestRate", "amortizationType", "interestType",
|
||||
"interestCalculationPeriodType", "inArrearsTolerance", "transactionProcessingStrategyId", "transactionProcessingStrategyName",
|
||||
"charges", "accountingRule", "accountingMappings", "fundOptions", "currencyOptions", "repaymentFrequencyTypeOptions",
|
||||
"interestRateFrequencyTypeOptions", "amortizationTypeOptions", "interestTypeOptions", "interestCalculationPeriodTypeOptions",
|
||||
"transactionProcessingStrategyOptions", "chargeOptions", "accountingOptions", "accountingRuleOptions",
|
||||
"accountingMappingOptions"));
|
||||
|
||||
|
||||
+36
-10
@@ -40,9 +40,13 @@ public class LoanProductData {
|
||||
private BigDecimal minPrincipal;
|
||||
private BigDecimal maxPrincipal;
|
||||
private final Integer numberOfRepayments;
|
||||
private final Integer minNumberOfRepayments;
|
||||
private final Integer maxNumberOfRepayments;
|
||||
private final Integer repaymentEvery;
|
||||
private final EnumOptionData repaymentFrequencyType;
|
||||
private final BigDecimal interestRatePerPeriod;
|
||||
private final BigDecimal minInterestRatePerPeriod;
|
||||
private final BigDecimal maxInterestRatePerPeriod;
|
||||
private final EnumOptionData interestRateFrequencyType;
|
||||
private final BigDecimal annualInterestRate;
|
||||
|
||||
@@ -86,8 +90,12 @@ public class LoanProductData {
|
||||
final BigDecimal maxPrincipal = null;
|
||||
final BigDecimal tolerance = null;
|
||||
final Integer numberOfRepayments = null;
|
||||
final Integer minNumberOfRepayments = null;
|
||||
final Integer maxNumberOfRepayments = null;
|
||||
final Integer repaymentEvery = null;
|
||||
final BigDecimal interestRatePerPeriod = null;
|
||||
final BigDecimal minInterestRatePerPeriod = null;
|
||||
final BigDecimal maxInterestRatePerPeriod = null;
|
||||
final BigDecimal annualInterestRate = null;
|
||||
final EnumOptionData repaymentFrequencyType = null;
|
||||
final EnumOptionData interestRateFrequencyType = null;
|
||||
@@ -101,8 +109,8 @@ public class LoanProductData {
|
||||
final Collection<ChargeData> charges = null;
|
||||
final EnumOptionData accountingType = null;
|
||||
|
||||
return new LoanProductData(id, name, description, currency, principal, minPrincipal, maxPrincipal, tolerance, numberOfRepayments, repaymentEvery,
|
||||
interestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType,
|
||||
return new LoanProductData(id, name, description, currency, principal, minPrincipal, maxPrincipal, tolerance, numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery,
|
||||
interestRatePerPeriod, minInterestRatePerPeriod, maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType,
|
||||
interestType, interestCalculationPeriodType, fundId, fundName, transactionProcessingStrategyId,
|
||||
transactionProcessingStrategyName, charges, accountingType);
|
||||
}
|
||||
@@ -114,8 +122,12 @@ public class LoanProductData {
|
||||
final BigDecimal maxPrincipal = null;
|
||||
final BigDecimal tolerance = null;
|
||||
final Integer numberOfRepayments = null;
|
||||
final Integer minNumberOfRepayments = null;
|
||||
final Integer maxNumberOfRepayments = null;
|
||||
final Integer repaymentEvery = null;
|
||||
final BigDecimal interestRatePerPeriod = null;
|
||||
final BigDecimal minInterestRatePerPeriod = null;
|
||||
final BigDecimal maxInterestRatePerPeriod = null;
|
||||
final BigDecimal annualInterestRate = null;
|
||||
final EnumOptionData repaymentFrequencyType = null;
|
||||
final EnumOptionData interestRateFrequencyType = null;
|
||||
@@ -129,8 +141,8 @@ public class LoanProductData {
|
||||
final Collection<ChargeData> charges = null;
|
||||
final EnumOptionData accountingType = null;
|
||||
|
||||
return new LoanProductData(id, name, description, currency, principal, minPrincipal, maxPrincipal, tolerance, numberOfRepayments, repaymentEvery,
|
||||
interestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType,
|
||||
return new LoanProductData(id, name, description, currency, principal, minPrincipal, maxPrincipal, tolerance, numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery,
|
||||
interestRatePerPeriod, minInterestRatePerPeriod, maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType,
|
||||
interestType, interestCalculationPeriodType, fundId, fundName, transactionProcessingStrategyId,
|
||||
transactionProcessingStrategyName, charges, accountingType);
|
||||
}
|
||||
@@ -145,8 +157,12 @@ public class LoanProductData {
|
||||
final BigDecimal maxPrincipal = null;
|
||||
final BigDecimal tolerance = null;
|
||||
final Integer numberOfRepayments = null;
|
||||
final Integer minNumberOfRepayments = null;
|
||||
final Integer maxNumberOfRepayments = null;
|
||||
final Integer repaymentEvery = null;
|
||||
final BigDecimal interestRatePerPeriod = null;
|
||||
final BigDecimal minInterestRatePerPeriod = null;
|
||||
final BigDecimal maxInterestRatePerPeriod = null;
|
||||
final BigDecimal annualInterestRate = null;
|
||||
final EnumOptionData repaymentFrequencyType = LoanEnumerations.repaymentFrequencyType(PeriodFrequencyType.MONTHS);
|
||||
final EnumOptionData interestRateFrequencyType = LoanEnumerations.interestRateFrequencyType(PeriodFrequencyType.MONTHS);
|
||||
@@ -161,8 +177,9 @@ public class LoanProductData {
|
||||
final Collection<ChargeData> charges = null;
|
||||
final EnumOptionData accountingType = LoanEnumerations.accountingRuleType(AccountingRuleType.NONE);
|
||||
|
||||
return new LoanProductData(id, name, description, currency, principal, minPrincipal, maxPrincipal, tolerance, numberOfRepayments, repaymentEvery,
|
||||
interestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType,
|
||||
return new LoanProductData(id, name, description, currency, principal, minPrincipal, maxPrincipal, tolerance, numberOfRepayments,
|
||||
minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod, minInterestRatePerPeriod,
|
||||
maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType, amortizationType,
|
||||
interestType, interestCalculationPeriodType, fundId, fundName, transactionProcessingStrategyId,
|
||||
transactionProcessingStrategyName, charges, accountingType);
|
||||
}
|
||||
@@ -178,12 +195,14 @@ public class LoanProductData {
|
||||
|
||||
public LoanProductData(final Long id, final String name, final String description, final CurrencyData currency,
|
||||
final BigDecimal principal, final BigDecimal minPrincipal, final BigDecimal maxPrincipal, final BigDecimal tolerance,
|
||||
final Integer numberOfRepayments, final Integer repaymentEvery, final BigDecimal interestRatePerPeriod,
|
||||
final BigDecimal annualInterestRate, final EnumOptionData repaymentFrequencyType,
|
||||
final Integer numberOfRepayments, final Integer minNumberOfRepayments, final Integer maxNumberOfRepayments,
|
||||
final Integer repaymentEvery, final BigDecimal interestRatePerPeriod, final BigDecimal minInterestRatePerPeriod,
|
||||
final BigDecimal maxInterestRatePerPeriod, final BigDecimal annualInterestRate, final EnumOptionData repaymentFrequencyType,
|
||||
final EnumOptionData interestRateFrequencyType, final EnumOptionData amortizationType, final EnumOptionData interestType,
|
||||
final EnumOptionData interestCalculationPeriodType, final Long fundId, final String fundName,
|
||||
final Long transactionProcessingStrategyId, final String transactionProcessingStrategyName,
|
||||
final Collection<ChargeData> charges, final EnumOptionData accountingType) {
|
||||
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
@@ -193,8 +212,12 @@ public class LoanProductData {
|
||||
this.maxPrincipal = maxPrincipal;
|
||||
this.inArrearsTolerance = tolerance;
|
||||
this.numberOfRepayments = numberOfRepayments;
|
||||
this.minNumberOfRepayments = minNumberOfRepayments;
|
||||
this.maxNumberOfRepayments = maxNumberOfRepayments;
|
||||
this.repaymentEvery = repaymentEvery;
|
||||
this.interestRatePerPeriod = interestRatePerPeriod;
|
||||
this.minInterestRatePerPeriod = minInterestRatePerPeriod;
|
||||
this.maxInterestRatePerPeriod = maxInterestRatePerPeriod;
|
||||
this.annualInterestRate = annualInterestRate;
|
||||
this.repaymentFrequencyType = repaymentFrequencyType;
|
||||
this.interestRateFrequencyType = interestRateFrequencyType;
|
||||
@@ -227,8 +250,7 @@ public class LoanProductData {
|
||||
final Collection<CurrencyData> currencyOptions, final List<EnumOptionData> amortizationTypeOptions,
|
||||
final List<EnumOptionData> interestTypeOptions, final List<EnumOptionData> interestCalculationPeriodTypeOptions,
|
||||
final List<EnumOptionData> repaymentFrequencyTypeOptions, final List<EnumOptionData> interestRateFrequencyTypeOptions,
|
||||
final Collection<FundData> fundOptions,
|
||||
final Collection<TransactionProcessingStrategyData> transactionStrategyOptions,
|
||||
final Collection<FundData> fundOptions, final Collection<TransactionProcessingStrategyData> transactionStrategyOptions,
|
||||
final Map<String, List<GLAccountData>> accountingMappingOptions, final List<EnumOptionData> accountingRuleOptions,
|
||||
final Map<String, Object> accountingMappings) {
|
||||
this.id = productData.id;
|
||||
@@ -242,8 +264,12 @@ public class LoanProductData {
|
||||
this.maxPrincipal = productData.maxPrincipal;
|
||||
this.inArrearsTolerance = productData.inArrearsTolerance;
|
||||
this.numberOfRepayments = productData.numberOfRepayments;
|
||||
this.minNumberOfRepayments = productData.minNumberOfRepayments;
|
||||
this.maxNumberOfRepayments = productData.maxNumberOfRepayments;
|
||||
this.repaymentEvery = productData.repaymentEvery;
|
||||
this.interestRatePerPeriod = productData.interestRatePerPeriod;
|
||||
this.minInterestRatePerPeriod = productData.minInterestRatePerPeriod;
|
||||
this.maxInterestRatePerPeriod = productData.maxInterestRatePerPeriod;
|
||||
this.annualInterestRate = productData.annualInterestRate;
|
||||
this.repaymentFrequencyType = productData.repaymentFrequencyType;
|
||||
this.interestRateFrequencyType = productData.interestRateFrequencyType;
|
||||
|
||||
+45
-6
@@ -91,16 +91,20 @@ public class LoanProduct extends AbstractPersistable<Long> {
|
||||
final PeriodFrequencyType interestFrequencyType = PeriodFrequencyType.fromInt(command
|
||||
.integerValueOfParameterNamed("interestRateFrequencyType"));
|
||||
final BigDecimal interestRatePerPeriod = command.bigDecimalValueOfParameterNamed("interestRatePerPeriod");
|
||||
final BigDecimal minInterestRatePerPeriod = command.bigDecimalValueOfParameterNamed("minInterestRatePerPeriod");
|
||||
final BigDecimal maxInterestRatePerPeriod = command.bigDecimalValueOfParameterNamed("maxInterestRatePerPeriod");
|
||||
final BigDecimal annualInterestRate = aprCalculator.calculateFrom(interestFrequencyType, interestRatePerPeriod);
|
||||
|
||||
final Integer repaymentEvery = command.integerValueOfParameterNamed("repaymentEvery");
|
||||
final Integer numberOfRepayments = command.integerValueOfParameterNamed("numberOfRepayments");
|
||||
final Integer minNumberOfRepayments = command.integerValueOfParameterNamed("minNumberOfRepayments");
|
||||
final Integer maxNumberOfRepayments = command.integerValueOfParameterNamed("maxNumberOfRepayments");
|
||||
final BigDecimal inArrearsTolerance = command.bigDecimalValueOfParameterNamed("inArrearsTolerance");
|
||||
final AccountingRuleType accountingRuleType = AccountingRuleType.fromInt(command.integerValueOfParameterNamed("accountingRule"));
|
||||
|
||||
return new LoanProduct(fund, loanTransactionProcessingStrategy, name, description, currency, principal, minPrincipal, maxPrincipal,
|
||||
interestRatePerPeriod, interestFrequencyType, annualInterestRate, interestMethod, interestCalculationPeriodMethod,
|
||||
repaymentEvery, repaymentFrequencyType, numberOfRepayments, amortizationMethod, inArrearsTolerance, productCharges,
|
||||
interestRatePerPeriod, minInterestRatePerPeriod, maxInterestRatePerPeriod, interestFrequencyType, annualInterestRate, interestMethod, interestCalculationPeriodMethod,
|
||||
repaymentEvery, repaymentFrequencyType, numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, amortizationMethod, inArrearsTolerance, productCharges,
|
||||
accountingRuleType);
|
||||
}
|
||||
|
||||
@@ -111,10 +115,12 @@ public class LoanProduct extends AbstractPersistable<Long> {
|
||||
public LoanProduct(final Fund fund, final LoanTransactionProcessingStrategy transactionProcessingStrategy, final String name,
|
||||
final String description, final MonetaryCurrency currency, final BigDecimal defaultPrincipal,
|
||||
final BigDecimal defaultMinPrincipal, final BigDecimal defaultMaxPrincipal,
|
||||
final BigDecimal defaultNominalInterestRatePerPeriod, final PeriodFrequencyType interestPeriodFrequencyType,
|
||||
final BigDecimal defaultNominalInterestRatePerPeriod, final BigDecimal defaultMinNominalInterestRatePerPeriod,
|
||||
final BigDecimal defaultMaxNominalInterestRatePerPeriod, final PeriodFrequencyType interestPeriodFrequencyType,
|
||||
final BigDecimal defaultAnnualNominalInterestRate, final InterestMethod interestMethod,
|
||||
final InterestCalculationPeriodMethod interestCalculationPeriodMethod, final Integer repayEvery,
|
||||
final PeriodFrequencyType repaymentFrequencyType, final Integer defaultNumberOfInstallments,
|
||||
final Integer defaultMinNumberOfInstallments, final Integer defaultMaxNumberOfInstallments,
|
||||
final AmortizationMethod amortizationMethod, final BigDecimal inArrearsTolerance, final List<Charge> charges,
|
||||
final AccountingRuleType accountingRuleType) {
|
||||
this.fund = fund;
|
||||
@@ -131,9 +137,10 @@ public class LoanProduct extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
this.loanProductRelatedDetail = new LoanProductRelatedDetail(currency, defaultPrincipal, defaultMinPrincipal, defaultMaxPrincipal,
|
||||
defaultNominalInterestRatePerPeriod, interestPeriodFrequencyType, defaultAnnualNominalInterestRate, interestMethod,
|
||||
interestCalculationPeriodMethod, repayEvery, repaymentFrequencyType, defaultNumberOfInstallments, amortizationMethod,
|
||||
inArrearsTolerance);
|
||||
defaultNominalInterestRatePerPeriod, defaultMinNominalInterestRatePerPeriod, defaultMaxNominalInterestRatePerPeriod,
|
||||
interestPeriodFrequencyType, defaultAnnualNominalInterestRate, interestMethod, interestCalculationPeriodMethod, repayEvery,
|
||||
repaymentFrequencyType, defaultNumberOfInstallments, defaultMinNumberOfInstallments, defaultMaxNumberOfInstallments,
|
||||
amortizationMethod, inArrearsTolerance);
|
||||
|
||||
if (accountingRuleType != null) {
|
||||
this.accountingRule = accountingRuleType.getValue();
|
||||
@@ -234,6 +241,10 @@ public class LoanProduct extends AbstractPersistable<Long> {
|
||||
return AccountingRuleType.ACCRUAL_BASED.getValue().equals(this.accountingRule);
|
||||
}
|
||||
|
||||
public Money getPrincipalAmount(){
|
||||
return this.loanProductRelatedDetail.getPrincipal();
|
||||
}
|
||||
|
||||
public Money getMinPrincipalAmount(){
|
||||
return this.loanProductRelatedDetail.getMinPrincipal();
|
||||
}
|
||||
@@ -241,4 +252,32 @@ public class LoanProduct extends AbstractPersistable<Long> {
|
||||
public Money getMaxPrincipalAmount(){
|
||||
return this.loanProductRelatedDetail.getMaxPrincipal();
|
||||
}
|
||||
|
||||
public BigDecimal getNominalInterestRatePerPeriod() {
|
||||
return this.loanProductRelatedDetail.getNominalInterestRatePerPeriod();
|
||||
}
|
||||
|
||||
public BigDecimal getMinNominalInterestRatePerPeriod() {
|
||||
return this.loanProductRelatedDetail.getMinNominalInterestRatePerPeriod();
|
||||
}
|
||||
|
||||
public BigDecimal getMaxNominalInterestRatePerPeriod(){
|
||||
return this.loanProductRelatedDetail.getMaxNominalInterestRatePerPeriod();
|
||||
}
|
||||
|
||||
public Integer getNumberOfRepayments(){
|
||||
return this.loanProductRelatedDetail.getNumberOfRepayments();
|
||||
}
|
||||
|
||||
public Integer getMinNumberOfRepayments() {
|
||||
return this.loanProductRelatedDetail.getMinNumberOfRepayments();
|
||||
}
|
||||
|
||||
public Integer getMaxNumberOfRepayments() {
|
||||
return this.loanProductRelatedDetail.getMaxNumberOfRepayments();
|
||||
}
|
||||
|
||||
public LoanProductRelatedDetail loanProductRelatedDetail(){
|
||||
return this.loanProductRelatedDetail;
|
||||
}
|
||||
}
|
||||
+79
-17
@@ -20,7 +20,6 @@ import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.mifosplatform.organisation.monetary.domain.Money;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
|
||||
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.AprCalculator;
|
||||
import org.mifosplatform.portfolio.loanproduct.exception.NotInMinMaxRangeException;
|
||||
|
||||
/**
|
||||
* LoanRepaymentScheduleDetail encapsulates all the details of a
|
||||
@@ -35,14 +34,20 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
|
||||
@Column(name = "principal_amount", scale = 6, precision = 19, nullable = false)
|
||||
private BigDecimal principal;
|
||||
|
||||
@Column(name = "min_principal_amount", scale = 6, precision = 19, nullable = false)
|
||||
@Column(name = "min_principal_amount", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal minPrincipal;
|
||||
|
||||
@Column(name = "max_principal_amount", scale = 6, precision = 19, nullable = false)
|
||||
@Column(name = "max_principal_amount", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal maxPrincipal;
|
||||
|
||||
@Column(name = "nominal_interest_rate_per_period", scale = 6, precision = 19, nullable = false)
|
||||
private BigDecimal nominalInterestRatePerPeriod;
|
||||
|
||||
@Column(name = "min_nominal_interest_rate_per_period", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal minNominalInterestRatePerPeriod;
|
||||
|
||||
@Column(name = "max_nominal_interest_rate_per_period", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal maxNominalInterestRatePerPeriod;
|
||||
|
||||
// FIXME - move away form JPA ordinal use for enums using just integer -
|
||||
// requires sql patch for existing users of software.
|
||||
@@ -77,6 +82,12 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
|
||||
@Column(name = "number_of_repayments", nullable = false)
|
||||
private Integer numberOfRepayments;
|
||||
|
||||
@Column(name = "min_number_of_repayments", nullable = true)
|
||||
private Integer minNumberOfRepayments;
|
||||
|
||||
@Column(name = "max_number_of_repayments", nullable = true)
|
||||
private Integer maxNumberOfRepayments;
|
||||
|
||||
// FIXME - move away form JPA ordinal use for enums using just integer -
|
||||
// requires sql patch for existing users of software.
|
||||
@Enumerated(EnumType.ORDINAL)
|
||||
@@ -88,14 +99,17 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
|
||||
|
||||
public static LoanProductRelatedDetail createFrom(final MonetaryCurrency currency, final BigDecimal principal,
|
||||
final BigDecimal minPrincipal, final BigDecimal maxPrincipal, final BigDecimal nominalInterestRatePerPeriod,
|
||||
final BigDecimal minNominalInterestRatePerPeriod, final BigDecimal maxNominalInterestRatePerPeriod,
|
||||
final PeriodFrequencyType interestRatePeriodFrequencyType, final BigDecimal nominalAnnualInterestRate,
|
||||
final InterestMethod interestMethod, final InterestCalculationPeriodMethod interestCalculationPeriodMethod,
|
||||
final Integer repaymentEvery, final PeriodFrequencyType repaymentPeriodFrequencyType, final Integer numberOfRepayments,
|
||||
final AmortizationMethod amortizationMethod, final BigDecimal inArrearsTolerance) {
|
||||
final Integer minNumberOfRepayments, final Integer maxNumberOfRepayments, final AmortizationMethod amortizationMethod,
|
||||
final BigDecimal inArrearsTolerance) {
|
||||
|
||||
return new LoanProductRelatedDetail(currency, principal, minPrincipal, maxPrincipal, nominalInterestRatePerPeriod, interestRatePeriodFrequencyType,
|
||||
return new LoanProductRelatedDetail(currency, principal, minPrincipal, maxPrincipal, nominalInterestRatePerPeriod,
|
||||
minNominalInterestRatePerPeriod, maxNominalInterestRatePerPeriod, interestRatePeriodFrequencyType,
|
||||
nominalAnnualInterestRate, interestMethod, interestCalculationPeriodMethod, repaymentEvery, repaymentPeriodFrequencyType,
|
||||
numberOfRepayments, amortizationMethod, inArrearsTolerance);
|
||||
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, amortizationMethod, inArrearsTolerance);
|
||||
}
|
||||
|
||||
protected LoanProductRelatedDetail() {
|
||||
@@ -104,16 +118,20 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
|
||||
|
||||
public LoanProductRelatedDetail(final MonetaryCurrency currency, final BigDecimal defaultPrincipal,
|
||||
final BigDecimal defaultMinPrincipal, final BigDecimal defaultMaxPrincipal,
|
||||
final BigDecimal defaultNominalInterestRatePerPeriod, final PeriodFrequencyType interestPeriodFrequencyType,
|
||||
final BigDecimal defaultNominalInterestRatePerPeriod, final BigDecimal defaultMinNominalInterestRatePerPeriod,
|
||||
final BigDecimal defaultMaxNominalInterestRatePerPeriod, final PeriodFrequencyType interestPeriodFrequencyType,
|
||||
final BigDecimal defaultAnnualNominalInterestRate, final InterestMethod interestMethod,
|
||||
final InterestCalculationPeriodMethod interestCalculationPeriodMethod, final Integer repayEvery,
|
||||
final PeriodFrequencyType repaymentFrequencyType, final Integer defaultNumberOfRepayments,
|
||||
final Integer defaultMinNumberOfRepayments, final Integer defaultMaxNumberOfRepayments,
|
||||
final AmortizationMethod amortizationMethod, final BigDecimal inArrearsTolerance) {
|
||||
this.currency = currency;
|
||||
this.principal = defaultPrincipal;
|
||||
this.minPrincipal = defaultMinPrincipal;
|
||||
this.maxPrincipal = defaultMaxPrincipal;
|
||||
this.nominalInterestRatePerPeriod = defaultNominalInterestRatePerPeriod;
|
||||
this.minNominalInterestRatePerPeriod = defaultMinNominalInterestRatePerPeriod;
|
||||
this.maxNominalInterestRatePerPeriod = defaultMaxNominalInterestRatePerPeriod;
|
||||
this.interestPeriodFrequencyType = interestPeriodFrequencyType;
|
||||
this.annualNominalInterestRate = defaultAnnualNominalInterestRate;
|
||||
this.interestMethod = interestMethod;
|
||||
@@ -121,6 +139,8 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
|
||||
this.repayEvery = repayEvery;
|
||||
this.repaymentPeriodFrequencyType = repaymentFrequencyType;
|
||||
this.numberOfRepayments = defaultNumberOfRepayments;
|
||||
this.minNumberOfRepayments = defaultMinNumberOfRepayments;
|
||||
this.maxNumberOfRepayments = defaultMaxNumberOfRepayments;
|
||||
this.amortizationMethod = amortizationMethod;
|
||||
if (inArrearsTolerance != null && BigDecimal.ZERO.compareTo(inArrearsTolerance) == 0) {
|
||||
this.inArrearsTolerance = null;
|
||||
@@ -152,7 +172,17 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
|
||||
public BigDecimal getNominalInterestRatePerPeriod() {
|
||||
return BigDecimal.valueOf(Double.valueOf(this.nominalInterestRatePerPeriod.stripTrailingZeros().toString()));
|
||||
}
|
||||
|
||||
public BigDecimal getMinNominalInterestRatePerPeriod() {
|
||||
return this.minNominalInterestRatePerPeriod == null ? null : BigDecimal.valueOf(Double.valueOf(this.minNominalInterestRatePerPeriod
|
||||
.stripTrailingZeros().toString()));
|
||||
}
|
||||
|
||||
public BigDecimal getMaxNominalInterestRatePerPeriod() {
|
||||
return this.maxNominalInterestRatePerPeriod == null ? null : BigDecimal.valueOf(Double.valueOf(this.maxNominalInterestRatePerPeriod
|
||||
.stripTrailingZeros().toString()));
|
||||
}
|
||||
|
||||
public PeriodFrequencyType getInterestPeriodFrequencyType() {
|
||||
return interestPeriodFrequencyType;
|
||||
}
|
||||
@@ -183,7 +213,15 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
|
||||
public Integer getNumberOfRepayments() {
|
||||
return numberOfRepayments;
|
||||
}
|
||||
|
||||
public Integer getMinNumberOfRepayments() {
|
||||
return minNumberOfRepayments;
|
||||
}
|
||||
|
||||
public Integer getMaxNumberOfRepayments() {
|
||||
return maxNumberOfRepayments;
|
||||
}
|
||||
|
||||
public AmortizationMethod getAmortizationMethod() {
|
||||
return amortizationMethod;
|
||||
}
|
||||
@@ -227,7 +265,7 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
|
||||
final String localeAsInput = command.locale();
|
||||
|
||||
final String minPrincipalParamName = "minPrincipal";
|
||||
if (command.isChangeInBigDecimalParameterNamed(minPrincipalParamName, this.minPrincipal)) {
|
||||
if (command.isChangeInBigDecimalParameterNamedWithNullCheck(minPrincipalParamName, this.minPrincipal)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(minPrincipalParamName);
|
||||
actualChanges.put(minPrincipalParamName, newValue);
|
||||
actualChanges.put("locale", localeAsInput);
|
||||
@@ -235,7 +273,7 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
|
||||
}
|
||||
|
||||
final String maxPrincipalParamName = "maxPrincipal";
|
||||
if (command.isChangeInBigDecimalParameterNamed(maxPrincipalParamName, this.maxPrincipal)) {
|
||||
if (command.isChangeInBigDecimalParameterNamedWithNullCheck(maxPrincipalParamName, this.maxPrincipal)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(maxPrincipalParamName);
|
||||
actualChanges.put(maxPrincipalParamName, newValue);
|
||||
actualChanges.put("locale", localeAsInput);
|
||||
@@ -248,7 +286,6 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
|
||||
actualChanges.put(principalParamName, newValue);
|
||||
actualChanges.put("locale", localeAsInput);
|
||||
this.principal = newValue;
|
||||
validatePrincipalAmount();
|
||||
}
|
||||
|
||||
final String repaymentEveryParamName = "repaymentEvery";
|
||||
@@ -267,6 +304,22 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
|
||||
this.repaymentPeriodFrequencyType = PeriodFrequencyType.fromInt(newValue);
|
||||
}
|
||||
|
||||
final String minNumberOfRepaymentsParamName = "minNumberOfRepayments";
|
||||
if (command.isChangeInIntegerParameterNamed(minNumberOfRepaymentsParamName, this.minNumberOfRepayments)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(minNumberOfRepaymentsParamName);
|
||||
actualChanges.put(minNumberOfRepaymentsParamName, newValue);
|
||||
actualChanges.put("locale", localeAsInput);
|
||||
this.minNumberOfRepayments = newValue;
|
||||
}
|
||||
|
||||
final String maxNumberOfRepaymentsParamName = "maxNumberOfRepayments";
|
||||
if (command.isChangeInIntegerParameterNamed(maxNumberOfRepaymentsParamName, this.maxNumberOfRepayments)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(maxNumberOfRepaymentsParamName);
|
||||
actualChanges.put(maxNumberOfRepaymentsParamName, newValue);
|
||||
actualChanges.put("locale", localeAsInput);
|
||||
this.maxNumberOfRepayments = newValue;
|
||||
}
|
||||
|
||||
final String numberOfRepaymentsParamName = "numberOfRepayments";
|
||||
if (command.isChangeInIntegerParameterNamed(numberOfRepaymentsParamName, this.numberOfRepayments)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(numberOfRepaymentsParamName);
|
||||
@@ -291,6 +344,22 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
|
||||
this.inArrearsTolerance = newValue;
|
||||
}
|
||||
|
||||
final String minInterestRatePerPeriodParamName = "minInterestRatePerPeriod";
|
||||
if (command.isChangeInBigDecimalParameterNamedWithNullCheck(minInterestRatePerPeriodParamName, this.minNominalInterestRatePerPeriod)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(minInterestRatePerPeriodParamName);
|
||||
actualChanges.put(minInterestRatePerPeriodParamName, newValue);
|
||||
actualChanges.put("locale", localeAsInput);
|
||||
this.minNominalInterestRatePerPeriod = newValue;
|
||||
}
|
||||
|
||||
final String maxInterestRatePerPeriodParamName = "maxInterestRatePerPeriod";
|
||||
if (command.isChangeInBigDecimalParameterNamedWithNullCheck(maxInterestRatePerPeriodParamName, this.maxNominalInterestRatePerPeriod)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(maxInterestRatePerPeriodParamName);
|
||||
actualChanges.put(maxInterestRatePerPeriodParamName, newValue);
|
||||
actualChanges.put("locale", localeAsInput);
|
||||
this.maxNominalInterestRatePerPeriod = newValue;
|
||||
}
|
||||
|
||||
final String interestRatePerPeriodParamName = "interestRatePerPeriod";
|
||||
if (command.isChangeInBigDecimalParameterNamed(interestRatePerPeriodParamName, this.nominalInterestRatePerPeriod)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(interestRatePerPeriodParamName);
|
||||
@@ -329,13 +398,6 @@ public class LoanProductRelatedDetail implements LoanProductMinimumRepaymentSche
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
private void validatePrincipalAmount() {
|
||||
if(this.principal.compareTo(this.minPrincipal) == -1 || this.principal.compareTo(maxPrincipal) == 1){
|
||||
final String errorMessage = "The Principal amount " + this.principal + " is invalid. Must be an amount between " + this.minPrincipal + " and " + this.maxPrincipal + " inclusive.";
|
||||
throw new NotInMinMaxRangeException("loan", "principal.amount", errorMessage, this.principal, this.minPrincipal, this.maxPrincipal);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateInterestRateDerivedFields(final AprCalculator aprCalculator) {
|
||||
this.annualNominalInterestRate = aprCalculator.calculateFrom(this.interestPeriodFrequencyType, this.nominalInterestRatePerPeriod);
|
||||
}
|
||||
|
||||
+296
-26
@@ -23,6 +23,7 @@ import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.AccountingRuleType;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRelatedDetail;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -36,9 +37,10 @@ public final class LoanProductCommandFromApiJsonDeserializer {
|
||||
* The parameters supported for this command.
|
||||
*/
|
||||
private final Set<String> supportedParameters = new HashSet<String>(Arrays.asList("locale", "name", "description", "fundId",
|
||||
"currencyCode", "digitsAfterDecimal", "principal", "minPrincipal", "maxPrincipal", "repaymentEvery", "numberOfRepayments", "repaymentFrequencyType",
|
||||
"interestRatePerPeriod", "interestRateFrequencyType", "amortizationType", "interestType", "interestCalculationPeriodType",
|
||||
"inArrearsTolerance", "transactionProcessingStrategyId", "charges", "accountingRule",
|
||||
"currencyCode", "digitsAfterDecimal", "principal", "minPrincipal", "maxPrincipal", "repaymentEvery", "numberOfRepayments",
|
||||
"minNumberOfRepayments", "maxNumberOfRepayments", "repaymentFrequencyType", "interestRatePerPeriod",
|
||||
"minInterestRatePerPeriod", "maxInterestRatePerPeriod", "interestRateFrequencyType", "amortizationType", "interestType",
|
||||
"interestCalculationPeriodType", "inArrearsTolerance", "transactionProcessingStrategyId", "charges", "accountingRule",
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.FEES_RECEIVABLE.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.FUND_SOURCE.getValue(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(),
|
||||
LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_LOANS.getValue(), LOAN_PRODUCT_ACCOUNTING_PARAMS.INTEREST_RECEIVABLE.getValue(),
|
||||
@@ -80,29 +82,104 @@ public final class LoanProductCommandFromApiJsonDeserializer {
|
||||
|
||||
final Integer digitsAfterDecimal = fromApiJsonHelper.extractIntegerNamed("digitsAfterDecimal", element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("digitsAfterDecimal").value(digitsAfterDecimal).notNull().inMinMaxRange(0, 6);
|
||||
|
||||
final BigDecimal minPrincipal = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("minPrincipal", element);
|
||||
baseDataValidator.reset().parameter("minPrincipal").value(minPrincipal).notNull().positiveAmount();
|
||||
|
||||
final BigDecimal maxPrincipal = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("maxPrincipal", element);
|
||||
baseDataValidator.reset().parameter("maxPrincipal").value(maxPrincipal).notNull().positiveAmount();
|
||||
|
||||
final BigDecimal principal = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("principal", element);
|
||||
baseDataValidator.reset().parameter("principal").value(principal).notNull().positiveAmount().inMinAndMaxAmountRange(minPrincipal, maxPrincipal);
|
||||
baseDataValidator.reset().parameter("principal").value(principal).notNull().positiveAmount();
|
||||
|
||||
String minPrincipalParameterName = "minPrincipal";
|
||||
BigDecimal minPrincipalAmount = null;
|
||||
if(fromApiJsonHelper.parameterExists(minPrincipalParameterName, element)){
|
||||
minPrincipalAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(minPrincipalParameterName, element);
|
||||
baseDataValidator.reset().parameter(minPrincipalParameterName).value(minPrincipalAmount).ignoreIfNull().positiveAmount();
|
||||
}
|
||||
|
||||
String maxPrincipalParameterName = "maxPrincipal";
|
||||
BigDecimal maxPrincipalAmount = null;
|
||||
if(fromApiJsonHelper.parameterExists(maxPrincipalParameterName, element)){
|
||||
maxPrincipalAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(maxPrincipalParameterName, element);
|
||||
baseDataValidator.reset().parameter(maxPrincipalParameterName).value(maxPrincipalAmount).ignoreIfNull().positiveAmount();
|
||||
}
|
||||
|
||||
if (maxPrincipalAmount != null && maxPrincipalAmount.compareTo(BigDecimal.ZERO) != -1) {
|
||||
if (minPrincipalAmount != null && minPrincipalAmount.compareTo(BigDecimal.ZERO) != -1) {
|
||||
baseDataValidator.reset().parameter(maxPrincipalParameterName).value(maxPrincipalAmount).notLessThanMin(minPrincipalAmount);
|
||||
if(minPrincipalAmount.compareTo(maxPrincipalAmount) <= 0){
|
||||
baseDataValidator.reset().parameter("principal").value(principal).inMinAndMaxAmountRange(minPrincipalAmount, maxPrincipalAmount);
|
||||
}
|
||||
}else{
|
||||
baseDataValidator.reset().parameter("principal").value(principal).notGreaterThanMax(maxPrincipalAmount);
|
||||
}
|
||||
}else if (minPrincipalAmount != null && minPrincipalAmount.compareTo(BigDecimal.ZERO) != -1) {
|
||||
baseDataValidator.reset().parameter("principal").value(principal).notLessThanMin(minPrincipalAmount);
|
||||
}
|
||||
|
||||
final Integer numberOfRepayments = fromApiJsonHelper.extractIntegerWithLocaleNamed("numberOfRepayments", element);
|
||||
baseDataValidator.reset().parameter("numberOfRepayments").value(numberOfRepayments).notNull().integerGreaterThanZero();
|
||||
|
||||
String minNumberOfRepaymentsParameterName = "minNumberOfRepayments";
|
||||
Integer minNumberOfRepayments = null;
|
||||
if(fromApiJsonHelper.parameterExists(minNumberOfRepaymentsParameterName, element)){
|
||||
minNumberOfRepayments = fromApiJsonHelper.extractIntegerWithLocaleNamed(minNumberOfRepaymentsParameterName, element);
|
||||
baseDataValidator.reset().parameter(minNumberOfRepaymentsParameterName).value(minNumberOfRepayments).ignoreIfNull().integerGreaterThanZero();
|
||||
}
|
||||
|
||||
String maxNumberOfRepaymentsParameterName = "maxNumberOfRepayments";
|
||||
Integer maxNumberOfRepayments = null;
|
||||
if(fromApiJsonHelper.parameterExists(maxNumberOfRepaymentsParameterName, element)){
|
||||
maxNumberOfRepayments = fromApiJsonHelper.extractIntegerWithLocaleNamed(maxNumberOfRepaymentsParameterName, element);
|
||||
baseDataValidator.reset().parameter(maxNumberOfRepaymentsParameterName).value(maxNumberOfRepayments).ignoreIfNull().integerGreaterThanZero();
|
||||
}
|
||||
|
||||
if(maxNumberOfRepayments != null && maxNumberOfRepayments.compareTo(0) == 1){
|
||||
if(minNumberOfRepayments != null && minNumberOfRepayments.compareTo(0) == 1){
|
||||
baseDataValidator.reset().parameter(maxNumberOfRepaymentsParameterName).value(maxNumberOfRepayments).notLessThanMin(minNumberOfRepayments);
|
||||
if(minNumberOfRepayments.compareTo(maxNumberOfRepayments) <= 0){
|
||||
baseDataValidator.reset().parameter("numberOfRepayments").value(numberOfRepayments).inMinMaxRange(minNumberOfRepayments, maxNumberOfRepayments);
|
||||
}
|
||||
}else{
|
||||
baseDataValidator.reset().parameter("numberOfRepayments").value(numberOfRepayments).notGreaterThanMax(maxNumberOfRepayments);
|
||||
}
|
||||
}else if(minNumberOfRepayments != null && minNumberOfRepayments.compareTo(0) == 1){
|
||||
baseDataValidator.reset().parameter("numberOfRepayments").value(numberOfRepayments).notLessThanMin(minNumberOfRepayments);
|
||||
}
|
||||
|
||||
final Integer repaymentEvery = fromApiJsonHelper.extractIntegerWithLocaleNamed("repaymentEvery", element);
|
||||
baseDataValidator.reset().parameter("repaymentEvery").value(repaymentEvery).notNull().integerGreaterThanZero();
|
||||
|
||||
final Integer repaymentFrequencyType = fromApiJsonHelper
|
||||
.extractIntegerNamed("repaymentFrequencyType", element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("repaymentFrequencyType").value(repaymentFrequencyType).notNull().inMinMaxRange(0, 3);
|
||||
|
||||
|
||||
final BigDecimal interestRatePerPeriod = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("interestRatePerPeriod", element);
|
||||
baseDataValidator.reset().parameter("interestRatePerPeriod").value(interestRatePerPeriod).notNull().zeroOrPositiveAmount();
|
||||
|
||||
String minInterestRatePerPeriodParameterName = "minInterestRatePerPeriod";
|
||||
BigDecimal minInterestRatePerPeriod = null;
|
||||
if(fromApiJsonHelper.parameterExists(minInterestRatePerPeriodParameterName, element)){
|
||||
minInterestRatePerPeriod = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(minInterestRatePerPeriodParameterName, element);
|
||||
baseDataValidator.reset().parameter(minInterestRatePerPeriodParameterName).value(minInterestRatePerPeriod).ignoreIfNull().zeroOrPositiveAmount();
|
||||
}
|
||||
|
||||
String maxInterestRatePerPeriodParameterName = "maxInterestRatePerPeriod";
|
||||
BigDecimal maxInterestRatePerPeriod = null;
|
||||
if(fromApiJsonHelper.parameterExists(maxInterestRatePerPeriodParameterName, element)){
|
||||
maxInterestRatePerPeriod = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(maxInterestRatePerPeriodParameterName, element);
|
||||
baseDataValidator.reset().parameter(maxInterestRatePerPeriodParameterName).value(maxInterestRatePerPeriod).ignoreIfNull().zeroOrPositiveAmount();
|
||||
}
|
||||
|
||||
if(maxInterestRatePerPeriod != null && maxInterestRatePerPeriod.compareTo(BigDecimal.ZERO) != -1){
|
||||
if(minInterestRatePerPeriod != null && minInterestRatePerPeriod.compareTo(BigDecimal.ZERO) != -1){
|
||||
baseDataValidator.reset().parameter(maxInterestRatePerPeriodParameterName).value(maxInterestRatePerPeriod).notLessThanMin(minInterestRatePerPeriod);
|
||||
if(minInterestRatePerPeriod.compareTo(maxInterestRatePerPeriod) <= 0){
|
||||
baseDataValidator.reset().parameter("interestRatePerPeriod").value(interestRatePerPeriod).inMinAndMaxAmountRange(minInterestRatePerPeriod, maxInterestRatePerPeriod);
|
||||
}
|
||||
}else{
|
||||
baseDataValidator.reset().parameter("interestRatePerPeriod").value(interestRatePerPeriod).notGreaterThanMax(maxInterestRatePerPeriod);
|
||||
}
|
||||
}else if(minInterestRatePerPeriod != null && minInterestRatePerPeriod.compareTo(BigDecimal.ZERO) != -1){
|
||||
baseDataValidator.reset().parameter("interestRatePerPeriod").value(interestRatePerPeriod).notLessThanMin(minInterestRatePerPeriod);
|
||||
}
|
||||
|
||||
final Integer interestRateFrequencyType = fromApiJsonHelper.extractIntegerNamed("interestRateFrequencyType", element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("interestRateFrequencyType").value(interestRateFrequencyType).notNull().inMinMaxRange(0, 3);
|
||||
@@ -223,28 +300,19 @@ public final class LoanProductCommandFromApiJsonDeserializer {
|
||||
BigDecimal minPrincipalAmount = null;
|
||||
if(fromApiJsonHelper.parameterExists(minPrincipalParameterName, element)){
|
||||
minPrincipalAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(minPrincipalParameterName, element);
|
||||
baseDataValidator.reset().parameter(minPrincipalParameterName).value(minPrincipalAmount).ignoreIfNull().positiveAmount();
|
||||
}
|
||||
|
||||
String maxPrincipalParameterName = "maxPrincipal";
|
||||
BigDecimal maxPrincipalAmount = null;
|
||||
if(fromApiJsonHelper.parameterExists(maxPrincipalParameterName, element)){
|
||||
maxPrincipalAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(maxPrincipalParameterName, element);
|
||||
}
|
||||
|
||||
//Principal amount is allowed to change only when Min and Max principal amounts are sent in JSON request
|
||||
//Validate if minPrincipal amount or principal amount is part of JSON request.
|
||||
if(fromApiJsonHelper.parameterExists(minPrincipalParameterName, element) || fromApiJsonHelper.parameterExists("principal", element)){
|
||||
baseDataValidator.reset().parameter(minPrincipalParameterName).value(minPrincipalAmount).notNull().positiveAmount();
|
||||
}
|
||||
|
||||
//Validate if maxPrincipal amount or principal amount is part of JSON request.
|
||||
if(fromApiJsonHelper.parameterExists(maxPrincipalParameterName, element) || fromApiJsonHelper.parameterExists("principal", element)){
|
||||
baseDataValidator.reset().parameter(maxPrincipalParameterName).value(maxPrincipalAmount).notNull().positiveAmount();
|
||||
baseDataValidator.reset().parameter(maxPrincipalParameterName).value(maxPrincipalAmount).ignoreIfNull().positiveAmount();
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("principal", element)) {
|
||||
final BigDecimal principal = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("principal", element);
|
||||
baseDataValidator.reset().parameter("principal").value(principal).notNull().positiveAmount().inMinAndMaxAmountRange(minPrincipalAmount, maxPrincipalAmount);
|
||||
baseDataValidator.reset().parameter("principal").value(principal).notNull().positiveAmount();
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("inArrearsTolerance", element)) {
|
||||
@@ -252,11 +320,39 @@ public final class LoanProductCommandFromApiJsonDeserializer {
|
||||
baseDataValidator.reset().parameter("inArrearsTolerance").value(inArrearsTolerance).ignoreIfNull().zeroOrPositiveAmount();
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("interestRatePerPeriod", element)) {
|
||||
final BigDecimal interestRatePerPeriod = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("interestRatePerPeriod", element);
|
||||
baseDataValidator.reset().parameter("interestRatePerPeriod").value(interestRatePerPeriod).notNull().zeroOrPositiveAmount();
|
||||
String minInterestRatePerPeriodParameterName = "minInterestRatePerPeriod";
|
||||
BigDecimal minInterestRatePerPeriod = null;
|
||||
if (fromApiJsonHelper.parameterExists(minInterestRatePerPeriodParameterName, element)) {
|
||||
minInterestRatePerPeriod = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(minInterestRatePerPeriodParameterName, element);
|
||||
baseDataValidator.reset().parameter(minInterestRatePerPeriodParameterName).value(minInterestRatePerPeriod).ignoreIfNull().zeroOrPositiveAmount();
|
||||
}
|
||||
|
||||
String maxInterestRatePerPeriodParameterName = "maxInterestRatePerPeriod";
|
||||
BigDecimal maxInterestRatePerPeriod = null;
|
||||
if (fromApiJsonHelper.parameterExists(maxInterestRatePerPeriodParameterName, element)) {
|
||||
maxInterestRatePerPeriod = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(maxInterestRatePerPeriodParameterName, element);
|
||||
baseDataValidator.reset().parameter(maxInterestRatePerPeriodParameterName).value(maxInterestRatePerPeriod).ignoreIfNull().zeroOrPositiveAmount();
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("interestRatePerPeriod", element)) {
|
||||
final BigDecimal interestRatePerPeriod = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("interestRatePerPeriod", element);
|
||||
baseDataValidator.reset().parameter("interestRatePerPeriod").value(interestRatePerPeriod).notNull().positiveAmount();
|
||||
}
|
||||
|
||||
String minNumberOfRepaymentsParameterName = "minNumberOfRepayments";
|
||||
Integer minNumberOfRepayments = null;
|
||||
if (fromApiJsonHelper.parameterExists(minNumberOfRepaymentsParameterName, element)) {
|
||||
minNumberOfRepayments = fromApiJsonHelper.extractIntegerWithLocaleNamed(minNumberOfRepaymentsParameterName, element);
|
||||
baseDataValidator.reset().parameter(minNumberOfRepaymentsParameterName).value(minNumberOfRepayments).ignoreIfNull().integerGreaterThanZero();
|
||||
}
|
||||
|
||||
String maxNumberOfRepaymentsParameterName = "maxNumberOfRepayments";
|
||||
Integer maxNumberOfRepayments = null;
|
||||
if (fromApiJsonHelper.parameterExists(maxNumberOfRepaymentsParameterName, element)) {
|
||||
maxNumberOfRepayments = fromApiJsonHelper.extractIntegerWithLocaleNamed(maxNumberOfRepaymentsParameterName, element);
|
||||
baseDataValidator.reset().parameter(maxNumberOfRepaymentsParameterName).value(maxNumberOfRepayments).ignoreIfNull().integerGreaterThanZero();
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("numberOfRepayments", element)) {
|
||||
final Integer numberOfRepayments = fromApiJsonHelper.extractIntegerWithLocaleNamed("numberOfRepayments", element);
|
||||
baseDataValidator.reset().parameter("numberOfRepayments").value(numberOfRepayments).notNull().integerGreaterThanZero();
|
||||
@@ -352,6 +448,180 @@ public final class LoanProductCommandFromApiJsonDeserializer {
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
public void validateMinMaxConstraints(final JsonElement element, final LoanProductRelatedDetail loanProductRelatedDetail, final String resource){
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource(resource);
|
||||
|
||||
validatePrincipalMinMaxConstraint(element, loanProductRelatedDetail, baseDataValidator);
|
||||
|
||||
validateNumberOfRepaymentsMinMaxConstraint(element, loanProductRelatedDetail, baseDataValidator);
|
||||
|
||||
validateNominalInterestRatePerPeriodMinMaxConstraint(element, loanProductRelatedDetail, baseDataValidator);
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
private void validatePrincipalMinMaxConstraint(final JsonElement element, final LoanProductRelatedDetail loanProductRelatedDetail, final DataValidatorBuilder baseDataValidator) {
|
||||
|
||||
boolean principalUpdated = false;
|
||||
boolean minPrincipalUpdated = false;
|
||||
boolean maxPrincipalUpdated = false;
|
||||
String principalParameterName = "principal";
|
||||
BigDecimal principalAmount = null;
|
||||
if (fromApiJsonHelper.parameterExists(principalParameterName, element)) {
|
||||
principalAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(principalParameterName, element);
|
||||
principalUpdated = true;
|
||||
}else{
|
||||
principalAmount = loanProductRelatedDetail.getPrincipal().getAmount();
|
||||
}
|
||||
|
||||
String minPrincipalParameterName = "minPrincipal";
|
||||
BigDecimal minPrincipalAmount = null;
|
||||
if(fromApiJsonHelper.parameterExists(minPrincipalParameterName, element)){
|
||||
minPrincipalAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(minPrincipalParameterName, element);
|
||||
minPrincipalUpdated = true;
|
||||
}else{
|
||||
minPrincipalAmount = loanProductRelatedDetail.getMinPrincipal().getAmount();
|
||||
}
|
||||
|
||||
String maxPrincipalParameterName = "maxPrincipal";
|
||||
BigDecimal maxPrincipalAmount = null;
|
||||
if(fromApiJsonHelper.parameterExists(maxPrincipalParameterName, element)){
|
||||
maxPrincipalAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(maxPrincipalParameterName, element);
|
||||
maxPrincipalUpdated = true;
|
||||
}else{
|
||||
maxPrincipalAmount = loanProductRelatedDetail.getMaxPrincipal().getAmount();
|
||||
}
|
||||
|
||||
if(minPrincipalUpdated){
|
||||
baseDataValidator.reset().parameter(minPrincipalParameterName).value(minPrincipalAmount).notGreaterThanMax(maxPrincipalAmount);
|
||||
}
|
||||
|
||||
if(maxPrincipalUpdated){
|
||||
baseDataValidator.reset().parameter(maxPrincipalParameterName).value(maxPrincipalAmount).notLessThanMin(minPrincipalAmount);
|
||||
}
|
||||
|
||||
if((principalUpdated || minPrincipalUpdated || maxPrincipalUpdated)){
|
||||
|
||||
if((minPrincipalAmount != null && minPrincipalAmount.compareTo(BigDecimal.ZERO) == 1) && (maxPrincipalAmount != null && maxPrincipalAmount.compareTo(BigDecimal.ZERO) == 1)){
|
||||
baseDataValidator.reset().parameter(principalParameterName).value(principalAmount).inMinAndMaxAmountRange(minPrincipalAmount, maxPrincipalAmount);
|
||||
}else{
|
||||
if(minPrincipalAmount != null && minPrincipalAmount.compareTo(BigDecimal.ZERO) == 1){
|
||||
baseDataValidator.reset().parameter(principalParameterName).value(principalAmount).notLessThanMin(minPrincipalAmount);
|
||||
}else if(maxPrincipalAmount != null && maxPrincipalAmount.compareTo(BigDecimal.ZERO) == 1){
|
||||
baseDataValidator.reset().parameter(principalParameterName).value(principalAmount).notGreaterThanMax(maxPrincipalAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateNumberOfRepaymentsMinMaxConstraint(final JsonElement element, final LoanProductRelatedDetail loanProductRelatedDetail, final DataValidatorBuilder baseDataValidator) {
|
||||
boolean numberOfRepaymentsUpdated = false;
|
||||
boolean minNumberOfRepaymentsUpdated = false;
|
||||
boolean maxNumberOfRepaymentsUpdated = false;
|
||||
|
||||
String numberOfRepaymentsParameterName = "numberOfRepayments";
|
||||
Integer numberOfRepayments = null;
|
||||
if (fromApiJsonHelper.parameterExists(numberOfRepaymentsParameterName, element)) {
|
||||
numberOfRepayments = fromApiJsonHelper.extractIntegerWithLocaleNamed(numberOfRepaymentsParameterName, element);
|
||||
numberOfRepaymentsUpdated = true;
|
||||
}else{
|
||||
numberOfRepayments = loanProductRelatedDetail.getNumberOfRepayments();
|
||||
}
|
||||
|
||||
String minNumberOfRepaymentsParameterName = "minNumberOfRepayments";
|
||||
Integer minNumberOfRepayments = null;
|
||||
if (fromApiJsonHelper.parameterExists(minNumberOfRepaymentsParameterName, element)) {
|
||||
minNumberOfRepayments = fromApiJsonHelper.extractIntegerWithLocaleNamed(minNumberOfRepaymentsParameterName, element);
|
||||
minNumberOfRepaymentsUpdated = true;
|
||||
}else{
|
||||
minNumberOfRepayments = loanProductRelatedDetail.getMinNumberOfRepayments();
|
||||
}
|
||||
|
||||
String maxNumberOfRepaymentsParameterName = "maxNumberOfRepayments";
|
||||
Integer maxNumberOfRepayments = null;
|
||||
if (fromApiJsonHelper.parameterExists(maxNumberOfRepaymentsParameterName, element)) {
|
||||
maxNumberOfRepayments = fromApiJsonHelper.extractIntegerWithLocaleNamed(maxNumberOfRepaymentsParameterName, element);
|
||||
maxNumberOfRepaymentsUpdated = true;
|
||||
}else{
|
||||
maxNumberOfRepayments = loanProductRelatedDetail.getMaxNumberOfRepayments();
|
||||
}
|
||||
|
||||
if(minNumberOfRepaymentsUpdated){
|
||||
baseDataValidator.reset().parameter(minNumberOfRepaymentsParameterName).value(minNumberOfRepayments).ignoreIfNull().notGreaterThanMax(maxNumberOfRepayments);
|
||||
}
|
||||
|
||||
if(maxNumberOfRepaymentsUpdated){
|
||||
baseDataValidator.reset().parameter(maxNumberOfRepaymentsParameterName).value(maxNumberOfRepayments).notLessThanMin(minNumberOfRepayments);
|
||||
}
|
||||
|
||||
if(numberOfRepaymentsUpdated || minNumberOfRepaymentsUpdated || maxNumberOfRepaymentsUpdated){
|
||||
if(maxNumberOfRepayments != null && maxNumberOfRepayments.compareTo(0) == 1){
|
||||
if(minNumberOfRepayments != null && minNumberOfRepayments.compareTo(0) == 1){
|
||||
baseDataValidator.reset().parameter(numberOfRepaymentsParameterName).value(numberOfRepayments).inMinMaxRange(minNumberOfRepayments, maxNumberOfRepayments);
|
||||
}else{
|
||||
baseDataValidator.reset().parameter(numberOfRepaymentsParameterName).value(numberOfRepayments).notGreaterThanMax(maxNumberOfRepayments);
|
||||
}
|
||||
}else if(minNumberOfRepayments != null && minNumberOfRepayments.compareTo(0) == 1){
|
||||
baseDataValidator.reset().parameter(numberOfRepaymentsParameterName).value(numberOfRepayments).notLessThanMin(minNumberOfRepayments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateNominalInterestRatePerPeriodMinMaxConstraint(final JsonElement element, final LoanProductRelatedDetail loanProductRelatedDetail, final DataValidatorBuilder baseDataValidator) {
|
||||
|
||||
boolean iRPUpdated = false;
|
||||
boolean minIRPUpdated = false;
|
||||
boolean maxIRPUpdated = false;
|
||||
String interestRatePerPeriodParameterName = "interestRatePerPeriod";
|
||||
BigDecimal interestRatePerPeriod = null;
|
||||
|
||||
if (fromApiJsonHelper.parameterExists(interestRatePerPeriodParameterName, element)) {
|
||||
interestRatePerPeriod = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(interestRatePerPeriodParameterName, element);
|
||||
iRPUpdated = true;
|
||||
}else{
|
||||
interestRatePerPeriod = loanProductRelatedDetail.getNominalInterestRatePerPeriod();
|
||||
}
|
||||
|
||||
String minInterestRatePerPeriodParameterName = "minInterestRatePerPeriod";
|
||||
BigDecimal minInterestRatePerPeriod = null;
|
||||
if (fromApiJsonHelper.parameterExists(minInterestRatePerPeriodParameterName, element)) {
|
||||
minInterestRatePerPeriod = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(minInterestRatePerPeriodParameterName, element);
|
||||
minIRPUpdated = true;
|
||||
}else{
|
||||
minInterestRatePerPeriod = loanProductRelatedDetail.getMinNominalInterestRatePerPeriod();
|
||||
}
|
||||
|
||||
String maxInterestRatePerPeriodParameterName = "maxInterestRatePerPeriod";
|
||||
BigDecimal maxInterestRatePerPeriod = null;
|
||||
if (fromApiJsonHelper.parameterExists(maxInterestRatePerPeriodParameterName, element)) {
|
||||
maxInterestRatePerPeriod = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(maxInterestRatePerPeriodParameterName, element);
|
||||
maxIRPUpdated = true;
|
||||
}else{
|
||||
maxInterestRatePerPeriod = loanProductRelatedDetail.getMaxNominalInterestRatePerPeriod();
|
||||
}
|
||||
|
||||
if(minIRPUpdated){
|
||||
baseDataValidator.reset().parameter(minInterestRatePerPeriodParameterName).value(minInterestRatePerPeriod).ignoreIfNull().notGreaterThanMax(maxInterestRatePerPeriod);
|
||||
}
|
||||
|
||||
if(maxIRPUpdated){
|
||||
baseDataValidator.reset().parameter(maxInterestRatePerPeriodParameterName).value(maxInterestRatePerPeriod).ignoreIfNull().notLessThanMin(minInterestRatePerPeriod);
|
||||
}
|
||||
|
||||
if(iRPUpdated || minIRPUpdated || maxIRPUpdated){
|
||||
if(maxInterestRatePerPeriod != null){
|
||||
if(minInterestRatePerPeriod != null){
|
||||
baseDataValidator.reset().parameter(interestRatePerPeriodParameterName).value(interestRatePerPeriod).inMinAndMaxAmountRange(minInterestRatePerPeriod, maxInterestRatePerPeriod);
|
||||
}else{
|
||||
baseDataValidator.reset().parameter(interestRatePerPeriodParameterName).value(interestRatePerPeriod).notGreaterThanMax(maxInterestRatePerPeriod);
|
||||
}
|
||||
}else if(minInterestRatePerPeriod != null){
|
||||
baseDataValidator.reset().parameter(interestRatePerPeriodParameterName).value(interestRatePerPeriod).notLessThanMin(minInterestRatePerPeriod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isCashBasedAccounting(final Integer accountingRuleType) {
|
||||
return AccountingRuleType.CASH_BASED.getValue().equals(accountingRuleType);
|
||||
}
|
||||
|
||||
+8
-3
@@ -97,9 +97,9 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
||||
return "lp.id as id, lp.fund_id as fundId, f.name as fundName, lp.loan_transaction_strategy_id as transactionStrategyId, ltps.name as transactionStrategyName, "
|
||||
+ "lp.name as name, lp.description as description, "
|
||||
+ "lp.principal_amount as principal, lp.min_principal_amount as minPrincipal, lp.max_principal_amount as maxPrincipal, lp.currency_code as currencyCode, lp.currency_digits as currencyDigits, "
|
||||
+ "lp.nominal_interest_rate_per_period as interestRatePerPeriod, lp.interest_period_frequency_enum as interestRatePerPeriodFreq, "
|
||||
+ "lp.nominal_interest_rate_per_period as interestRatePerPeriod, lp.min_nominal_interest_rate_per_period as minInterestRatePerPeriod, lp.max_nominal_interest_rate_per_period as maxInterestRatePerPeriod, lp.interest_period_frequency_enum as interestRatePerPeriodFreq, "
|
||||
+ "lp.annual_nominal_interest_rate as annualInterestRate, lp.interest_method_enum as interestMethod, lp.interest_calculated_in_period_enum as interestCalculationInPeriodMethod,"
|
||||
+ "lp.repay_every as repaidEvery, lp.repayment_period_frequency_enum as repaymentPeriodFrequency, lp.number_of_repayments as numberOfRepayments, "
|
||||
+ "lp.repay_every as repaidEvery, lp.repayment_period_frequency_enum as repaymentPeriodFrequency, lp.number_of_repayments as numberOfRepayments, lp.min_number_of_repayments as minNumberOfRepayments, lp.max_number_of_repayments as maxNumberOfRepayments, "
|
||||
+ "lp.amortization_method_enum as amortizationMethod, lp.arrearstolerance_amount as tolerance, "
|
||||
+ "lp.accounting_type as accountingType, "
|
||||
+ "curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, curr.display_symbol as currencyDisplaySymbol "
|
||||
@@ -135,12 +135,16 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
||||
final BigDecimal tolerance = rs.getBigDecimal("tolerance");
|
||||
|
||||
final Integer numberOfRepayments = JdbcSupport.getInteger(rs, "numberOfRepayments");
|
||||
final Integer minNumberOfRepayments = JdbcSupport.getInteger(rs, "minNumberOfRepayments");
|
||||
final Integer maxNumberOfRepayments = JdbcSupport.getInteger(rs, "maxNumberOfRepayments");
|
||||
final Integer repaymentEvery = JdbcSupport.getInteger(rs, "repaidEvery");
|
||||
|
||||
final Integer accountingRuleId = JdbcSupport.getInteger(rs, "accountingType");
|
||||
final EnumOptionData accountingRuleType = LoanEnumerations.accountingRuleType(accountingRuleId);
|
||||
|
||||
final BigDecimal interestRatePerPeriod = rs.getBigDecimal("interestRatePerPeriod");
|
||||
final BigDecimal minInterestRatePerPeriod = rs.getBigDecimal("minInterestRatePerPeriod");
|
||||
final BigDecimal maxInterestRatePerPeriod = rs.getBigDecimal("maxInterestRatePerPeriod");
|
||||
final BigDecimal annualInterestRate = rs.getBigDecimal("annualInterestRate");
|
||||
|
||||
final int repaymentFrequencyTypeId = JdbcSupport.getInteger(rs, "repaymentPeriodFrequency");
|
||||
@@ -160,7 +164,8 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
||||
.interestCalculationPeriodType(interestCalculationPeriodTypeId);
|
||||
|
||||
return new LoanProductData(id, name, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
|
||||
numberOfRepayments, repaymentEvery, interestRatePerPeriod, annualInterestRate, repaymentFrequencyType,
|
||||
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
|
||||
minInterestRatePerPeriod, maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType,
|
||||
interestRateFrequencyType, amortizationType, interestType, interestCalculationPeriodType, fundId, fundName,
|
||||
transactionStrategyId, transactionStrategyName, this.charges, accountingRuleType);
|
||||
}
|
||||
|
||||
+2
@@ -137,6 +137,8 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
final LoanProduct product = this.loanProductRepository.findOne(loanProductId);
|
||||
if (product == null) { throw new LoanProductNotFoundException(loanProductId); }
|
||||
|
||||
this.fromApiJsonDeserializer.validateMinMaxConstraints(command.parsedJson(), product.loanProductRelatedDetail(), "loanproduct");
|
||||
|
||||
final Map<String, Object> changes = product.update(command, this.aprCalculator);
|
||||
|
||||
if (changes.containsKey("fundId")) {
|
||||
|
||||
+41
-16
@@ -26,6 +26,8 @@ public class LoanProductRelatedDetailTestHelper {
|
||||
|
||||
// 2% per month, 24% per year
|
||||
BigDecimal defaultNominalInterestRatePerPeriod = BigDecimal.valueOf(Double.valueOf("2"));
|
||||
BigDecimal defaultMinNominalInterestRatePerPeriod = BigDecimal.valueOf(Double.valueOf("1"));
|
||||
BigDecimal defaultMaxNominalInterestRatePerPeriod = BigDecimal.valueOf(Double.valueOf("10"));
|
||||
PeriodFrequencyType interestPeriodFrequencyType = PeriodFrequencyType.MONTHS;
|
||||
BigDecimal defaultAnnualNominalInterestRate = BigDecimal.valueOf(Double.valueOf("24"));
|
||||
|
||||
@@ -35,13 +37,17 @@ public class LoanProductRelatedDetailTestHelper {
|
||||
PeriodFrequencyType repaymentFrequencyType = PeriodFrequencyType.MONTHS;
|
||||
|
||||
Integer defaultNumberOfRepayments = Integer.valueOf(4);
|
||||
Integer defaultMinNumberOfRepayments = Integer.valueOf(2);
|
||||
Integer defaultMaxNumberOfRepayments = Integer.valueOf(6);
|
||||
AmortizationMethod amortizationMethod = AmortizationMethod.EQUAL_PRINCIPAL;
|
||||
|
||||
BigDecimal inArrearsTolerance = BigDecimal.ZERO;
|
||||
|
||||
return createLoanProductRelatedDetail(currency, defaultPrincipal, defaultMinPrincipal, defaultMaxPrincipal, defaultNominalInterestRatePerPeriod, interestPeriodFrequencyType,
|
||||
defaultAnnualNominalInterestRate, interestMethod, interestCalculationPeriodMethod, repayEvery, repaymentFrequencyType,
|
||||
defaultNumberOfRepayments, amortizationMethod, inArrearsTolerance);
|
||||
return createLoanProductRelatedDetail(currency, defaultPrincipal, defaultMinPrincipal, defaultMaxPrincipal,
|
||||
defaultNominalInterestRatePerPeriod, defaultMinNominalInterestRatePerPeriod, defaultMaxNominalInterestRatePerPeriod,
|
||||
interestPeriodFrequencyType, defaultAnnualNominalInterestRate, interestMethod, interestCalculationPeriodMethod, repayEvery,
|
||||
repaymentFrequencyType, defaultNumberOfRepayments, defaultMinNumberOfRepayments, defaultMaxNumberOfRepayments,
|
||||
amortizationMethod, inArrearsTolerance);
|
||||
}
|
||||
|
||||
public static LoanProductRelatedDetail createSettingsForEqualInstallmentAmortizationQuarterly() {
|
||||
@@ -52,6 +58,8 @@ public class LoanProductRelatedDetailTestHelper {
|
||||
|
||||
// 2% per month, 24% per year
|
||||
BigDecimal defaultNominalInterestRatePerPeriod = BigDecimal.valueOf(Double.valueOf("2"));
|
||||
BigDecimal defaultMinNominalInterestRatePerPeriod = BigDecimal.valueOf(Double.valueOf("2"));
|
||||
BigDecimal defaultMaxNominalInterestRatePerPeriod = BigDecimal.valueOf(Double.valueOf("2"));
|
||||
PeriodFrequencyType interestPeriodFrequencyType = PeriodFrequencyType.MONTHS;
|
||||
BigDecimal defaultAnnualNominalInterestRate = BigDecimal.valueOf(Double.valueOf("24"));
|
||||
|
||||
@@ -61,13 +69,17 @@ public class LoanProductRelatedDetailTestHelper {
|
||||
PeriodFrequencyType repaymentFrequencyType = PeriodFrequencyType.MONTHS;
|
||||
|
||||
Integer defaultNumberOfRepayments = Integer.valueOf(4);
|
||||
Integer defaultMinNumberOfRepayments = Integer.valueOf(4);
|
||||
Integer defaultMaxNumberOfRepayments = Integer.valueOf(4);
|
||||
AmortizationMethod amortizationMethod = AmortizationMethod.EQUAL_INSTALLMENTS;
|
||||
|
||||
BigDecimal inArrearsTolerance = BigDecimal.ZERO;
|
||||
|
||||
return createLoanProductRelatedDetail(currency, defaultPrincipal, defaultMinPrincipal, defaultMaxPrincipal, defaultNominalInterestRatePerPeriod, interestPeriodFrequencyType,
|
||||
defaultAnnualNominalInterestRate, interestMethod, interestCalculationPeriodMethod, repayEvery, repaymentFrequencyType,
|
||||
defaultNumberOfRepayments, amortizationMethod, inArrearsTolerance);
|
||||
return createLoanProductRelatedDetail(currency, defaultPrincipal, defaultMinPrincipal, defaultMaxPrincipal,
|
||||
defaultNominalInterestRatePerPeriod, defaultMinNominalInterestRatePerPeriod, defaultMaxNominalInterestRatePerPeriod,
|
||||
interestPeriodFrequencyType, defaultAnnualNominalInterestRate, interestMethod, interestCalculationPeriodMethod, repayEvery,
|
||||
repaymentFrequencyType, defaultNumberOfRepayments, defaultMinNumberOfRepayments, defaultMaxNumberOfRepayments,
|
||||
amortizationMethod, inArrearsTolerance);
|
||||
}
|
||||
|
||||
public static LoanProductRelatedDetail createSettingsForFlatQuarterly(final AmortizationMethod amortizationMethod) {
|
||||
@@ -79,6 +91,8 @@ public class LoanProductRelatedDetailTestHelper {
|
||||
|
||||
// 2% per month, 24% per year
|
||||
BigDecimal defaultNominalInterestRatePerPeriod = BigDecimal.valueOf(Double.valueOf("2"));
|
||||
BigDecimal defaultMinNominalInterestRatePerPeriod = BigDecimal.valueOf(Double.valueOf("2"));
|
||||
BigDecimal defaultMaxNominalInterestRatePerPeriod = BigDecimal.valueOf(Double.valueOf("2"));
|
||||
PeriodFrequencyType interestPeriodFrequencyType = PeriodFrequencyType.MONTHS;
|
||||
BigDecimal defaultAnnualNominalInterestRate = BigDecimal.valueOf(Double.valueOf("24"));
|
||||
|
||||
@@ -88,12 +102,16 @@ public class LoanProductRelatedDetailTestHelper {
|
||||
PeriodFrequencyType repaymentFrequencyType = PeriodFrequencyType.MONTHS;
|
||||
|
||||
Integer defaultNumberOfRepayments = Integer.valueOf(4);
|
||||
Integer defaultMinNumberOfRepayments = Integer.valueOf(4);
|
||||
Integer defaultMaxNumberOfRepayments = Integer.valueOf(4);
|
||||
|
||||
BigDecimal inArrearsTolerance = BigDecimal.ZERO;
|
||||
|
||||
return createLoanProductRelatedDetail(currency, defaultPrincipal, defaultMinPrincipal, defaultMaxPrincipal, defaultNominalInterestRatePerPeriod, interestPeriodFrequencyType,
|
||||
defaultAnnualNominalInterestRate, interestMethod, interestCalculationPeriodMethod, repayEvery, repaymentFrequencyType,
|
||||
defaultNumberOfRepayments, amortizationMethod, inArrearsTolerance);
|
||||
return createLoanProductRelatedDetail(currency, defaultPrincipal, defaultMinPrincipal, defaultMaxPrincipal,
|
||||
defaultNominalInterestRatePerPeriod, defaultMinNominalInterestRatePerPeriod, defaultMaxNominalInterestRatePerPeriod,
|
||||
interestPeriodFrequencyType, defaultAnnualNominalInterestRate, interestMethod, interestCalculationPeriodMethod, repayEvery,
|
||||
repaymentFrequencyType, defaultNumberOfRepayments, defaultMinNumberOfRepayments, defaultMaxNumberOfRepayments,
|
||||
amortizationMethod, inArrearsTolerance);
|
||||
}
|
||||
|
||||
public static LoanProductRelatedDetail createSettingsForIrregularFlatEveryFourMonths() {
|
||||
@@ -105,6 +123,8 @@ public class LoanProductRelatedDetailTestHelper {
|
||||
|
||||
// 2% per month, 24% per year
|
||||
BigDecimal defaultNominalInterestRatePerPeriod = BigDecimal.valueOf(Double.valueOf("2"));
|
||||
BigDecimal defaultMinNominalInterestRatePerPeriod = BigDecimal.valueOf(Double.valueOf("2"));
|
||||
BigDecimal defaultMaxNominalInterestRatePerPeriod = BigDecimal.valueOf(Double.valueOf("4"));
|
||||
PeriodFrequencyType interestPeriodFrequencyType = PeriodFrequencyType.MONTHS;
|
||||
BigDecimal defaultAnnualNominalInterestRate = BigDecimal.valueOf(Double.valueOf("24"));
|
||||
|
||||
@@ -114,26 +134,31 @@ public class LoanProductRelatedDetailTestHelper {
|
||||
PeriodFrequencyType repaymentFrequencyType = PeriodFrequencyType.MONTHS;
|
||||
|
||||
Integer defaultNumberOfRepayments = Integer.valueOf(2);
|
||||
Integer defaultMinNumberOfRepayments = Integer.valueOf(2);
|
||||
Integer defaultMaxNumberOfRepayments = Integer.valueOf(2);
|
||||
|
||||
BigDecimal inArrearsTolerance = BigDecimal.ZERO;
|
||||
|
||||
AmortizationMethod amortizationMethod = AmortizationMethod.EQUAL_PRINCIPAL;
|
||||
|
||||
return createLoanProductRelatedDetail(currency, defaultPrincipal, defaultMinPrincipal, defaultMaxPrincipal,
|
||||
defaultNominalInterestRatePerPeriod, interestPeriodFrequencyType, defaultAnnualNominalInterestRate, interestMethod,
|
||||
interestCalculationPeriodMethod, repayEvery, repaymentFrequencyType, defaultNumberOfRepayments, amortizationMethod,
|
||||
defaultNominalInterestRatePerPeriod, defaultMinNominalInterestRatePerPeriod, defaultMaxNominalInterestRatePerPeriod, interestPeriodFrequencyType, defaultAnnualNominalInterestRate, interestMethod,
|
||||
interestCalculationPeriodMethod, repayEvery, repaymentFrequencyType, defaultNumberOfRepayments, defaultMinNumberOfRepayments, defaultMaxNumberOfRepayments, amortizationMethod,
|
||||
inArrearsTolerance);
|
||||
}
|
||||
|
||||
private static LoanProductRelatedDetail createLoanProductRelatedDetail(MonetaryCurrency currency, BigDecimal defaultPrincipal,
|
||||
BigDecimal defaultMinPrincipal, BigDecimal defaultMaxPrincipal, BigDecimal defaultNominalInterestRatePerPeriod,
|
||||
BigDecimal defaultMinNominalInterestRatePerPeriod, BigDecimal defaultMaxNominalInterestRatePerPeriod,
|
||||
PeriodFrequencyType interestPeriodFrequencyType, BigDecimal defaultAnnualNominalInterestRate, InterestMethod interestMethod,
|
||||
InterestCalculationPeriodMethod interestCalculationPeriodMethod, Integer repayEvery,
|
||||
PeriodFrequencyType repaymentFrequencyType, Integer defaultNumberOfRepayments, AmortizationMethod amortizationMethod,
|
||||
BigDecimal inArrearsTolerance) {
|
||||
PeriodFrequencyType repaymentFrequencyType, Integer defaultNumberOfRepayments, Integer defaultMinNumberOfRepayments,
|
||||
Integer defaultMaxNumberOfRepayments, AmortizationMethod amortizationMethod, BigDecimal inArrearsTolerance) {
|
||||
|
||||
return new LoanProductRelatedDetail(currency, defaultPrincipal, defaultMinPrincipal, defaultMaxPrincipal, defaultNominalInterestRatePerPeriod, interestPeriodFrequencyType,
|
||||
defaultAnnualNominalInterestRate, interestMethod, interestCalculationPeriodMethod, repayEvery, repaymentFrequencyType,
|
||||
defaultNumberOfRepayments, amortizationMethod, inArrearsTolerance);
|
||||
return new LoanProductRelatedDetail(currency, defaultPrincipal, defaultMinPrincipal, defaultMaxPrincipal,
|
||||
defaultNominalInterestRatePerPeriod, defaultMinNominalInterestRatePerPeriod, defaultMaxNominalInterestRatePerPeriod,
|
||||
interestPeriodFrequencyType, defaultAnnualNominalInterestRate, interestMethod, interestCalculationPeriodMethod, repayEvery,
|
||||
repaymentFrequencyType, defaultNumberOfRepayments, defaultMinNumberOfRepayments, defaultMaxNumberOfRepayments,
|
||||
amortizationMethod, inArrearsTolerance);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user