Change declarations for enums and spell checks
Adding Saving account & product creation from UI Add state transitions for Saving accounts Approve saving account state patch partially done Approval of saving account Soft delete of saving account Add intereset calculation method for saving account Interest Posting functionality not completed yet Saving Interest Posting without interest calculation method
This commit is contained in:
@@ -1507,7 +1507,7 @@ CREATE TABLE `m_saving_account` (
|
||||
`lastmodified_date` datetime DEFAULT NULL,
|
||||
`lastmodifiedby_id` bigint(20) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `deposit_acc_external_id` (`external_id`),
|
||||
UNIQUE KEY `saving_acc_external_id` (`external_id`),
|
||||
KEY `FKSA0000000000001` (`client_id`),
|
||||
KEY `FKSA0000000000002` (`product_id`),
|
||||
CONSTRAINT `FKSA0000000000001` FOREIGN KEY (`client_id`) REFERENCES `m_client` (`id`),
|
||||
|
||||
@@ -1320,7 +1320,7 @@ CREATE TABLE `m_saving_account` (
|
||||
`lastmodified_date` datetime DEFAULT NULL,
|
||||
`lastmodifiedby_id` bigint(20) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `deposit_acc_external_id` (`external_id`),
|
||||
UNIQUE KEY `saving_acc_external_id` (`external_id`),
|
||||
KEY `FKSA0000000000001` (`client_id`),
|
||||
KEY `FKSA0000000000002` (`product_id`),
|
||||
CONSTRAINT `FKSA0000000000001` FOREIGN KEY (`client_id`) REFERENCES `m_client` (`id`),
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE m_saving_account
|
||||
ADD COLUMN `deposit_every` bigint(20) DEFAULT NULL AFTER `tenure_type`;
|
||||
@@ -0,0 +1,4 @@
|
||||
ALTER TABLE m_note
|
||||
ADD COLUMN `saving_account_id` bigint(20) DEFAULT NULL AFTER `deposit_account_id`,
|
||||
ADD KEY `FK_m_note_m_saving_account` (`saving_account_id`),
|
||||
ADD CONSTRAINT `FK_m_note_m_saving_account` FOREIGN KEY (`saving_account_id`) REFERENCES `m_saving_account` (`id`);
|
||||
@@ -0,0 +1,21 @@
|
||||
DROP TABLE IF EXISTS `m_saving_account_transaction`;
|
||||
CREATE TABLE `m_saving_account_transaction` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`saving_account_id` bigint(20) NOT NULL,
|
||||
`transaction_type_enum` smallint(5) NOT NULL,
|
||||
`contra_id` bigint(20) DEFAULT NULL,
|
||||
`transaction_date` date NOT NULL,
|
||||
`amount` decimal(19,6) NOT NULL,
|
||||
`createdby_id` bigint(20) DEFAULT NULL,
|
||||
`created_date` datetime DEFAULT NULL,
|
||||
`lastmodified_date` datetime DEFAULT NULL,
|
||||
`lastmodifiedby_id` bigint(20) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `FKSAT0000000001` (`saving_account_id`),
|
||||
KEY `FKSAT0000000002` (`contra_id`),
|
||||
CONSTRAINT `FKSAT0000000001` FOREIGN KEY (`saving_account_id`) REFERENCES `m_saving_account` (`id`),
|
||||
CONSTRAINT `FKSAT0000000002` FOREIGN KEY (`contra_id`) REFERENCES `m_saving_account_transaction` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
ALTER TABLE `m_saving_account`
|
||||
ADD COLUMN `outstanding_amount` decimal(19,6) NOT NULL AFTER `pre_closure_interest_rate`;
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
Alter TABLE `m_saving_account`
|
||||
add column `interest_posting_every` int(11) DEFAULT NULL AFTER `frequency`,
|
||||
add column `interest_posting_frequency` int(11) DEFAULT NULL AFTER `interest_posting_every`;
|
||||
@@ -0,0 +1,4 @@
|
||||
ALTER TABLE `m_saving_account`
|
||||
ADD COLUMN `interest_posted_amount` decimal(19,6) DEFAULT '0.000000' AFTER `outstanding_amount`,
|
||||
ADD COLUMN `last_interest_posted_date` date DEFAULT NULL AFTER `interest_posted_amount`,
|
||||
ADD COLUMN `next_interest_posting_date` date DEFAULT NULL AFTER `last_interest_posted_date`;
|
||||
+3
-2
@@ -51,10 +51,11 @@ public class GoogleGsonPortfolioApiJsonSerializerService implements PortfolioApi
|
||||
"clientId", "clientName", "productId", "productName", "productType", "currencyData", "savingsDepostiAmountPerPeriod",
|
||||
"savingsFrequencyType", "totalDepositAmount", "reccuringInterestRate", "savingInterestRate", "interestType",
|
||||
"interestCalculationMethod", "tenure", "tenureType", "projectedCommencementDate", "actualCommencementDate", "maturesOnDate",
|
||||
"projectedInterestAccuredOnMaturity", "actualInterestAccured", "projectedMaturityAmount", "actualMaturityAmount",
|
||||
"projectedInterestAccuredOnMaturity", "actualInterestAccured", "projectedMaturityAmount", "actualMaturityAmount","outstandingAmount",
|
||||
"preClosureAllowed", "preClosureInterestRate", "withdrawnonDate", "rejectedonDate", "closedonDate", "isLockinPeriodAllowed",
|
||||
"lockinPeriod", "lockinPeriodType", "productOptions", "currencyOptions", "savingsProductTypeOptions", "tenureTypeOptions",
|
||||
"savingFrequencyOptions", "savingsInterestTypeOptions", "lockinPeriodTypeOptions", "interestCalculationOptions"));
|
||||
"savingFrequencyOptions", "savingsInterestTypeOptions", "lockinPeriodTypeOptions", "interestCalculationOptions","permissions","savingScheduleDatas",
|
||||
"dueAmount", "savingScheduleData"));
|
||||
|
||||
// guarantors
|
||||
private static final Set<String> GUARANTOR_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("externalGuarantor", "existingClientId",
|
||||
|
||||
+12
@@ -3,7 +3,11 @@ package org.mifosplatform.infrastructure.core.api;
|
||||
import org.mifosplatform.portfolio.client.data.ClientData;
|
||||
import org.mifosplatform.portfolio.group.command.GroupCommand;
|
||||
import org.mifosplatform.portfolio.loanaccount.gaurantor.command.GuarantorCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountApprovalCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountDepositCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountWithdrawalCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingStateTransitionsCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccountproduct.command.SavingProductCommand;
|
||||
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositAccountCommand;
|
||||
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositAccountWithdrawInterestCommand;
|
||||
@@ -35,4 +39,12 @@ public interface PortfolioApiDataConversionService {
|
||||
SavingAccountCommand convertJsonToSavingAccountCommand(Long resourceIdentifier, String json);
|
||||
|
||||
GuarantorCommand convertJsonToGuarantorCommand(Long resourceIdentifier, Long loanId, String json);
|
||||
|
||||
SavingStateTransitionsCommand convertJsonToSavingStateTransitionCommand(Long accountId, String json);
|
||||
|
||||
SavingAccountApprovalCommand convertJsonToSavingApprovalCommand(Long accountId, String json);
|
||||
|
||||
SavingAccountDepositCommand convertJsonToSavingAccountDepositCommand(Long accountId, String json);
|
||||
|
||||
SavingAccountWithdrawalCommand convertJsonToSavingAccountWithdrawalCommand(Long accountId, String jsonRequestBody);
|
||||
}
|
||||
+102
-6
@@ -26,7 +26,11 @@ import org.mifosplatform.portfolio.client.data.ClientData;
|
||||
import org.mifosplatform.portfolio.client.serialization.ClientCommandFromApiJsonDeserializer;
|
||||
import org.mifosplatform.portfolio.group.command.GroupCommand;
|
||||
import org.mifosplatform.portfolio.loanaccount.gaurantor.command.GuarantorCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountApprovalCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountDepositCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountWithdrawalCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingStateTransitionsCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccountproduct.command.SavingProductCommand;
|
||||
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositAccountCommand;
|
||||
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositAccountWithdrawInterestCommand;
|
||||
@@ -813,8 +817,8 @@ 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", "frequency", "interestType", "interestCalculationMethod", "minimumBalanceForWithdrawal",
|
||||
"isPartialDepositAllowed", "payEvery"));
|
||||
"savingProductType", "tenureType", "depositfrequency", "interestType", "interestCalculationMethod", "minimumBalanceForWithdrawal",
|
||||
"isPartialDepositAllowed", "depositEvery","interestPostEvery","interestPostFrequency"));
|
||||
checkForUnsupportedParameters(requestMap, supportedParams);
|
||||
Set<String> modifiedParameters = new HashSet<String>();
|
||||
|
||||
@@ -835,17 +839,20 @@ public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataCo
|
||||
LocalDate commencementDate = extractLocalDateParameter("commencementDate", requestMap, modifiedParameters);
|
||||
Integer savingProductType = extractIntegerParameter("savingProductType", requestMap, modifiedParameters);
|
||||
Integer tenureType = extractIntegerParameter("tenureType", requestMap, modifiedParameters);
|
||||
Integer frequency = extractIntegerParameter("frequency", requestMap, modifiedParameters);
|
||||
Integer depositfrequency = extractIntegerParameter("depositfrequency", requestMap, modifiedParameters);
|
||||
Integer interestType = extractIntegerParameter("interestType", requestMap, modifiedParameters);
|
||||
Integer interestCalculationMethod = extractIntegerParameter("interestCalculationMethod", requestMap, modifiedParameters);
|
||||
BigDecimal minimumBalanceForWithdrawal = extractBigDecimalParameter("minimumBalanceForWithdrawal", requestMap, modifiedParameters);
|
||||
boolean isPartialDepositAllowed = extractBooleanParameter("isPartialDepositAllowed", requestMap, modifiedParameters);
|
||||
Integer payEvery = extractIntegerParameter("payEvery", requestMap, modifiedParameters);
|
||||
Integer depositEvery = extractIntegerParameter("depositEvery", requestMap, modifiedParameters);
|
||||
|
||||
Integer interestPostEvery = extractIntegerParameter("interestPostEvery", requestMap, modifiedParameters);
|
||||
Integer interestPostFrequency = extractIntegerParameter("interestPostFrequency", requestMap, modifiedParameters);
|
||||
|
||||
return new SavingAccountCommand(modifiedParameters, resourceIdentifier, clientId, productId, externalId, currencyCode,
|
||||
digitsAfterDecimalValue, savingsDepositAmount, recurringInterestRate, savingInterestRate, tenure, commencementDate,
|
||||
savingProductType, tenureType, frequency, interestType, minimumBalanceForWithdrawal, interestCalculationMethod,
|
||||
isLockinPeriodAllowed, isPartialDepositAllowed, lockinPeriod, lockinPeriodType, payEvery);
|
||||
savingProductType, tenureType, depositfrequency, interestType, minimumBalanceForWithdrawal, interestCalculationMethod,
|
||||
isLockinPeriodAllowed, isPartialDepositAllowed, lockinPeriod, lockinPeriodType, depositEvery, interestPostEvery, interestPostFrequency);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -889,4 +896,93 @@ public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataCo
|
||||
command.setLocale(locale);
|
||||
return command;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavingStateTransitionsCommand convertJsonToSavingStateTransitionCommand( Long accountId, String json) {
|
||||
|
||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||
|
||||
Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
Map<String, Object> requestMap = gsonConverter.fromJson(json, typeOfMap);
|
||||
|
||||
Set<String> supportedParams = new HashSet<String>(Arrays.asList("eventDate", "locale", "dateFormat", "note"));
|
||||
|
||||
checkForUnsupportedParameters(requestMap, supportedParams);
|
||||
|
||||
Set<String> modifiedParameters = new HashSet<String>();
|
||||
|
||||
LocalDate eventDate = extractLocalDateParameter("eventDate", requestMap, modifiedParameters);
|
||||
String note = extractStringParameter("note", requestMap, modifiedParameters);
|
||||
|
||||
return new SavingStateTransitionsCommand(accountId, eventDate, note);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavingAccountApprovalCommand convertJsonToSavingApprovalCommand( Long accountId, String json) {
|
||||
|
||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||
|
||||
Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
Map<String, Object> requestMap = gsonConverter.fromJson(json, typeOfMap);
|
||||
|
||||
Set<String> supportedParams = new HashSet<String>(Arrays.asList("locale", "dateFormat", "commencementDate", "savingsDepositAmountPerPeriod",
|
||||
"minimumBalanceForWithdrawal", "recurringInterestRate", "savingInterestRate", "interestType", "tenure", "tenureType", "frequency", "payEvery", "note",
|
||||
"interestPostEvery", "interestPostFrequency"));
|
||||
|
||||
checkForUnsupportedParameters(requestMap, supportedParams);
|
||||
Set<String> modifiedParameters = new HashSet<String>();
|
||||
|
||||
LocalDate commencementDate = extractLocalDateParameter("commencementDate", requestMap, modifiedParameters);
|
||||
BigDecimal savingsDepositAmountPerPeriod = extractBigDecimalParameter("savingsDepositAmountPerPeriod", requestMap, modifiedParameters);
|
||||
BigDecimal minimumBalanceForWithdrawal = extractBigDecimalParameter("minimumBalanceForWithdrawal", requestMap, modifiedParameters);
|
||||
BigDecimal recurringInterestRate = extractBigDecimalParameter("recurringInterestRate", requestMap, modifiedParameters);
|
||||
BigDecimal savingInterestRate = extractBigDecimalParameter("savingInterestRate", requestMap, modifiedParameters);
|
||||
Integer interestType = extractIntegerParameter("interestType", requestMap, modifiedParameters);
|
||||
Integer tenure = extractIntegerParameter("tenure", requestMap, modifiedParameters);
|
||||
Integer tenureType = extractIntegerParameter("tenureType", requestMap, modifiedParameters);
|
||||
Integer frequency = extractIntegerParameter("frequency", requestMap, modifiedParameters);
|
||||
Integer payEvery = extractIntegerParameter("payEvery", requestMap, modifiedParameters);
|
||||
String note = extractStringParameter("note", requestMap, modifiedParameters);
|
||||
Integer interestPostEvery = extractIntegerParameter("interestPostEvery", requestMap, modifiedParameters);
|
||||
Integer interestPostFrequency = extractIntegerParameter("interestPostFrequency", requestMap, modifiedParameters);
|
||||
return new SavingAccountApprovalCommand(accountId, commencementDate, savingsDepositAmountPerPeriod, minimumBalanceForWithdrawal, recurringInterestRate,
|
||||
savingInterestRate, interestType, tenure, tenureType, frequency, payEvery, note, interestPostEvery, interestPostFrequency);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavingAccountDepositCommand convertJsonToSavingAccountDepositCommand(Long accountId, String json) {
|
||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||
|
||||
Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
Map<String, Object> requestMap = gsonConverter.fromJson(json, typeOfMap);
|
||||
|
||||
Set<String> supportedParams = new HashSet<String>(Arrays.asList("locale", "dateFormat", "depositDate", "savingsDepositAmountPerPeriod", "note"));
|
||||
|
||||
checkForUnsupportedParameters(requestMap, supportedParams);
|
||||
Set<String> modifiedParameters = new HashSet<String>();
|
||||
|
||||
LocalDate depositDate = extractLocalDateParameter("depositDate", requestMap, modifiedParameters);
|
||||
BigDecimal savingsDepositAmountPerPeriod = extractBigDecimalParameter("savingsDepositAmountPerPeriod", requestMap, modifiedParameters);
|
||||
String note = extractStringParameter("note", requestMap, modifiedParameters);
|
||||
return new SavingAccountDepositCommand(accountId, savingsDepositAmountPerPeriod, depositDate, note);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavingAccountWithdrawalCommand convertJsonToSavingAccountWithdrawalCommand(Long accountId, String json) {
|
||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||
|
||||
Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
Map<String, Object> requestMap = gsonConverter.fromJson(json, typeOfMap);
|
||||
|
||||
Set<String> supportedParams = new HashSet<String>(Arrays.asList("locale", "dateFormat", "transactionDate", "amount", "note"));
|
||||
|
||||
checkForUnsupportedParameters(requestMap, supportedParams);
|
||||
Set<String> modifiedParameters = new HashSet<String>();
|
||||
|
||||
LocalDate transactionDate = extractLocalDateParameter("transactionDate", requestMap, modifiedParameters);
|
||||
BigDecimal amount = extractBigDecimalParameter("amount", requestMap, modifiedParameters);
|
||||
String note = extractStringParameter("note", requestMap, modifiedParameters);
|
||||
return new SavingAccountWithdrawalCommand(accountId, transactionDate, amount, note);
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
|
||||
import org.mifosplatform.portfolio.savingsaccount.domain.SavingAccount;
|
||||
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositAccount;
|
||||
import org.mifosplatform.useradministration.domain.AppUser;
|
||||
|
||||
@@ -46,10 +47,15 @@ public class Note extends AbstractAuditableCustom<AppUser, Long> {
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "deposit_account_id", nullable = true)
|
||||
private DepositAccount depositAccount;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "saving_account_id", nullable = true)
|
||||
private SavingAccount savingAccount;
|
||||
|
||||
public enum NoteType {
|
||||
CLIENT(100, "noteType.client"), LOAN(200, "noteType.loan"), LOAN_TRANSACTION(300, "noteType.loan.transaction"), DEPOSIT(400,
|
||||
"noteType.deposit");
|
||||
"noteType.deposit"), SAVING(500,"noteType.saving");
|
||||
|
||||
private Integer value;
|
||||
private String code;
|
||||
@@ -132,7 +138,14 @@ public class Note extends AbstractAuditableCustom<AppUser, Long> {
|
||||
this.noteTypeId = NoteType.DEPOSIT.getValue();
|
||||
}
|
||||
|
||||
public Map<String, Object> update(final JsonCommand command) {
|
||||
public Note(SavingAccount account, String note) {
|
||||
this.savingAccount = account;
|
||||
this.client = account.getClient();
|
||||
this.note = note;
|
||||
this.noteTypeId = NoteType.SAVING.getValue();
|
||||
}
|
||||
|
||||
public Map<String, Object> update(final JsonCommand command) {
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(7);
|
||||
|
||||
final String noteParamName = "note";
|
||||
@@ -147,4 +160,8 @@ public class Note extends AbstractAuditableCustom<AppUser, Long> {
|
||||
public boolean isNotAgainstClientWithIdOf(Long clientId) {
|
||||
return !this.client.identifiedBy(clientId);
|
||||
}
|
||||
|
||||
public static Note savingNote(final SavingAccount account, final String noteText) {
|
||||
return new Note(account, noteText);
|
||||
}
|
||||
}
|
||||
+4
@@ -24,8 +24,12 @@ public class NoteEnumerations {
|
||||
case DEPOSIT:
|
||||
optionData = new EnumOptionData(type.getValue().longValue(), type.getCode(), "Deposit transaction note");
|
||||
break;
|
||||
case SAVING:
|
||||
optionData = new EnumOptionData(type.getValue().longValue(), type.getCode(), "Saving transaction note");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
+106
-7
@@ -1,5 +1,6 @@
|
||||
package org.mifosplatform.portfolio.savingsaccount.api;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
@@ -7,6 +8,7 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
@@ -25,13 +27,22 @@ import org.mifosplatform.infrastructure.core.api.PortfolioApiDataConversionServi
|
||||
import org.mifosplatform.infrastructure.core.api.PortfolioApiJsonSerializerService;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.infrastructure.core.exception.UnrecognizedQueryParamException;
|
||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.mifosplatform.infrastructure.core.serialization.ToApiJsonSerializer;
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
||||
import org.mifosplatform.organisation.monetary.service.CurrencyReadPlatformService;
|
||||
import org.mifosplatform.portfolio.loanaccount.command.UndoStateTransitionCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.CalculateSavingScheduleCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountApprovalCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountDepositCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountWithdrawalCommand;
|
||||
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.SavingPermissionData;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingScheduleData;
|
||||
import org.mifosplatform.portfolio.savingsaccount.service.CalculateSavingSchedule;
|
||||
import org.mifosplatform.portfolio.savingsaccount.service.SavingAccountReadPlatformService;
|
||||
@@ -82,6 +93,9 @@ public class SavingsAccountApiResource {
|
||||
|
||||
@Autowired
|
||||
private ToApiJsonSerializer<SavingAccountData> toApiJsonSerializer;
|
||||
|
||||
@Autowired
|
||||
private FromJsonHelper fromJsonHelper;
|
||||
|
||||
private static final Set<String> typicalResponseParameters = new HashSet<String>(Arrays.asList("id", "status", "externalId",
|
||||
"clientId", "clientName", "productId", "productName", "productType", "currencyData", "savingsDepostiAmountPerPeriod",
|
||||
@@ -89,7 +103,7 @@ public class SavingsAccountApiResource {
|
||||
"interestCalculationMethod", "tenure", "tenureType", "projectedCommencementDate", "actualCommencementDate", "maturesOnDate",
|
||||
"projectedInterestAccuredOnMaturity", "actualInterestAccured", "projectedMaturityAmount", "actualMaturityAmount",
|
||||
"preClosureAllowed", "preClosureInterestRate", "withdrawnonDate", "rejectedonDate", "closedonDate", "isLockinPeriodAllowed",
|
||||
"lockinPeriod", "lockinPeriodType"));
|
||||
"lockinPeriod", "lockinPeriodType","outstandingAmount","savingScheduleData"));
|
||||
|
||||
@POST
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@@ -156,18 +170,42 @@ public class SavingsAccountApiResource {
|
||||
public String retrieveDepositAccount(@PathParam("accountId") final Long accountId, @Context final UriInfo uriInfo) {
|
||||
|
||||
context.authenticatedUser().validateHasReadPermission(entityType);
|
||||
|
||||
SavingPermissionData permissions = null;
|
||||
SavingScheduleData savingScheduleData = null;
|
||||
|
||||
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
|
||||
|
||||
if (responseParameters.isEmpty()) {
|
||||
responseParameters.addAll(typicalResponseParameters);
|
||||
}
|
||||
|
||||
|
||||
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
|
||||
|
||||
SavingAccountData account = this.savingAccountReadPlatformService.retrieveSavingsAccount(accountId);
|
||||
|
||||
boolean template = ApiParameterHelper.template(uriInfo.getQueryParameters());
|
||||
if (template) {
|
||||
account = handleTemplateRelatedData(responseParameters, account);
|
||||
}
|
||||
|
||||
Set<String> associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters());
|
||||
if (!associationParameters.isEmpty()) {
|
||||
if (associationParameters.contains("all")) {
|
||||
associationParameters.add("savingScheduleData");
|
||||
responseParameters.addAll(Arrays.asList("permissions","savingScheduleData"));
|
||||
} else {
|
||||
responseParameters.addAll(associationParameters);
|
||||
}
|
||||
|
||||
if (associationParameters.contains("savingScheduleData")) {
|
||||
CurrencyData currencyData = account.getCurrencyData();
|
||||
savingScheduleData = this.savingAccountReadPlatformService.retrieveSavingsAccountSchedule(accountId,currencyData);
|
||||
account = new SavingAccountData(account,savingScheduleData);
|
||||
}
|
||||
permissions = this.savingAccountReadPlatformService.retrieveSavingAccountPermissions(account);
|
||||
account = new SavingAccountData(account, permissions);
|
||||
}
|
||||
|
||||
return this.apiJsonSerializerService.serializeSavingAccountsDataToJson(prettyPrint, responseParameters, account);
|
||||
}
|
||||
|
||||
@@ -196,14 +234,14 @@ public class SavingsAccountApiResource {
|
||||
|
||||
private SavingAccountData handleTemplateRelatedData(Set<String> responseParameters, SavingAccountData account) {
|
||||
responseParameters.addAll(Arrays.asList("productOptions", "currencyOptions", "savingsProductTypeOptions", "tenureTypeOptions",
|
||||
"savingFrequencyOptions", "savingsInterestTypeOptions", "lockinPeriodTypeOptions", "interestCalculationOptions"));
|
||||
"savingFrequencyOptions", "savingsInterestTypeOptions", "lockinPeriodTypeOptions", "interestCalculationOptions", "dueAmount"));
|
||||
|
||||
Collection<SavingProductLookup> productOptions = savingProductReadPlatformService.retrieveAllSavingProductsForLookup();
|
||||
List<CurrencyData> currencyOptions = this.currencyReadPlatformService.retrieveAllowedCurrencies();
|
||||
|
||||
EnumOptionData reccuring = SavingProductEnumerations.savingProductType(SavingProductType.RECCURING);
|
||||
EnumOptionData recurring = SavingProductEnumerations.savingProductType(SavingProductType.RECURRING);
|
||||
EnumOptionData regular = SavingProductEnumerations.savingProductType(SavingProductType.REGULAR);
|
||||
List<EnumOptionData> savingsProductTypeOptions = Arrays.asList(reccuring, regular);
|
||||
List<EnumOptionData> savingsProductTypeOptions = Arrays.asList(recurring, regular);
|
||||
|
||||
EnumOptionData fixed = SavingProductEnumerations.tenureTypeEnum(TenureTypeEnum.FIXED_PERIOD);
|
||||
EnumOptionData perpetual = SavingProductEnumerations.tenureTypeEnum(TenureTypeEnum.PERPETUAL);
|
||||
@@ -224,12 +262,73 @@ public class SavingsAccountApiResource {
|
||||
EnumOptionData monthlyCollection = SavingProductEnumerations
|
||||
.savingInterestCalculationMethod(SavingInterestCalculationMethod.MONTHLYCOLLECTION);
|
||||
List<EnumOptionData> interestCalculationOptions = Arrays.asList(averagebal, minbal, monthlyCollection);
|
||||
BigDecimal dueAmount = this.savingAccountReadPlatformService.deriveSavingDueAmount(account);
|
||||
return new SavingAccountData(account, productOptions, currencyOptions, savingsProductTypeOptions,tenureTypeOptions,savingFrequencyOptions,
|
||||
savingsInterestTypeOptions,lockinPeriodTypeOptions,interestCalculationOptions);
|
||||
savingsInterestTypeOptions,lockinPeriodTypeOptions,interestCalculationOptions, dueAmount);
|
||||
}
|
||||
|
||||
private boolean is(final String commandParam, final String commandValue) {
|
||||
return StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase(commandValue);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("{accountId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public Response savingStateTransitions(@PathParam("accountId") final Long accountId, @QueryParam("command") final String commandParam, final String jsonRequestBody) {
|
||||
Response response = null;
|
||||
if (is(commandParam, "approve")) {
|
||||
SavingAccountApprovalCommand command = this.apiDataConversionService.convertJsonToSavingApprovalCommand(accountId, jsonRequestBody);
|
||||
CommandProcessingResult identifier = this.savingAccountWritePlatformService.approveSavingAccount(command);
|
||||
response = Response.ok().entity(identifier).build();
|
||||
} else if (is(commandParam, "depositmoney")) {
|
||||
SavingAccountDepositCommand command = this.apiDataConversionService.convertJsonToSavingAccountDepositCommand(accountId, jsonRequestBody);
|
||||
CommandProcessingResult identifier = this.savingAccountWritePlatformService.depositMoney(command);
|
||||
response = Response.ok().entity(identifier).build();
|
||||
} else if (is(commandParam, "withdraw")) {
|
||||
SavingAccountWithdrawalCommand command = this.apiDataConversionService.convertJsonToSavingAccountWithdrawalCommand(accountId, jsonRequestBody);
|
||||
CommandProcessingResult identifier = this.savingAccountWritePlatformService.withdrawSavingAmount(command);
|
||||
response = Response.ok().entity(identifier).build();
|
||||
} else {
|
||||
SavingStateTransitionsCommand command = this.apiDataConversionService.convertJsonToSavingStateTransitionCommand(accountId, jsonRequestBody);
|
||||
if (is(commandParam, "reject")) {
|
||||
CommandProcessingResult identifier = this.savingAccountWritePlatformService.rejectSavingApplication(command);
|
||||
response = Response.ok().entity(identifier).build();
|
||||
} else if (is(commandParam, "withdrewbyclient")) {
|
||||
CommandProcessingResult identifier = this.savingAccountWritePlatformService.withdrawSavingApplication(command);
|
||||
response = Response.ok().entity(identifier).build();
|
||||
}
|
||||
UndoStateTransitionCommand undoCommand = new UndoStateTransitionCommand(accountId, command.getNote());
|
||||
if (is(commandParam, "undoapproval")) {
|
||||
CommandProcessingResult identifier = this.savingAccountWritePlatformService.undoSavingAccountApproval(undoCommand);
|
||||
response = Response.ok().entity(identifier).build();
|
||||
}
|
||||
}
|
||||
if (response == null) { throw new UnrecognizedQueryParamException("command", commandParam); }
|
||||
return response;
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("{accountId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public Response deleteSavingAccount(@PathParam("accountId") final Long accountId) {
|
||||
|
||||
this.savingAccountWritePlatformService.deleteSavingAccount(accountId);
|
||||
|
||||
return Response.ok(new CommandProcessingResult(accountId)).build();
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("postinterest")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public Response postInterest() {
|
||||
|
||||
Collection<SavingAccountForLookup> savingAccounts = this.savingAccountReadPlatformService.retrieveSavingAccountsForLookUp();
|
||||
CommandProcessingResult entityIdentifier = this.savingAccountWritePlatformService.postInterest(savingAccounts);
|
||||
return Response.ok().entity(entityIdentifier).build();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+17
-6
@@ -8,23 +8,27 @@ public class CalculateSavingScheduleCommand {
|
||||
|
||||
private final Long productId;
|
||||
private final BigDecimal deposit;
|
||||
private final Integer payEvery;
|
||||
private final Integer depositEvery;
|
||||
private final Integer paymentFrequencyType;
|
||||
private final BigDecimal interestRate;
|
||||
private final LocalDate paymentsStartingFromDate;
|
||||
private final Integer tenure;
|
||||
private final Integer interestPostEvery;
|
||||
private final Integer interestPostFrequency;
|
||||
|
||||
public CalculateSavingScheduleCommand(final Long productId, final BigDecimal deposit, final Integer payEvery,
|
||||
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 tenure,final Integer interestPostEvery, final Integer interestPostFrequency) {
|
||||
|
||||
this.productId = productId;
|
||||
this.deposit = deposit;
|
||||
this.payEvery = payEvery;
|
||||
this.depositEvery = depositEvery;
|
||||
this.paymentFrequencyType = paymentFrequencyType;
|
||||
this.interestRate = interestRate;
|
||||
this.paymentsStartingFromDate = paymentsStartingFromDate;
|
||||
this.tenure = tenure;
|
||||
this.interestPostEvery = interestPostEvery;
|
||||
this.interestPostFrequency = interestPostFrequency;
|
||||
|
||||
}
|
||||
|
||||
@@ -36,8 +40,8 @@ public class CalculateSavingScheduleCommand {
|
||||
return this.deposit;
|
||||
}
|
||||
|
||||
public Integer getPayEvery() {
|
||||
return this.payEvery;
|
||||
public Integer getDepositEvery() {
|
||||
return this.depositEvery;
|
||||
}
|
||||
|
||||
public Integer getPaymentFrequencyType() {
|
||||
@@ -56,5 +60,12 @@ public class CalculateSavingScheduleCommand {
|
||||
return this.tenure;
|
||||
}
|
||||
|
||||
public Integer getInterestPostEvery() {
|
||||
return this.interestPostEvery;
|
||||
}
|
||||
|
||||
public Integer getInterestPostFrequency() {
|
||||
return this.interestPostFrequency;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
package org.mifosplatform.portfolio.savingsaccount.command;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
|
||||
public class SavingAccountApprovalCommand {
|
||||
|
||||
private final Long accountId;
|
||||
private final LocalDate approvalDate;
|
||||
private final BigDecimal depositAmountPerPeriod;
|
||||
private final BigDecimal minimumBalanceForWithdrawal;
|
||||
private final BigDecimal recurringInterestRate;
|
||||
private final BigDecimal savingInterestRate;
|
||||
private final Integer interestType;
|
||||
private final Integer tenure;
|
||||
private final Integer tenureType;
|
||||
private final Integer depositFrequencyType;
|
||||
private final Integer depositEvery;
|
||||
|
||||
private final Integer interestPostEvery;
|
||||
private final Integer interestPostFrequency;
|
||||
|
||||
private final String note;
|
||||
|
||||
public SavingAccountApprovalCommand(final Long accountId, final LocalDate approvalDate,
|
||||
final BigDecimal depositAmountPerPeriod, final BigDecimal minimumBalanceForWithdrawal, final BigDecimal recurringInterestRate,
|
||||
final BigDecimal savingInterestRate, final Integer interestType, final Integer tenure, final Integer tenureType,
|
||||
final Integer depositFrequencyType, final Integer depositEvery, final String note,
|
||||
final Integer interestPostEvery, final Integer interestPostFrequency) {
|
||||
this.accountId = accountId;
|
||||
this.approvalDate = approvalDate;
|
||||
this.depositAmountPerPeriod = depositAmountPerPeriod;
|
||||
this.minimumBalanceForWithdrawal = minimumBalanceForWithdrawal;
|
||||
this.recurringInterestRate = recurringInterestRate;
|
||||
this.savingInterestRate = savingInterestRate;
|
||||
this.interestType = interestType;
|
||||
this.tenure = tenure;
|
||||
this.tenureType = tenureType;
|
||||
this.depositFrequencyType = depositFrequencyType;
|
||||
this.depositEvery = depositEvery;
|
||||
this.note = note;
|
||||
|
||||
this.interestPostEvery = interestPostEvery;
|
||||
this.interestPostFrequency = interestPostFrequency;
|
||||
}
|
||||
|
||||
public Long getAccountId() {
|
||||
return this.accountId;
|
||||
}
|
||||
|
||||
public LocalDate getApprovalDate() {
|
||||
return this.approvalDate;
|
||||
}
|
||||
|
||||
public BigDecimal getDepositAmountPerPeriod() {
|
||||
return this.depositAmountPerPeriod;
|
||||
}
|
||||
|
||||
public BigDecimal getMinimumBalanceForWithdrawal() {
|
||||
return this.minimumBalanceForWithdrawal;
|
||||
}
|
||||
|
||||
public BigDecimal getRecurringInterestRate() {
|
||||
return this.recurringInterestRate;
|
||||
}
|
||||
|
||||
public BigDecimal getSavingInterestRate() {
|
||||
return this.savingInterestRate;
|
||||
}
|
||||
|
||||
public Integer getInterestType() {
|
||||
return this.interestType;
|
||||
}
|
||||
|
||||
public Integer getTenure() {
|
||||
return this.tenure;
|
||||
}
|
||||
|
||||
public Integer getTenureType() {
|
||||
return this.tenureType;
|
||||
}
|
||||
|
||||
public Integer getDepositFrequencyType() {
|
||||
return this.depositFrequencyType;
|
||||
}
|
||||
|
||||
public Integer getDepositEvery() {
|
||||
return this.depositEvery;
|
||||
}
|
||||
|
||||
public String getNote() {
|
||||
return this.note;
|
||||
}
|
||||
|
||||
public Integer getInterestPostEvery() {
|
||||
return this.interestPostEvery;
|
||||
}
|
||||
|
||||
public Integer getInterestPostFrequency() {
|
||||
return this.interestPostFrequency;
|
||||
}
|
||||
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package org.mifosplatform.portfolio.savingsaccount.command;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
|
||||
public class SavingAccountApprovalCommandValidator {
|
||||
|
||||
private final SavingAccountApprovalCommand command;
|
||||
|
||||
public SavingAccountApprovalCommandValidator(final SavingAccountApprovalCommand command) {
|
||||
this.command = command ;
|
||||
}
|
||||
|
||||
public void validate() {
|
||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("saving.account.transition.approve");
|
||||
baseDataValidator.reset().parameter("accountId").value(command.getAccountId()).notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter("commencementDate").value(command.getApprovalDate()).notNull();
|
||||
baseDataValidator.reset().parameter("savingsDepositAmountPerPeriod").value(command.getDepositAmountPerPeriod()).notNull().zeroOrPositiveAmount();
|
||||
baseDataValidator.reset().parameter("minimumBalanceForWithdrawal").value(command.getMinimumBalanceForWithdrawal()).notNull().zeroOrPositiveAmount();
|
||||
baseDataValidator.reset().parameter("recurringInterestRate").value(command.getRecurringInterestRate()).notNull().zeroOrPositiveAmount();
|
||||
baseDataValidator.reset().parameter("savingInterestRate").value(command.getSavingInterestRate()).notNull().zeroOrPositiveAmount();
|
||||
baseDataValidator.reset().parameter("interestType").value(command.getInterestType()).notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter("tenure").value(command.getTenure()).notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter("tenureType").value(command.getTenureType()).notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter("frequency").value(command.getDepositFrequencyType()).notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter("payEvery").value(command.getDepositEvery()).notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter("note").value(command.getNote()).notNull();
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
|
||||
"Validation errors exist.", dataValidationErrors); }
|
||||
}
|
||||
|
||||
}
|
||||
+34
-10
@@ -32,7 +32,10 @@ public class SavingAccountCommand {
|
||||
private final Integer interestCalculationMethod;
|
||||
private final BigDecimal minimumBalanceForWithdrawal;
|
||||
private final boolean isPartialDepositAllowed;
|
||||
private final Integer payEvery;
|
||||
private final Integer depositEvery;
|
||||
|
||||
private final Integer interestPostEvery;
|
||||
private final Integer interestPostFrequency;
|
||||
|
||||
private final Set<String> modifiedParameters;
|
||||
|
||||
@@ -42,7 +45,7 @@ public class SavingAccountCommand {
|
||||
final LocalDate commencementDate, final Integer savingProductType, 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 payEvery) {
|
||||
final Integer lockinPeriodType, final Integer depositEvery,final Integer interestPostEvery,final Integer interestPostFrequency) {
|
||||
this.id = id;
|
||||
this.clientId = clientId;
|
||||
this.productId = productId;
|
||||
@@ -69,7 +72,10 @@ public class SavingAccountCommand {
|
||||
this.lockinPeriodType = lockinPeriodType;
|
||||
this.minimumBalanceForWithdrawal = minimumBalanceForWithdrawal;
|
||||
this.interestCalculationMethod = interestCalculationMethod;
|
||||
this.payEvery = payEvery;
|
||||
this.depositEvery = depositEvery;
|
||||
|
||||
this.interestPostEvery = interestPostEvery;
|
||||
this.interestPostFrequency = interestPostFrequency;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
@@ -156,11 +162,19 @@ public class SavingAccountCommand {
|
||||
return isPartialDepositAllowed;
|
||||
}
|
||||
|
||||
public Integer getPayEvery() {
|
||||
return this.payEvery;
|
||||
public Integer getDepositEvery() {
|
||||
return this.depositEvery;
|
||||
}
|
||||
|
||||
public boolean isNoFieldChanged() {
|
||||
public Integer getInterestPostEvery() {
|
||||
return this.interestPostEvery;
|
||||
}
|
||||
|
||||
public Integer getInterestPostFrequency() {
|
||||
return this.interestPostFrequency;
|
||||
}
|
||||
|
||||
public boolean isNoFieldChanged() {
|
||||
return this.modifiedParameters.isEmpty();
|
||||
}
|
||||
|
||||
@@ -231,13 +245,23 @@ public class SavingAccountCommand {
|
||||
public boolean isPartialDepositAllowedChanged() {
|
||||
return this.modifiedParameters.contains("isPartialDepositAllowed");
|
||||
}
|
||||
public boolean isPayEveryChanged() {
|
||||
return this.modifiedParameters.contains("payEvery");
|
||||
|
||||
public boolean isDepositEveryChanged() {
|
||||
return this.modifiedParameters.contains("depositEvery");
|
||||
}
|
||||
|
||||
public boolean isInterestPostedEveryChanged(){
|
||||
return this.modifiedParameters.contains(interestPostEvery);
|
||||
}
|
||||
|
||||
public boolean isInterestPostingChanged(){
|
||||
return this.modifiedParameters.contains(interestPostFrequency);
|
||||
}
|
||||
|
||||
|
||||
public CalculateSavingScheduleCommand toCalculateSavingScheduleCommand() {
|
||||
return new CalculateSavingScheduleCommand(productId, savingsDepositAmount, payEvery, frequency, recurringInterestRate,
|
||||
commencementDate, tenure);
|
||||
return new CalculateSavingScheduleCommand(productId, savingsDepositAmount, depositEvery, frequency, recurringInterestRate,
|
||||
commencementDate, tenure, interestPostEvery, interestPostFrequency);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ public class SavingAccountCommandValidator {
|
||||
|
||||
baseDataValidator.reset().parameter("clientId").value(command.getClientId()).notNull();
|
||||
baseDataValidator.reset().parameter("productId").value(command.getProductId()).notNull();
|
||||
baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).ignoreIfNull().notExceedingLengthOf(100);
|
||||
baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).notNull().notExceedingLengthOf(100);
|
||||
baseDataValidator.reset().parameter("currencyCode").value(command.getCurrencyCode()).notBlank();
|
||||
baseDataValidator.reset().parameter("digitsAfterDecimal").value(command.getDigitsAfterDecimal()).notNull().inMinMaxRange(0, 6);
|
||||
baseDataValidator.reset().parameter("savingsDepositAmountPerPeriod").value(command.getSavingsDepositAmount()).notNull()
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package org.mifosplatform.portfolio.savingsaccount.command;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
|
||||
public class SavingAccountDepositCommand {
|
||||
|
||||
private final Long accountId;
|
||||
private final BigDecimal savingsDepostiAmountPerPeriod;
|
||||
private final LocalDate depositDate;
|
||||
private final String note;
|
||||
|
||||
public SavingAccountDepositCommand(final Long accountId, final BigDecimal savingsDepostiAmountPerPeriod, final LocalDate depositDate, final String note) {
|
||||
this.accountId = accountId;
|
||||
this.savingsDepostiAmountPerPeriod = savingsDepostiAmountPerPeriod;
|
||||
this.depositDate = depositDate;
|
||||
this.note = note;
|
||||
}
|
||||
|
||||
public Long getAccountId() {
|
||||
return this.accountId;
|
||||
}
|
||||
|
||||
public BigDecimal getSavingsDepostiAmountPerPeriod() {
|
||||
return this.savingsDepostiAmountPerPeriod;
|
||||
}
|
||||
|
||||
public LocalDate getDepositDate() {
|
||||
return this.depositDate;
|
||||
}
|
||||
|
||||
public String getNote() {
|
||||
return this.note;
|
||||
}
|
||||
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package org.mifosplatform.portfolio.savingsaccount.command;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
|
||||
public class SavingAccountDepositCommandValidator {
|
||||
|
||||
private final SavingAccountDepositCommand command;
|
||||
|
||||
public SavingAccountDepositCommandValidator(final SavingAccountDepositCommand command) {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public void validate(){
|
||||
|
||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("saving.account.transaction.deposit");
|
||||
baseDataValidator.reset().parameter("accountId").value(command.getAccountId()).notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter("depositDate").value(command.getDepositDate()).notNull();
|
||||
baseDataValidator.reset().parameter("savingsDepositAmountPerPeriod").value(command.getSavingsDepostiAmountPerPeriod()).notNull().zeroOrPositiveAmount();
|
||||
baseDataValidator.reset().parameter("note").value(command.getNote()).notNull();
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
|
||||
"Validation errors exist.", dataValidationErrors); }
|
||||
}
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package org.mifosplatform.portfolio.savingsaccount.command;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
|
||||
public class SavingAccountStateTransitionCommandValidator {
|
||||
|
||||
private final SavingStateTransitionsCommand command;
|
||||
|
||||
public SavingAccountStateTransitionCommandValidator(final SavingStateTransitionsCommand command) {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public void validate() {
|
||||
|
||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("saving.account.transition");
|
||||
baseDataValidator.reset().parameter("accountId").value(command.getAccountId()).notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset().parameter("eventDate").value(command.getEventDate()).notNull();
|
||||
baseDataValidator.reset().parameter("note").value(command.getNote()).notNull();
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
|
||||
"Validation errors exist.", dataValidationErrors); }
|
||||
}
|
||||
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package org.mifosplatform.portfolio.savingsaccount.command;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
|
||||
public class SavingAccountWithdrawalCommand {
|
||||
|
||||
private final Long accountId;
|
||||
private final LocalDate transactionDate;
|
||||
private final BigDecimal amount;
|
||||
private final String note;
|
||||
|
||||
public SavingAccountWithdrawalCommand(final Long accountId, final LocalDate transactionDate, final BigDecimal amount, final String note) {
|
||||
this.accountId = accountId;
|
||||
this.transactionDate = transactionDate;
|
||||
this.amount = amount;
|
||||
this.note = note;
|
||||
}
|
||||
|
||||
public Long getAccountId() {
|
||||
return this.accountId;
|
||||
}
|
||||
|
||||
public LocalDate getTransactionDate() {
|
||||
return this.transactionDate;
|
||||
}
|
||||
|
||||
public BigDecimal getAmount() {
|
||||
return this.amount;
|
||||
}
|
||||
|
||||
public String getNote() {
|
||||
return this.note;
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package org.mifosplatform.portfolio.savingsaccount.command;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
|
||||
public class SavingStateTransitionsCommand {
|
||||
|
||||
private final Long accountId;
|
||||
private final LocalDate eventDate;
|
||||
private final String note;
|
||||
|
||||
public SavingStateTransitionsCommand( final Long accountId, final LocalDate eventDate, final String note) {
|
||||
this.accountId = accountId;
|
||||
this.eventDate = eventDate;
|
||||
this.note = note;
|
||||
}
|
||||
|
||||
public Long getAccountId() {
|
||||
return this.accountId;
|
||||
}
|
||||
|
||||
public LocalDate getEventDate() {
|
||||
return this.eventDate;
|
||||
}
|
||||
|
||||
public String getNote() {
|
||||
return this.note;
|
||||
}
|
||||
}
|
||||
+317
-20
@@ -24,12 +24,10 @@ public class SavingAccountData {
|
||||
private final String productName;
|
||||
private final EnumOptionData productType;
|
||||
private final CurrencyData currencyData;
|
||||
// FIXME - Madhukar - spelling mistake on word 'deposit' - directly affects api and how people use it.
|
||||
private final BigDecimal savingsDepostiAmountPerPeriod;
|
||||
private final BigDecimal savingsDepositAmountPerPeriod;
|
||||
private final EnumOptionData savingsFrequencyType;
|
||||
private final BigDecimal totalDepositAmount;
|
||||
// FIXME - Madhukar - spelling mistake on work 'recurring' - directly affects api and how people use it.
|
||||
private final BigDecimal reccuringInterestRate;
|
||||
private final BigDecimal recurringInterestRate;
|
||||
private final BigDecimal savingInterestRate;
|
||||
private final EnumOptionData interestType;
|
||||
private final EnumOptionData interestCalculationMethod;
|
||||
@@ -69,19 +67,25 @@ public class SavingAccountData {
|
||||
@SuppressWarnings("unused")
|
||||
private final List<EnumOptionData> interestCalculationOptions;
|
||||
|
||||
private final Collection<SavingScheduleData> savingScheduleDatas;
|
||||
private final SavingPermissionData permissions;
|
||||
private final BigDecimal outstandingAmount;
|
||||
private final BigDecimal dueAmount;
|
||||
private final SavingScheduleData savingScheduleData;
|
||||
|
||||
public static SavingAccountData createFrom(final Long clientId, final String clientDisplayName) {
|
||||
return new SavingAccountData(clientId, clientDisplayName);
|
||||
}
|
||||
|
||||
public SavingAccountData(Long id, EnumOptionData status, String externalId, Long clientId, String clientName, Long productId,
|
||||
String productName, EnumOptionData productType, CurrencyData currencyData, BigDecimal savingsDepostiAmountPerPeriod,
|
||||
EnumOptionData savingsFrequencyType, BigDecimal totalDepositAmount, BigDecimal reccuringInterestRate,
|
||||
String productName, EnumOptionData productType, CurrencyData currencyData, BigDecimal savingsDepositAmountPerPeriod,
|
||||
EnumOptionData savingsFrequencyType, BigDecimal totalDepositAmount, BigDecimal recurringInterestRate,
|
||||
BigDecimal savingInterestRate, EnumOptionData interestType, EnumOptionData interestCalculationMethod, Integer tenure,
|
||||
EnumOptionData tenureType, LocalDate projectedCommencementDate, LocalDate actualCommencementDate, LocalDate maturesOnDate,
|
||||
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) {
|
||||
EnumOptionData lockinPeriodType, Integer depositEvery, BigDecimal outstandingAmount) {
|
||||
this.id = id;
|
||||
this.status = status;
|
||||
this.externalId = externalId;
|
||||
@@ -91,10 +95,10 @@ public class SavingAccountData {
|
||||
this.productName = productName;
|
||||
this.productType = productType;
|
||||
this.currencyData = currencyData;
|
||||
this.savingsDepostiAmountPerPeriod = savingsDepostiAmountPerPeriod;
|
||||
this.savingsDepositAmountPerPeriod = savingsDepositAmountPerPeriod;
|
||||
this.savingsFrequencyType = savingsFrequencyType;
|
||||
this.totalDepositAmount = totalDepositAmount;
|
||||
this.reccuringInterestRate = reccuringInterestRate;
|
||||
this.recurringInterestRate = recurringInterestRate;
|
||||
this.savingInterestRate = savingInterestRate;
|
||||
this.interestType = interestType;
|
||||
this.interestCalculationMethod = interestCalculationMethod;
|
||||
@@ -124,7 +128,11 @@ public class SavingAccountData {
|
||||
this.savingsInterestTypeOptions = null;
|
||||
this.lockinPeriodTypeOptions = null;
|
||||
this.interestCalculationOptions = null;
|
||||
|
||||
this.savingScheduleDatas = null;
|
||||
this.permissions = null;
|
||||
this.outstandingAmount = outstandingAmount;
|
||||
this.dueAmount = BigDecimal.ZERO;
|
||||
this.savingScheduleData = null;
|
||||
}
|
||||
|
||||
public SavingAccountData(Long clientId, String clientName) {
|
||||
@@ -137,11 +145,10 @@ public class SavingAccountData {
|
||||
this.productName = null;
|
||||
this.productType = null;
|
||||
this.currencyData = new CurrencyData("USD", "US Dollar", 2, "$", "currency.USD");
|
||||
;
|
||||
this.savingsDepostiAmountPerPeriod = null;
|
||||
this.savingsDepositAmountPerPeriod = null;
|
||||
this.savingsFrequencyType = null;
|
||||
this.totalDepositAmount = null;
|
||||
this.reccuringInterestRate = null;
|
||||
this.recurringInterestRate = null;
|
||||
this.savingInterestRate = null;
|
||||
this.interestType = null;
|
||||
this.interestCalculationMethod = null;
|
||||
@@ -171,12 +178,17 @@ public class SavingAccountData {
|
||||
this.savingsInterestTypeOptions = null;
|
||||
this.lockinPeriodTypeOptions = null;
|
||||
this.interestCalculationOptions = null;
|
||||
this.savingScheduleDatas = null;
|
||||
this.permissions = null;
|
||||
this.outstandingAmount = BigDecimal.ZERO;
|
||||
this.dueAmount =BigDecimal.ZERO;
|
||||
this.savingScheduleData = null;
|
||||
}
|
||||
|
||||
public SavingAccountData(SavingAccountData account, Collection<SavingProductLookup> productOptions, List<CurrencyData> currencyOptions,
|
||||
List<EnumOptionData> savingsProductTypeOptions, List<EnumOptionData> tenureTypeOptions,
|
||||
List<EnumOptionData> savingFrequencyOptions, List<EnumOptionData> savingsInterestTypeOptions,
|
||||
List<EnumOptionData> lockinPeriodTypeOptions, List<EnumOptionData> interestCalculationOptions) {
|
||||
List<EnumOptionData> lockinPeriodTypeOptions, List<EnumOptionData> interestCalculationOptions,BigDecimal dueAmount) {
|
||||
this.id = account.id;
|
||||
this.status = account.status;
|
||||
this.externalId = account.externalId;
|
||||
@@ -186,10 +198,10 @@ public class SavingAccountData {
|
||||
this.productName = account.productName;
|
||||
this.productType = account.productType;
|
||||
this.currencyData = account.currencyData;
|
||||
this.savingsDepostiAmountPerPeriod = account.savingsDepostiAmountPerPeriod;
|
||||
this.savingsDepositAmountPerPeriod = account.savingsDepositAmountPerPeriod;
|
||||
this.savingsFrequencyType = account.savingsFrequencyType;
|
||||
this.totalDepositAmount = account.totalDepositAmount;
|
||||
this.reccuringInterestRate = account.reccuringInterestRate;
|
||||
this.recurringInterestRate = account.recurringInterestRate;
|
||||
this.savingInterestRate = account.savingInterestRate;
|
||||
this.interestType = account.interestType;
|
||||
this.interestCalculationMethod = account.interestCalculationMethod;
|
||||
@@ -220,11 +232,17 @@ public class SavingAccountData {
|
||||
this.savingsInterestTypeOptions = savingsInterestTypeOptions;
|
||||
this.lockinPeriodTypeOptions = lockinPeriodTypeOptions;
|
||||
this.interestCalculationOptions = interestCalculationOptions;
|
||||
this.dueAmount = dueAmount;
|
||||
|
||||
this.savingScheduleDatas = account.savingScheduleDatas;
|
||||
this.permissions = account.permissions;
|
||||
this.outstandingAmount = account.outstandingAmount;
|
||||
this.savingScheduleData = account.savingScheduleData;
|
||||
}
|
||||
|
||||
// FIXME - Madhukar - unused variables been passed into construction - why?
|
||||
public SavingAccountData(Long clientId, String clientName, Long productId, String productName, CurrencyData currency,
|
||||
BigDecimal interestRate, BigDecimal savingsDepostiAmountPerPeriod, EnumOptionData productType, EnumOptionData tenureType,
|
||||
BigDecimal interestRate, BigDecimal savingsDepositAmountPerPeriod, EnumOptionData productType, EnumOptionData tenureType,
|
||||
Integer tenure, EnumOptionData savingsFrequencyType, EnumOptionData interestType, EnumOptionData interestCalculationMethod,
|
||||
BigDecimal minimumBalanceForWithdrawal, boolean partialDepositAllowed, boolean lockinPeriodAllowed, Integer lockinPeriod,
|
||||
EnumOptionData lockinPeriodType, Integer depositEvery) {
|
||||
@@ -238,10 +256,10 @@ public class SavingAccountData {
|
||||
this.productName = productName;
|
||||
this.productType = productType;
|
||||
this.currencyData = currency;
|
||||
this.savingsDepostiAmountPerPeriod = savingsDepostiAmountPerPeriod;
|
||||
this.savingsDepositAmountPerPeriod = savingsDepositAmountPerPeriod;
|
||||
this.savingsFrequencyType = savingsFrequencyType;
|
||||
this.totalDepositAmount = null;
|
||||
this.reccuringInterestRate = interestRate;
|
||||
this.recurringInterestRate = interestRate;
|
||||
this.savingInterestRate = interestRate;
|
||||
this.interestType = interestType;
|
||||
this.interestCalculationMethod = interestCalculationMethod;
|
||||
@@ -271,6 +289,285 @@ public class SavingAccountData {
|
||||
this.savingsInterestTypeOptions = null;
|
||||
this.lockinPeriodTypeOptions = null;
|
||||
this.interestCalculationOptions = null;
|
||||
|
||||
this.savingScheduleDatas = null;
|
||||
this.permissions = null;
|
||||
this.outstandingAmount = BigDecimal.ZERO;
|
||||
this.dueAmount = BigDecimal.ZERO;
|
||||
this.savingScheduleData = null;
|
||||
}
|
||||
|
||||
public SavingAccountData(SavingAccountData account, SavingPermissionData permissions) {
|
||||
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 = permissions;
|
||||
this.outstandingAmount = account.outstandingAmount;
|
||||
this.dueAmount = account.dueAmount;
|
||||
this.savingScheduleData = account.savingScheduleData;
|
||||
}
|
||||
|
||||
public SavingAccountData(SavingAccountData account, SavingScheduleData savingScheduleData) {
|
||||
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 = savingScheduleData;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public EnumOptionData getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
public String getExternalId() {
|
||||
return this.externalId;
|
||||
}
|
||||
|
||||
public Long getClientId() {
|
||||
return this.clientId;
|
||||
}
|
||||
|
||||
public String getClientName() {
|
||||
return this.clientName;
|
||||
}
|
||||
|
||||
public Long getProductId() {
|
||||
return this.productId;
|
||||
}
|
||||
|
||||
public String getProductName() {
|
||||
return this.productName;
|
||||
}
|
||||
|
||||
public EnumOptionData getProductType() {
|
||||
return this.productType;
|
||||
}
|
||||
|
||||
public CurrencyData getCurrencyData() {
|
||||
return this.currencyData;
|
||||
}
|
||||
|
||||
public BigDecimal getSavingsDepostiAmountPerPeriod() {
|
||||
return this.savingsDepositAmountPerPeriod;
|
||||
}
|
||||
|
||||
public EnumOptionData getSavingsFrequencyType() {
|
||||
return this.savingsFrequencyType;
|
||||
}
|
||||
|
||||
public BigDecimal getTotalDepositAmount() {
|
||||
return this.totalDepositAmount;
|
||||
}
|
||||
|
||||
public BigDecimal getReccuringInterestRate() {
|
||||
return this.recurringInterestRate;
|
||||
}
|
||||
|
||||
public BigDecimal getSavingInterestRate() {
|
||||
return this.savingInterestRate;
|
||||
}
|
||||
|
||||
public EnumOptionData getInterestType() {
|
||||
return this.interestType;
|
||||
}
|
||||
|
||||
public EnumOptionData getInterestCalculationMethod() {
|
||||
return this.interestCalculationMethod;
|
||||
}
|
||||
|
||||
public Integer getTenure() {
|
||||
return this.tenure;
|
||||
}
|
||||
|
||||
public EnumOptionData getTenureType() {
|
||||
return this.tenureType;
|
||||
}
|
||||
|
||||
public LocalDate getProjectedCommencementDate() {
|
||||
return this.projectedCommencementDate;
|
||||
}
|
||||
|
||||
public LocalDate getActualCommencementDate() {
|
||||
return this.actualCommencementDate;
|
||||
}
|
||||
|
||||
public LocalDate getMaturesOnDate() {
|
||||
return this.maturesOnDate;
|
||||
}
|
||||
|
||||
public BigDecimal getProjectedInterestAccuredOnMaturity() {
|
||||
return this.projectedInterestAccuredOnMaturity;
|
||||
}
|
||||
|
||||
public BigDecimal getActualInterestAccured() {
|
||||
return this.actualInterestAccured;
|
||||
}
|
||||
|
||||
public BigDecimal getProjectedMaturityAmount() {
|
||||
return this.projectedMaturityAmount;
|
||||
}
|
||||
|
||||
public BigDecimal getActualMaturityAmount() {
|
||||
return this.actualMaturityAmount;
|
||||
}
|
||||
|
||||
public boolean isPreClosureAllowed() {
|
||||
return this.preClosureAllowed;
|
||||
}
|
||||
|
||||
public BigDecimal getPreClosureInterestRate() {
|
||||
return this.preClosureInterestRate;
|
||||
}
|
||||
|
||||
public LocalDate getWithdrawnonDate() {
|
||||
return this.withdrawnonDate;
|
||||
}
|
||||
|
||||
public LocalDate getRejectedonDate() {
|
||||
return this.rejectedonDate;
|
||||
}
|
||||
|
||||
public LocalDate getClosedonDate() {
|
||||
return this.closedonDate;
|
||||
}
|
||||
|
||||
public boolean isLockinPeriodAllowed() {
|
||||
return this.isLockinPeriodAllowed;
|
||||
}
|
||||
|
||||
public Integer getLockinPeriod() {
|
||||
return this.lockinPeriod;
|
||||
}
|
||||
|
||||
public EnumOptionData getLockinPeriodType() {
|
||||
return this.lockinPeriodType;
|
||||
}
|
||||
|
||||
public Integer getDepositEvery() {
|
||||
return this.depositEvery;
|
||||
}
|
||||
|
||||
public List<SavingProductLookup> getProductOptions() {
|
||||
return this.productOptions;
|
||||
}
|
||||
|
||||
public List<CurrencyData> getCurrencyOptions() {
|
||||
return this.currencyOptions;
|
||||
}
|
||||
|
||||
public List<EnumOptionData> getSavingsProductTypeOptions() {
|
||||
return this.savingsProductTypeOptions;
|
||||
}
|
||||
|
||||
public List<EnumOptionData> getTenureTypeOptions() {
|
||||
return this.tenureTypeOptions;
|
||||
}
|
||||
|
||||
public List<EnumOptionData> getSavingFrequencyOptions() {
|
||||
return this.savingFrequencyOptions;
|
||||
}
|
||||
|
||||
public List<EnumOptionData> getSavingsInterestTypeOptions() {
|
||||
return this.savingsInterestTypeOptions;
|
||||
}
|
||||
|
||||
public List<EnumOptionData> getLockinPeriodTypeOptions() {
|
||||
return this.lockinPeriodTypeOptions;
|
||||
}
|
||||
|
||||
public List<EnumOptionData> getInterestCalculationOptions() {
|
||||
return this.interestCalculationOptions;
|
||||
}
|
||||
|
||||
public BigDecimal getOutstandingAmount() {
|
||||
return this.outstandingAmount;
|
||||
}
|
||||
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package org.mifosplatform.portfolio.savingsaccount.data;
|
||||
|
||||
public class SavingAccountForLookup {
|
||||
|
||||
private final Long id;
|
||||
|
||||
public SavingAccountForLookup(final Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package org.mifosplatform.portfolio.savingsaccount.data;
|
||||
|
||||
public class SavingPermissionData {
|
||||
|
||||
|
||||
|
||||
private final boolean rejectAllowed;
|
||||
private final boolean withdrawnByApplicantAllowed;
|
||||
private final boolean undoApprovalAllowed;
|
||||
private final boolean pendingApproval;
|
||||
private final boolean renewelAllowed;
|
||||
private final boolean isMaturedDepositAccount;
|
||||
|
||||
private final boolean anyActionOnAccountAllowed;
|
||||
|
||||
public SavingPermissionData(final boolean rejectAllowed, final boolean withdrawnByApplicantAllowed, final boolean undoApprovalAllowed,
|
||||
final boolean pendingApproval, final boolean renewelAllowed, final boolean isMaturedDepositAccount) {
|
||||
this.rejectAllowed = rejectAllowed;
|
||||
this.withdrawnByApplicantAllowed = withdrawnByApplicantAllowed;
|
||||
this.undoApprovalAllowed = undoApprovalAllowed;
|
||||
this.pendingApproval = pendingApproval;
|
||||
this.renewelAllowed = renewelAllowed;
|
||||
this.isMaturedDepositAccount = isMaturedDepositAccount;
|
||||
this.anyActionOnAccountAllowed = isRejectAllowed() || isPendingApproval() || isUndoApprovalAllowed()
|
||||
|| isWithdrawnByApplicantAllowed() || isRenewelAllowed() || isMaturedDepositAccount();
|
||||
}
|
||||
|
||||
public boolean isRejectAllowed() {
|
||||
return rejectAllowed;
|
||||
}
|
||||
|
||||
public boolean isWithdrawnByApplicantAllowed() {
|
||||
return withdrawnByApplicantAllowed;
|
||||
}
|
||||
|
||||
public boolean isUndoApprovalAllowed() {
|
||||
return undoApprovalAllowed;
|
||||
}
|
||||
|
||||
public boolean isPendingApproval() {
|
||||
return pendingApproval;
|
||||
}
|
||||
|
||||
public boolean isAnyActionOnAccountAllowed() {
|
||||
return anyActionOnAccountAllowed;
|
||||
}
|
||||
|
||||
public boolean isRenewelAllowed() {
|
||||
return renewelAllowed;
|
||||
}
|
||||
|
||||
public boolean isMaturedDepositAccount() {
|
||||
return isMaturedDepositAccount;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+84
-48
@@ -13,62 +13,98 @@ import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class ReccuringDepositInterestCalculator {
|
||||
|
||||
private final Integer monthsInYear = 12;
|
||||
|
||||
// FIXME - MADHUKAR - Are the unused field here needed?
|
||||
public Money calculateInterestOnMaturityFor(Money savingsDepositPerPeriod, Integer tenure, BigDecimal reccuringInterestRate,
|
||||
LocalDate commencementDate, TenureTypeEnum tenureTypeEnum, SavingFrequencyType savingFrequencyType,
|
||||
SavingInterestCalculationMethod savingInterestCalculationMethod) {
|
||||
|
||||
/*
|
||||
* // Assuming tenure in months // see
|
||||
* http://www.onemint.com/2012/04/03/
|
||||
* how-to-calculate-interest-on-recurring-deposits/
|
||||
*
|
||||
* A=P(1+r/n)^nt
|
||||
*
|
||||
* A = final amount P = principal amount (initial investment) r = annual
|
||||
* nominal interest rate (as a decimal, not in percentage) n = number of
|
||||
* times the interest is compounded per year t = number of years
|
||||
*/
|
||||
MathContext mc = new MathContext(8, RoundingMode.HALF_EVEN);
|
||||
Integer monthsInYear = 12;
|
||||
SavingInterestCalculationMethod savingInterestCalculationMethod, Integer depositEvery) {
|
||||
|
||||
BigDecimal finalAmount = BigDecimal.ZERO;
|
||||
MathContext mc = new MathContext(8, RoundingMode.HALF_EVEN);
|
||||
|
||||
|
||||
BigDecimal interestRateAsFraction = reccuringInterestRate.divide(BigDecimal.valueOf(100), mc);
|
||||
Integer noofTimesInterestCompoundPerYear = Integer.valueOf(0);
|
||||
switch (savingFrequencyType) {
|
||||
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");
|
||||
|
||||
}
|
||||
|
||||
Integer noofTimesInterestCompoundPerYear = determineIntValue(savingFrequencyType);
|
||||
|
||||
BigDecimal interestRatePerPeriod = BigDecimal.valueOf(interestRateAsFraction.doubleValue()
|
||||
/ noofTimesInterestCompoundPerYear.doubleValue());
|
||||
BigDecimal onePlusInterestRatePerPeriod = BigDecimal.ONE.add(interestRatePerPeriod);
|
||||
BigDecimal monthsExpressedInYears;
|
||||
BigDecimal timeforOneCalculationPeriod;
|
||||
BigDecimal amountPerPeriod;
|
||||
BigDecimal finalAmount = BigDecimal.ZERO;
|
||||
while (tenure > 0) {
|
||||
monthsExpressedInYears = BigDecimal.valueOf(tenure.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);
|
||||
tenure--;
|
||||
}
|
||||
Integer noOfTimestobeCalculated = tenure/depositEvery;
|
||||
|
||||
if(savingInterestCalculationMethod.isAverageBalance()){
|
||||
|
||||
BigDecimal totalAmount = BigDecimal.ZERO;
|
||||
BigDecimal termAmount = BigDecimal.ZERO;
|
||||
BigDecimal totalInterest = BigDecimal.ZERO;
|
||||
BigDecimal amountPerPeriod = savingsDepositPerPeriod.getAmount();
|
||||
Integer depositEveryOriginalValue = depositEvery;
|
||||
BigDecimal amountPermonth = amountPerPeriod.divide(BigDecimal.valueOf(depositEvery.doubleValue()));
|
||||
while (noOfTimestobeCalculated > 0) {
|
||||
while (depositEvery > 0) {
|
||||
termAmount = termAmount.add(amountPermonth);
|
||||
totalAmount = totalAmount.add(termAmount);
|
||||
depositEvery--;
|
||||
}
|
||||
BigDecimal averageAmount = BigDecimal.valueOf(totalAmount.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;
|
||||
noOfTimestobeCalculated--;
|
||||
}
|
||||
finalAmount = termAmount.add(totalInterest);
|
||||
|
||||
} else if(savingInterestCalculationMethod.isMonthlyCollection()){
|
||||
/*
|
||||
* // Assuming tenure in months // see
|
||||
* http://www.onemint.com/2012/04/03/
|
||||
* how-to-calculate-interest-on-recurring-deposits/
|
||||
*
|
||||
* A=P(1+r/n)^nt
|
||||
*
|
||||
* A = final amount P = principal amount (initial investment) r = annual
|
||||
* nominal interest rate (as a decimal, not in percentage) n = number of
|
||||
* times the interest is compounded per year t = number of years
|
||||
*/
|
||||
|
||||
BigDecimal onePlusInterestRatePerPeriod = BigDecimal.ONE.add(interestRatePerPeriod);
|
||||
BigDecimal monthsExpressedInYears;
|
||||
BigDecimal timeforOneCalculationPeriod;
|
||||
BigDecimal amountPerPeriod;
|
||||
|
||||
while (noOfTimestobeCalculated > 0) {
|
||||
monthsExpressedInYears = BigDecimal.valueOf(tenure.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--;
|
||||
}
|
||||
}
|
||||
return Money.of(savingsDepositPerPeriod.getCurrency(), finalAmount);
|
||||
}
|
||||
|
||||
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 Money.of(savingsDepositPerPeriod.getCurrency(), finalAmount);
|
||||
}
|
||||
return noofTimesInterestCompoundPerYear;
|
||||
}
|
||||
}
|
||||
+368
-40
@@ -1,6 +1,8 @@
|
||||
package org.mifosplatform.portfolio.savingsaccount.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
@@ -12,6 +14,7 @@ import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OrderBy;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
@@ -20,11 +23,13 @@ import javax.persistence.UniqueConstraint;
|
||||
import org.hibernate.annotations.LazyCollection;
|
||||
import org.hibernate.annotations.LazyCollectionOption;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.Months;
|
||||
import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom;
|
||||
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.mifosplatform.organisation.monetary.domain.Money;
|
||||
import org.mifosplatform.portfolio.client.domain.Client;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountDepositCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingFrequencyType;
|
||||
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingInterestCalculationMethod;
|
||||
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProduct;
|
||||
@@ -33,6 +38,7 @@ import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingsInterestT
|
||||
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositAccountEvent;
|
||||
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositAccountStatus;
|
||||
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositLifecycleStateMachine;
|
||||
import org.mifosplatform.portfolio.savingsdepositaccount.exception.InvalidDepositStateTransitionException;
|
||||
import org.mifosplatform.portfolio.savingsdepositproduct.domain.TenureTypeEnum;
|
||||
import org.mifosplatform.useradministration.domain.AppUser;
|
||||
|
||||
@@ -48,10 +54,8 @@ public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
@JoinColumn(name = "product_id")
|
||||
private SavingProduct product;
|
||||
|
||||
// FIXME - MADHUKAR - Do not use the actual enum type here but instead use
|
||||
// Integer e.g. private Integer savingProductType;
|
||||
@Column(name = "savings_product_type", nullable = false)
|
||||
private SavingProductType savingProductType;
|
||||
private Integer savingProductType;
|
||||
|
||||
@Column(name = "external_id")
|
||||
private String externalId;
|
||||
@@ -76,24 +80,17 @@ public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
@Column(name = "tenure", nullable = false)
|
||||
private Integer tenure;
|
||||
|
||||
// FIXME - MADHUKAR - Do not use the actual enum type here use integer representation
|
||||
@Column(name = "tenure_type", nullable = false)
|
||||
private TenureTypeEnum tenureType;
|
||||
private Integer tenureType;
|
||||
|
||||
// FIXME - MADHUKAR - Do not use the actual enum type here but instead use
|
||||
// Integer e.g. private Integer savingProductType;
|
||||
@Column(name = "frequency", nullable = false)
|
||||
private SavingFrequencyType frequency;
|
||||
private Integer frequency;
|
||||
|
||||
// FIXME - MADHUKAR - Do not use the actual enum type here but instead use
|
||||
// Integer e.g. private Integer savingProductType;
|
||||
@Column(name = "interest_type", nullable = false)
|
||||
private SavingsInterestType interestType;
|
||||
private Integer interestType;
|
||||
|
||||
// FIXME - MADHUKAR - Do not use the actual enum type here but instead use
|
||||
// Integer e.g. private Integer savingProductType;
|
||||
@Column(name = "interest_calculation_method")
|
||||
private SavingInterestCalculationMethod interestCalculationMethod;
|
||||
private Integer interestCalculationMethod;
|
||||
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "projected_commencement_date")
|
||||
@@ -127,6 +124,9 @@ public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
|
||||
@Column(name = "pre_closure_interest_rate", scale = 6, precision = 19, nullable = false)
|
||||
private BigDecimal preClosureInterestRate;
|
||||
|
||||
@Column(name = "outstanding_amount", scale = 6, precision = 19, nullable = false)
|
||||
private BigDecimal outstandingAmount;
|
||||
|
||||
@Column(name = "is_preclosure_allowed", nullable = false)
|
||||
private boolean preClosureAllowed = false;
|
||||
@@ -158,16 +158,42 @@ public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
private Integer lockinPeriod;
|
||||
|
||||
@Column(name = "lock_in_period_type", nullable = false)
|
||||
private PeriodFrequencyType lockinPeriodType;
|
||||
private Integer lockinPeriodType;
|
||||
|
||||
@Column(name = "deposit_every", nullable = false)
|
||||
private Integer payEvery;
|
||||
|
||||
@Column(name = "interest_posting_every", nullable = false)
|
||||
private Integer interestPostEvery;
|
||||
|
||||
@Column(name = "interest_posting_frequency", nullable = false)
|
||||
private Integer interestPostFrequency;
|
||||
|
||||
@Column(name = "interest_posted_amount", scale = 6, precision = 19)
|
||||
private BigDecimal interestPostedAmount;
|
||||
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "last_interest_posted_date")
|
||||
private Date lastInterestPostedDate;
|
||||
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "next_interest_posting_date")
|
||||
private Date nextInterestPostingDate;
|
||||
|
||||
// see
|
||||
// http://stackoverflow.com/questions/4334970/hibernate-cannot-simultaneously-fetch-multiple-bags
|
||||
@LazyCollection(LazyCollectionOption.FALSE)
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "savingAccount", orphanRemoval = true)
|
||||
private final List<SavingScheduleInstallments> savingScheduleInstallments = new ArrayList<SavingScheduleInstallments>();
|
||||
|
||||
@OrderBy(value = "id")
|
||||
@LazyCollection(LazyCollectionOption.FALSE)
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "savingAccount", orphanRemoval = true)
|
||||
private final List<SavingAccountTransaction> savingAccountTransactions = new ArrayList<SavingAccountTransaction>();
|
||||
|
||||
public SavingAccount() {
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public static SavingAccount openNew(Client client, SavingProduct product, String externalId, Money savingsDeposit,
|
||||
BigDecimal reccuringInterestRate, BigDecimal savingInterestRate, Integer tenure, LocalDate commencementDate,
|
||||
@@ -175,27 +201,28 @@ public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
SavingsInterestType interestType, SavingInterestCalculationMethod savingInterestCalculationMethod,
|
||||
boolean isLockinPeriodAllowed, Integer lockinPeriod, PeriodFrequencyType lockinPeriodType,
|
||||
ReccuringDepositInterestCalculator reccuringDepositInterestCalculator, final DepositLifecycleStateMachine lifecycleStateMachine,
|
||||
Integer payEvery) {
|
||||
Integer depositEvery, Integer interestPostEvery, Integer interestPostFrequency) {
|
||||
|
||||
Money futureValueOnMaturity = null;
|
||||
if (savingProductType.isReccuring()) {
|
||||
futureValueOnMaturity = reccuringDepositInterestCalculator.calculateInterestOnMaturityFor(savingsDeposit, tenure,
|
||||
reccuringInterestRate, commencementDate, tenureTypeEnum, savingFrequencyType, savingInterestCalculationMethod);
|
||||
reccuringInterestRate, commencementDate, tenureTypeEnum, savingFrequencyType, savingInterestCalculationMethod,depositEvery);
|
||||
} else if (savingProductType.isRegular()) {
|
||||
futureValueOnMaturity = reccuringDepositInterestCalculator.calculateInterestOnMaturityFor(savingsDeposit, tenure,
|
||||
savingInterestRate, commencementDate, tenureTypeEnum, savingFrequencyType, savingInterestCalculationMethod);
|
||||
savingInterestRate, commencementDate, tenureTypeEnum, savingFrequencyType, savingInterestCalculationMethod,depositEvery);
|
||||
}
|
||||
|
||||
return new SavingAccount(client, externalId, product, savingsDeposit, reccuringInterestRate, savingInterestRate, tenure,
|
||||
commencementDate, tenureTypeEnum, savingProductType, savingFrequencyType, interestType, savingInterestCalculationMethod,
|
||||
isLockinPeriodAllowed, lockinPeriod, lockinPeriodType, futureValueOnMaturity, lifecycleStateMachine,payEvery);
|
||||
isLockinPeriodAllowed, lockinPeriod, lockinPeriodType, futureValueOnMaturity, lifecycleStateMachine,depositEvery,interestPostEvery, interestPostFrequency);
|
||||
}
|
||||
|
||||
public SavingAccount(Client client, String externalId, SavingProduct product, Money savingsDeposit, BigDecimal reccuringInterestRate,
|
||||
BigDecimal savingInterestRate, Integer tenure, LocalDate commencementDate, TenureTypeEnum tenureTypeEnum,
|
||||
SavingProductType savingProductType, SavingFrequencyType savingFrequencyType, SavingsInterestType interestType,
|
||||
SavingInterestCalculationMethod savingInterestCalculationMethod, boolean isLockinPeriodAllowed, Integer lockinPeriod,
|
||||
PeriodFrequencyType lockinPeriodType, Money futureValueOnMaturity, final DepositLifecycleStateMachine lifecycleStateMachine,Integer payEvery) {
|
||||
PeriodFrequencyType lockinPeriodType, Money futureValueOnMaturity, final DepositLifecycleStateMachine lifecycleStateMachine,Integer payEvery,
|
||||
Integer interestPostEvery, Integer interestPostFrequency) {
|
||||
|
||||
DepositAccountStatus from = null;
|
||||
if (accountStatus != null) {
|
||||
@@ -219,18 +246,21 @@ public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
this.savingInterestRate = savingInterestRate;
|
||||
this.tenure = tenure;
|
||||
this.projectedCommencementDate = commencementDate.toDate();
|
||||
this.tenureType = tenureTypeEnum;
|
||||
this.savingProductType = savingProductType;
|
||||
this.frequency = savingFrequencyType;
|
||||
this.interestType = interestType;
|
||||
this.interestCalculationMethod = savingInterestCalculationMethod;
|
||||
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;
|
||||
this.lockinPeriodType = lockinPeriodType.getValue();
|
||||
this.projectedTotalOnMaturity = futureValueOnMaturity.getAmount();
|
||||
this.projectedInterestAccruedOnMaturity = futureValueOnMaturity.getAmount().subtract(
|
||||
BigDecimal.valueOf(savingsDeposit.getAmount().doubleValue() * tenure.doubleValue()));
|
||||
BigDecimal.valueOf(savingsDeposit.getAmount().doubleValue() * tenure.doubleValue() / payEvery)); //presently only for months
|
||||
this.payEvery = payEvery;
|
||||
this.outstandingAmount = BigDecimal.ZERO;
|
||||
this.interestPostEvery = interestPostEvery;
|
||||
this.interestPostFrequency=interestPostFrequency;
|
||||
}
|
||||
|
||||
public void modifyAccount(SavingProduct product, String externalId, Money savingsDeposit, BigDecimal reccuringInterestRate,
|
||||
@@ -242,10 +272,10 @@ public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
Money futureValueOnMaturity = null;
|
||||
if (savingProductType.isReccuring()) {
|
||||
futureValueOnMaturity = reccuringDepositInterestCalculator.calculateInterestOnMaturityFor(savingsDeposit, tenure,
|
||||
reccuringInterestRate, commencementDate, tenureTypeEnum, savingFrequencyType, savingInterestCalculationMethod);
|
||||
reccuringInterestRate, commencementDate, tenureTypeEnum, savingFrequencyType, savingInterestCalculationMethod,payEvery);
|
||||
} else if (savingProductType.isRegular()) {
|
||||
futureValueOnMaturity = reccuringDepositInterestCalculator.calculateInterestOnMaturityFor(savingsDeposit, tenure,
|
||||
savingInterestRate, commencementDate, tenureTypeEnum, savingFrequencyType, savingInterestCalculationMethod);
|
||||
savingInterestRate, commencementDate, tenureTypeEnum, savingFrequencyType, savingInterestCalculationMethod,payEvery);
|
||||
}
|
||||
|
||||
this.product = product;
|
||||
@@ -255,14 +285,15 @@ public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
this.savingInterestRate = savingInterestRate;
|
||||
this.tenure = tenure;
|
||||
this.projectedCommencementDate = commencementDate.toDate();
|
||||
this.tenureType = tenureTypeEnum;
|
||||
this.savingProductType = savingProductType;
|
||||
this.frequency = savingFrequencyType;
|
||||
this.interestCalculationMethod = savingInterestCalculationMethod;
|
||||
this.tenureType = tenureTypeEnum.getValue();
|
||||
this.savingProductType = savingProductType.getValue();
|
||||
this.frequency = savingFrequencyType.getValue();
|
||||
this.interestCalculationMethod = savingInterestCalculationMethod.getValue();
|
||||
this.isLockinPeriodAllowed = isLockinPeriodAllowed;
|
||||
this.lockinPeriod = lockinPeriod;
|
||||
this.lockinPeriodType = lockinPeriodType;
|
||||
this.lockinPeriodType = lockinPeriodType.getValue();
|
||||
this.payEvery = payEvery;
|
||||
this.outstandingAmount = BigDecimal.ZERO;
|
||||
|
||||
// FIXME - MADHUKAR - futureValueOnMaturity is possibly null
|
||||
this.projectedTotalOnMaturity = futureValueOnMaturity.getAmount();
|
||||
@@ -286,7 +317,7 @@ public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
return product;
|
||||
}
|
||||
|
||||
public SavingProductType getSavingProductType() {
|
||||
public Integer getSavingProductType() {
|
||||
return savingProductType;
|
||||
}
|
||||
|
||||
@@ -310,19 +341,19 @@ public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
return tenure;
|
||||
}
|
||||
|
||||
public TenureTypeEnum getTenureType() {
|
||||
public Integer getTenureType() {
|
||||
return tenureType;
|
||||
}
|
||||
|
||||
public SavingFrequencyType getFrequency() {
|
||||
public Integer getFrequency() {
|
||||
return frequency;
|
||||
}
|
||||
|
||||
public SavingsInterestType getInterestType() {
|
||||
public Integer getInterestType() {
|
||||
return interestType;
|
||||
}
|
||||
|
||||
public SavingInterestCalculationMethod getInterestCalculationMethod() {
|
||||
public Integer getInterestCalculationMethod() {
|
||||
return interestCalculationMethod;
|
||||
}
|
||||
|
||||
@@ -350,7 +381,7 @@ public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
return lockinPeriod;
|
||||
}
|
||||
|
||||
public PeriodFrequencyType getLockinPeriodType() {
|
||||
public Integer getLockinPeriodType() {
|
||||
return lockinPeriodType;
|
||||
}
|
||||
|
||||
@@ -358,9 +389,306 @@ public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
return this.payEvery;
|
||||
}
|
||||
|
||||
public BigDecimal getOutstandingAmount() {
|
||||
return this.outstandingAmount;
|
||||
}
|
||||
|
||||
public Integer getInterestPostEvery() {
|
||||
return this.interestPostEvery;
|
||||
}
|
||||
|
||||
public Integer getInterestPostFrequency() {
|
||||
return this.interestPostFrequency;
|
||||
}
|
||||
|
||||
public List<SavingAccountTransaction> getSavingAccountTransactions() {
|
||||
return this.savingAccountTransactions;
|
||||
}
|
||||
|
||||
public void addSavingScheduleInstallment(final SavingScheduleInstallments installment) {
|
||||
installment.updateAccount(this);
|
||||
this.savingScheduleInstallments.add(installment);
|
||||
}
|
||||
|
||||
public void reject(LocalDate rejectedOn, DepositLifecycleStateMachine depositLifecycleStateMachine) {
|
||||
|
||||
|
||||
DepositAccountStatus statusEnum = depositLifecycleStateMachine.transition(DepositAccountEvent.DEPOSIT_REJECTED,
|
||||
DepositAccountStatus.fromInt(this.accountStatus));
|
||||
this.accountStatus = statusEnum.getValue();
|
||||
|
||||
this.maturesOnDate = null;
|
||||
this.rejectedOnDate = rejectedOn.toDateTimeAtCurrentTime().toDate();
|
||||
this.closedOnDate = rejectedOn.toDateTimeAtCurrentTime().toDate();
|
||||
|
||||
if (rejectedOn.isBefore(projectedCommencementDate())) {
|
||||
|
||||
final String errorMessage = "The date on which a saving account is rejected cannot be before its submittal date: "
|
||||
+ projectedCommencementDate().toString();
|
||||
throw new InvalidDepositStateTransitionException("reject", "cannot.be.before.submittal.date", errorMessage, rejectedOn,
|
||||
projectedCommencementDate());
|
||||
|
||||
}
|
||||
if (rejectedOn.isAfter(new LocalDate())) {
|
||||
|
||||
final String errorMessage = "The date on which a saving account is rejected cannot be in the future.";
|
||||
throw new InvalidDepositStateTransitionException("reject", "cannot.be.a.future.date", errorMessage, rejectedOn);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public LocalDate projectedCommencementDate() {
|
||||
LocalDate date = null;
|
||||
if (this.projectedCommencementDate != null) {
|
||||
date = new LocalDate(this.projectedCommencementDate);
|
||||
}
|
||||
return date;
|
||||
}
|
||||
|
||||
public void withdrawnByApplicant(LocalDate withdrawnOn, DepositLifecycleStateMachine depositLifecycleStateMachine) {
|
||||
|
||||
DepositAccountStatus statusEnum = depositLifecycleStateMachine.transition(DepositAccountEvent.DEPOSIT_WITHDRAWN,
|
||||
DepositAccountStatus.fromInt(this.accountStatus));
|
||||
this.accountStatus = statusEnum.getValue();
|
||||
|
||||
this.maturesOnDate = null;
|
||||
this.withdrawnOnDate = withdrawnOn.toDateTimeAtCurrentTime().toDate();
|
||||
this.closedOnDate = withdrawnOn.toDateTimeAtCurrentTime().toDate();
|
||||
|
||||
if (withdrawnOn.isBefore(projectedCommencementDate())) {
|
||||
|
||||
final String errorMessage = "The date on which a deposit is rejected cannot be before its submittal date: "
|
||||
+ projectedCommencementDate().toString();
|
||||
throw new InvalidDepositStateTransitionException("withdrawnbyclient", "cannot.be.before.submittal.date", errorMessage, withdrawnOn,
|
||||
projectedCommencementDate());
|
||||
|
||||
}
|
||||
|
||||
if (withdrawnOn.isAfter(new LocalDate())) {
|
||||
final String errorMessage = "The date on which a deposit is rejected cannot be in the future.";
|
||||
throw new InvalidDepositStateTransitionException("withdrawnbyclient", "cannot.be.a.future.date", errorMessage, withdrawnOn);
|
||||
}
|
||||
}
|
||||
|
||||
public void undoSavingAccountApproval(DepositLifecycleStateMachine depositLifecycleStateMachine) {
|
||||
DepositAccountStatus statusEnum = depositLifecycleStateMachine.transition(DepositAccountEvent.DEPOSIT_APPROVAL_UNDO,
|
||||
DepositAccountStatus.fromInt(this.accountStatus));
|
||||
this.accountStatus = statusEnum.getValue();
|
||||
this.savingScheduleInstallments.clear();
|
||||
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,
|
||||
Integer interestPostEvery, Integer interestPostFrequency) {
|
||||
|
||||
DepositAccountStatus statusEnum = depositLifecycleStateMachine.transition(DepositAccountEvent.DEPOSIT_APPROVED,
|
||||
DepositAccountStatus.fromInt(this.accountStatus));
|
||||
this.accountStatus = statusEnum.getValue();
|
||||
|
||||
Money savingsAmountPerPeriod = Money.of(currency, savingsDepositAmountPerPeriod);
|
||||
TenureTypeEnum tenureTypeEnum = TenureTypeEnum.fromInt(tenureType);
|
||||
SavingFrequencyType savingFrequencyType = SavingFrequencyType.fromInt(frequency);
|
||||
SavingInterestCalculationMethod interestCalculationMethod = SavingInterestCalculationMethod.fromInt(this.interestCalculationMethod);
|
||||
|
||||
Money futureValueOnMaturity = null;
|
||||
if (SavingProductType.fromInt(product.getSavingProductRelatedDetail().getSavingProductType()).isReccuring()) {
|
||||
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);
|
||||
}
|
||||
|
||||
this.actualCommencementDate = approvalDate.toDate();
|
||||
this.savingsDepositAmountPerPeriod = savingsDepositAmountPerPeriod;
|
||||
this.reccuringInterestRate = recurringInterestRate;
|
||||
this.savingInterestRate = savingInterestRate;
|
||||
this.interestType = interestType;
|
||||
this.tenure = tenure;
|
||||
this.tenureType = tenureType;
|
||||
this.frequency = frequency;
|
||||
this.payEvery = payEvery;
|
||||
this.savingScheduleInstallments.clear();
|
||||
this.total=futureValueOnMaturity.getAmount();
|
||||
this.interestAccrued = futureValueOnMaturity.getAmount().subtract(BigDecimal.valueOf(savingsDepositAmountPerPeriod.doubleValue() * tenure/payEvery.doubleValue()));
|
||||
this.interestPostEvery = interestPostEvery;
|
||||
this.interestPostFrequency = interestPostFrequency;
|
||||
|
||||
// for interest posting initializing
|
||||
this.lastInterestPostedDate = this.actualCommencementDate;
|
||||
this.nextInterestPostingDate = new LocalDate(this.lastInterestPostedDate).plusMonths(this.interestPostEvery).toDate();
|
||||
this.interestPostedAmount = BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
public void depositMoney(SavingAccountDepositCommand command) {
|
||||
|
||||
BigDecimal depositAmount = BigDecimal.ZERO;
|
||||
BigDecimal remainAmountToBePaid = BigDecimal.ZERO;
|
||||
BigDecimal commandRemainDepositAmount = command.getSavingsDepostiAmountPerPeriod();
|
||||
|
||||
SavingAccountTransaction savingAccountTransaction = SavingAccountTransaction.deposit(command.getSavingsDepostiAmountPerPeriod(),command.getDepositDate());
|
||||
savingAccountTransaction.updateAccount(this);
|
||||
this.savingAccountTransactions.add(savingAccountTransaction);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return DepositAccountStatus.fromInt(this.accountStatus).isActive();
|
||||
}
|
||||
|
||||
public void withdrawAmount(BigDecimal amount, LocalDate transactionDate) {
|
||||
this.outstandingAmount = this.outstandingAmount.subtract(amount);
|
||||
SavingAccountTransaction savingAccountTransaction = SavingAccountTransaction.withdraw(amount,transactionDate);
|
||||
savingAccountTransaction.updateAccount(this);
|
||||
this.savingAccountTransactions.add(savingAccountTransaction);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete is a <i>soft delete</i>. Updates flag on account so it wont appear
|
||||
* in query/report results.
|
||||
*
|
||||
* Any fields with unique constraints and prepended with id of record.
|
||||
*/
|
||||
public void delete() {
|
||||
this.deleted = true;
|
||||
this.externalId = this.getId() + "_" + this.externalId;
|
||||
}
|
||||
|
||||
public void postInterest(ReccuringDepositInterestCalculator reccuringDepositInterestCalculator) {
|
||||
|
||||
LocalDate lastInterestPostedDate = getLastInterestPostedDate();
|
||||
@SuppressWarnings("unused")
|
||||
LocalDate nextInterestPostingDate = getNextInterestPostedDate();
|
||||
@SuppressWarnings("unused")
|
||||
SavingInterestCalculationMethod savingInterestCalculationMethod = SavingInterestCalculationMethod.fromInt(this.interestCalculationMethod);
|
||||
|
||||
Integer monthsForInterestCalculation = Months.monthsBetween(lastInterestPostedDate, new LocalDate()).getMonths();
|
||||
Integer postInterestItereations = monthsForInterestCalculation / this.interestPostEvery;
|
||||
MathContext mc = new MathContext(8, RoundingMode.HALF_EVEN);
|
||||
BigDecimal interestRateAsFraction = reccuringInterestRate.divide(BigDecimal.valueOf(100), mc);
|
||||
final Integer monthsInYear = 12;
|
||||
|
||||
BigDecimal totalDepositedAmount = BigDecimal.ZERO;
|
||||
BigDecimal totalWithdrawableAmount = BigDecimal.ZERO;
|
||||
BigDecimal totalOutstandingAmount = BigDecimal.ZERO;
|
||||
boolean isOutstandingAmountCalculated = false;
|
||||
|
||||
while (postInterestItereations > 0 ) {
|
||||
lastInterestPostedDate = getLastInterestPostedDate();
|
||||
nextInterestPostingDate = getNextInterestPostedDate();
|
||||
LocalDate transactionStartDate = lastInterestPostedDate;
|
||||
|
||||
BigDecimal termTotalAmount = BigDecimal.ZERO;
|
||||
BigDecimal averageBalanceForTerm = BigDecimal.ZERO;
|
||||
|
||||
for (int i=0; i< interestPostEvery; i++){
|
||||
//default for months here
|
||||
LocalDate transactionEndDate = transactionStartDate.plusMonths(1);
|
||||
BigDecimal depositedAmount = BigDecimal.ZERO;
|
||||
BigDecimal withdrawableAmount = BigDecimal.ZERO;
|
||||
BigDecimal outstandingAmount = BigDecimal.ZERO;
|
||||
|
||||
for(SavingAccountTransaction savingAccountTransaction : this.savingAccountTransactions){
|
||||
LocalDate actualTransactionDate = savingAccountTransaction.getTransactionDate();
|
||||
if (actualTransactionDate != null && (actualTransactionDate.isAfter(transactionStartDate) || actualTransactionDate.isEqual(transactionStartDate))) {
|
||||
if (actualTransactionDate.isBefore(transactionEndDate)) {
|
||||
if(savingAccountTransaction.getTypeOf().isDeposit()){
|
||||
depositedAmount = depositedAmount.add(savingAccountTransaction.getAmount());
|
||||
} else if (savingAccountTransaction.getTypeOf().isWithdraw()) {
|
||||
withdrawableAmount = withdrawableAmount.add(savingAccountTransaction.getAmount());
|
||||
}
|
||||
}
|
||||
} else if (actualTransactionDate != null && (actualTransactionDate.isBefore(transactionStartDate))) {
|
||||
if(!isOutstandingAmountCalculated){
|
||||
if(savingAccountTransaction.getTypeOf().isDeposit()){
|
||||
depositedAmount = depositedAmount.add(savingAccountTransaction.getAmount());
|
||||
} else if (savingAccountTransaction.getTypeOf().isWithdraw()) {
|
||||
withdrawableAmount = withdrawableAmount.add(savingAccountTransaction.getAmount());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
outstandingAmount = depositedAmount.subtract(withdrawableAmount);
|
||||
totalDepositedAmount = totalDepositedAmount.add(depositedAmount);
|
||||
totalWithdrawableAmount = totalWithdrawableAmount.add(withdrawableAmount);
|
||||
totalOutstandingAmount = totalOutstandingAmount.add(outstandingAmount);
|
||||
termTotalAmount = termTotalAmount.add(totalOutstandingAmount);
|
||||
transactionStartDate = transactionEndDate;
|
||||
isOutstandingAmountCalculated = true;
|
||||
}
|
||||
// FIXME-MADHUKAR calculate interest on calculation method
|
||||
|
||||
// if (savingInterestCalculationMethod.isAverageBalance()) {
|
||||
averageBalanceForTerm =BigDecimal.valueOf(termTotalAmount.doubleValue()/this.interestPostEvery);
|
||||
BigDecimal interestRatePerTerm = BigDecimal.valueOf(interestRateAsFraction.doubleValue()/monthsInYear.doubleValue()*this.interestPostEvery.doubleValue());
|
||||
BigDecimal interestPerTerm = averageBalanceForTerm.multiply(interestRatePerTerm);
|
||||
this.interestPostedAmount = this.interestPostedAmount.add(interestPerTerm);
|
||||
totalOutstandingAmount = totalOutstandingAmount.add(interestPerTerm);
|
||||
// } else if(savingInterestCalculationMethod.isMonthlyCollection()){
|
||||
|
||||
//}
|
||||
this.outstandingAmount = this.outstandingAmount . add(interestPerTerm);
|
||||
this.lastInterestPostedDate = getNextInterestPostedDate().toDate();
|
||||
this.nextInterestPostingDate = getNextInterestPostedDate().plusMonths(this.interestPostEvery).toDate();
|
||||
postInterestItereations--;
|
||||
}
|
||||
}
|
||||
|
||||
private final LocalDate getLastInterestPostedDate() {
|
||||
LocalDate lastInterestPostedDate;
|
||||
if (this.lastInterestPostedDate == null) {
|
||||
lastInterestPostedDate = new LocalDate(this.actualCommencementDate);
|
||||
} else {
|
||||
lastInterestPostedDate = new LocalDate(this.lastInterestPostedDate);
|
||||
}
|
||||
return lastInterestPostedDate;
|
||||
}
|
||||
|
||||
private final LocalDate getNextInterestPostedDate() {
|
||||
LocalDate nextInterestPostingDate;
|
||||
if (this.nextInterestPostingDate == null) {
|
||||
nextInterestPostingDate = new LocalDate(this.nextInterestPostingDate).plusMonths(this.interestPostEvery);
|
||||
} else {
|
||||
nextInterestPostingDate = new LocalDate(this.nextInterestPostingDate);
|
||||
}
|
||||
return nextInterestPostingDate;
|
||||
}
|
||||
|
||||
private final LocalDate getMaturityDate(){
|
||||
LocalDate commencementDate;
|
||||
if (this.actualCommencementDate == null) {
|
||||
commencementDate = new LocalDate(this.projectedCommencementDate).plusMonths(this.tenure);
|
||||
} else {
|
||||
commencementDate = new LocalDate(this.actualCommencementDate).plusMonths(this.tenure);
|
||||
}
|
||||
return commencementDate;
|
||||
}
|
||||
}
|
||||
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
package org.mifosplatform.portfolio.savingsaccount.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom;
|
||||
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositAccountTransactionType;
|
||||
import org.mifosplatform.useradministration.domain.AppUser;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_saving_account_transaction")
|
||||
public class SavingAccountTransaction extends AbstractAuditableCustom<AppUser, Long> {
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "saving_account_id", nullable = false)
|
||||
private SavingAccount savingAccount;
|
||||
|
||||
// @Enumerated(EnumType.ORDINAL)
|
||||
@Column(name = "transaction_type_enum", nullable = false)
|
||||
private Integer typeOf;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@OneToOne(optional = true, cascade = { CascadeType.PERSIST })
|
||||
@JoinColumn(name = "contra_id")
|
||||
private SavingAccountTransaction contra;
|
||||
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "transaction_date", nullable = false)
|
||||
private final Date transactionDate;
|
||||
|
||||
@Column(name = "amount", scale = 6, precision = 19, nullable = false)
|
||||
private final BigDecimal amount;
|
||||
|
||||
public SavingAccountTransaction() {
|
||||
this.transactionDate = null;
|
||||
this.amount = BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
public SavingAccountTransaction(DepositAccountTransactionType transactionType, BigDecimal amount, LocalDate paymentDate) {
|
||||
this.typeOf = transactionType.getValue();
|
||||
this.amount = amount;
|
||||
this.transactionDate =paymentDate.toDate();
|
||||
}
|
||||
|
||||
public static SavingAccountTransaction deposit(BigDecimal amount, LocalDate paymentDate) {
|
||||
return new SavingAccountTransaction(DepositAccountTransactionType.DEPOSIT, amount == null ? new BigDecimal(0) : amount, paymentDate);
|
||||
}
|
||||
|
||||
public static SavingAccountTransaction withdraw(BigDecimal amount, LocalDate paymentDate) {
|
||||
return new SavingAccountTransaction(DepositAccountTransactionType.WITHDRAW, amount == null ? new BigDecimal(0) : amount, paymentDate);
|
||||
}
|
||||
|
||||
public static SavingAccountTransaction postInterest(BigDecimal amount, LocalDate paymentDate) {
|
||||
return new SavingAccountTransaction(DepositAccountTransactionType.INTEREST_POSTING, amount == null ? new BigDecimal(0) : amount, paymentDate);
|
||||
}
|
||||
|
||||
public void updateAccount(SavingAccount savingAccount) {
|
||||
this.savingAccount = savingAccount;
|
||||
}
|
||||
|
||||
public DepositAccountTransactionType getTypeOf() {
|
||||
return DepositAccountTransactionType.fromInt(this.typeOf);
|
||||
}
|
||||
|
||||
public BigDecimal getAmount() {
|
||||
return this.amount;
|
||||
}
|
||||
|
||||
public LocalDate getTransactionDate() {
|
||||
LocalDate transactionDate = null;
|
||||
if(this.transactionDate != null){
|
||||
transactionDate = new LocalDate(this.transactionDate);
|
||||
}
|
||||
return transactionDate;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+40
-1
@@ -39,7 +39,7 @@ public class SavingScheduleInstallments extends AbstractAuditableCustom<AppUser,
|
||||
@SuppressWarnings("unused")
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "payment_date", nullable = true)
|
||||
private final Date paymentDate;
|
||||
private Date paymentDate;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "deposit_paid", scale = 6, precision = 19, nullable = true)
|
||||
@@ -48,6 +48,12 @@ public class SavingScheduleInstallments extends AbstractAuditableCustom<AppUser,
|
||||
@SuppressWarnings("unused")
|
||||
@Column(name = "completed_derived", nullable = false)
|
||||
private boolean completed;
|
||||
|
||||
public SavingScheduleInstallments() {
|
||||
this.dueDate = null;
|
||||
this.installmentNumber = null;
|
||||
this.paymentDate = null;
|
||||
}
|
||||
|
||||
public SavingScheduleInstallments(SavingAccount account, Date dueDate, Integer installmentNumber, BigDecimal deposit) {
|
||||
this.savingAccount = account;
|
||||
@@ -62,5 +68,38 @@ public class SavingScheduleInstallments extends AbstractAuditableCustom<AppUser,
|
||||
public void updateAccount(SavingAccount account) {
|
||||
this.savingAccount = account;
|
||||
}
|
||||
|
||||
public Date getPaymentDate() {
|
||||
return this.paymentDate;
|
||||
}
|
||||
|
||||
public void setPaymentDate(Date paymentDate) {
|
||||
this.paymentDate = paymentDate;
|
||||
}
|
||||
|
||||
public BigDecimal getDepositPaid() {
|
||||
return this.depositPaid;
|
||||
}
|
||||
|
||||
public void setDepositPaid(BigDecimal depositPaid) {
|
||||
this.depositPaid = depositPaid;
|
||||
}
|
||||
|
||||
public Date getDueDate() {
|
||||
return this.dueDate;
|
||||
}
|
||||
|
||||
public BigDecimal getDeposit() {
|
||||
return this.deposit;
|
||||
}
|
||||
|
||||
public boolean isCompleted() {
|
||||
return this.completed;
|
||||
}
|
||||
|
||||
public void setCompleted(boolean completed) {
|
||||
this.completed = completed;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ public class CalculateSavingScheduleImpl implements CalculateSavingSchedule {
|
||||
final SavingProduct savingProduct = this.savingProductRepository.findOne(command.getProductId());
|
||||
if (savingProduct == null) throw new SavingProductNotFoundException(command.getProductId());
|
||||
|
||||
final Integer depositFrequency = command.getPayEvery();
|
||||
final Integer depositFrequency = command.getDepositEvery();
|
||||
final PeriodFrequencyType depositFrequencyType = PeriodFrequencyType.fromInt(command.getPaymentFrequencyType());
|
||||
final LocalDate scheduleStartDate = command.getPaymentsStartingFromDate();
|
||||
@SuppressWarnings("unused")
|
||||
|
||||
+111
-16
@@ -11,7 +11,10 @@ import org.mifosplatform.portfolio.client.domain.Client;
|
||||
import org.mifosplatform.portfolio.client.domain.ClientRepository;
|
||||
import org.mifosplatform.portfolio.client.exception.ClientNotFoundException;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.CalculateSavingScheduleCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountApprovalCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountWithdrawalCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingScheduleData;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingSchedulePeriodData;
|
||||
import org.mifosplatform.portfolio.savingsaccount.domain.ReccuringDepositInterestCalculator;
|
||||
@@ -27,6 +30,7 @@ import org.mifosplatform.portfolio.savingsaccountproduct.exception.SavingProduct
|
||||
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositAccountStatus;
|
||||
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositLifecycleStateMachine;
|
||||
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositLifecycleStateMachineImpl;
|
||||
import org.mifosplatform.portfolio.savingsdepositaccount.exception.DepositAccountTransactionsException;
|
||||
import org.mifosplatform.portfolio.savingsdepositproduct.domain.TenureTypeEnum;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -70,28 +74,28 @@ public class SavingAccountAssembler {
|
||||
tenure = command.getTenure();
|
||||
}
|
||||
|
||||
TenureTypeEnum tenureTypeEnum = product.getSavingProductRelatedDetail().getTenureType();
|
||||
TenureTypeEnum tenureTypeEnum = TenureTypeEnum.fromInt(product.getSavingProductRelatedDetail().getTenureType());
|
||||
if (command.getTenureType() != null) {
|
||||
tenureTypeEnum = TenureTypeEnum.fromInt(command.getTenureType());
|
||||
}
|
||||
|
||||
SavingProductType savingProductType = product.getSavingProductRelatedDetail().getSavingProductType();
|
||||
SavingProductType savingProductType = SavingProductType.fromInt(product.getSavingProductRelatedDetail().getSavingProductType());
|
||||
if (command.getSavingProductType() != null) {
|
||||
savingProductType = SavingProductType.fromInt(command.getSavingProductType());
|
||||
}
|
||||
|
||||
SavingFrequencyType savingFrequencyType = product.getSavingProductRelatedDetail().getFrequency();
|
||||
SavingFrequencyType savingFrequencyType = SavingFrequencyType.fromInt(product.getSavingProductRelatedDetail().getFrequency());
|
||||
if (command.getFrequency() != null) {
|
||||
savingFrequencyType = SavingFrequencyType.fromInt(command.getFrequency());
|
||||
}
|
||||
|
||||
SavingInterestCalculationMethod savingInterestCalculationMethod = product.getSavingProductRelatedDetail()
|
||||
.getInterestCalculationMethod();
|
||||
SavingInterestCalculationMethod savingInterestCalculationMethod = SavingInterestCalculationMethod.fromInt(product.getSavingProductRelatedDetail()
|
||||
.getInterestCalculationMethod());
|
||||
if (command.getInterestCalculationMethod() != null) {
|
||||
savingInterestCalculationMethod = SavingInterestCalculationMethod.fromInt(command.getInterestCalculationMethod());
|
||||
}
|
||||
|
||||
SavingsInterestType interestType = product.getSavingProductRelatedDetail().getInterestType();
|
||||
SavingsInterestType interestType = SavingsInterestType.fromInt(product.getSavingProductRelatedDetail().getInterestType());
|
||||
if (command.getInterestType() != null) {
|
||||
interestType = SavingsInterestType.fromInt(command.getInterestType());
|
||||
}
|
||||
@@ -110,17 +114,21 @@ public class SavingAccountAssembler {
|
||||
lockinPeriod = command.getLockinPeriod();
|
||||
}
|
||||
|
||||
PeriodFrequencyType lockinPeriodType = product.getSavingProductRelatedDetail().getLockinPeriodType();
|
||||
PeriodFrequencyType lockinPeriodType = PeriodFrequencyType.fromInt(product.getSavingProductRelatedDetail().getLockinPeriodType());
|
||||
if (command.getLockinPeriodType() != null) {
|
||||
lockinPeriodType = PeriodFrequencyType.fromInt(command.getLockinPeriodType());
|
||||
}
|
||||
|
||||
Integer payEvery = command.getPayEvery();
|
||||
Integer depositEvery = command.getDepositEvery();
|
||||
|
||||
Integer interestPostEvery = command.getInterestPostEvery();
|
||||
|
||||
Integer interestPostFrequency =command.getInterestPostFrequency();
|
||||
|
||||
SavingAccount account = SavingAccount.openNew(client, product, command.getExternalId(), savingsDeposit, reccuringInterestRate,
|
||||
savingInterestRate, tenure, command.getCommencementDate(), tenureTypeEnum, savingProductType, savingFrequencyType,
|
||||
interestType, savingInterestCalculationMethod, isLockinPeriodAllowed, lockinPeriod, lockinPeriodType,
|
||||
this.reccuringDepositInterestCalculator, defaultDepositLifecycleStateMachine(),payEvery);
|
||||
this.reccuringDepositInterestCalculator, defaultDepositLifecycleStateMachine(),depositEvery,interestPostEvery, interestPostFrequency);
|
||||
|
||||
SavingScheduleData savingScheduleData = this.calculateSavingSchedule.calculateSavingSchedule(command
|
||||
.toCalculateSavingScheduleCommand());
|
||||
@@ -163,22 +171,22 @@ public class SavingAccountAssembler {
|
||||
commencementDate = command.getCommencementDate();
|
||||
}
|
||||
|
||||
TenureTypeEnum tenureTypeEnum = account.getTenureType();
|
||||
TenureTypeEnum tenureTypeEnum = TenureTypeEnum.fromInt(account.getTenureType());
|
||||
if (command.isTenureTypeEnumChanged()) {
|
||||
tenureTypeEnum = TenureTypeEnum.fromInt(command.getTenureType());
|
||||
}
|
||||
|
||||
SavingProductType savingProductType = account.getSavingProductType();
|
||||
SavingProductType savingProductType = SavingProductType.fromInt(account.getSavingProductType());
|
||||
if (command.isSavingProductTypeChanged()) {
|
||||
savingProductType = SavingProductType.fromInt(command.getSavingProductType());
|
||||
}
|
||||
|
||||
SavingFrequencyType savingFrequencyType = account.getFrequency();
|
||||
SavingFrequencyType savingFrequencyType = SavingFrequencyType.fromInt(account.getFrequency());
|
||||
if (command.isSavingFrequencyTypeChanged()) {
|
||||
savingFrequencyType = SavingFrequencyType.fromInt(command.getFrequency());
|
||||
}
|
||||
|
||||
SavingInterestCalculationMethod savingInterestCalculationMethod = account.getInterestCalculationMethod();
|
||||
SavingInterestCalculationMethod savingInterestCalculationMethod = SavingInterestCalculationMethod.fromInt(account.getInterestCalculationMethod());
|
||||
if (command.isSavingInterestCalculationMethodChanged()) {
|
||||
savingInterestCalculationMethod = SavingInterestCalculationMethod.fromInt(command.getInterestCalculationMethod());
|
||||
}
|
||||
@@ -203,14 +211,14 @@ public class SavingAccountAssembler {
|
||||
lockinPeriod = command.getLockinPeriod();
|
||||
}
|
||||
|
||||
PeriodFrequencyType lockinPeriodType = account.getLockinPeriodType();
|
||||
PeriodFrequencyType lockinPeriodType = PeriodFrequencyType.fromInt(account.getLockinPeriodType());
|
||||
if (command.isLockinPeriodTypeChanged()) {
|
||||
lockinPeriodType = PeriodFrequencyType.fromInt(command.getLockinPeriodType());
|
||||
}
|
||||
|
||||
Integer payEvery = account.getPayEvery();
|
||||
if(command.isPayEveryChanged()){
|
||||
payEvery = command.getPayEvery();
|
||||
if(command.isDepositEveryChanged()){
|
||||
payEvery = command.getDepositEvery();
|
||||
}
|
||||
account.modifyAccount(product, externalId, savingsDeposit, reccuringInterestRate, savingInterestRate, tenure, commencementDate,
|
||||
tenureTypeEnum, savingProductType, savingFrequencyType, savingInterestCalculationMethod, isLockinPeriodAllowed,
|
||||
@@ -223,4 +231,91 @@ public class SavingAccountAssembler {
|
||||
return new DepositLifecycleStateMachineImpl(allowedDepositStatuses);
|
||||
}
|
||||
|
||||
public void approveSavingAccount(SavingAccountApprovalCommand command, SavingAccount account) {
|
||||
|
||||
LocalDate approvalDate = account.projectedCommencementDate();
|
||||
if (command.getApprovalDate() != null) {
|
||||
approvalDate = command.getApprovalDate();
|
||||
}
|
||||
|
||||
BigDecimal savingsDepositAmountPerPeriod=account.getSavingsDepositAmountPerPeriod();
|
||||
if (command.getDepositAmountPerPeriod() != null) {
|
||||
savingsDepositAmountPerPeriod = command.getDepositAmountPerPeriod();
|
||||
}
|
||||
|
||||
BigDecimal recurringInterestRate = account.getReccuringInterestRate();
|
||||
if (command.getRecurringInterestRate() != null) {
|
||||
recurringInterestRate = command.getRecurringInterestRate();
|
||||
}
|
||||
|
||||
BigDecimal savingInterestRate = account.getSavingInterestRate();
|
||||
if (command.getSavingInterestRate() != null) {
|
||||
savingInterestRate = command.getSavingInterestRate();
|
||||
}
|
||||
|
||||
Integer interestType = account.getInterestType();
|
||||
if (command.getInterestType() != null) {
|
||||
interestType = SavingsInterestType.fromInt(command.getInterestType()).getValue();
|
||||
}
|
||||
|
||||
Integer tenure = account.getTenure();
|
||||
if (command.getTenure() != null) {
|
||||
tenure = command.getTenure();
|
||||
}
|
||||
|
||||
Integer tenureType = account.getTenureType();
|
||||
if (command.getTenureType() != null) {
|
||||
tenureType = TenureTypeEnum.fromInt(command.getTenureType()).getValue();
|
||||
}
|
||||
|
||||
Integer frequency = account.getFrequency();
|
||||
if (command.getDepositFrequencyType() != null) {
|
||||
frequency = SavingFrequencyType.fromInt(command.getDepositFrequencyType()).getValue();
|
||||
}
|
||||
|
||||
Integer payEvery = account.getPayEvery();
|
||||
if (command.getDepositEvery() != null) {
|
||||
payEvery = command.getDepositEvery();
|
||||
}
|
||||
|
||||
Integer interestPostEvery = account.getInterestPostEvery();
|
||||
if (command.getInterestPostEvery() != null) {
|
||||
interestPostEvery = command.getInterestPostEvery();
|
||||
}
|
||||
Integer interestPostFrequency =account.getInterestPostFrequency();
|
||||
if (command.getInterestPostFrequency() != null) {
|
||||
interestPostFrequency = command.getInterestPostFrequency();
|
||||
}
|
||||
|
||||
account.approveSavingAccount(approvalDate, savingsDepositAmountPerPeriod, recurringInterestRate, savingInterestRate, interestType,
|
||||
tenure, tenureType, frequency, payEvery,defaultDepositLifecycleStateMachine(),this.reccuringDepositInterestCalculator, interestPostEvery, interestPostFrequency);
|
||||
|
||||
|
||||
CalculateSavingScheduleCommand calculateSavingScheduleCommand = new CalculateSavingScheduleCommand(account.getProduct().getId(), savingsDepositAmountPerPeriod, payEvery,
|
||||
frequency, recurringInterestRate, approvalDate, tenure,interestPostEvery,interestPostFrequency);
|
||||
|
||||
SavingScheduleData savingScheduleData = this.calculateSavingSchedule.calculateSavingSchedule(calculateSavingScheduleCommand);
|
||||
for (SavingSchedulePeriodData savingSchedulePeriodData : savingScheduleData.getPeriods()) {
|
||||
|
||||
final SavingScheduleInstallments installment = new SavingScheduleInstallments(account, savingSchedulePeriodData.getDueDate()
|
||||
.toDate(), savingSchedulePeriodData.getPeriod(), savingSchedulePeriodData.getDepositDue());
|
||||
account.addSavingScheduleInstallment(installment);
|
||||
}
|
||||
}
|
||||
|
||||
public void withdrawSavingAccountMoney( SavingAccountWithdrawalCommand command, SavingAccount account) {
|
||||
|
||||
if (command.getAmount().doubleValue() > account.getOutstandingAmount().doubleValue()) {
|
||||
throw new DepositAccountTransactionsException("deposit.transaction.interest.withdrawal.exceed", "You can Withdraw "
|
||||
+ account.getOutstandingAmount() + " only");
|
||||
}
|
||||
|
||||
account.withdrawAmount(command.getAmount(),command.getTransactionDate());
|
||||
|
||||
}
|
||||
|
||||
public void postInterest(SavingAccount account) {
|
||||
account.postInterest(this.reccuringDepositInterestCalculator);
|
||||
}
|
||||
|
||||
}
|
||||
+13
@@ -1,8 +1,13 @@
|
||||
package org.mifosplatform.portfolio.savingsaccount.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
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.SavingPermissionData;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingScheduleData;
|
||||
|
||||
public interface SavingAccountReadPlatformService {
|
||||
|
||||
@@ -11,4 +16,12 @@ public interface SavingAccountReadPlatformService {
|
||||
SavingAccountData retrieveSavingsAccount(Long accountId);
|
||||
|
||||
SavingAccountData retrieveNewSavingsAccountDetails(Long clientId, Long productId);
|
||||
|
||||
SavingPermissionData retrieveSavingAccountPermissions(SavingAccountData data);
|
||||
|
||||
BigDecimal deriveSavingDueAmount(SavingAccountData account);
|
||||
|
||||
SavingScheduleData retrieveSavingsAccountSchedule(Long accountId, CurrencyData currencyData);
|
||||
|
||||
Collection<SavingAccountForLookup> retrieveSavingAccountsForLookUp();
|
||||
}
|
||||
|
||||
+106
-2
@@ -4,8 +4,10 @@ import java.math.BigDecimal;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.Months;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
||||
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
|
||||
@@ -14,11 +16,16 @@ import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
||||
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.SavingPermissionData;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingScheduleData;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingSchedulePeriodData;
|
||||
import org.mifosplatform.portfolio.savingsaccountproduct.data.SavingProductData;
|
||||
import org.mifosplatform.portfolio.savingsaccountproduct.data.SavingProductLookup;
|
||||
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.savingsdepositproduct.domain.TenureTypeEnum;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
@@ -58,6 +65,7 @@ public class SavingAccountReadPlatformServiceImpl implements SavingAccountReadPl
|
||||
SavingAccountMapper mapper = new SavingAccountMapper();
|
||||
String sql = "select " + mapper.schema() + " where sa.id = ? and sa.is_deleted=0";
|
||||
SavingAccountData savingAccountData = this.jdbcTemplate.queryForObject(sql, mapper, new Object[] { accountId });
|
||||
|
||||
return savingAccountData;
|
||||
}
|
||||
|
||||
@@ -73,7 +81,7 @@ public class SavingAccountReadPlatformServiceImpl implements SavingAccountReadPl
|
||||
+ " sa.projected_commencement_date AS projectedCommencementDate, sa.actual_commencement_date AS actualCommencementDate,"
|
||||
+ " sa.matures_on_date AS maturesOnDate, sa.projected_interest_accrued_on_maturity AS projectedInterestAccuredOnMaturity,"
|
||||
+ " sa.actual_interest_accrued AS actualInterestAccured, sa.projected_total_maturity_amount AS projectedTotalMaturityAmount,"
|
||||
+ " sa.actual_total_amount AS actualTotalAmount, sa.is_preclosure_allowed AS isPreclosureAllowed,"
|
||||
+ " sa.actual_total_amount AS actualTotalAmount, sa.is_preclosure_allowed AS isPreclosureAllowed, sa.outstanding_amount as outstandingAmount, "
|
||||
+ " 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, "
|
||||
@@ -131,6 +139,7 @@ public class SavingAccountReadPlatformServiceImpl implements SavingAccountReadPl
|
||||
|
||||
boolean preClosureAllowed = rs.getBoolean("isPreclosureAllowed");
|
||||
BigDecimal preClosureInterestRate = rs.getBigDecimal("preClosureInterestRate");
|
||||
BigDecimal outstandingAmount = rs.getBigDecimal("outstandingAmount");
|
||||
|
||||
LocalDate withdrawnonDate = JdbcSupport.getLocalDate(rs, "withdrawnonDate");
|
||||
LocalDate rejectedonDate = JdbcSupport.getLocalDate(rs, "rejectedonDate");
|
||||
@@ -147,7 +156,7 @@ public class SavingAccountReadPlatformServiceImpl implements SavingAccountReadPl
|
||||
interestType, interestCalculationMethod, tenure, tenureType, projectedCommencementDate, actualCommencementDate,
|
||||
maturesOnDate, projectedInterestAccuredOnMaturity, actualInterestAccured, projectedMaturityAmount,
|
||||
actualMaturityAmount, preClosureAllowed, preClosureInterestRate, withdrawnonDate, rejectedonDate, closedonDate,
|
||||
isLockinPeriodAllowed, lockinPeriod, lockinPeriodType,depositEvery);
|
||||
isLockinPeriodAllowed, lockinPeriod, lockinPeriodType,depositEvery,outstandingAmount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,4 +197,99 @@ public class SavingAccountReadPlatformServiceImpl implements SavingAccountReadPl
|
||||
return match;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavingPermissionData retrieveSavingAccountPermissions(SavingAccountData savingAccountData) {
|
||||
boolean pendingApproval = (savingAccountData.getStatus().getId().equals(100L));
|
||||
boolean undoApprovalAllowed = (savingAccountData.getStatus().getId().equals(300L));
|
||||
boolean renewelAllowed = false;
|
||||
if (savingAccountData.getMaturesOnDate() != null && savingAccountData.getTenureType().equals(TenureTypeEnum.FIXED_PERIOD)) {
|
||||
if (new LocalDate().isAfter(savingAccountData.getMaturesOnDate())) {
|
||||
renewelAllowed = true;
|
||||
}
|
||||
}
|
||||
boolean rejectAllowed = pendingApproval;
|
||||
boolean withdrawnByApplicantAllowed = pendingApproval;
|
||||
boolean isMaturedDepositAccount = (savingAccountData.getStatus().getId().equals(700L));
|
||||
return new SavingPermissionData(rejectAllowed, withdrawnByApplicantAllowed, undoApprovalAllowed, pendingApproval, renewelAllowed, isMaturedDepositAccount);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public BigDecimal deriveSavingDueAmount(SavingAccountData account) {
|
||||
|
||||
BigDecimal dueAmount = BigDecimal.ZERO;
|
||||
EnumOptionData status = account.getStatus();
|
||||
LocalDate date = account.getActualCommencementDate();
|
||||
|
||||
if (account.getStatus() != null && account.getActualCommencementDate() != null) {
|
||||
BigDecimal amountPerPeriod = account.getSavingsDepostiAmountPerPeriod();
|
||||
Integer tenure = account.getTenure();
|
||||
Integer depositEvery = account.getDepositEvery();
|
||||
Integer noOfPeriods = tenure/depositEvery ;
|
||||
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()));
|
||||
|
||||
}
|
||||
|
||||
return dueAmount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavingScheduleData retrieveSavingsAccountSchedule(Long accountId, CurrencyData currency) {
|
||||
this.context.authenticatedUser();
|
||||
SavingAccountScheduleMapper mapper = new SavingAccountScheduleMapper();
|
||||
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;
|
||||
for(SavingSchedulePeriodData data : periods){
|
||||
cumulativeDepositDue = cumulativeDepositDue.add(data.getDepositDue()).subtract(data.getDepositPaid());
|
||||
}
|
||||
SavingScheduleData scheduleData = new SavingScheduleData(currency, cumulativeDepositDue, periods);
|
||||
return scheduleData;
|
||||
}
|
||||
|
||||
public static final class SavingAccountScheduleMapper implements RowMapper<SavingSchedulePeriodData> {
|
||||
|
||||
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";
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavingSchedulePeriodData mapRow(ResultSet rs, @SuppressWarnings("unused") int rowNum) throws SQLException {
|
||||
|
||||
LocalDate dueDate = JdbcSupport.getLocalDate(rs, "dueDate");
|
||||
Integer installment = JdbcSupport.getInteger(rs, "installment");
|
||||
BigDecimal depositDue = rs.getBigDecimal("deposit");
|
||||
BigDecimal depositPaid = rs.getBigDecimal("depositPaid");
|
||||
|
||||
return new SavingSchedulePeriodData(installment, dueDate, depositDue, depositPaid);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SavingAccountForLookup> retrieveSavingAccountsForLookUp() {
|
||||
SavingAccountLookupMapper mapper = new SavingAccountLookupMapper();
|
||||
String sql = "select "+ mapper.schema();
|
||||
return this.jdbcTemplate.query(sql, mapper, new Object[] {});
|
||||
}
|
||||
|
||||
private static final class SavingAccountLookupMapper implements RowMapper<SavingAccountForLookup> {
|
||||
|
||||
public String schema(){
|
||||
return " sa.id as id from m_saving_account sa where sa.is_deleted=0 and sa.status_enum=300";
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavingAccountForLookup mapRow(ResultSet rs, @SuppressWarnings("unused") int rowNum) throws SQLException {
|
||||
Long id = rs.getLong("id");
|
||||
return new SavingAccountForLookup(id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+32
@@ -1,7 +1,15 @@
|
||||
package org.mifosplatform.portfolio.savingsaccount.service;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.mifosplatform.portfolio.loanaccount.command.UndoStateTransitionCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountApprovalCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountDepositCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountWithdrawalCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingStateTransitionsCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountForLookup;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
|
||||
public interface SavingAccountWritePlatformService {
|
||||
@@ -11,4 +19,28 @@ public interface SavingAccountWritePlatformService {
|
||||
|
||||
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'UPDATE_SAVINGSACCOUNT')")
|
||||
CommandProcessingResult updateSavingAccount(SavingAccountCommand command);
|
||||
|
||||
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER')")
|
||||
CommandProcessingResult rejectSavingApplication(SavingStateTransitionsCommand command);
|
||||
|
||||
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER')")
|
||||
CommandProcessingResult withdrawSavingApplication(SavingStateTransitionsCommand command);
|
||||
|
||||
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER')")
|
||||
CommandProcessingResult undoSavingAccountApproval(UndoStateTransitionCommand undoCommand);
|
||||
|
||||
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER')")
|
||||
CommandProcessingResult approveSavingAccount(SavingAccountApprovalCommand command);
|
||||
|
||||
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER')")
|
||||
CommandProcessingResult depositMoney(SavingAccountDepositCommand command);
|
||||
|
||||
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER')")
|
||||
CommandProcessingResult withdrawSavingAmount(SavingAccountWithdrawalCommand command);
|
||||
|
||||
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER')")
|
||||
CommandProcessingResult deleteSavingAccount(Long accountId);
|
||||
|
||||
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER')")
|
||||
CommandProcessingResult postInterest(Collection<SavingAccountForLookup> savingAccounts);
|
||||
}
|
||||
+190
-1
@@ -1,14 +1,34 @@
|
||||
package org.mifosplatform.portfolio.savingsaccount.service;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bouncycastle.crypto.RuntimeCryptoException;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.mifosplatform.portfolio.client.domain.Note;
|
||||
import org.mifosplatform.portfolio.client.domain.NoteRepository;
|
||||
import org.mifosplatform.portfolio.loanaccount.command.UndoStateTransitionCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountApprovalCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountApprovalCommandValidator;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountCommandValidator;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountDepositCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountDepositCommandValidator;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountStateTransitionCommandValidator;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountWithdrawalCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.command.SavingStateTransitionsCommand;
|
||||
import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountForLookup;
|
||||
import org.mifosplatform.portfolio.savingsaccount.domain.SavingAccount;
|
||||
import org.mifosplatform.portfolio.savingsaccount.domain.SavingAccountRepository;
|
||||
import org.mifosplatform.portfolio.savingsaccount.exception.SavingAccountNotFoundException;
|
||||
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositAccountStatus;
|
||||
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositLifecycleStateMachine;
|
||||
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositLifecycleStateMachineImpl;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -24,7 +44,6 @@ public class SavingAccountWritePlatformServiceJpaRepositoryImpl implements Savin
|
||||
private final PlatformSecurityContext context;
|
||||
private final SavingAccountRepository savingAccountRepository;
|
||||
private final SavingAccountAssembler savingAccountAssembler;
|
||||
@SuppressWarnings("unused")
|
||||
private final NoteRepository noteRepository;
|
||||
|
||||
@Autowired
|
||||
@@ -91,4 +110,174 @@ public class SavingAccountWritePlatformServiceJpaRepositoryImpl implements Savin
|
||||
throw new PlatformDataIntegrityException("error.msg.saving.account.unknown.data.integrity.issue",
|
||||
"Unknown data integrity issue with resource.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult rejectSavingApplication(SavingStateTransitionsCommand command) {
|
||||
|
||||
this.context.authenticatedUser();
|
||||
|
||||
SavingAccountStateTransitionCommandValidator validator = new SavingAccountStateTransitionCommandValidator(command);
|
||||
validator.validate();
|
||||
|
||||
SavingAccount account = this.savingAccountRepository.findOne(command.getAccountId());
|
||||
if (account == null || account.isDeleted()) {
|
||||
throw new SavingAccountNotFoundException(command.getAccountId());
|
||||
}
|
||||
LocalDate eventDate = command.getEventDate();
|
||||
account.reject(eventDate, defaultDepositLifecycleStateMachine());
|
||||
this.savingAccountRepository.save(account);
|
||||
|
||||
String noteText = command.getNote();
|
||||
if (StringUtils.isNotBlank(noteText)) {
|
||||
Note note = Note.savingNote(account, noteText);
|
||||
this.noteRepository.save(note);
|
||||
}
|
||||
|
||||
return new CommandProcessingResult(account.getId());
|
||||
}
|
||||
|
||||
private DepositLifecycleStateMachine defaultDepositLifecycleStateMachine() {
|
||||
List<DepositAccountStatus> allowedDepositStatuses = Arrays.asList(DepositAccountStatus.values());
|
||||
return new DepositLifecycleStateMachineImpl(allowedDepositStatuses);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult withdrawSavingApplication(SavingStateTransitionsCommand command) {
|
||||
this.context.authenticatedUser();
|
||||
|
||||
SavingAccountStateTransitionCommandValidator validator = new SavingAccountStateTransitionCommandValidator(command);
|
||||
validator.validate();
|
||||
|
||||
SavingAccount account = this.savingAccountRepository.findOne(command.getAccountId());
|
||||
if (account == null || account.isDeleted()) {
|
||||
throw new SavingAccountNotFoundException(command.getAccountId());
|
||||
}
|
||||
LocalDate eventDate = command.getEventDate();
|
||||
account.withdrawnByApplicant(eventDate, defaultDepositLifecycleStateMachine());
|
||||
this.savingAccountRepository.save(account);
|
||||
|
||||
String noteText = command.getNote();
|
||||
if (StringUtils.isNotBlank(noteText)) {
|
||||
Note note = Note.savingNote(account, noteText);
|
||||
this.noteRepository.save(note);
|
||||
}
|
||||
|
||||
return new CommandProcessingResult(account.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult undoSavingAccountApproval(UndoStateTransitionCommand command) {
|
||||
|
||||
this.context.authenticatedUser();
|
||||
SavingAccount account = this.savingAccountRepository.findOne(command.getLoanId());
|
||||
if (account == null || account.isDeleted()) {
|
||||
throw new SavingAccountNotFoundException(command.getLoanId());
|
||||
}
|
||||
account.undoSavingAccountApproval(defaultDepositLifecycleStateMachine());
|
||||
this.savingAccountRepository.save(account);
|
||||
|
||||
String noteText = command.getNote();
|
||||
if (StringUtils.isNotBlank(noteText)) {
|
||||
Note note = Note.savingNote(account, noteText);
|
||||
this.noteRepository.save(note);
|
||||
}
|
||||
|
||||
return new CommandProcessingResult(account.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult approveSavingAccount(SavingAccountApprovalCommand command) {
|
||||
|
||||
this.context.authenticatedUser();
|
||||
SavingAccountApprovalCommandValidator validator = new SavingAccountApprovalCommandValidator(command);
|
||||
validator.validate();
|
||||
SavingAccount account = this.savingAccountRepository.findOne(command.getAccountId());
|
||||
if (account == null || account.isDeleted()) {
|
||||
throw new SavingAccountNotFoundException(command.getAccountId());
|
||||
}
|
||||
LocalDate approvalDate = command.getApprovalDate();
|
||||
if (approvalDate.isBefore(account.projectedCommencementDate())) {
|
||||
throw new RuntimeCryptoException("Date of approval cannot before application submission date");
|
||||
}
|
||||
this.savingAccountAssembler.approveSavingAccount(command,account);
|
||||
this.savingAccountRepository.save(account);
|
||||
|
||||
String noteText = command.getNote();
|
||||
if (StringUtils.isNotBlank(noteText)) {
|
||||
Note note = Note.savingNote(account, noteText);
|
||||
this.noteRepository.save(note);
|
||||
}
|
||||
|
||||
return new CommandProcessingResult(account.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult depositMoney(SavingAccountDepositCommand command) {
|
||||
|
||||
this.context.authenticatedUser();
|
||||
SavingAccountDepositCommandValidator validator = new SavingAccountDepositCommandValidator(command);
|
||||
validator.validate();
|
||||
|
||||
SavingAccount account = this.savingAccountRepository.findOne(command.getAccountId());
|
||||
if (account == null || account.isDeleted()) {
|
||||
throw new SavingAccountNotFoundException(command.getAccountId());
|
||||
}
|
||||
|
||||
if (account.isActive())
|
||||
account.depositMoney(command);
|
||||
this.savingAccountRepository.save(account);
|
||||
String noteText = command.getNote();
|
||||
if (StringUtils.isNotBlank(noteText)) {
|
||||
Note note = Note.savingNote(account, noteText);
|
||||
this.noteRepository.save(note);
|
||||
}
|
||||
return new CommandProcessingResult(account.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult withdrawSavingAmount(SavingAccountWithdrawalCommand command) {
|
||||
|
||||
this.context.authenticatedUser();
|
||||
SavingAccount account = this.savingAccountRepository.findOne(command.getAccountId());
|
||||
if (account == null || account.isDeleted()) {
|
||||
throw new SavingAccountNotFoundException(command.getAccountId());
|
||||
}
|
||||
if (account.isActive())
|
||||
this.savingAccountAssembler.withdrawSavingAccountMoney(command,account);
|
||||
this.savingAccountRepository.save(account);
|
||||
String noteText = command.getNote();
|
||||
if (StringUtils.isNotBlank(noteText)) {
|
||||
Note note = Note.savingNote(account, noteText);
|
||||
this.noteRepository.save(note);
|
||||
}
|
||||
return new CommandProcessingResult(account.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult deleteSavingAccount(Long accountId) {
|
||||
this.context.authenticatedUser();
|
||||
SavingAccount account = this.savingAccountRepository.findOne(accountId);
|
||||
if (account == null || account.isDeleted()) {
|
||||
throw new SavingAccountNotFoundException(accountId);
|
||||
}
|
||||
account.delete();
|
||||
this.savingAccountRepository.save(account);
|
||||
return new CommandProcessingResult(accountId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult postInterest(Collection<SavingAccountForLookup> savingAccounts) {
|
||||
this.context.authenticatedUser();
|
||||
try {
|
||||
for(SavingAccountForLookup accountForLookup : savingAccounts ){
|
||||
SavingAccount account = this.savingAccountRepository.findOne(accountForLookup.getId());
|
||||
if (account == null || account.isDeleted()) { throw new SavingAccountNotFoundException(accountForLookup.getId()); }
|
||||
this.savingAccountAssembler.postInterest(account);
|
||||
this.savingAccountRepository.save(account);
|
||||
}
|
||||
return new CommandProcessingResult(new Long(savingAccounts.size()));
|
||||
} catch (Exception e) {
|
||||
return new CommandProcessingResult(Long.valueOf(-1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -173,7 +173,7 @@ public class SavingProductsApiResource {
|
||||
"savingFrequencyOptions", "savingsInterestTypeOptions", "lockinPeriodTypeOptions", "interestCalculationOptions"));
|
||||
List<CurrencyData> currencyOptions = this.currencyReadPlatformService.retrieveAllowedCurrencies();
|
||||
|
||||
EnumOptionData reccuring = SavingProductEnumerations.savingProductType(SavingProductType.RECCURING);
|
||||
EnumOptionData reccuring = SavingProductEnumerations.savingProductType(SavingProductType.RECURRING);
|
||||
EnumOptionData regular = SavingProductEnumerations.savingProductType(SavingProductType.REGULAR);
|
||||
List<EnumOptionData> savingsProductTypeOptions = Arrays.asList(reccuring, regular);
|
||||
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ public class SavingProductData implements Serializable {
|
||||
this.currency = new CurrencyData("USD", "US Dollar", 2, "$", "currency.USD");
|
||||
this.digitsAfterDecimal = Integer.valueOf(2);
|
||||
this.savingsDepositAmount = BigDecimal.ZERO;
|
||||
this.savingProductType = SavingProductEnumerations.savingProductType(SavingProductType.RECCURING);
|
||||
this.savingProductType = SavingProductEnumerations.savingProductType(SavingProductType.RECURRING);
|
||||
this.tenureType = SavingProductEnumerations.tenureTypeEnum(TenureTypeEnum.FIXED_PERIOD);
|
||||
this.tenure = Integer.valueOf(12);
|
||||
this.savingFrequencyType = SavingProductEnumerations.interestFrequencyType(SavingFrequencyType.MONTHLY);
|
||||
|
||||
+8
@@ -40,4 +40,12 @@ public enum SavingInterestCalculationMethod {
|
||||
}
|
||||
return savingInterestCalculationMethod;
|
||||
}
|
||||
|
||||
public boolean isAverageBalance() {
|
||||
return this.value.equals(SavingInterestCalculationMethod.AVERAGEBAL.value);
|
||||
}
|
||||
|
||||
public boolean isMonthlyCollection() {
|
||||
return this.value.equals(SavingInterestCalculationMethod.MONTHLYCOLLECTION.value);
|
||||
}
|
||||
}
|
||||
|
||||
+24
-24
@@ -35,22 +35,22 @@ public class SavingProductRelatedDetail {
|
||||
private Integer depositEvery;
|
||||
|
||||
@Column(name = "savings_product_type", nullable = false)
|
||||
private SavingProductType savingProductType;
|
||||
private Integer savingProductType;
|
||||
|
||||
@Column(name = "tenure_type", nullable = false)
|
||||
private TenureTypeEnum tenureType;
|
||||
private Integer tenureType;
|
||||
|
||||
@Column(name = "tenure", nullable = false)
|
||||
private Integer tenure;
|
||||
|
||||
@Column(name = "frequency", nullable = false)
|
||||
private SavingFrequencyType frequency;
|
||||
private Integer frequency;
|
||||
|
||||
@Column(name = "interest_type", nullable = false)
|
||||
private SavingsInterestType interestType;
|
||||
private Integer interestType;
|
||||
|
||||
@Column(name = "interest_calculation_method")
|
||||
private SavingInterestCalculationMethod interestCalculationMethod;
|
||||
private Integer interestCalculationMethod;
|
||||
|
||||
@Column(name = "min_bal_for_withdrawal", scale = 6, precision = 19, nullable = false)
|
||||
private BigDecimal minimumBalanceForWithdrawal;
|
||||
@@ -65,7 +65,7 @@ public class SavingProductRelatedDetail {
|
||||
private Integer lockinPeriod;
|
||||
|
||||
@Column(name = "lock_in_period_type", nullable = false)
|
||||
private PeriodFrequencyType lockinPeriodType;
|
||||
private Integer lockinPeriodType;
|
||||
|
||||
public SavingProductRelatedDetail() {
|
||||
this.interestRate = null;
|
||||
@@ -84,17 +84,17 @@ public class SavingProductRelatedDetail {
|
||||
this.maxInterestRate = maxInterestRate;
|
||||
this.savingsDepositAmount = savingsDepositAmount;
|
||||
this.depositEvery=depositEvery;
|
||||
this.savingProductType = savingProductType;
|
||||
this.tenureType = tenureType;
|
||||
this.savingProductType = savingProductType.getValue();
|
||||
this.tenureType = tenureType.getValue();
|
||||
this.tenure = tenure;
|
||||
this.frequency = frequency;
|
||||
this.interestType = interestType;
|
||||
this.interestCalculationMethod = interestCalculationMethod;
|
||||
this.frequency = frequency.getValue();
|
||||
this.interestType = interestType.getValue();
|
||||
this.interestCalculationMethod = interestCalculationMethod.getValue();
|
||||
this.minimumBalanceForWithdrawal = minimumBalanceForWithdrawal;
|
||||
this.isPartialDepositAllowed = isPartialDepositAllowed;
|
||||
this.isLockinPeriodAllowed = isLockinPeriodAllowed;
|
||||
this.lockinPeriod = lockinPeriod;
|
||||
this.lockinPeriodType = lockinPeriodType;
|
||||
this.lockinPeriodType = lockinPeriodType.getValue();
|
||||
}
|
||||
|
||||
public MonetaryCurrency getCurrency() {
|
||||
@@ -137,11 +137,11 @@ public class SavingProductRelatedDetail {
|
||||
}
|
||||
|
||||
if (command.isSavingProductTypeChanged()) {
|
||||
this.savingProductType = SavingProductType.fromInt(command.getSavingProductType());
|
||||
this.savingProductType = SavingProductType.fromInt(command.getSavingProductType()).getValue();
|
||||
}
|
||||
|
||||
if (command.isTenureTypeChanged()) {
|
||||
this.tenureType = TenureTypeEnum.fromInt(command.getTenureType());
|
||||
this.tenureType = TenureTypeEnum.fromInt(command.getTenureType()).getValue();
|
||||
}
|
||||
|
||||
if (command.isTenureChanged()) {
|
||||
@@ -149,15 +149,15 @@ public class SavingProductRelatedDetail {
|
||||
}
|
||||
|
||||
if (command.isFrequencyChanged()) {
|
||||
this.frequency = SavingFrequencyType.fromInt(command.getFrequency());
|
||||
this.frequency = SavingFrequencyType.fromInt(command.getFrequency()).getValue();
|
||||
}
|
||||
|
||||
if (command.isInterestTypeChanged()) {
|
||||
this.interestType = SavingsInterestType.fromInt(command.getInterestType());
|
||||
this.interestType = SavingsInterestType.fromInt(command.getInterestType()).getValue();
|
||||
}
|
||||
|
||||
if (command.isInterestCalculationMethodChanged()) {
|
||||
this.interestCalculationMethod = SavingInterestCalculationMethod.fromInt(command.getInterestCalculationMethod());
|
||||
this.interestCalculationMethod = SavingInterestCalculationMethod.fromInt(command.getInterestCalculationMethod()).getValue();
|
||||
}
|
||||
|
||||
if (command.isMinimumBalanceForWithdrawalChanged()) {
|
||||
@@ -177,7 +177,7 @@ public class SavingProductRelatedDetail {
|
||||
}
|
||||
|
||||
if (command.isLockinPeriodTypeChanged()) {
|
||||
this.lockinPeriodType = PeriodFrequencyType.fromInt(command.getLockinPeriodType());
|
||||
this.lockinPeriodType = PeriodFrequencyType.fromInt(command.getLockinPeriodType()).getValue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,11 +189,11 @@ public class SavingProductRelatedDetail {
|
||||
return this.depositEvery;
|
||||
}
|
||||
|
||||
public SavingProductType getSavingProductType() {
|
||||
public Integer getSavingProductType() {
|
||||
return savingProductType;
|
||||
}
|
||||
|
||||
public TenureTypeEnum getTenureType() {
|
||||
public Integer getTenureType() {
|
||||
return tenureType;
|
||||
}
|
||||
|
||||
@@ -201,15 +201,15 @@ public class SavingProductRelatedDetail {
|
||||
return tenure;
|
||||
}
|
||||
|
||||
public SavingFrequencyType getFrequency() {
|
||||
public Integer getFrequency() {
|
||||
return frequency;
|
||||
}
|
||||
|
||||
public SavingsInterestType getInterestType() {
|
||||
public Integer getInterestType() {
|
||||
return interestType;
|
||||
}
|
||||
|
||||
public SavingInterestCalculationMethod getInterestCalculationMethod() {
|
||||
public Integer getInterestCalculationMethod() {
|
||||
return interestCalculationMethod;
|
||||
}
|
||||
|
||||
@@ -229,7 +229,7 @@ public class SavingProductRelatedDetail {
|
||||
return lockinPeriod;
|
||||
}
|
||||
|
||||
public PeriodFrequencyType getLockinPeriodType() {
|
||||
public Integer getLockinPeriodType() {
|
||||
return lockinPeriodType;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -3,7 +3,7 @@ package org.mifosplatform.portfolio.savingsaccountproduct.domain;
|
||||
public enum SavingProductType {
|
||||
|
||||
INVALID(0, "savingProductType.invalid"), //
|
||||
RECCURING(1, "savingProductType.reccuring"), //
|
||||
RECURRING(1, "savingProductType.reccuring"), //
|
||||
REGULAR(2, "savingProductType.regular");
|
||||
|
||||
private final Integer value;
|
||||
@@ -27,7 +27,7 @@ public enum SavingProductType {
|
||||
SavingProductType savingProductType = SavingProductType.INVALID;
|
||||
switch (frequency) {
|
||||
case 1:
|
||||
savingProductType = SavingProductType.RECCURING;
|
||||
savingProductType = SavingProductType.RECURRING;
|
||||
break;
|
||||
case 2:
|
||||
savingProductType = SavingProductType.REGULAR;
|
||||
@@ -40,7 +40,7 @@ public enum SavingProductType {
|
||||
}
|
||||
|
||||
public boolean isReccuring() {
|
||||
return this.value.equals(SavingProductType.RECCURING.getValue());
|
||||
return this.value.equals(SavingProductType.RECURRING.getValue());
|
||||
}
|
||||
|
||||
public boolean isRegular() {
|
||||
|
||||
+4
-4
@@ -167,9 +167,9 @@ public class SavingProductEnumerations {
|
||||
EnumOptionData optionData = null;
|
||||
switch (type) {
|
||||
// FIXME - Madhukar - spelling mistake on 'Recurring'
|
||||
case RECCURING:
|
||||
optionData = new EnumOptionData(SavingProductType.RECCURING.getValue().longValue(), codePrefix
|
||||
+ SavingProductType.RECCURING.getCode(), "Reccuring");
|
||||
case RECURRING:
|
||||
optionData = new EnumOptionData(SavingProductType.RECURRING.getValue().longValue(), codePrefix
|
||||
+ SavingProductType.RECURRING.getCode(), "Recurring");
|
||||
break;
|
||||
case REGULAR:
|
||||
optionData = new EnumOptionData(SavingProductType.REGULAR.getValue().longValue(), codePrefix
|
||||
@@ -186,4 +186,4 @@ public class SavingProductEnumerations {
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-2
@@ -44,9 +44,18 @@ public class SavingProductWritePlatformServiceJpaRepositoryImpl implements Savin
|
||||
SavingFrequencyType savingFrequencyType = SavingFrequencyType.fromInt(command.getFrequency());
|
||||
SavingsInterestType interestType = SavingsInterestType.fromInt(command.getInterestType());
|
||||
PeriodFrequencyType lockinPeriodType = PeriodFrequencyType.fromInt(command.getLockinPeriodType());
|
||||
SavingInterestCalculationMethod savingInterestCalculationMethod = SavingInterestCalculationMethod.fromInt(command
|
||||
.getInterestCalculationMethod());
|
||||
SavingInterestCalculationMethod savingInterestCalculationMethod = SavingInterestCalculationMethod.fromInt(command.getInterestCalculationMethod());
|
||||
MonetaryCurrency currency = new MonetaryCurrency(command.getCurrencyCode(), command.getDigitsAfterDecimal());
|
||||
|
||||
if ( savingProductType.equals(SavingProductType.INVALID) ||
|
||||
tenureType.equals(TenureTypeEnum.INVALID) ||
|
||||
savingFrequencyType.equals(SavingFrequencyType.INVALID) ||
|
||||
interestType.equals(SavingsInterestType.INVALID) ||
|
||||
lockinPeriodType.equals(PeriodFrequencyType.INVALID)||
|
||||
savingInterestCalculationMethod.equals(SavingInterestCalculationMethod.INVALID)
|
||||
) {
|
||||
throw new RuntimeException("Please select a valid types");
|
||||
}
|
||||
|
||||
SavingProduct product = new SavingProduct(command.getName(), command.getDescription(), currency, command.getInterestRate(),
|
||||
command.getMinInterestRate(), command.getMaxInterestRate(), command.getSavingsDepositAmount(),command.getDepositEvery(), savingProductType,
|
||||
|
||||
+8
@@ -58,4 +58,12 @@ public enum DepositAccountTransactionType {
|
||||
return depositTransactionType;
|
||||
}
|
||||
|
||||
public boolean isDeposit() {
|
||||
return this.value.equals(DepositAccountTransactionType.DEPOSIT.value);
|
||||
}
|
||||
|
||||
public boolean isWithdraw() {
|
||||
return this.value.equals(DepositAccountTransactionType.WITHDRAW.value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user