diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/CalculateLoanScheduleCommand.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/CalculateLoanScheduleCommand.java index 1d9d4e6d4..3c489147c 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/CalculateLoanScheduleCommand.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/CalculateLoanScheduleCommand.java @@ -12,6 +12,9 @@ public class CalculateLoanScheduleCommand { private final Long productId; private final BigDecimal principal; + private final Integer loanTermFrequency; + private final Integer loanTermFrequencyType; + private final Integer repaymentEvery; private final Integer repaymentFrequencyType; private final Integer numberOfRepayments; @@ -31,6 +34,7 @@ public class CalculateLoanScheduleCommand { final BigDecimal principal, final BigDecimal interestRatePerPeriod, Integer interestRateFrequencyMethod, final Integer interestMethod, final Integer interestCalculationPeriodMethod, final Integer repaymentEvery, final Integer repaymentFrequency, final Integer numberOfRepayments, Integer amortizationMethod, + final Integer loanTermFrequency, final Integer loanTermFrequencyType, final LocalDate expectedDisbursementDate, final LocalDate repaymentsStartingFromDate, final LocalDate interestCalculatedFromDate) { @@ -44,6 +48,8 @@ public class CalculateLoanScheduleCommand { this.repaymentFrequencyType = repaymentFrequency; this.numberOfRepayments = numberOfRepayments; this.amortizationType = amortizationMethod; + this.loanTermFrequency = loanTermFrequency; + this.loanTermFrequencyType = loanTermFrequencyType; this.expectedDisbursementDate = expectedDisbursementDate; this.repaymentsStartingFromDate = repaymentsStartingFromDate; @@ -57,6 +63,14 @@ public class CalculateLoanScheduleCommand { public BigDecimal getPrincipal() { return principal; } + + public Integer getLoanTermFrequency() { + return loanTermFrequency; + } + + public Integer getLoanTermFrequencyType() { + return loanTermFrequencyType; + } public Integer getRepaymentEvery() { return repaymentEvery; diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/SubmitLoanApplicationCommand.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/SubmitLoanApplicationCommand.java index c7fdd044d..30e1ee5f0 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/SubmitLoanApplicationCommand.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/SubmitLoanApplicationCommand.java @@ -20,11 +20,13 @@ public class SubmitLoanApplicationCommand { private final BigDecimal principal; private final BigDecimal inArrearsTolerance; + private final Integer loanTermFrequency; + private final Integer loanTermFrequencyType; + private final Integer numberOfRepayments; private final Integer repaymentEvery; private final BigDecimal interestRatePerPeriod; - private final Integer repaymentFrequencyType; private final Integer interestRateFrequencyType; private final Integer amortizationType; @@ -52,6 +54,7 @@ public class SubmitLoanApplicationCommand { final Integer interestMethod, final Integer interestCalculationPeriodMethod, final Integer repaymentEvery, final Integer repaymentFrequency, final Integer numberOfRepayments, Integer amortizationMethod, + final Integer loanTermFrequency, final Integer loanTermFrequencyType, final BigDecimal toleranceAmount) { this.clientId = clientId; this.productId = productId; @@ -66,6 +69,8 @@ public class SubmitLoanApplicationCommand { this.interestChargedFromDate = interestChargedFromLocalDate; this.principal = principal; + this.loanTermFrequency = loanTermFrequency; + this.loanTermFrequencyType = loanTermFrequencyType; this.inArrearsTolerance = toleranceAmount; this.interestRatePerPeriod = interestRatePerPeriod; @@ -80,7 +85,8 @@ public class SubmitLoanApplicationCommand { public CalculateLoanScheduleCommand toCalculateLoanScheduleCommand() { return new CalculateLoanScheduleCommand(productId, - principal, interestRatePerPeriod, interestRateFrequencyType, interestType, interestCalculationPeriodType, repaymentEvery, repaymentFrequencyType, numberOfRepayments, amortizationType, + principal, interestRatePerPeriod, interestRateFrequencyType, interestType, interestCalculationPeriodType, repaymentEvery, repaymentFrequencyType, numberOfRepayments, amortizationType, + this.loanTermFrequency, this.loanTermFrequencyType, expectedDisbursementDate, repaymentsStartingFromDate, interestChargedFromDate); } @@ -127,6 +133,14 @@ public class SubmitLoanApplicationCommand { public Integer getRepaymentEvery() { return repaymentEvery; } + + public Integer getLoanTermFrequency() { + return loanTermFrequency; + } + + public Integer getLoanTermFrequencyType() { + return loanTermFrequencyType; + } public BigDecimal getInterestRatePerPeriod() { return interestRatePerPeriod; diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanProductData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanProductData.java index 39b259e46..5065eeddd 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanProductData.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanProductData.java @@ -23,6 +23,7 @@ public class LoanProductData { private MoneyData inArrearsTolerance; private Integer numberOfRepayments; + private Integer loanTermFrequency; private Integer repaymentEvery; private BigDecimal interestRatePerPeriod = BigDecimal.ZERO; private BigDecimal annualInterestRate = BigDecimal.ZERO; @@ -54,6 +55,7 @@ public class LoanProductData { public LoanProductData(DateTime createdOn, DateTime lastModifedOn, Long id, String name, String description, MoneyData principal, MoneyData tolerance, Integer numberOfRepayments, + Integer loanTermFrequency, Integer repaymentEvery, BigDecimal interestRatePerPeriod, BigDecimal annualInterestRate, EnumOptionData loanTermFrequencyType, @@ -70,6 +72,7 @@ public class LoanProductData { this.principal = principal; this.inArrearsTolerance = tolerance; this.numberOfRepayments = numberOfRepayments; + this.loanTermFrequency = loanTermFrequency; this.repaymentEvery = repaymentEvery; this.interestRatePerPeriod = interestRatePerPeriod; this.annualInterestRate = annualInterestRate; @@ -165,6 +168,14 @@ public class LoanProductData { public void setNumberOfRepayments(Integer numberOfRepayments) { this.numberOfRepayments = numberOfRepayments; } + + public Integer getLoanTermFrequency() { + return loanTermFrequency; + } + + public void setLoanTermFrequency(Integer loanTermFrequency) { + this.loanTermFrequency = loanTermFrequency; + } public Integer getRepaymentEvery() { return repaymentEvery; diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java index 90641aad1..19f0ff721 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java @@ -933,6 +933,7 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { Set supportedParams = new HashSet( Arrays.asList("clientId", "productId", "externalId", "fundId", "transactionProcessingStrategyId", "principal", "inArrearsTolerance", "interestRatePerPeriod", "repaymentEvery", "numberOfRepayments", + "loanTermFrequency", "loanTermFrequencyType", "repaymentFrequencyType", "interestRateFrequencyType", "amortizationType", "interestType", "interestCalculationPeriodType", "expectedDisbursementDate", "repaymentsStartingFromDate", "interestChargedFromDate", "submittedOnDate", "submittedOnNote", "locale", "dateFormat") @@ -956,6 +957,9 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { Integer numberOfRepayments = extractIntegerParameter("numberOfRepayments", requestMap, modifiedParameters); Integer repaymentFrequencyType = extractIntegerParameter("repaymentFrequencyType", requestMap, modifiedParameters); + Integer loanTermFrequency = extractIntegerParameter("loanTermFrequency", requestMap, modifiedParameters); + Integer loanTermFrequencyType = extractIntegerParameter("loanTermFrequencyType", requestMap, modifiedParameters); + Integer interestRateFrequencyTypeValue = extractIntegerParameter("interestRateFrequencyType", requestMap, modifiedParameters); Integer amortizationTypeValue = extractIntegerParameter("amortizationType", requestMap, modifiedParameters); Integer interestTypeValue = extractIntegerParameter("interestType", requestMap, modifiedParameters); @@ -972,7 +976,9 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { submittedOnDate, submittedOnNote, expectedDisbursementDate, repaymentsStartingFromDate, interestChargedFromDate, principal, interestRatePerPeriod, interestRateFrequencyTypeValue, interestTypeValue, interestCalculationPeriodTypeValue, - repaymentEvery, repaymentFrequencyType, numberOfRepayments, amortizationTypeValue, inArrearsToleranceValue); + repaymentEvery, repaymentFrequencyType, numberOfRepayments, amortizationTypeValue, + loanTermFrequency, loanTermFrequencyType, + inArrearsToleranceValue); } @Override diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformServiceJpaRepositoryImpl.java index f2d804983..c0577a567 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -270,7 +270,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf Integer repaidEvery = loan.getLoanRepaymentScheduleDetail().getRepayEvery(); Integer selectedRepaymentFrequency = loan.getLoanRepaymentScheduleDetail().getRepaymentPeriodFrequencyType().getValue(); - Integer selectedRepaymentSchedule = loan.getLoanRepaymentScheduleDetail().getAmortizationMethod().getValue(); + Integer selectedAmortizationMethod = loan.getLoanRepaymentScheduleDetail().getAmortizationMethod().getValue(); + + // FIXME - use values from loan table here instead of inferring. + Integer loanTermFrequency = repaidEvery * numberOfInstallments; + Integer loanTermFrequencyType = selectedRepaymentFrequency; // use annual percentage rate to re-calculate loan schedule for late disbursement BigDecimal interestRatePerPeriod = interestRatePerYear; @@ -283,8 +287,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf loan.getLoanProduct().getId(), principalAsDecimal, interestRatePerPeriod, interestRateFrequencyMethod, interestMethod, interestCalculationInPeriod, - repaidEvery, selectedRepaymentFrequency, numberOfInstallments, - selectedRepaymentSchedule, actualDisbursementDate, repaymentsStartingFromDate, interestCalculatedFromDate); + repaidEvery, selectedRepaymentFrequency, numberOfInstallments, selectedAmortizationMethod, + loanTermFrequency, loanTermFrequencyType, + actualDisbursementDate, repaymentsStartingFromDate, interestCalculatedFromDate); LoanSchedule loanSchedule = this.calculationPlatformService.calculateLoanSchedule(calculateCommand); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanDropdownReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanDropdownReadPlatformService.java index 36ef5fa09..667a8da56 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanDropdownReadPlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanDropdownReadPlatformService.java @@ -14,6 +14,8 @@ public interface LoanDropdownReadPlatformService { List retrieveLoanInterestRateCalculatedInPeriodOptions(); + List retrieveLoanTermFrequencyTypeOptions(); + List retrieveRepaymentFrequencyTypeOptions(); List retrieveInterestRateFrequencyTypeOptions(); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanDropdownReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanDropdownReadPlatformServiceImpl.java index a602c7852..e16569804 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanDropdownReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanDropdownReadPlatformServiceImpl.java @@ -4,6 +4,7 @@ import static org.mifosng.platform.loanproduct.service.LoanEnumerations.amortiza import static org.mifosng.platform.loanproduct.service.LoanEnumerations.interestCalculationPeriodType; import static org.mifosng.platform.loanproduct.service.LoanEnumerations.interestRateFrequencyType; import static org.mifosng.platform.loanproduct.service.LoanEnumerations.interestType; +import static org.mifosng.platform.loanproduct.service.LoanEnumerations.loanTermFrequencyType; import static org.mifosng.platform.loanproduct.service.LoanEnumerations.repaymentFrequencyType; import java.util.ArrayList; @@ -60,6 +61,16 @@ public class LoanDropdownReadPlatformServiceImpl implements LoanDropdownReadPlat return allowedOptions; } + + @Override + public List retrieveLoanTermFrequencyTypeOptions() { + List loanTermFrequencyOptions = Arrays.asList( + loanTermFrequencyType(PeriodFrequencyType.DAYS), + loanTermFrequencyType(PeriodFrequencyType.WEEKS), + loanTermFrequencyType(PeriodFrequencyType.MONTHS), + loanTermFrequencyType(PeriodFrequencyType.YEARS)); + return loanTermFrequencyOptions; + } @Override public List retrieveRepaymentFrequencyTypeOptions() { diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanProductReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanProductReadPlatformServiceImpl.java index a1f4bb9c6..f9227df0c 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanProductReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanProductReadPlatformServiceImpl.java @@ -105,13 +105,14 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo .amortizationType(AmortizationMethod.EQUAL_INSTALLMENTS)); productData.setInterestType(LoanEnumerations .interestType(InterestMethod.DECLINING_BALANCE)); - productData.setRepaymentFrequencyType(LoanEnumerations - .repaymentFrequencyType(PeriodFrequencyType.MONTHS)); - productData.setInterestRateFrequencyType(LoanEnumerations - .interestRateFrequencyType(PeriodFrequencyType.MONTHS)); - productData - .setInterestCalculationPeriodType(LoanEnumerations - .interestCalculationPeriodType(InterestCalculationPeriodMethod.SAME_AS_REPAYMENT_PERIOD)); + + productData.setLoanTermFrequencyType(LoanEnumerations.loanTermFrequencyType(PeriodFrequencyType.MONTHS)); + + productData.setRepaymentFrequencyType(LoanEnumerations.repaymentFrequencyType(PeriodFrequencyType.MONTHS)); + + productData.setInterestRateFrequencyType(LoanEnumerations.interestRateFrequencyType(PeriodFrequencyType.MONTHS)); + + productData.setInterestCalculationPeriodType(LoanEnumerations.interestCalculationPeriodType(InterestCalculationPeriodMethod.SAME_AS_REPAYMENT_PERIOD)); populateProductDataWithDropdownOptions(productData); @@ -179,13 +180,11 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo MoneyData principalMoney = MoneyData.of(currencyData, principal); MoneyData toleranceMoney = MoneyData.of(currencyData, tolerance); - Integer numberOfRepayments = JdbcSupport.getInteger(rs, - "numberOfRepayments"); + Integer numberOfRepayments = JdbcSupport.getInteger(rs,"numberOfRepayments"); Integer repaymentEvery = JdbcSupport.getInteger(rs, "repaidEvery"); - BigDecimal interestRatePerPeriod = rs - .getBigDecimal("interestRatePerPeriod"); - BigDecimal annualInterestRate = rs - .getBigDecimal("annualInterestRate"); + Integer loanTermFrequency = repaymentEvery * numberOfRepayments; + BigDecimal interestRatePerPeriod = rs.getBigDecimal("interestRatePerPeriod"); + BigDecimal annualInterestRate = rs.getBigDecimal("annualInterestRate"); int repaymentFrequencyTypeId = JdbcSupport.getInteger(rs, "repaymentPeriodFrequency"); EnumOptionData repaymentFrequencyType = LoanEnumerations.repaymentFrequencyType(repaymentFrequencyTypeId); @@ -213,7 +212,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo return new LoanProductData(createdOn, lastModifedOn, id, name, description, principalMoney, toleranceMoney, - numberOfRepayments, repaymentEvery, interestRatePerPeriod, + numberOfRepayments, loanTermFrequency, repaymentEvery, interestRatePerPeriod, annualInterestRate, loanTermFrequencyType, repaymentFrequencyType, interestRateFrequencyType, amortizationType, interestType, interestCalculationPeriodType, fundId, fundName, transactionStrategyId, transactionStrategyName); @@ -246,6 +245,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo List amortizationTypeOptions = dropdownReadPlatformService.retrieveLoanAmortizationTypeOptions(); List interestTypeOptions = dropdownReadPlatformService.retrieveLoanInterestTypeOptions(); List interestCalculationPeriodTypeOptions = dropdownReadPlatformService.retrieveLoanInterestRateCalculatedInPeriodOptions(); + List loanTermFrequencyTypeOptions = dropdownReadPlatformService.retrieveLoanTermFrequencyTypeOptions(); List repaymentFrequencyTypeOptions = dropdownReadPlatformService.retrieveRepaymentFrequencyTypeOptions(); List interestRateFrequencyTypeOptions = dropdownReadPlatformService.retrieveInterestRateFrequencyTypeOptions(); @@ -256,6 +256,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo productData.setAmortizationTypeOptions(amortizationTypeOptions); productData.setInterestTypeOptions(interestTypeOptions); productData.setInterestCalculationPeriodTypeOptions(interestCalculationPeriodTypeOptions); + productData.setLoanTermFrequencyTypeOptions(loanTermFrequencyTypeOptions); productData.setRepaymentFrequencyTypeOptions(repaymentFrequencyTypeOptions); productData.setInterestRateFrequencyTypeOptions(interestRateFrequencyTypeOptions); productData.setFundOptions(fundOptions); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loanschedule/domain/FlatLoanScheduleGenerator.java b/mifosng-provider/src/main/java/org/mifosng/platform/loanschedule/domain/FlatLoanScheduleGenerator.java index cf85de1b4..d8d014ce0 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loanschedule/domain/FlatLoanScheduleGenerator.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loanschedule/domain/FlatLoanScheduleGenerator.java @@ -27,10 +27,12 @@ public class FlatLoanScheduleGenerator implements LoanScheduleGenerator { List scheduledLoanInstallments = new ArrayList(); - List scheduledDates = this.scheduledDateGenerator.generate( - loanScheduleInfo, disbursementDate, firstRepaymentDate); + List scheduledDates = this.scheduledDateGenerator.generate(loanScheduleInfo, disbursementDate, firstRepaymentDate); MathContext mc = new MathContext(8, RoundingMode.HALF_EVEN); + + // FIXME - use the expected loan term to work out interest due + // loan term = 9 months Money principalPerInstallment = loanScheduleInfo.getPrincipal() .dividedBy(loanScheduleInfo.getNumberOfRepayments(), @@ -46,9 +48,7 @@ public class FlatLoanScheduleGenerator implements LoanScheduleGenerator { .divide(BigDecimal.valueOf(Double.valueOf("100.0")), mc) .multiply(BigDecimal.valueOf(loanScheduleInfo.getRepayEvery())); - Money interestPerInstallment = loanScheduleInfo.getPrincipal() - .multiplyRetainScale(periodicInterestRate, - RoundingMode.HALF_EVEN); + Money interestPerInstallment = loanScheduleInfo.getPrincipal().multiplyRetainScale(periodicInterestRate, RoundingMode.HALF_EVEN); Money outstandingBalance = loanScheduleInfo.getPrincipal(); Money totalPrincipal = Money.zero(outstandingBalance.getCurrency()); @@ -59,14 +59,11 @@ public class FlatLoanScheduleGenerator implements LoanScheduleGenerator { totalPrincipal = totalPrincipal.plus(principalPerInstallment); if (installmentNumber == loanScheduleInfo.getNumberOfRepayments()) { - Money difference = totalPrincipal.minus(loanScheduleInfo - .getPrincipal()); + Money difference = totalPrincipal.minus(loanScheduleInfo.getPrincipal()); if (difference.isLessThanZero()) { - principalPerInstallment = principalPerInstallment - .plus(difference.abs()); + principalPerInstallment = principalPerInstallment.plus(difference.abs()); } else if (difference.isGreaterThanZero()) { - principalPerInstallment = principalPerInstallment - .minus(difference.abs()); + principalPerInstallment = principalPerInstallment.minus(difference.abs()); } }