Add interest posting functionality for saving accounts
rename_patches_after_rebasing remove existed db script file
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
Alter TABLE `m_saving_schedule`
|
||||
ADD COLUMN `interest_accured` decimal(21,4) DEFAULT '0.0000' AFTER `deposit_paid`
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
ALTER TABLE m_saving_account
|
||||
ADD COLUMN `deposit_every` bigint(20) DEFAULT NULL AFTER `tenure_type`;
|
||||
+1
-1
@@ -55,7 +55,7 @@ public class GoogleGsonPortfolioApiJsonSerializerService implements PortfolioApi
|
||||
"preClosureAllowed", "preClosureInterestRate", "withdrawnonDate", "rejectedonDate", "closedonDate", "isLockinPeriodAllowed",
|
||||
"lockinPeriod", "lockinPeriodType", "productOptions", "currencyOptions", "savingsProductTypeOptions", "tenureTypeOptions",
|
||||
"savingFrequencyOptions", "savingsInterestTypeOptions", "lockinPeriodTypeOptions", "interestCalculationOptions","permissions","savingScheduleDatas",
|
||||
"dueAmount", "savingScheduleData"));
|
||||
"dueAmount", "savingScheduleData", "transactions","interestPostEvery","interestPostFrequency"));
|
||||
|
||||
// guarantors
|
||||
private static final Set<String> GUARANTOR_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("externalGuarantor", "existingClientId",
|
||||
|
||||
+2
-3
@@ -817,7 +817,7 @@ public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataCo
|
||||
Set<String> supportedParams = new HashSet<String>(Arrays.asList("clientId", "productId", "externalId", "currencyCode",
|
||||
"digitsAfterDecimal", "savingsDepositAmountPerPeriod", "recurringInterestRate", "savingInterestRate", "tenure",
|
||||
"commencementDate", "locale", "dateFormat", "isLockinPeriodAllowed", "lockinPeriod", "lockinPeriodType",
|
||||
"savingProductType", "tenureType", "depositfrequency", "interestType", "interestCalculationMethod", "minimumBalanceForWithdrawal",
|
||||
"tenureType", "depositfrequency", "interestType", "interestCalculationMethod", "minimumBalanceForWithdrawal",
|
||||
"isPartialDepositAllowed", "depositEvery","interestPostEvery","interestPostFrequency"));
|
||||
checkForUnsupportedParameters(requestMap, supportedParams);
|
||||
Set<String> modifiedParameters = new HashSet<String>();
|
||||
@@ -837,7 +837,6 @@ public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataCo
|
||||
Integer lockinPeriodType = extractIntegerParameter("lockinPeriodType", requestMap, modifiedParameters);
|
||||
|
||||
LocalDate commencementDate = extractLocalDateParameter("commencementDate", requestMap, modifiedParameters);
|
||||
Integer savingProductType = extractIntegerParameter("savingProductType", requestMap, modifiedParameters);
|
||||
Integer tenureType = extractIntegerParameter("tenureType", requestMap, modifiedParameters);
|
||||
Integer depositfrequency = extractIntegerParameter("depositfrequency", requestMap, modifiedParameters);
|
||||
Integer interestType = extractIntegerParameter("interestType", requestMap, modifiedParameters);
|
||||
@@ -851,7 +850,7 @@ public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataCo
|
||||
|
||||
return new SavingAccountCommand(modifiedParameters, resourceIdentifier, clientId, productId, externalId, currencyCode,
|
||||
digitsAfterDecimalValue, savingsDepositAmount, recurringInterestRate, savingInterestRate, tenure, commencementDate,
|
||||
savingProductType, tenureType, depositfrequency, interestType, minimumBalanceForWithdrawal, interestCalculationMethod,
|
||||
tenureType, depositfrequency, interestType, minimumBalanceForWithdrawal, interestCalculationMethod,
|
||||
isLockinPeriodAllowed, isPartialDepositAllowed, lockinPeriod, lockinPeriodType, depositEvery, interestPostEvery, interestPostFrequency);
|
||||
}
|
||||
|
||||
|
||||
+11
-5
@@ -42,6 +42,7 @@ import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountWithdrawa
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingStateTransitionsCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountData;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountForLookup;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountTransactionsData;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingPermissionData;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingScheduleData;
|
||||
import org.mifosplatform.portfolio.savingsaccount.service.CalculateSavingSchedule;
|
||||
@@ -103,7 +104,7 @@ public class SavingsAccountApiResource {
|
||||
"interestCalculationMethod", "tenure", "tenureType", "projectedCommencementDate", "actualCommencementDate", "maturesOnDate",
|
||||
"projectedInterestAccuredOnMaturity", "actualInterestAccured", "projectedMaturityAmount", "actualMaturityAmount",
|
||||
"preClosureAllowed", "preClosureInterestRate", "withdrawnonDate", "rejectedonDate", "closedonDate", "isLockinPeriodAllowed",
|
||||
"lockinPeriod", "lockinPeriodType","outstandingAmount","savingScheduleData"));
|
||||
"lockinPeriod", "lockinPeriodType","outstandingAmount","savingScheduleData","transactions","interestPostEvery","interestPostFrequency"));
|
||||
|
||||
@POST
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@@ -173,6 +174,7 @@ public class SavingsAccountApiResource {
|
||||
|
||||
SavingPermissionData permissions = null;
|
||||
SavingScheduleData savingScheduleData = null;
|
||||
Collection<SavingAccountTransactionsData> transactions = null;
|
||||
|
||||
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
|
||||
if (responseParameters.isEmpty()) {
|
||||
@@ -191,8 +193,8 @@ public class SavingsAccountApiResource {
|
||||
Set<String> associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters());
|
||||
if (!associationParameters.isEmpty()) {
|
||||
if (associationParameters.contains("all")) {
|
||||
associationParameters.add("savingScheduleData");
|
||||
responseParameters.addAll(Arrays.asList("permissions","savingScheduleData"));
|
||||
associationParameters.addAll(Arrays.asList("savingScheduleData","transactions"));
|
||||
responseParameters.addAll(Arrays.asList("permissions","savingScheduleData","transactions"));
|
||||
} else {
|
||||
responseParameters.addAll(associationParameters);
|
||||
}
|
||||
@@ -202,6 +204,10 @@ public class SavingsAccountApiResource {
|
||||
savingScheduleData = this.savingAccountReadPlatformService.retrieveSavingsAccountSchedule(accountId,currencyData);
|
||||
account = new SavingAccountData(account,savingScheduleData);
|
||||
}
|
||||
if (associationParameters.contains("transactions")) {
|
||||
transactions = this.savingAccountReadPlatformService.retrieveSavingsAccountTransactions(accountId);
|
||||
account = new SavingAccountData(account,transactions);
|
||||
}
|
||||
permissions = this.savingAccountReadPlatformService.retrieveSavingAccountPermissions(account);
|
||||
account = new SavingAccountData(account, permissions);
|
||||
}
|
||||
@@ -258,10 +264,10 @@ public class SavingsAccountApiResource {
|
||||
List<EnumOptionData> lockinPeriodTypeOptions = Arrays.asList(months);
|
||||
|
||||
EnumOptionData averagebal = SavingProductEnumerations.savingInterestCalculationMethod(SavingInterestCalculationMethod.AVERAGEBAL);
|
||||
EnumOptionData minbal = SavingProductEnumerations.savingInterestCalculationMethod(SavingInterestCalculationMethod.MINBAL);
|
||||
// EnumOptionData minbal = SavingProductEnumerations.savingInterestCalculationMethod(SavingInterestCalculationMethod.MINBAL);
|
||||
EnumOptionData monthlyCollection = SavingProductEnumerations
|
||||
.savingInterestCalculationMethod(SavingInterestCalculationMethod.MONTHLYCOLLECTION);
|
||||
List<EnumOptionData> interestCalculationOptions = Arrays.asList(averagebal, minbal, monthlyCollection);
|
||||
List<EnumOptionData> interestCalculationOptions = Arrays.asList(averagebal, monthlyCollection);
|
||||
BigDecimal dueAmount = this.savingAccountReadPlatformService.deriveSavingDueAmount(account);
|
||||
return new SavingAccountData(account, productOptions, currencyOptions, savingsProductTypeOptions,tenureTypeOptions,savingFrequencyOptions,
|
||||
savingsInterestTypeOptions,lockinPeriodTypeOptions,interestCalculationOptions, dueAmount);
|
||||
|
||||
+13
-1
@@ -13,12 +13,14 @@ public class CalculateSavingScheduleCommand {
|
||||
private final BigDecimal interestRate;
|
||||
private final LocalDate paymentsStartingFromDate;
|
||||
private final Integer tenure;
|
||||
private final Integer tenureType;
|
||||
private final Integer interestPostEvery;
|
||||
private final Integer interestPostFrequency;
|
||||
private final Integer interestCalculationMethod;
|
||||
|
||||
public CalculateSavingScheduleCommand(final Long productId, final BigDecimal deposit, final Integer depositEvery,
|
||||
final Integer paymentFrequencyType, final BigDecimal interestRate, final LocalDate paymentsStartingFromDate,
|
||||
final Integer tenure,final Integer interestPostEvery, final Integer interestPostFrequency) {
|
||||
final Integer tenure, final Integer tenureType, final Integer interestPostEvery, final Integer interestPostFrequency, final Integer interestCalculationMethod) {
|
||||
|
||||
this.productId = productId;
|
||||
this.deposit = deposit;
|
||||
@@ -27,8 +29,10 @@ public class CalculateSavingScheduleCommand {
|
||||
this.interestRate = interestRate;
|
||||
this.paymentsStartingFromDate = paymentsStartingFromDate;
|
||||
this.tenure = tenure;
|
||||
this.tenureType = tenureType;
|
||||
this.interestPostEvery = interestPostEvery;
|
||||
this.interestPostFrequency = interestPostFrequency;
|
||||
this.interestCalculationMethod = interestCalculationMethod;
|
||||
|
||||
}
|
||||
|
||||
@@ -68,4 +72,12 @@ public class CalculateSavingScheduleCommand {
|
||||
return this.interestPostFrequency;
|
||||
}
|
||||
|
||||
public Integer getTenureType() {
|
||||
return this.tenureType;
|
||||
}
|
||||
|
||||
public Integer getInterestCalculationMethod() {
|
||||
return this.interestCalculationMethod;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-8
@@ -24,7 +24,6 @@ public class SavingAccountCommand {
|
||||
private final Integer lockinPeriodType;
|
||||
|
||||
private final LocalDate commencementDate;
|
||||
private final Integer savingProductType;
|
||||
private final Integer tenureType;
|
||||
private final Integer frequency;
|
||||
private final Integer interestType;
|
||||
@@ -42,7 +41,7 @@ public class SavingAccountCommand {
|
||||
public SavingAccountCommand(final Set<String> modifiedParameters, final Long id, final Long clientId, final Long productId,
|
||||
final String externalId, final String currencyCode, final Integer digitsAfterDecimal, final BigDecimal savingsDepositAmount,
|
||||
final BigDecimal recurringInterestRate, final BigDecimal savingInterestRate, final Integer tenure,
|
||||
final LocalDate commencementDate, final Integer savingProductType, final Integer tenureType, final Integer frequency,
|
||||
final LocalDate commencementDate, final Integer tenureType, final Integer frequency,
|
||||
final Integer interestType, final BigDecimal minimumBalanceForWithdrawal, final Integer interestCalculationMethod,
|
||||
final boolean isLockinPeriodAllowed, final boolean isPartialDepositAllowed, final Integer lockInPeriod,
|
||||
final Integer lockinPeriodType, final Integer depositEvery,final Integer interestPostEvery,final Integer interestPostFrequency) {
|
||||
@@ -61,7 +60,6 @@ public class SavingAccountCommand {
|
||||
this.modifiedParameters = modifiedParameters;
|
||||
this.commencementDate = commencementDate;
|
||||
|
||||
this.savingProductType = savingProductType;
|
||||
this.tenureType = tenureType;
|
||||
this.frequency = frequency;
|
||||
this.interestType = interestType;
|
||||
@@ -134,10 +132,6 @@ public class SavingAccountCommand {
|
||||
return commencementDate;
|
||||
}
|
||||
|
||||
public Integer getSavingProductType() {
|
||||
return savingProductType;
|
||||
}
|
||||
|
||||
public Integer getTenureType() {
|
||||
return tenureType;
|
||||
}
|
||||
@@ -261,7 +255,7 @@ public class SavingAccountCommand {
|
||||
|
||||
public CalculateSavingScheduleCommand toCalculateSavingScheduleCommand() {
|
||||
return new CalculateSavingScheduleCommand(productId, savingsDepositAmount, depositEvery, frequency, recurringInterestRate,
|
||||
commencementDate, tenure, interestPostEvery, interestPostFrequency);
|
||||
commencementDate, tenure, tenureType, interestPostEvery, interestPostFrequency,interestCalculationMethod);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-2
@@ -32,7 +32,6 @@ public class SavingAccountCommandValidator {
|
||||
baseDataValidator.reset().parameter("savingInterestRate").value(command.getSavingInterestRate()).notNull().zeroOrPositiveAmount();
|
||||
baseDataValidator.reset().parameter("savingInterestRate")
|
||||
.comapareMinAndMaxOfTwoBigDecmimalNos(command.getSavingInterestRate(), command.getRecurringInterestRate());
|
||||
baseDataValidator.reset().parameter("savingProductType").value(command.getSavingProductType()).notNull();
|
||||
baseDataValidator.reset().parameter("tenureType").value(command.getTenureType()).notNull();
|
||||
baseDataValidator.reset().parameter("tenure").value(command.getTenure()).notNull();
|
||||
baseDataValidator.reset().parameter("frequency").value(command.getFrequency()).notNull();
|
||||
@@ -72,7 +71,6 @@ public class SavingAccountCommandValidator {
|
||||
.zeroOrPositiveAmount();
|
||||
baseDataValidator.reset().parameter("savingInterestRate")
|
||||
.comapareMinAndMaxOfTwoBigDecmimalNos(command.getSavingInterestRate(), command.getRecurringInterestRate());
|
||||
baseDataValidator.reset().parameter("savingProductType").value(command.getSavingProductType()).ignoreIfNull();
|
||||
baseDataValidator.reset().parameter("tenureType").value(command.getTenureType()).ignoreIfNull();
|
||||
baseDataValidator.reset().parameter("tenure").value(command.getTenure()).ignoreIfNull();
|
||||
baseDataValidator.reset().parameter("frequency").value(command.getFrequency()).ignoreIfNull();
|
||||
|
||||
+86
-2
@@ -72,6 +72,10 @@ public class SavingAccountData {
|
||||
private final BigDecimal outstandingAmount;
|
||||
private final BigDecimal dueAmount;
|
||||
private final SavingScheduleData savingScheduleData;
|
||||
private final Collection<SavingAccountTransactionsData> transactions;
|
||||
|
||||
private final Integer interestPostEvery;
|
||||
private final EnumOptionData interestPostFrequency;
|
||||
|
||||
public static SavingAccountData createFrom(final Long clientId, final String clientDisplayName) {
|
||||
return new SavingAccountData(clientId, clientDisplayName);
|
||||
@@ -85,7 +89,7 @@ public class SavingAccountData {
|
||||
BigDecimal projectedInterestAccuredOnMaturity, BigDecimal actualInterestAccured, BigDecimal projectedMaturityAmount,
|
||||
BigDecimal actualMaturityAmount, boolean preClosureAllowed, BigDecimal preClosureInterestRate, LocalDate withdrawnonDate,
|
||||
LocalDate rejectedonDate, LocalDate closedonDate, boolean isLockinPeriodAllowed, Integer lockinPeriod,
|
||||
EnumOptionData lockinPeriodType, Integer depositEvery, BigDecimal outstandingAmount) {
|
||||
EnumOptionData lockinPeriodType, Integer depositEvery, BigDecimal outstandingAmount, Integer interestPostEvery, EnumOptionData interestPostFrequency) {
|
||||
this.id = id;
|
||||
this.status = status;
|
||||
this.externalId = externalId;
|
||||
@@ -133,6 +137,9 @@ public class SavingAccountData {
|
||||
this.outstandingAmount = outstandingAmount;
|
||||
this.dueAmount = BigDecimal.ZERO;
|
||||
this.savingScheduleData = null;
|
||||
this.transactions = null;
|
||||
this.interestPostEvery = interestPostEvery;
|
||||
this.interestPostFrequency = interestPostFrequency;
|
||||
}
|
||||
|
||||
public SavingAccountData(Long clientId, String clientName) {
|
||||
@@ -183,6 +190,9 @@ public class SavingAccountData {
|
||||
this.outstandingAmount = BigDecimal.ZERO;
|
||||
this.dueAmount =BigDecimal.ZERO;
|
||||
this.savingScheduleData = null;
|
||||
this.transactions = null;
|
||||
this.interestPostEvery =null;
|
||||
this.interestPostFrequency = null;
|
||||
}
|
||||
|
||||
public SavingAccountData(SavingAccountData account, Collection<SavingProductLookup> productOptions, List<CurrencyData> currencyOptions,
|
||||
@@ -238,6 +248,9 @@ public class SavingAccountData {
|
||||
this.permissions = account.permissions;
|
||||
this.outstandingAmount = account.outstandingAmount;
|
||||
this.savingScheduleData = account.savingScheduleData;
|
||||
this.transactions = account.transactions;
|
||||
this.interestPostEvery = account.interestPostEvery;
|
||||
this.interestPostFrequency = account.interestPostFrequency;
|
||||
}
|
||||
|
||||
// FIXME - Madhukar - unused variables been passed into construction - why?
|
||||
@@ -277,7 +290,7 @@ public class SavingAccountData {
|
||||
this.withdrawnonDate = null;
|
||||
this.rejectedonDate = null;
|
||||
this.closedonDate = null;
|
||||
this.isLockinPeriodAllowed = false;
|
||||
this.isLockinPeriodAllowed = lockinPeriodAllowed;
|
||||
this.lockinPeriod = lockinPeriod;
|
||||
this.lockinPeriodType = lockinPeriodType;
|
||||
this.depositEvery = depositEvery;
|
||||
@@ -294,6 +307,9 @@ public class SavingAccountData {
|
||||
this.outstandingAmount = BigDecimal.ZERO;
|
||||
this.dueAmount = BigDecimal.ZERO;
|
||||
this.savingScheduleData = null;
|
||||
this.transactions = null;
|
||||
this.interestPostEvery =3;
|
||||
this.interestPostFrequency = savingsFrequencyType;
|
||||
}
|
||||
|
||||
public SavingAccountData(SavingAccountData account, SavingPermissionData permissions) {
|
||||
@@ -345,6 +361,9 @@ public class SavingAccountData {
|
||||
this.outstandingAmount = account.outstandingAmount;
|
||||
this.dueAmount = account.dueAmount;
|
||||
this.savingScheduleData = account.savingScheduleData;
|
||||
this.transactions = account.transactions;
|
||||
this.interestPostEvery = account.interestPostEvery;
|
||||
this.interestPostFrequency = account.interestPostFrequency;
|
||||
}
|
||||
|
||||
public SavingAccountData(SavingAccountData account, SavingScheduleData savingScheduleData) {
|
||||
@@ -396,6 +415,63 @@ public class SavingAccountData {
|
||||
this.outstandingAmount = account.outstandingAmount;
|
||||
this.dueAmount = account.dueAmount;
|
||||
this.savingScheduleData = savingScheduleData;
|
||||
this.transactions = account.transactions;
|
||||
this.interestPostEvery = account.interestPostEvery;
|
||||
this.interestPostFrequency = account.interestPostFrequency;
|
||||
}
|
||||
|
||||
public SavingAccountData(SavingAccountData account, Collection<SavingAccountTransactionsData> transactions) {
|
||||
this.id = account.id;
|
||||
this.status = account.status;
|
||||
this.externalId = account.externalId;
|
||||
this.clientId = account.clientId;
|
||||
this.clientName = account.clientName;
|
||||
this.productId = account.productId;
|
||||
this.productName = account.productName;
|
||||
this.productType = account.productType;
|
||||
this.currencyData = account.currencyData;
|
||||
this.savingsDepositAmountPerPeriod = account.savingsDepositAmountPerPeriod;
|
||||
this.savingsFrequencyType = account.savingsFrequencyType;
|
||||
this.totalDepositAmount = account.totalDepositAmount;
|
||||
this.recurringInterestRate = account.recurringInterestRate;
|
||||
this.savingInterestRate = account.savingInterestRate;
|
||||
this.interestType = account.interestType;
|
||||
this.interestCalculationMethod = account.interestCalculationMethod;
|
||||
this.tenure = account.tenure;
|
||||
this.tenureType = account.tenureType;
|
||||
this.projectedCommencementDate = account.projectedCommencementDate;
|
||||
this.actualCommencementDate = account.actualCommencementDate;
|
||||
this.maturesOnDate = account.maturesOnDate;
|
||||
this.projectedInterestAccuredOnMaturity = account.projectedInterestAccuredOnMaturity;
|
||||
this.actualInterestAccured = account.actualInterestAccured;
|
||||
this.projectedMaturityAmount = account.projectedMaturityAmount;
|
||||
this.actualMaturityAmount = account.actualMaturityAmount;
|
||||
this.preClosureAllowed = account.preClosureAllowed;
|
||||
this.preClosureInterestRate = account.preClosureInterestRate;
|
||||
this.withdrawnonDate = account.withdrawnonDate;
|
||||
this.rejectedonDate = account.rejectedonDate;
|
||||
this.closedonDate = account.closedonDate;
|
||||
this.isLockinPeriodAllowed = account.isLockinPeriodAllowed;
|
||||
this.lockinPeriod = account.lockinPeriod;
|
||||
this.lockinPeriodType = account.lockinPeriodType;
|
||||
this.depositEvery = account.depositEvery;
|
||||
|
||||
this.productOptions = account.productOptions;
|
||||
this.currencyOptions = account.currencyOptions;
|
||||
this.savingsProductTypeOptions = account.savingsProductTypeOptions;
|
||||
this.tenureTypeOptions = account.tenureTypeOptions;
|
||||
this.savingFrequencyOptions = account.savingFrequencyOptions;
|
||||
this.savingsInterestTypeOptions = account.savingsInterestTypeOptions;
|
||||
this.lockinPeriodTypeOptions = account.lockinPeriodTypeOptions;
|
||||
this.interestCalculationOptions = account.interestCalculationOptions;
|
||||
this.savingScheduleDatas = account.savingScheduleDatas;
|
||||
this.permissions = account.permissions;
|
||||
this.outstandingAmount = account.outstandingAmount;
|
||||
this.dueAmount = account.dueAmount;
|
||||
this.savingScheduleData = account.savingScheduleData;
|
||||
this.transactions = transactions;
|
||||
this.interestPostEvery = account.interestPostEvery;
|
||||
this.interestPostFrequency = account.interestPostFrequency;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
@@ -569,5 +645,13 @@ public class SavingAccountData {
|
||||
public BigDecimal getOutstandingAmount() {
|
||||
return this.outstandingAmount;
|
||||
}
|
||||
|
||||
public Integer getInterestPostEvery() {
|
||||
return this.interestPostEvery;
|
||||
}
|
||||
|
||||
public EnumOptionData getInterestPostFrequency() {
|
||||
return this.interestPostFrequency;
|
||||
}
|
||||
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package org.mifosplatform.portfolio.savingsaccount.data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
|
||||
public class SavingAccountTransactionsData {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final Long id;
|
||||
@SuppressWarnings("unused")
|
||||
private final LocalDate transactionDate;
|
||||
@SuppressWarnings("unused")
|
||||
private final EnumOptionData transactionType;
|
||||
@SuppressWarnings("unused")
|
||||
private final BigDecimal amount;
|
||||
|
||||
public SavingAccountTransactionsData() {
|
||||
this.id = null;
|
||||
this.transactionDate = null;
|
||||
this.transactionType = null;
|
||||
this.amount = BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
public SavingAccountTransactionsData(final Long id, final LocalDate transactionDate, EnumOptionData transactionType, BigDecimal amount){
|
||||
this.id = id;
|
||||
this.transactionDate = transactionDate;
|
||||
this.transactionType = transactionType;
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
}
|
||||
+15
-3
@@ -9,12 +9,16 @@ public class SavingScheduleData {
|
||||
|
||||
private final CurrencyData currency;
|
||||
private final BigDecimal cumulativeDepositDue;
|
||||
private final BigDecimal cumulativeDepositPaid;
|
||||
private final BigDecimal cummulativeInterestAccured;
|
||||
private final Collection<SavingSchedulePeriodData> periods;
|
||||
|
||||
public SavingScheduleData(final CurrencyData currency, final BigDecimal cumulativeDepositDue,
|
||||
final Collection<SavingSchedulePeriodData> periods) {
|
||||
public SavingScheduleData(final CurrencyData currency, final BigDecimal cumulativeDepositDue, final BigDecimal cumulativeDepositPaid,
|
||||
final BigDecimal cummulativeInterestAccured, final Collection<SavingSchedulePeriodData> periods) {
|
||||
this.currency = currency;
|
||||
this.cumulativeDepositDue = cumulativeDepositDue;
|
||||
this.cumulativeDepositPaid = cumulativeDepositPaid;
|
||||
this.cummulativeInterestAccured = cummulativeInterestAccured;
|
||||
this.periods = periods;
|
||||
|
||||
}
|
||||
@@ -27,7 +31,15 @@ public class SavingScheduleData {
|
||||
return this.cumulativeDepositDue;
|
||||
}
|
||||
|
||||
public Collection<SavingSchedulePeriodData> getPeriods() {
|
||||
public BigDecimal getCumulativeDepositPaid() {
|
||||
return this.cumulativeDepositPaid;
|
||||
}
|
||||
|
||||
public BigDecimal getCummulativeInterestAccured() {
|
||||
return this.cummulativeInterestAccured;
|
||||
}
|
||||
|
||||
public Collection<SavingSchedulePeriodData> getPeriods() {
|
||||
return this.periods;
|
||||
}
|
||||
|
||||
|
||||
+8
-4
@@ -10,17 +10,19 @@ public class SavingSchedulePeriodData {
|
||||
private final LocalDate dueDate;
|
||||
private final BigDecimal depositDue;
|
||||
private final BigDecimal depositPaid;
|
||||
private final BigDecimal interestAccured;
|
||||
|
||||
public SavingSchedulePeriodData(final Integer period, final LocalDate dueDate, final BigDecimal depositDue, final BigDecimal depositPaid) {
|
||||
public SavingSchedulePeriodData(final Integer period, final LocalDate dueDate, final BigDecimal depositDue, final BigDecimal depositPaid, final BigDecimal interestAccured) {
|
||||
this.period = period;
|
||||
this.dueDate = dueDate;
|
||||
this.depositDue = depositDue;
|
||||
this.depositPaid = depositPaid;
|
||||
this.interestAccured = interestAccured;
|
||||
}
|
||||
|
||||
public static SavingSchedulePeriodData addScheduleInformation(int periodNumber, LocalDate scheduleDate,
|
||||
BigDecimal depositAmountPerPeriod) {
|
||||
return new SavingSchedulePeriodData(periodNumber, scheduleDate, depositAmountPerPeriod, BigDecimal.ZERO);
|
||||
BigDecimal depositAmountPerPeriod, BigDecimal interestAccured) {
|
||||
return new SavingSchedulePeriodData(periodNumber, scheduleDate, depositAmountPerPeriod, BigDecimal.ZERO, interestAccured);
|
||||
}
|
||||
|
||||
public Integer getPeriod() {
|
||||
@@ -39,5 +41,7 @@ public class SavingSchedulePeriodData {
|
||||
return this.depositPaid;
|
||||
}
|
||||
|
||||
|
||||
public BigDecimal getInterestAccured() {
|
||||
return this.interestAccured;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -3,11 +3,11 @@ package org.mifosplatform.portfolio.savingsaccount.domain;
|
||||
import java.util.List;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
|
||||
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingFrequencyType;
|
||||
|
||||
public interface DepositScheduleDateGenerator {
|
||||
|
||||
List<LocalDate> generate(LocalDate startDate, Integer paymentPeriods, Integer depositFrequency, PeriodFrequencyType depositFrequencyType);
|
||||
List<LocalDate> generate(LocalDate startDate, Integer paymentPeriods, Integer depositFrequency, SavingFrequencyType savingFrequencyType);
|
||||
|
||||
}
|
||||
|
||||
|
||||
+12
-9
@@ -34,27 +34,29 @@ public class ReccuringDepositInterestCalculator {
|
||||
|
||||
if(savingInterestCalculationMethod.isAverageBalance()){
|
||||
|
||||
BigDecimal totalAmount = BigDecimal.ZERO;
|
||||
BigDecimal termAmount = BigDecimal.ZERO;
|
||||
BigDecimal totalInterest = BigDecimal.ZERO;
|
||||
BigDecimal closingBalance = BigDecimal.ZERO;
|
||||
BigDecimal amountPerPeriod = savingsDepositPerPeriod.getAmount();
|
||||
Integer depositEveryOriginalValue = depositEvery;
|
||||
BigDecimal amountPermonth = amountPerPeriod.divide(BigDecimal.valueOf(depositEvery.doubleValue()));
|
||||
BigDecimal amountPermonth = BigDecimal.valueOf(amountPerPeriod.doubleValue()/depositEvery.doubleValue());
|
||||
|
||||
while (noOfTimestobeCalculated > 0) {
|
||||
while (depositEvery > 0) {
|
||||
termAmount = termAmount.add(amountPermonth);
|
||||
totalAmount = totalAmount.add(termAmount);
|
||||
closingBalance = closingBalance.add(amountPermonth);
|
||||
termAmount = termAmount.add(closingBalance);
|
||||
depositEvery--;
|
||||
}
|
||||
BigDecimal averageAmount = BigDecimal.valueOf(totalAmount.doubleValue()/depositEveryOriginalValue.doubleValue());
|
||||
|
||||
BigDecimal averageAmount = BigDecimal.valueOf(termAmount.doubleValue()/depositEveryOriginalValue.doubleValue());
|
||||
BigDecimal interestRatePerTerm = BigDecimal.valueOf(interestRateAsFraction.doubleValue()/monthsInYear.doubleValue()*depositEveryOriginalValue.doubleValue());
|
||||
BigDecimal interestperTerm = averageAmount.multiply(interestRatePerTerm);
|
||||
totalInterest = totalInterest.add(interestperTerm);
|
||||
depositEvery = depositEveryOriginalValue;
|
||||
totalAmount = BigDecimal.ZERO;
|
||||
termAmount = BigDecimal.ZERO;
|
||||
noOfTimestobeCalculated--;
|
||||
}
|
||||
finalAmount = termAmount.add(totalInterest);
|
||||
finalAmount = closingBalance.add(totalInterest);
|
||||
|
||||
} else if(savingInterestCalculationMethod.isMonthlyCollection()){
|
||||
/*
|
||||
@@ -73,14 +75,15 @@ public class ReccuringDepositInterestCalculator {
|
||||
BigDecimal monthsExpressedInYears;
|
||||
BigDecimal timeforOneCalculationPeriod;
|
||||
BigDecimal amountPerPeriod;
|
||||
|
||||
Integer tempTenure = tenure;
|
||||
while (noOfTimestobeCalculated > 0) {
|
||||
monthsExpressedInYears = BigDecimal.valueOf(tenure.doubleValue() / monthsInYear.doubleValue());
|
||||
monthsExpressedInYears = BigDecimal.valueOf(tempTenure.doubleValue() / monthsInYear.doubleValue());
|
||||
timeforOneCalculationPeriod = BigDecimal.valueOf(noofTimesInterestCompoundPerYear * monthsExpressedInYears.doubleValue());
|
||||
amountPerPeriod = savingsDepositPerPeriod.getAmount().multiply(
|
||||
BigDecimal.valueOf(Math.pow(onePlusInterestRatePerPeriod.doubleValue(), timeforOneCalculationPeriod.doubleValue())));
|
||||
finalAmount = finalAmount.add(amountPerPeriod);
|
||||
noOfTimestobeCalculated--;
|
||||
tempTenure = tempTenure-depositEvery;
|
||||
}
|
||||
}
|
||||
return Money.of(savingsDepositPerPeriod.getCurrency(), finalAmount);
|
||||
|
||||
+54
-38
@@ -204,12 +204,13 @@ public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
Integer depositEvery, Integer interestPostEvery, Integer interestPostFrequency) {
|
||||
|
||||
Money futureValueOnMaturity = null;
|
||||
if (savingProductType.isReccuring()) {
|
||||
if (savingProductType.isReccuring() && tenureTypeEnum.isFixedPeriod()) {
|
||||
futureValueOnMaturity = reccuringDepositInterestCalculator.calculateInterestOnMaturityFor(savingsDeposit, tenure,
|
||||
reccuringInterestRate, commencementDate, tenureTypeEnum, savingFrequencyType, savingInterestCalculationMethod,depositEvery);
|
||||
} else if (savingProductType.isRegular()) {
|
||||
futureValueOnMaturity = reccuringDepositInterestCalculator.calculateInterestOnMaturityFor(savingsDeposit, tenure,
|
||||
savingInterestRate, commencementDate, tenureTypeEnum, savingFrequencyType, savingInterestCalculationMethod,depositEvery);
|
||||
} else if (savingProductType.isReccuring() && tenureTypeEnum.isPerpetual()) {
|
||||
futureValueOnMaturity = savingsDeposit;
|
||||
} else {
|
||||
futureValueOnMaturity = savingsDeposit;
|
||||
}
|
||||
|
||||
return new SavingAccount(client, externalId, product, savingsDeposit, reccuringInterestRate, savingInterestRate, tenure,
|
||||
@@ -255,8 +256,8 @@ public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
this.lockinPeriod = lockinPeriod;
|
||||
this.lockinPeriodType = lockinPeriodType.getValue();
|
||||
this.projectedTotalOnMaturity = futureValueOnMaturity.getAmount();
|
||||
this.projectedInterestAccruedOnMaturity = futureValueOnMaturity.getAmount().subtract(
|
||||
BigDecimal.valueOf(savingsDeposit.getAmount().doubleValue() * tenure.doubleValue() / payEvery)); //presently only for months
|
||||
BigDecimal projectedInterestForReccuring = futureValueOnMaturity.getAmount().subtract(BigDecimal.valueOf(savingsDeposit.getAmount().doubleValue() * tenure.doubleValue() / payEvery)); //presently only for months
|
||||
this.projectedInterestAccruedOnMaturity = savingProductType.isReccuring() && tenureTypeEnum.isFixedPeriod() ? projectedInterestForReccuring : BigDecimal.ZERO;
|
||||
this.payEvery = payEvery;
|
||||
this.outstandingAmount = BigDecimal.ZERO;
|
||||
this.interestPostEvery = interestPostEvery;
|
||||
@@ -267,15 +268,17 @@ public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
BigDecimal savingInterestRate, Integer tenure, LocalDate commencementDate, TenureTypeEnum tenureTypeEnum,
|
||||
SavingProductType savingProductType, SavingFrequencyType savingFrequencyType,
|
||||
SavingInterestCalculationMethod savingInterestCalculationMethod, boolean isLockinPeriodAllowed, Integer lockinPeriod,
|
||||
PeriodFrequencyType lockinPeriodType, ReccuringDepositInterestCalculator reccuringDepositInterestCalculator,Integer payEvery) {
|
||||
PeriodFrequencyType lockinPeriodType, ReccuringDepositInterestCalculator reccuringDepositInterestCalculator,Integer payEvery,
|
||||
SavingsInterestType interestType, Integer interestPostEvery, Integer interestPostFrequency) {
|
||||
|
||||
Money futureValueOnMaturity = null;
|
||||
if (savingProductType.isReccuring()) {
|
||||
Money futureValueOnMaturity = null;
|
||||
if (savingProductType.isReccuring() && tenureTypeEnum.isFixedPeriod()) {
|
||||
futureValueOnMaturity = reccuringDepositInterestCalculator.calculateInterestOnMaturityFor(savingsDeposit, tenure,
|
||||
reccuringInterestRate, commencementDate, tenureTypeEnum, savingFrequencyType, savingInterestCalculationMethod,payEvery);
|
||||
} else if (savingProductType.isRegular()) {
|
||||
futureValueOnMaturity = reccuringDepositInterestCalculator.calculateInterestOnMaturityFor(savingsDeposit, tenure,
|
||||
savingInterestRate, commencementDate, tenureTypeEnum, savingFrequencyType, savingInterestCalculationMethod,payEvery);
|
||||
} else if (savingProductType.isReccuring() && tenureTypeEnum.isPerpetual()) {
|
||||
futureValueOnMaturity = savingsDeposit;
|
||||
} else {
|
||||
futureValueOnMaturity = savingsDeposit;
|
||||
}
|
||||
|
||||
this.product = product;
|
||||
@@ -288,17 +291,20 @@ public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
this.tenureType = tenureTypeEnum.getValue();
|
||||
this.savingProductType = savingProductType.getValue();
|
||||
this.frequency = savingFrequencyType.getValue();
|
||||
this.interestType = interestType.getValue();
|
||||
this.interestCalculationMethod = savingInterestCalculationMethod.getValue();
|
||||
this.isLockinPeriodAllowed = isLockinPeriodAllowed;
|
||||
this.lockinPeriod = lockinPeriod;
|
||||
this.lockinPeriodType = lockinPeriodType.getValue();
|
||||
this.payEvery = payEvery;
|
||||
this.outstandingAmount = BigDecimal.ZERO;
|
||||
this.interestPostEvery = interestPostEvery;
|
||||
this.interestPostFrequency=interestPostFrequency;
|
||||
this.savingScheduleInstallments.clear();
|
||||
|
||||
// FIXME - MADHUKAR - futureValueOnMaturity is possibly null
|
||||
this.projectedTotalOnMaturity = futureValueOnMaturity.getAmount();
|
||||
this.projectedInterestAccruedOnMaturity = futureValueOnMaturity.getAmount().subtract(
|
||||
BigDecimal.valueOf(savingsDeposit.getAmount().doubleValue() * tenure.doubleValue()));
|
||||
BigDecimal projectedInterestForReccuring = futureValueOnMaturity.getAmount().subtract(BigDecimal.valueOf(savingsDeposit.getAmount().doubleValue() * tenure.doubleValue() / payEvery)); //presently only for months
|
||||
this.projectedInterestAccruedOnMaturity = savingProductType.isReccuring() && tenureTypeEnum.isFixedPeriod() ? projectedInterestForReccuring : BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
public boolean isDeleted() {
|
||||
@@ -456,6 +462,7 @@ public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
this.maturesOnDate = null;
|
||||
this.withdrawnOnDate = withdrawnOn.toDateTimeAtCurrentTime().toDate();
|
||||
this.closedOnDate = withdrawnOn.toDateTimeAtCurrentTime().toDate();
|
||||
this.savingScheduleInstallments.clear();
|
||||
|
||||
if (withdrawnOn.isBefore(projectedCommencementDate())) {
|
||||
|
||||
@@ -480,7 +487,6 @@ public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
this.closedOnDate = new Date();
|
||||
}
|
||||
|
||||
@SuppressWarnings("null")
|
||||
public void approveSavingAccount(LocalDate approvalDate, BigDecimal savingsDepositAmountPerPeriod, BigDecimal recurringInterestRate,
|
||||
BigDecimal savingInterestRate, Integer interestType, Integer tenure, Integer tenureType, Integer frequency, Integer payEvery,
|
||||
DepositLifecycleStateMachine depositLifecycleStateMachine, ReccuringDepositInterestCalculator reccuringDepositInterestCalculator,
|
||||
@@ -496,12 +502,13 @@ public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
SavingInterestCalculationMethod interestCalculationMethod = SavingInterestCalculationMethod.fromInt(this.interestCalculationMethod);
|
||||
|
||||
Money futureValueOnMaturity = null;
|
||||
if (SavingProductType.fromInt(product.getSavingProductRelatedDetail().getSavingProductType()).isReccuring()) {
|
||||
if (SavingProductType.fromInt(this.savingProductType).isReccuring() && tenureTypeEnum.isFixedPeriod()) {
|
||||
futureValueOnMaturity = reccuringDepositInterestCalculator.calculateInterestOnMaturityFor(savingsAmountPerPeriod, tenure,
|
||||
recurringInterestRate, approvalDate, tenureTypeEnum, savingFrequencyType, interestCalculationMethod,payEvery);
|
||||
} else if (SavingProductType.fromInt(product.getSavingProductRelatedDetail().getSavingProductType()).isRegular()) {
|
||||
futureValueOnMaturity = reccuringDepositInterestCalculator.calculateInterestOnMaturityFor(savingsAmountPerPeriod, tenure,
|
||||
savingInterestRate, approvalDate, tenureTypeEnum, savingFrequencyType, interestCalculationMethod,payEvery);
|
||||
} else if (SavingProductType.fromInt(this.savingProductType).isReccuring() && tenureTypeEnum.isPerpetual()) {
|
||||
futureValueOnMaturity = savingsAmountPerPeriod;
|
||||
} else {
|
||||
futureValueOnMaturity = savingsAmountPerPeriod;
|
||||
}
|
||||
|
||||
this.actualCommencementDate = approvalDate.toDate();
|
||||
@@ -515,7 +522,8 @@ public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
this.payEvery = payEvery;
|
||||
this.savingScheduleInstallments.clear();
|
||||
this.total=futureValueOnMaturity.getAmount();
|
||||
this.interestAccrued = futureValueOnMaturity.getAmount().subtract(BigDecimal.valueOf(savingsDepositAmountPerPeriod.doubleValue() * tenure/payEvery.doubleValue()));
|
||||
BigDecimal interestForReccuring = futureValueOnMaturity.getAmount().subtract(BigDecimal.valueOf(savingsDepositAmountPerPeriod.doubleValue() * tenure.doubleValue()/payEvery.doubleValue())); //presently only for months
|
||||
this.interestAccrued = SavingProductType.fromInt(this.savingProductType).isReccuring() && tenureTypeEnum.isFixedPeriod() ? interestForReccuring : BigDecimal.ZERO;
|
||||
this.interestPostEvery = interestPostEvery;
|
||||
this.interestPostFrequency = interestPostFrequency;
|
||||
|
||||
@@ -537,25 +545,32 @@ public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
this.outstandingAmount = this.outstandingAmount.add(command.getSavingsDepostiAmountPerPeriod());
|
||||
this.totalSavingsAmount = this.totalSavingsAmount.add(command.getSavingsDepostiAmountPerPeriod());
|
||||
|
||||
for(SavingScheduleInstallments savingScheduleInstallment : this.savingScheduleInstallments){
|
||||
if(!savingScheduleInstallment.isCompleted()){
|
||||
depositAmount = savingScheduleInstallment.getDeposit();
|
||||
remainAmountToBePaid = depositAmount.subtract(savingScheduleInstallment.getDepositPaid());
|
||||
if (remainAmountToBePaid.doubleValue() > 0) {
|
||||
if (commandRemainDepositAmount.doubleValue() > 0) {
|
||||
if (commandRemainDepositAmount.doubleValue() >= remainAmountToBePaid.doubleValue()) {
|
||||
savingScheduleInstallment.setDepositPaid(remainAmountToBePaid.add(savingScheduleInstallment.getDepositPaid()));
|
||||
savingScheduleInstallment.setPaymentDate(command.getDepositDate().toDate());
|
||||
savingScheduleInstallment.setCompleted(true);
|
||||
commandRemainDepositAmount = commandRemainDepositAmount.subtract(remainAmountToBePaid);
|
||||
} else if(commandRemainDepositAmount.doubleValue() < remainAmountToBePaid.doubleValue()){
|
||||
savingScheduleInstallment.setDepositPaid(commandRemainDepositAmount.add(savingScheduleInstallment.getDepositPaid()));
|
||||
savingScheduleInstallment.setPaymentDate(command.getDepositDate().toDate());
|
||||
commandRemainDepositAmount = BigDecimal.ZERO;
|
||||
if(SavingProductType.fromInt(this.savingProductType).isReccuring() && TenureTypeEnum.fromInt(tenureType).isFixedPeriod()) {
|
||||
for(SavingScheduleInstallments savingScheduleInstallment : this.savingScheduleInstallments){
|
||||
if(!savingScheduleInstallment.isCompleted()){
|
||||
depositAmount = savingScheduleInstallment.getDeposit();
|
||||
remainAmountToBePaid = depositAmount.subtract(savingScheduleInstallment.getDepositPaid());
|
||||
if (remainAmountToBePaid.doubleValue() > 0) {
|
||||
if (commandRemainDepositAmount.doubleValue() > 0) {
|
||||
if (commandRemainDepositAmount.doubleValue() >= remainAmountToBePaid.doubleValue()) {
|
||||
savingScheduleInstallment.setDepositPaid(remainAmountToBePaid.add(savingScheduleInstallment.getDepositPaid()));
|
||||
savingScheduleInstallment.setPaymentDate(command.getDepositDate().toDate());
|
||||
savingScheduleInstallment.setCompleted(true);
|
||||
commandRemainDepositAmount = commandRemainDepositAmount.subtract(remainAmountToBePaid);
|
||||
} else if(commandRemainDepositAmount.doubleValue() < remainAmountToBePaid.doubleValue()){
|
||||
savingScheduleInstallment.setDepositPaid(commandRemainDepositAmount.add(savingScheduleInstallment.getDepositPaid()));
|
||||
savingScheduleInstallment.setPaymentDate(command.getDepositDate().toDate());
|
||||
commandRemainDepositAmount = BigDecimal.ZERO;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(SavingScheduleInstallments savingScheduleInstallment : this.savingScheduleInstallments){
|
||||
savingScheduleInstallment.setDepositPaid(remainAmountToBePaid.add(savingScheduleInstallment.getDepositPaid()));
|
||||
savingScheduleInstallment.setPaymentDate(command.getDepositDate().toDate());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -582,7 +597,7 @@ public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
this.externalId = this.getId() + "_" + this.externalId;
|
||||
}
|
||||
|
||||
public void postInterest(ReccuringDepositInterestCalculator reccuringDepositInterestCalculator) {
|
||||
public void postInterest() {
|
||||
|
||||
LocalDate lastInterestPostedDate = getLastInterestPostedDate();
|
||||
@SuppressWarnings("unused")
|
||||
@@ -643,8 +658,9 @@ public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
termTotalAmount = termTotalAmount.add(totalOutstandingAmount);
|
||||
transactionStartDate = transactionEndDate;
|
||||
isOutstandingAmountCalculated = true;
|
||||
|
||||
}
|
||||
// FIXME-MADHUKAR calculate interest on calculation method
|
||||
// TODO- calculate interest on calculation method
|
||||
|
||||
// if (savingInterestCalculationMethod.isAverageBalance()) {
|
||||
averageBalanceForTerm =BigDecimal.valueOf(termTotalAmount.doubleValue()/this.interestPostEvery);
|
||||
|
||||
+6
-1
@@ -45,6 +45,10 @@ public class SavingScheduleInstallments extends AbstractAuditableCustom<AppUser,
|
||||
@Column(name = "deposit_paid", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal depositPaid;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "interest_accured", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal interstAccured;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "completed_derived", nullable = false)
|
||||
private boolean completed;
|
||||
@@ -55,7 +59,7 @@ public class SavingScheduleInstallments extends AbstractAuditableCustom<AppUser,
|
||||
this.paymentDate = null;
|
||||
}
|
||||
|
||||
public SavingScheduleInstallments(SavingAccount account, Date dueDate, Integer installmentNumber, BigDecimal deposit) {
|
||||
public SavingScheduleInstallments(SavingAccount account, Date dueDate, Integer installmentNumber, BigDecimal deposit, BigDecimal interstAccured) {
|
||||
this.savingAccount = account;
|
||||
this.dueDate = dueDate;
|
||||
this.installmentNumber = installmentNumber;
|
||||
@@ -63,6 +67,7 @@ public class SavingScheduleInstallments extends AbstractAuditableCustom<AppUser,
|
||||
this.paymentDate = null;
|
||||
this.depositPaid = BigDecimal.ZERO;
|
||||
this.completed = false;
|
||||
this.interstAccured = interstAccured;
|
||||
}
|
||||
|
||||
public void updateAccount(SavingAccount account) {
|
||||
|
||||
+26
-6
@@ -1,17 +1,24 @@
|
||||
package org.mifosplatform.portfolio.savingsaccount.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
||||
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrency;
|
||||
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrencyRepository;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.CalculateSavingScheduleCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingScheduleData;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingSchedulePeriodData;
|
||||
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingFrequencyType;
|
||||
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingInterestCalculationMethod;
|
||||
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProduct;
|
||||
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProductRepository;
|
||||
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProductType;
|
||||
import org.mifosplatform.portfolio.savingsaccountproduct.exception.SavingProductNotFoundException;
|
||||
import org.mifosplatform.portfolio.savingsdepositproduct.domain.TenureTypeEnum;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -36,23 +43,36 @@ public class CalculateSavingScheduleImpl implements CalculateSavingSchedule {
|
||||
public SavingScheduleData calculateSavingSchedule(CalculateSavingScheduleCommand command) {
|
||||
|
||||
context.authenticatedUser();
|
||||
SavingScheduleData savingScheduleData = null;
|
||||
|
||||
// FIXME Validations should write here
|
||||
final SavingProduct savingProduct = this.savingProductRepository.findOne(command.getProductId());
|
||||
if (savingProduct == null) throw new SavingProductNotFoundException(command.getProductId());
|
||||
|
||||
final Integer depositFrequency = command.getDepositEvery();
|
||||
final PeriodFrequencyType depositFrequencyType = PeriodFrequencyType.fromInt(command.getPaymentFrequencyType());
|
||||
final SavingFrequencyType savingFrequencyType = SavingFrequencyType.fromInt(command.getPaymentFrequencyType());
|
||||
final LocalDate scheduleStartDate = command.getPaymentsStartingFromDate();
|
||||
@SuppressWarnings("unused")
|
||||
final BigDecimal interestRate = command.getInterestRate();
|
||||
final BigDecimal depositAmountPerPeriod = command.getDeposit();
|
||||
final Integer tenure = command.getTenure();
|
||||
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneByCode(savingProduct.getCurrency()
|
||||
.getCode());
|
||||
|
||||
SavingScheduleData savingScheduleData = savingScheduleGenerator.generate(scheduleStartDate, depositAmountPerPeriod,
|
||||
depositFrequency, depositFrequencyType, savingProduct, tenure, applicationCurrency);
|
||||
|
||||
SavingProductType savingProductType = SavingProductType.fromInt(savingProduct.getSavingProductRelatedDetail().getSavingProductType());
|
||||
TenureTypeEnum tenureType = TenureTypeEnum.fromInt(command.getTenureType());
|
||||
SavingInterestCalculationMethod interestCalculationMethod = SavingInterestCalculationMethod.fromInt(command.getInterestCalculationMethod());
|
||||
if (savingProductType.isReccuring() && tenureType.isFixedPeriod()) {
|
||||
savingScheduleData = savingScheduleGenerator.generate(scheduleStartDate, depositAmountPerPeriod,
|
||||
depositFrequency, savingFrequencyType, savingProduct, tenure, applicationCurrency,interestRate,interestCalculationMethod);
|
||||
} else {
|
||||
final Collection<SavingSchedulePeriodData> periods = new ArrayList<SavingSchedulePeriodData>();
|
||||
CurrencyData currencyData = new CurrencyData(applicationCurrency.getCode(), applicationCurrency.getName(),
|
||||
savingProduct.getCurrency().getDigitsAfterDecimal(), applicationCurrency.getDisplaySymbol(), applicationCurrency.getNameCode());
|
||||
SavingSchedulePeriodData installment = SavingSchedulePeriodData.addScheduleInformation(1, new LocalDate(command.getPaymentsStartingFromDate()).plusMonths(depositFrequency), command.getDeposit(), BigDecimal.ZERO);
|
||||
periods.add(installment);
|
||||
savingScheduleData = new SavingScheduleData(currencyData, command.getDeposit(), BigDecimal.ZERO, BigDecimal.ZERO, periods);
|
||||
}
|
||||
|
||||
|
||||
return savingScheduleData;
|
||||
}
|
||||
|
||||
+14
-11
@@ -4,14 +4,14 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
|
||||
import org.mifosplatform.portfolio.savingsaccount.domain.DepositScheduleDateGenerator;
|
||||
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingFrequencyType;
|
||||
|
||||
public class DefaultDepositScheduleDateGenerator implements DepositScheduleDateGenerator {
|
||||
|
||||
@Override
|
||||
public List<LocalDate> generate(LocalDate scheuleStartDate, Integer paymentPeriods, Integer depositFrequency,
|
||||
PeriodFrequencyType depositFrequencyType) {
|
||||
SavingFrequencyType savingFrequencyType) {
|
||||
|
||||
List<LocalDate> duePaymentPeriodDates = new ArrayList<LocalDate>(depositFrequency);
|
||||
LocalDate startDate = scheuleStartDate;
|
||||
@@ -22,21 +22,24 @@ public class DefaultDepositScheduleDateGenerator implements DepositScheduleDateG
|
||||
if (period == 1) {
|
||||
duePaymentPeriodDate = startDate;
|
||||
} else {
|
||||
switch (depositFrequencyType) {
|
||||
case DAYS:
|
||||
switch (savingFrequencyType) {
|
||||
case DAILY:
|
||||
duePaymentPeriodDate = startDate.plusDays(depositFrequency);
|
||||
break;
|
||||
case WEEKS:
|
||||
duePaymentPeriodDate = startDate.plusWeeks(depositFrequency);
|
||||
break;
|
||||
case MONTHS:
|
||||
case MONTHLY:
|
||||
duePaymentPeriodDate = startDate.plusMonths(depositFrequency);
|
||||
break;
|
||||
case YEARS:
|
||||
duePaymentPeriodDate = startDate.plusYears(depositFrequency);
|
||||
case QUATERLY:
|
||||
duePaymentPeriodDate = startDate.plusMonths(3*depositFrequency);
|
||||
break;
|
||||
case INVALID:
|
||||
case HALFYEARLY:
|
||||
duePaymentPeriodDate = startDate.plusMonths(6*depositFrequency);
|
||||
break;
|
||||
case YEARLY:
|
||||
duePaymentPeriodDate = startDate.plusYears(depositFrequency);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
duePaymentPeriodDates.add(duePaymentPeriodDate);
|
||||
|
||||
+24
-11
@@ -80,9 +80,6 @@ public class SavingAccountAssembler {
|
||||
}
|
||||
|
||||
SavingProductType savingProductType = SavingProductType.fromInt(product.getSavingProductRelatedDetail().getSavingProductType());
|
||||
if (command.getSavingProductType() != null) {
|
||||
savingProductType = SavingProductType.fromInt(command.getSavingProductType());
|
||||
}
|
||||
|
||||
SavingFrequencyType savingFrequencyType = SavingFrequencyType.fromInt(product.getSavingProductRelatedDetail().getFrequency());
|
||||
if (command.getFrequency() != null) {
|
||||
@@ -135,7 +132,7 @@ public class SavingAccountAssembler {
|
||||
for (SavingSchedulePeriodData savingSchedulePeriodData : savingScheduleData.getPeriods()) {
|
||||
|
||||
final SavingScheduleInstallments installment = new SavingScheduleInstallments(account, savingSchedulePeriodData.getDueDate()
|
||||
.toDate(), savingSchedulePeriodData.getPeriod(), savingSchedulePeriodData.getDepositDue());
|
||||
.toDate(), savingSchedulePeriodData.getPeriod(), savingSchedulePeriodData.getDepositDue(), savingSchedulePeriodData.getInterestAccured());
|
||||
account.addSavingScheduleInstallment(installment);
|
||||
}
|
||||
|
||||
@@ -177,9 +174,6 @@ public class SavingAccountAssembler {
|
||||
}
|
||||
|
||||
SavingProductType savingProductType = SavingProductType.fromInt(account.getSavingProductType());
|
||||
if (command.isSavingProductTypeChanged()) {
|
||||
savingProductType = SavingProductType.fromInt(command.getSavingProductType());
|
||||
}
|
||||
|
||||
SavingFrequencyType savingFrequencyType = SavingFrequencyType.fromInt(account.getFrequency());
|
||||
if (command.isSavingFrequencyTypeChanged()) {
|
||||
@@ -220,9 +214,28 @@ public class SavingAccountAssembler {
|
||||
if(command.isDepositEveryChanged()){
|
||||
payEvery = command.getDepositEvery();
|
||||
}
|
||||
|
||||
SavingsInterestType interestType = SavingsInterestType.fromInt(product.getSavingProductRelatedDetail().getInterestType());
|
||||
if (command.getInterestType() != null) {
|
||||
interestType = SavingsInterestType.fromInt(command.getInterestType());
|
||||
}
|
||||
|
||||
Integer interestPostEvery = command.getInterestPostEvery();
|
||||
|
||||
Integer interestPostFrequency =command.getInterestPostFrequency();
|
||||
|
||||
account.modifyAccount(product, externalId, savingsDeposit, reccuringInterestRate, savingInterestRate, tenure, commencementDate,
|
||||
tenureTypeEnum, savingProductType, savingFrequencyType, savingInterestCalculationMethod, isLockinPeriodAllowed,
|
||||
lockinPeriod, lockinPeriodType, this.reccuringDepositInterestCalculator,payEvery);
|
||||
lockinPeriod, lockinPeriodType, this.reccuringDepositInterestCalculator,payEvery, interestType, interestPostEvery, interestPostFrequency);
|
||||
|
||||
SavingScheduleData savingScheduleData = this.calculateSavingSchedule.calculateSavingSchedule(command
|
||||
.toCalculateSavingScheduleCommand());
|
||||
for (SavingSchedulePeriodData savingSchedulePeriodData : savingScheduleData.getPeriods()) {
|
||||
|
||||
final SavingScheduleInstallments installment = new SavingScheduleInstallments(account, savingSchedulePeriodData.getDueDate()
|
||||
.toDate(), savingSchedulePeriodData.getPeriod(), savingSchedulePeriodData.getDepositDue(), savingSchedulePeriodData.getInterestAccured());
|
||||
account.addSavingScheduleInstallment(installment);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -292,13 +305,13 @@ public class SavingAccountAssembler {
|
||||
|
||||
|
||||
CalculateSavingScheduleCommand calculateSavingScheduleCommand = new CalculateSavingScheduleCommand(account.getProduct().getId(), savingsDepositAmountPerPeriod, payEvery,
|
||||
frequency, recurringInterestRate, approvalDate, tenure,interestPostEvery,interestPostFrequency);
|
||||
frequency, recurringInterestRate, approvalDate, tenure,tenureType,interestPostEvery,interestPostFrequency,account.getInterestCalculationMethod());
|
||||
|
||||
SavingScheduleData savingScheduleData = this.calculateSavingSchedule.calculateSavingSchedule(calculateSavingScheduleCommand);
|
||||
for (SavingSchedulePeriodData savingSchedulePeriodData : savingScheduleData.getPeriods()) {
|
||||
|
||||
final SavingScheduleInstallments installment = new SavingScheduleInstallments(account, savingSchedulePeriodData.getDueDate()
|
||||
.toDate(), savingSchedulePeriodData.getPeriod(), savingSchedulePeriodData.getDepositDue());
|
||||
.toDate(), savingSchedulePeriodData.getPeriod(), savingSchedulePeriodData.getDepositDue(),savingSchedulePeriodData.getInterestAccured());
|
||||
account.addSavingScheduleInstallment(installment);
|
||||
}
|
||||
}
|
||||
@@ -315,7 +328,7 @@ public class SavingAccountAssembler {
|
||||
}
|
||||
|
||||
public void postInterest(SavingAccount account) {
|
||||
account.postInterest(this.reccuringDepositInterestCalculator);
|
||||
account.postInterest();
|
||||
}
|
||||
|
||||
}
|
||||
+3
@@ -6,6 +6,7 @@ import java.util.Collection;
|
||||
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountData;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountForLookup;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountTransactionsData;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingPermissionData;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingScheduleData;
|
||||
|
||||
@@ -24,4 +25,6 @@ public interface SavingAccountReadPlatformService {
|
||||
SavingScheduleData retrieveSavingsAccountSchedule(Long accountId, CurrencyData currencyData);
|
||||
|
||||
Collection<SavingAccountForLookup> retrieveSavingAccountsForLookUp();
|
||||
|
||||
Collection<SavingAccountTransactionsData> retrieveSavingsAccountTransactions(Long accountId);
|
||||
}
|
||||
|
||||
+45
-7
@@ -17,6 +17,7 @@ import org.mifosplatform.portfolio.client.data.ClientData;
|
||||
import org.mifosplatform.portfolio.client.service.ClientReadPlatformService;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountData;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountForLookup;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountTransactionsData;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingPermissionData;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingScheduleData;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingSchedulePeriodData;
|
||||
@@ -25,6 +26,7 @@ import org.mifosplatform.portfolio.savingsaccountproduct.data.SavingProductLooku
|
||||
import org.mifosplatform.portfolio.savingsaccountproduct.service.SavingProductEnumerations;
|
||||
import org.mifosplatform.portfolio.savingsaccountproduct.service.SavingProductReadPlatformService;
|
||||
import org.mifosplatform.portfolio.savingsdepositaccount.service.DepositAccountEnumerations;
|
||||
import org.mifosplatform.portfolio.savingsdepositaccount.service.DepositAccountTransactionEnumerations;
|
||||
import org.mifosplatform.portfolio.savingsdepositproduct.domain.TenureTypeEnum;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
@@ -85,6 +87,7 @@ public class SavingAccountReadPlatformServiceImpl implements SavingAccountReadPl
|
||||
+ " sa.pre_closure_interest_rate AS preClosureInterestRate, sa.is_lock_in_period_allowed AS isLockinPeriodAllowed,"
|
||||
+ " sa.lock_in_period AS lockinPeriod, sa.lock_in_period_type AS lockinPeriodType, sa.withdrawnon_date AS withdrawnonDate,"
|
||||
+ " sa.rejectedon_date AS rejectedonDate, sa.closedon_date AS closedonDate, ps.name AS productName, sa.deposit_every as depositEvery, "
|
||||
+ " sa.interest_posting_every AS interestPostEvery, sa.interest_posting_frequency AS interestPostFrequency, "
|
||||
+ " c.firstname AS firstname, c.lastname AS lastname, curr.name AS currencyName, "
|
||||
+ " curr.internationalized_name_code AS currencyNameCode, curr.display_symbol AS currencyDisplaySymbol "
|
||||
+ " FROM m_saving_account sa " + " JOIN m_client c ON c.id = sa.client_id"
|
||||
@@ -150,13 +153,17 @@ public class SavingAccountReadPlatformServiceImpl implements SavingAccountReadPl
|
||||
Integer lockinPeriodTypeValue = JdbcSupport.getInteger(rs, "lockinPeriodType");
|
||||
EnumOptionData lockinPeriodType = SavingProductEnumerations.savingsLockinPeriod(lockinPeriodTypeValue);
|
||||
Integer depositEvery = JdbcSupport.getInteger(rs, "depositEvery");
|
||||
|
||||
Integer interestPostEvery = JdbcSupport.getInteger(rs, "interestPostEvery");
|
||||
EnumOptionData interestPostFrequency = SavingProductEnumerations.interestFrequencyType(JdbcSupport.getInteger(rs, "interestPostFrequency"));
|
||||
|
||||
|
||||
return new SavingAccountData(id, status, externalId, clientId, clientName, productId, productName, productType, currencyData,
|
||||
savingsDepostiAmountPerPeriod, savingsFrequencyType, totalDepositAmount, reccuringInterestRate, savingInterestRate,
|
||||
interestType, interestCalculationMethod, tenure, tenureType, projectedCommencementDate, actualCommencementDate,
|
||||
maturesOnDate, projectedInterestAccuredOnMaturity, actualInterestAccured, projectedMaturityAmount,
|
||||
actualMaturityAmount, preClosureAllowed, preClosureInterestRate, withdrawnonDate, rejectedonDate, closedonDate,
|
||||
isLockinPeriodAllowed, lockinPeriod, lockinPeriodType,depositEvery,outstandingAmount);
|
||||
isLockinPeriodAllowed, lockinPeriod, lockinPeriodType,depositEvery,outstandingAmount, interestPostEvery, interestPostFrequency);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,10 +236,10 @@ public class SavingAccountReadPlatformServiceImpl implements SavingAccountReadPl
|
||||
Integer noOfMonths = Months.monthsBetween(date, new LocalDate()).getMonths();
|
||||
Integer noOfPeriodsExistedTillDate = noOfMonths/depositEvery;
|
||||
BigDecimal totalAmountToBePaidTillDate = BigDecimal.valueOf(noOfPeriodsExistedTillDate.doubleValue()*amountPerPeriod.doubleValue());
|
||||
dueAmount = dueAmount.add(BigDecimal.valueOf(totalAmountToBePaidTillDate.doubleValue() - account.getTotalDepositAmount().doubleValue()));
|
||||
dueAmount = dueAmount.add(BigDecimal.valueOf(totalAmountToBePaidTillDate.doubleValue() - account.getOutstandingAmount().doubleValue()));
|
||||
|
||||
}
|
||||
|
||||
dueAmount = dueAmount.doubleValue() < 0 ? BigDecimal.ZERO : dueAmount;
|
||||
return dueAmount;
|
||||
}
|
||||
|
||||
@@ -243,10 +250,14 @@ public class SavingAccountReadPlatformServiceImpl implements SavingAccountReadPl
|
||||
String sql = "Select " + mapper.savingScheduleSchema() +" where ss.saving_account_id =? order by ss.installment";
|
||||
List<SavingSchedulePeriodData> periods = this.jdbcTemplate.query(sql, mapper, new Object[]{accountId});
|
||||
BigDecimal cumulativeDepositDue = BigDecimal.ZERO;
|
||||
BigDecimal cumulativeDepositPaid = BigDecimal.ZERO;
|
||||
BigDecimal cummulativeInterestAccured = BigDecimal.ZERO;
|
||||
for(SavingSchedulePeriodData data : periods){
|
||||
cumulativeDepositDue = cumulativeDepositDue.add(data.getDepositDue()).subtract(data.getDepositPaid());
|
||||
cumulativeDepositDue = cumulativeDepositDue.add(data.getDepositDue())/*.subtract(data.getDepositPaid())*/;
|
||||
cumulativeDepositPaid = cumulativeDepositPaid.add(data.getDepositPaid());
|
||||
cummulativeInterestAccured = cummulativeInterestAccured.add(data.getInterestAccured());
|
||||
}
|
||||
SavingScheduleData scheduleData = new SavingScheduleData(currency, cumulativeDepositDue, periods);
|
||||
SavingScheduleData scheduleData = new SavingScheduleData(currency, cumulativeDepositDue, cumulativeDepositPaid, cummulativeInterestAccured, periods);
|
||||
return scheduleData;
|
||||
}
|
||||
|
||||
@@ -255,7 +266,7 @@ public class SavingAccountReadPlatformServiceImpl implements SavingAccountReadPl
|
||||
public String savingScheduleSchema(){
|
||||
return "ss.id as id, ss.saving_account_id as savingAccountId, ss.duedate as dueDate, ss.installment as installment, "
|
||||
+ " ss.deposit as deposit, ss.payment_date as paymentDate, ss.deposit_paid as depositPaid, "
|
||||
+ " ss.completed_derived as completedDerived FROM m_saving_schedule ss";
|
||||
+ " ss.completed_derived as completedDerived, ss.interest_accured AS interestAccured FROM m_saving_schedule ss";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -265,8 +276,9 @@ public class SavingAccountReadPlatformServiceImpl implements SavingAccountReadPl
|
||||
Integer installment = JdbcSupport.getInteger(rs, "installment");
|
||||
BigDecimal depositDue = rs.getBigDecimal("deposit");
|
||||
BigDecimal depositPaid = rs.getBigDecimal("depositPaid");
|
||||
BigDecimal interestAccured = rs.getBigDecimal("interestAccured");
|
||||
|
||||
return new SavingSchedulePeriodData(installment, dueDate, depositDue, depositPaid);
|
||||
return new SavingSchedulePeriodData(installment, dueDate, depositDue, depositPaid, interestAccured);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -292,4 +304,30 @@ public class SavingAccountReadPlatformServiceImpl implements SavingAccountReadPl
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SavingAccountTransactionsData> retrieveSavingsAccountTransactions(Long accountId) {
|
||||
this.context.authenticatedUser();
|
||||
SavingAccountTransactionMapper savingAccountTransactionMapper = new SavingAccountTransactionMapper();
|
||||
String sql = "select "+ savingAccountTransactionMapper.schema() + " where stxn.saving_account_id = ? ";
|
||||
return jdbcTemplate.query(sql, savingAccountTransactionMapper, new Object[] {accountId});
|
||||
}
|
||||
|
||||
private static final class SavingAccountTransactionMapper implements RowMapper<SavingAccountTransactionsData> {
|
||||
|
||||
public String schema() {
|
||||
return "stxn.id as id, stxn.transaction_type_enum as type, stxn.transaction_date as transactionDate, stxn.amount as amount FROM m_saving_account_transaction stxn";
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavingAccountTransactionsData mapRow(ResultSet rs, @SuppressWarnings("unused") int rowNum) throws SQLException {
|
||||
Long id = rs.getLong("id");
|
||||
LocalDate transactionDate = JdbcSupport.getLocalDate(rs, "transactionDate");
|
||||
Integer transactionTypeValue = JdbcSupport.getInteger(rs, "type");
|
||||
EnumOptionData transactionType = DepositAccountTransactionEnumerations.depositType(transactionTypeValue);
|
||||
BigDecimal amount = rs.getBigDecimal("amount");
|
||||
return new SavingAccountTransactionsData(id, transactionDate, transactionType, amount);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+84
-11
@@ -1,6 +1,8 @@
|
||||
package org.mifosplatform.portfolio.savingsaccount.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -10,19 +12,21 @@ import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
||||
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrency;
|
||||
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.mifosplatform.organisation.monetary.domain.Money;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingScheduleData;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingSchedulePeriodData;
|
||||
import org.mifosplatform.portfolio.savingsaccount.domain.DepositScheduleDateGenerator;
|
||||
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingFrequencyType;
|
||||
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingInterestCalculationMethod;
|
||||
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProduct;
|
||||
|
||||
public class SavingScheduleGenerator {
|
||||
|
||||
private final DepositScheduleDateGenerator scheduledDateGenerator = new DefaultDepositScheduleDateGenerator();
|
||||
private final Integer monthsInYear = 12;
|
||||
|
||||
public SavingScheduleData generate(final LocalDate scheduleStartDate, final BigDecimal depositAmountPerPeriod,
|
||||
final Integer depositFrequency, final PeriodFrequencyType depositFrequencyType, final SavingProduct savingProduct,
|
||||
final Integer tenure, final ApplicationCurrency applicationCurrency) {
|
||||
final Integer depositFrequency, final SavingFrequencyType savingFrequencyType, final SavingProduct savingProduct,
|
||||
final Integer tenure, final ApplicationCurrency applicationCurrency, final BigDecimal interestRate, final SavingInterestCalculationMethod interestCalculationMethod) {
|
||||
|
||||
LocalDate startDate = scheduleStartDate;
|
||||
int periodNumber = 1;
|
||||
@@ -30,23 +34,92 @@ public class SavingScheduleGenerator {
|
||||
Integer paymentPeriods = tenure / depositFrequency;
|
||||
final Collection<SavingSchedulePeriodData> periods = new ArrayList<SavingSchedulePeriodData>();
|
||||
final List<LocalDate> scheduledDates = this.scheduledDateGenerator.generate(startDate, paymentPeriods, depositFrequency,
|
||||
depositFrequencyType);
|
||||
savingFrequencyType);
|
||||
final MonetaryCurrency currency = savingProduct.getCurrency();
|
||||
final Money depositAmount = Money.of(currency, depositAmountPerPeriod);
|
||||
Money totalDeposit = Money.zero(currency);
|
||||
|
||||
|
||||
|
||||
MathContext mc = new MathContext(8, RoundingMode.HALF_EVEN);
|
||||
BigDecimal interestRateAsFraction = interestRate.divide(BigDecimal.valueOf(100), mc);
|
||||
Integer noofTimesInterestCompoundPerYear = determineIntValue(savingFrequencyType);
|
||||
BigDecimal interestRatePerPeriod = BigDecimal.valueOf(interestRateAsFraction.doubleValue()/ noofTimesInterestCompoundPerYear.doubleValue());
|
||||
BigDecimal onePlusInterestRatePerPeriod = BigDecimal.ONE.add(interestRatePerPeriod);
|
||||
BigDecimal cummulativeDepositPaid = BigDecimal.ZERO;
|
||||
BigDecimal cummulativeInterestAccured = BigDecimal.ZERO;
|
||||
Integer tempTenure = tenure;
|
||||
|
||||
BigDecimal termAmount = BigDecimal.ZERO;
|
||||
BigDecimal totalInterest = BigDecimal.ZERO;
|
||||
BigDecimal closingBalance = BigDecimal.ZERO;
|
||||
|
||||
for (LocalDate scheduleDate : scheduledDates) {
|
||||
totalDeposit = totalDeposit.plus(depositAmount);
|
||||
SavingSchedulePeriodData installment = SavingSchedulePeriodData.addScheduleInformation(periodNumber, scheduleDate,
|
||||
depositAmount.getAmount());
|
||||
periods.add(installment);
|
||||
periodNumber++;
|
||||
|
||||
if (interestCalculationMethod.isMonthlyCollection()) {
|
||||
BigDecimal monthsExpressedInYears = BigDecimal.valueOf(tempTenure.doubleValue() / monthsInYear.doubleValue());
|
||||
BigDecimal timeforOneCalculationPeriod = BigDecimal.valueOf(noofTimesInterestCompoundPerYear * monthsExpressedInYears.doubleValue());
|
||||
BigDecimal amountPerPeriod = depositAmountPerPeriod.multiply(BigDecimal.valueOf(Math.pow(onePlusInterestRatePerPeriod.doubleValue(), timeforOneCalculationPeriod.doubleValue())));
|
||||
BigDecimal interestAccured = amountPerPeriod.subtract(depositAmountPerPeriod);
|
||||
|
||||
totalDeposit = totalDeposit.plus(depositAmount);
|
||||
cummulativeInterestAccured = cummulativeInterestAccured.add(interestAccured);
|
||||
SavingSchedulePeriodData installment = SavingSchedulePeriodData.addScheduleInformation(periodNumber, scheduleDate,
|
||||
depositAmount.getAmount(), interestAccured);
|
||||
periods.add(installment);
|
||||
periodNumber++;
|
||||
tempTenure = tempTenure - depositFrequency;
|
||||
} else if (interestCalculationMethod.isAverageBalance()){
|
||||
|
||||
BigDecimal amountPerPeriod = depositAmount.getAmount();
|
||||
Integer depositEveryOriginalValue = depositFrequency;
|
||||
BigDecimal amountPermonth = BigDecimal.valueOf(amountPerPeriod.doubleValue()/depositFrequency.doubleValue());
|
||||
|
||||
while (depositEveryOriginalValue > 0) {
|
||||
closingBalance = closingBalance.add(amountPermonth);
|
||||
termAmount = termAmount.add(closingBalance);
|
||||
depositEveryOriginalValue--;
|
||||
}
|
||||
|
||||
BigDecimal averageAmount = BigDecimal.valueOf(termAmount.doubleValue()/depositFrequency.doubleValue());
|
||||
BigDecimal interestRatePerTerm = BigDecimal.valueOf(interestRateAsFraction.doubleValue()/monthsInYear.doubleValue()*depositFrequency.doubleValue());
|
||||
BigDecimal interestAccured = averageAmount.multiply(interestRatePerTerm);
|
||||
totalInterest = totalInterest.add(interestAccured);
|
||||
depositEveryOriginalValue = depositFrequency;
|
||||
termAmount = BigDecimal.ZERO;
|
||||
|
||||
totalDeposit = totalDeposit.plus(depositAmount);
|
||||
cummulativeInterestAccured = totalInterest;
|
||||
SavingSchedulePeriodData installment = SavingSchedulePeriodData.addScheduleInformation(periodNumber, scheduleDate,
|
||||
depositAmount.getAmount(), interestAccured);
|
||||
periods.add(installment);
|
||||
periodNumber++;
|
||||
}
|
||||
}
|
||||
CurrencyData currencyData = new CurrencyData(applicationCurrency.getCode(), applicationCurrency.getName(),
|
||||
currency.getDigitsAfterDecimal(), applicationCurrency.getDisplaySymbol(), applicationCurrency.getNameCode());
|
||||
|
||||
return new SavingScheduleData(currencyData, totalDeposit.getAmount(), periods);
|
||||
return new SavingScheduleData(currencyData, totalDeposit.getAmount(),cummulativeDepositPaid, cummulativeInterestAccured, periods);
|
||||
}
|
||||
|
||||
private Integer determineIntValue(SavingFrequencyType frequencyType){
|
||||
Integer noofTimesInterestCompoundPerYear = Integer.valueOf(0);
|
||||
switch (frequencyType) {
|
||||
case MONTHLY:
|
||||
noofTimesInterestCompoundPerYear = monthsInYear;
|
||||
break;
|
||||
case QUATERLY:
|
||||
noofTimesInterestCompoundPerYear = monthsInYear / 3;
|
||||
break;
|
||||
case HALFYEARLY:
|
||||
noofTimesInterestCompoundPerYear = monthsInYear / 6;
|
||||
break;
|
||||
case YEARLY:
|
||||
noofTimesInterestCompoundPerYear = monthsInYear / 12;
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("The specified frequency not supported");
|
||||
|
||||
}
|
||||
return noofTimesInterestCompoundPerYear;
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -38,4 +38,12 @@ public enum TenureTypeEnum {
|
||||
}
|
||||
return tenureTypeEnum;
|
||||
}
|
||||
|
||||
public boolean isFixedPeriod() {
|
||||
return this.value.equals(TenureTypeEnum.FIXED_PERIOD.value);
|
||||
}
|
||||
|
||||
public boolean isPerpetual() {
|
||||
return this.value.equals(TenureTypeEnum.PERPETUAL.value);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user