MifosX-1466-Flexible Savings Interest Posting
This commit is contained in:
@@ -13145,6 +13145,8 @@ Request Body:
|
||||
<li><b>allow-transactions-on-non_workingday</b> - defaults to false - if true allows transactions on non-working days</li>
|
||||
<li><b>reschedule-repayments-on-holidays</b> - defaults to false - if true reschedules repayemnts which falls on a non-working day to defined <a href="#holidays">reschedule date</a></li>
|
||||
<li><b>allow-transactions-on-holiday</b> - defaults to false - if true allows transactions on <a href="#holidays">holidays</a></li>
|
||||
<li><b>savings-interest-posting-current-period-end</b> - Set it at the database level before any savings interest is posted. When set as false(default), interest will be posted on the first date of next period. If set as true, interest will be posted on last date of current period. There is no difference in the interest amount posted.</li>
|
||||
<li><b>financial-year-beginning-month</b> - Set it at the database level before any savings interest is posted. Allowed values 1 - 12 (January - December). Interest posting periods are evaluated based on this configuration.</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
/**
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package org.mifosplatform.integrationtests;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mifosplatform.integrationtests.common.ClientHelper;
|
||||
import org.mifosplatform.integrationtests.common.CommonConstants;
|
||||
import org.mifosplatform.integrationtests.common.GlobalConfigurationHelper;
|
||||
import org.mifosplatform.integrationtests.common.Utils;
|
||||
import org.mifosplatform.integrationtests.common.savings.SavingsAccountHelper;
|
||||
import org.mifosplatform.integrationtests.common.savings.SavingsProductHelper;
|
||||
import org.mifosplatform.integrationtests.common.savings.SavingsStatusChecker;
|
||||
|
||||
import com.jayway.restassured.builder.RequestSpecBuilder;
|
||||
import com.jayway.restassured.builder.ResponseSpecBuilder;
|
||||
import com.jayway.restassured.http.ContentType;
|
||||
import com.jayway.restassured.specification.RequestSpecification;
|
||||
import com.jayway.restassured.specification.ResponseSpecification;
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unused", "unchecked" })
|
||||
public class FlexibleSavingsInterestPostingIntegrationTest {
|
||||
|
||||
public static final String ACCOUNT_TYPE_INDIVIDUAL = "INDIVIDUAL";
|
||||
|
||||
private ResponseSpecification responseSpec;
|
||||
private RequestSpecification requestSpec;
|
||||
private SavingsProductHelper savingsProductHelper;
|
||||
private SavingsAccountHelper savingsAccountHelper;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
Utils.initializeRESTAssured();
|
||||
this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
|
||||
this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
|
||||
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
|
||||
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
|
||||
this.savingsProductHelper = new SavingsProductHelper();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSavingsInterestPostingAtPeriodEnd() {
|
||||
//client activation, savings activation and 1st transaction date
|
||||
final String startDate = "01 December 2013";
|
||||
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, startDate);
|
||||
Assert.assertNotNull(clientID);
|
||||
|
||||
// Configuring global config flags
|
||||
configureInterestPosting(true, 4);
|
||||
|
||||
final Integer savingsId = createSavingsAccount(clientID, startDate);
|
||||
|
||||
Integer depositTransactionId = (Integer) this.savingsAccountHelper.depositToSavingsAccount(savingsId, "1000",
|
||||
startDate, CommonConstants.RESPONSE_RESOURCE_ID);
|
||||
|
||||
/***
|
||||
* Perform Post interest transaction and verify the posted transaction date
|
||||
*/
|
||||
this.savingsAccountHelper.postInterestForSavings(savingsId);
|
||||
HashMap accountDetails = this.savingsAccountHelper.getSavingsDetails(savingsId);
|
||||
ArrayList<HashMap<String, Object>> transactions = (ArrayList<HashMap<String, Object>>)
|
||||
accountDetails.get("transactions");
|
||||
HashMap<String, Object> interestPostingTransaction = transactions.get(0);
|
||||
for(Entry<String, Object> entry : interestPostingTransaction.entrySet())
|
||||
System.out.println(entry.getKey() + "-" + entry.getValue().toString());
|
||||
//1st Dec 13 to 31st March 14 - 365 days, daily compounding using daily balance
|
||||
//33.7016 obtained from formula in excel provided by Subramanya
|
||||
assertEquals("Equality check for interest posted amount",
|
||||
"33.7016", interestPostingTransaction.get("amount").toString());
|
||||
assertEquals("Date check for Interest Posting transaction",
|
||||
"[2014, 3, 31]", interestPostingTransaction.get("date").toString());
|
||||
|
||||
}
|
||||
|
||||
private Integer createSavingsAccount(final Integer clientID, final String startDate) {
|
||||
final Integer savingsProductID = createSavingsProduct();
|
||||
Assert.assertNotNull(savingsProductID);
|
||||
final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplicationOnDate(clientID,
|
||||
savingsProductID, ACCOUNT_TYPE_INDIVIDUAL, startDate);
|
||||
Assert.assertNotNull(savingsId);
|
||||
HashMap savingsStatusHashMap = this.savingsAccountHelper.approveSavingsOnDate(savingsId, startDate);
|
||||
SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap);
|
||||
savingsStatusHashMap = this.savingsAccountHelper.activateSavingsAccount(savingsId, startDate);
|
||||
SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap);
|
||||
return savingsId;
|
||||
}
|
||||
|
||||
private void configureInterestPosting(final Boolean periodEndEnable,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
final ArrayList<HashMap> globalConfig = GlobalConfigurationHelper.getAllGlobalConfigurations(this.requestSpec,
|
||||
this.responseSpec);
|
||||
Assert.assertNotNull(globalConfig);
|
||||
|
||||
// Updating flag for interest posting at period end
|
||||
Integer periodEndConfigId = (Integer) globalConfig.get(10).get("id");
|
||||
Assert.assertNotNull(periodEndConfigId);
|
||||
|
||||
HashMap periodEndConfigData = GlobalConfigurationHelper.getGlobalConfigurationById(this.requestSpec, this.responseSpec,
|
||||
periodEndConfigId.toString());
|
||||
Assert.assertNotNull(periodEndConfigData);
|
||||
|
||||
Boolean enabled = (Boolean) globalConfig.get(10).get("enabled");
|
||||
|
||||
if (enabled != periodEndEnable)
|
||||
periodEndConfigId = GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(this.requestSpec, this.responseSpec,
|
||||
periodEndConfigId.toString(), periodEndEnable);
|
||||
|
||||
|
||||
//Updating value for financial year beginning month
|
||||
Integer financialYearBeginningConfigId = (Integer) globalConfig.get(11).get("id");
|
||||
Assert.assertNotNull(financialYearBeginningConfigId);
|
||||
|
||||
HashMap financialYearBeginningConfigData = GlobalConfigurationHelper.getGlobalConfigurationById(this.requestSpec, this.responseSpec,
|
||||
financialYearBeginningConfigId.toString());
|
||||
Assert.assertNotNull(financialYearBeginningConfigData);
|
||||
|
||||
financialYearBeginningConfigId = GlobalConfigurationHelper.updateValueForGlobalConfiguration(this.requestSpec, this.responseSpec,
|
||||
financialYearBeginningConfigId.toString(), financialYearBeginningMonth.toString());
|
||||
Assert.assertNotNull(financialYearBeginningConfigId);
|
||||
}
|
||||
|
||||
private Integer createSavingsProduct() {
|
||||
final String savingsProductJSON = this.savingsProductHelper
|
||||
.withInterestCompoundingPeriodTypeAsDaily()
|
||||
.withInterestPostingPeriodTypeAsAnnual()
|
||||
.withInterestCalculationPeriodTypeAsDailyBalance()
|
||||
.build();
|
||||
return SavingsProductHelper.createSavingsProduct(savingsProductJSON, requestSpec, responseSpec);
|
||||
}
|
||||
|
||||
//Reset configuration fields
|
||||
@After
|
||||
public void tearDown() {
|
||||
configureInterestPosting(false, 1);
|
||||
}
|
||||
|
||||
}
|
||||
+22
-6
@@ -59,9 +59,14 @@ public class SavingsAccountHelper {
|
||||
}
|
||||
|
||||
public Integer applyForSavingsApplication(final Integer ID, final Integer savingsProductID, final String accountType) {
|
||||
System.out.println("--------------------------------APPLYING FOR SAVINGS APPLICATION--------------------------------");
|
||||
return applyForSavingsApplicationOnDate(ID, savingsProductID, accountType, CREATED_DATE);
|
||||
}
|
||||
|
||||
public Integer applyForSavingsApplicationOnDate(final Integer ID, final Integer savingsProductID, final String accountType,
|
||||
final String submittedOnDate) {
|
||||
System.out.println("--------------------------------APPLYING FOR SAVINGS APPLICATION--------------------------------");
|
||||
final String savingsApplicationJSON = new SavingsApplicationTestBuilder() //
|
||||
.withSubmittedOnDate(CREATED_DATE) //
|
||||
.withSubmittedOnDate(submittedOnDate) //
|
||||
.build(ID.toString(), savingsProductID.toString(), accountType);
|
||||
return Utils.performServerPost(this.requestSpec, this.responseSpec, SAVINGS_ACCOUNT_URL + "?" + Utils.TENANT_IDENTIFIER,
|
||||
savingsApplicationJSON, "savingsId");
|
||||
@@ -77,8 +82,15 @@ public class SavingsAccountHelper {
|
||||
}
|
||||
|
||||
public HashMap approveSavings(final Integer savingsID) {
|
||||
System.out.println("--------------------------------- APPROVING SAVINGS APPLICATION ------------------------------------");
|
||||
return performSavingApplicationActions(createSavingsOperationURL(APPROVE_SAVINGS_COMMAND, savingsID), getApproveSavingsAsJSON());
|
||||
return approveSavingsOnDate(savingsID, null);
|
||||
}
|
||||
|
||||
public HashMap approveSavingsOnDate(final Integer savingsID, final String approvalDate) {
|
||||
System.out.println("--------------------------------- APPROVING SAVINGS APPLICATION ------------------------------------");
|
||||
final String savingsOperationURL = createSavingsOperationURL(APPROVE_SAVINGS_COMMAND, savingsID);
|
||||
if(approvalDate == null || approvalDate == "")
|
||||
return performSavingApplicationActions(savingsOperationURL, getApproveSavingsAsJSON());
|
||||
return performSavingApplicationActions(savingsOperationURL, getApproveSavingsAsJsonOnDate(approvalDate));
|
||||
}
|
||||
|
||||
public HashMap undoApproval(final Integer savingsID) {
|
||||
@@ -185,10 +197,14 @@ public class SavingsAccountHelper {
|
||||
}
|
||||
|
||||
private String getApproveSavingsAsJSON() {
|
||||
final HashMap<String, String> map = new HashMap<>();
|
||||
return getApproveSavingsAsJsonOnDate(CREATED_DATE_PLUS_ONE);
|
||||
}
|
||||
|
||||
private String getApproveSavingsAsJsonOnDate(final String approvalDate) {
|
||||
final HashMap<String, String> map = new HashMap<>();
|
||||
map.put("locale", CommonConstants.locale);
|
||||
map.put("dateFormat", CommonConstants.dateFormat);
|
||||
map.put("approvedOnDate", CREATED_DATE_PLUS_ONE);
|
||||
map.put("approvedOnDate", approvalDate);
|
||||
map.put("note", "Approval NOTE");
|
||||
String savingsAccountApproveJson = new Gson().toJson(map);
|
||||
System.out.println(savingsAccountApproveJson);
|
||||
|
||||
+8
-2
@@ -18,18 +18,24 @@ public class GlobalConfigurationPropertyData {
|
||||
private final Long value;
|
||||
@SuppressWarnings("unused")
|
||||
private final Long id;
|
||||
@SuppressWarnings("unused")
|
||||
private final String description;
|
||||
|
||||
public GlobalConfigurationPropertyData(final String name, final boolean enabled, final Long value) {
|
||||
public GlobalConfigurationPropertyData(final String name, final boolean enabled, final Long value,
|
||||
final String description) {
|
||||
this.name = name;
|
||||
this.enabled = enabled;
|
||||
this.value = value;
|
||||
this.id = null;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public GlobalConfigurationPropertyData(final String name, final boolean enabled, final Long value, final Long id) {
|
||||
public GlobalConfigurationPropertyData(final String name, final boolean enabled, final Long value,
|
||||
final Long id, final String description) {
|
||||
this.name = name;
|
||||
this.enabled = enabled;
|
||||
this.value = value;
|
||||
this.id = id;
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
+4
@@ -35,4 +35,8 @@ public interface ConfigurationDomainService {
|
||||
|
||||
Long retrieveGraceOnPenaltyPostingPeriod();
|
||||
|
||||
boolean isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
|
||||
Integer retrieveFinancialYearBeginningMonth();
|
||||
|
||||
}
|
||||
+16
@@ -135,5 +135,21 @@ public class ConfigurationDomainServiceJpa implements ConfigurationDomainService
|
||||
final GlobalConfigurationProperty property = this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
|
||||
return property.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSavingsInterestPostingAtCurrentPeriodEnd() {
|
||||
final String propertyName = "savings-interest-posting-current-period-end";
|
||||
final GlobalConfigurationProperty property = this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
|
||||
return property.isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer retrieveFinancialYearBeginningMonth() {
|
||||
final String propertyName = "financial-year-beginning-month";
|
||||
final GlobalConfigurationProperty property = this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
|
||||
if(property.isEnabled())
|
||||
return property.getValue().intValue();
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
+8
-2
@@ -27,17 +27,23 @@ public class GlobalConfigurationProperty extends AbstractPersistable<Long> {
|
||||
|
||||
@Column(name = "value", nullable = true)
|
||||
private Long value;
|
||||
|
||||
@Column(name = "description", nullable = true)
|
||||
private final String description;
|
||||
|
||||
protected GlobalConfigurationProperty() {
|
||||
this.name = null;
|
||||
this.enabled = false;
|
||||
this.value = null;
|
||||
this.description = null;
|
||||
}
|
||||
|
||||
public GlobalConfigurationProperty(final String name, final boolean enabled, final Long value) {
|
||||
public GlobalConfigurationProperty(final String name, final boolean enabled, final Long value,
|
||||
final String description) {
|
||||
this.name = name;
|
||||
this.enabled = enabled;
|
||||
this.value = value;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
@@ -78,7 +84,7 @@ public class GlobalConfigurationProperty extends AbstractPersistable<Long> {
|
||||
|
||||
public static GlobalConfigurationProperty newSurveyConfiguration(final String name)
|
||||
{
|
||||
return new GlobalConfigurationProperty(name,false,null);
|
||||
return new GlobalConfigurationProperty(name, false, null, null);
|
||||
}
|
||||
|
||||
}
|
||||
+5
-3
@@ -39,7 +39,7 @@ public class ConfigurationReadPlatformServiceImpl implements ConfigurationReadPl
|
||||
|
||||
this.context.authenticatedUser();
|
||||
|
||||
String sql = "SELECT c.id, c.name, c.enabled, c.value FROM c_configuration c ";
|
||||
String sql = "SELECT c.id, c.name, c.enabled, c.value, c.description FROM c_configuration c ";
|
||||
|
||||
if(survey)
|
||||
{
|
||||
@@ -59,7 +59,8 @@ public class ConfigurationReadPlatformServiceImpl implements ConfigurationReadPl
|
||||
|
||||
this.context.authenticatedUser();
|
||||
|
||||
final String sql = "SELECT c.id, c.name, c.enabled, c.value FROM c_configuration c where c.id=? order by c.id";
|
||||
final String sql = "SELECT c.id, c.name, c.enabled, c.value, c.description FROM "
|
||||
+ "c_configuration c where c.id=? order by c.id";
|
||||
final GlobalConfigurationPropertyData globalConfiguration = this.jdbcTemplate.queryForObject(sql, this.rm, new Object[] {configId});
|
||||
|
||||
return globalConfiguration;
|
||||
@@ -76,9 +77,10 @@ public class ConfigurationReadPlatformServiceImpl implements ConfigurationReadPl
|
||||
final String name = rs.getString("name");
|
||||
final boolean enabled = rs.getBoolean("enabled");
|
||||
final Long value = rs.getLong("value");
|
||||
final String description = rs.getString("description");
|
||||
final Long id = rs.getLong("id");
|
||||
|
||||
return new GlobalConfigurationPropertyData(name, enabled, value, id);
|
||||
return new GlobalConfigurationPropertyData(name, enabled, value, id, description);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -50,7 +50,7 @@ public class GlobalConfigurationWritePlatformServiceJpaRepositoryImpl implements
|
||||
this.globalConfigurationDataValidator.validateForUpdate(command);
|
||||
|
||||
final GlobalConfigurationProperty configItemForUpdate = this.repository.findOneWithNotFoundDetection(configId);
|
||||
|
||||
|
||||
final Map<String, Object> changes = configItemForUpdate.update(command);
|
||||
|
||||
if (!changes.isEmpty()) {
|
||||
@@ -66,7 +66,6 @@ public class GlobalConfigurationWritePlatformServiceJpaRepositoryImpl implements
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void addSurveyConfig(final String name)
|
||||
|
||||
+54
-11
@@ -20,6 +20,7 @@ import org.joda.time.LocalDate;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
import org.mifosplatform.accounting.journalentry.service.JournalEntryWritePlatformService;
|
||||
import org.mifosplatform.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.service.DateUtils;
|
||||
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrency;
|
||||
@@ -53,6 +54,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
private final DepositAccountAssembler depositAccountAssembler;
|
||||
private final SavingsAccountDomainService savingsAccountDomainService;
|
||||
private final AccountTransfersWritePlatformService accountTransfersWritePlatformService;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
|
||||
@Autowired
|
||||
public DepositAccountDomainServiceJpa(final SavingsAccountRepositoryWrapper savingsAccountRepository,
|
||||
@@ -60,7 +62,8 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
final JournalEntryWritePlatformService journalEntryWritePlatformService,
|
||||
final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory, final DepositAccountAssembler depositAccountAssembler,
|
||||
final SavingsAccountDomainService savingsAccountDomainService,
|
||||
final AccountTransfersWritePlatformService accountTransfersWritePlatformService) {
|
||||
final AccountTransfersWritePlatformService accountTransfersWritePlatformService,
|
||||
final ConfigurationDomainService configurationDomainService) {
|
||||
this.savingsAccountRepository = savingsAccountRepository;
|
||||
this.applicationCurrencyRepositoryWrapper = applicationCurrencyRepositoryWrapper;
|
||||
this.journalEntryWritePlatformService = journalEntryWritePlatformService;
|
||||
@@ -68,6 +71,7 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
this.depositAccountAssembler = depositAccountAssembler;
|
||||
this.savingsAccountDomainService = savingsAccountDomainService;
|
||||
this.accountTransfersWritePlatformService = accountTransfersWritePlatformService;
|
||||
this.configurationDomainService = configurationDomainService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -100,6 +104,12 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
public SavingsAccountTransaction handleRDDeposit(final RecurringDepositAccount account, final DateTimeFormatter fmt,
|
||||
final LocalDate transactionDate, final BigDecimal transactionAmount, final PaymentDetail paymentDetail,
|
||||
final boolean isRegularTransaction) {
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
boolean isAccountTransfer = false;
|
||||
final boolean isPreMatureClosure = false;
|
||||
final MathContext mc = MathContext.DECIMAL64;
|
||||
@@ -107,7 +117,8 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
transactionAmount, paymentDetail, isAccountTransfer, isRegularTransaction);
|
||||
|
||||
account.handleScheduleInstallments(deposit);
|
||||
account.updateMaturityDateAndAmount(mc, isPreMatureClosure);
|
||||
account.updateMaturityDateAndAmount(mc, isPreMatureClosure,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
|
||||
account.updateOverduePayments(DateUtils.getLocalDateOfTenant());
|
||||
return deposit;
|
||||
}
|
||||
@@ -116,6 +127,12 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
@Override
|
||||
public Long handleFDAccountClosure(final FixedDepositAccount account, final PaymentDetail paymentDetail, final AppUser user,
|
||||
final JsonCommand command, final LocalDate tenantsTodayDate, final Map<String, Object> changes) {
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
boolean isRegularTransaction = false;
|
||||
boolean isAccountTransfer = false;
|
||||
final boolean isPreMatureClosure = false;
|
||||
@@ -140,13 +157,15 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
|
||||
final LocalDate closedDate = command.localDateValueOfParameterNamed(SavingsApiConstants.closedOnDateParamName);
|
||||
Long savingsTransactionId = null;
|
||||
account.postMaturityInterest();
|
||||
account.postMaturityInterest(isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
final Integer onAccountClosureId = command.integerValueOfParameterNamed(onAccountClosureIdParamName);
|
||||
final DepositAccountOnClosureType onClosureType = DepositAccountOnClosureType.fromInt(onAccountClosureId);
|
||||
if (onClosureType.isReinvest()) {
|
||||
FixedDepositAccount reinvestedDeposit = account.reInvest(account.getAccountBalance());
|
||||
this.depositAccountAssembler.assignSavingAccountHelpers(reinvestedDeposit);
|
||||
reinvestedDeposit.updateMaturityDateAndAmountBeforeAccountActivation(mc, isPreMatureClosure);
|
||||
reinvestedDeposit.updateMaturityDateAndAmountBeforeAccountActivation(mc, isPreMatureClosure,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
|
||||
this.savingsAccountRepository.save(reinvestedDeposit);
|
||||
autoGenerateAccountNumber(reinvestedDeposit);
|
||||
final SavingsAccountTransaction withdrawal = this.handleWithdrawal(account, fmt, closedDate, account.getAccountBalance(),
|
||||
@@ -185,6 +204,12 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
@Override
|
||||
public Long handleRDAccountClosure(final RecurringDepositAccount account, final PaymentDetail paymentDetail, final AppUser user,
|
||||
final JsonCommand command, final LocalDate tenantsTodayDate, final Map<String, Object> changes) {
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
boolean isRegularTransaction = false;
|
||||
boolean isAccountTransfer = false;
|
||||
final boolean isPreMatureClosure = false;
|
||||
@@ -197,16 +222,19 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
|
||||
final LocalDate closedDate = command.localDateValueOfParameterNamed(SavingsApiConstants.closedOnDateParamName);
|
||||
Long savingsTransactionId = null;
|
||||
account.postMaturityInterest();
|
||||
account.postMaturityInterest(isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
final BigDecimal transactionAmount = account.getAccountBalance();
|
||||
final Integer onAccountClosureId = command.integerValueOfParameterNamed(onAccountClosureIdParamName);
|
||||
final DepositAccountOnClosureType onClosureType = DepositAccountOnClosureType.fromInt(onAccountClosureId);
|
||||
if (onClosureType.isReinvest()) {
|
||||
RecurringDepositAccount reinvestedDeposit = account.reInvest(transactionAmount);
|
||||
depositAccountAssembler.assignSavingAccountHelpers(reinvestedDeposit);
|
||||
reinvestedDeposit.updateMaturityDateAndAmount(mc, isPreMatureClosure);
|
||||
reinvestedDeposit.updateMaturityDateAndAmount(mc, isPreMatureClosure,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
|
||||
reinvestedDeposit.processAccountUponActivation(fmt);
|
||||
reinvestedDeposit.updateMaturityDateAndAmount(mc, isPreMatureClosure);
|
||||
reinvestedDeposit.updateMaturityDateAndAmount(mc, isPreMatureClosure,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
|
||||
this.savingsAccountRepository.save(reinvestedDeposit);
|
||||
|
||||
Money amountForDeposit = reinvestedDeposit.activateWithBalance();
|
||||
@@ -214,7 +242,8 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
handleRDDeposit(reinvestedDeposit, fmt, reinvestedDeposit.getActivationLocalDate(), amountForDeposit.getAmount(),
|
||||
paymentDetail, isRegularTransaction);
|
||||
}
|
||||
reinvestedDeposit.updateMaturityDateAndAmount(mc, isPreMatureClosure);
|
||||
reinvestedDeposit.updateMaturityDateAndAmount(mc, isPreMatureClosure,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
|
||||
this.savingsAccountRepository.save(reinvestedDeposit);
|
||||
autoGenerateAccountNumber(reinvestedDeposit);
|
||||
|
||||
@@ -265,6 +294,12 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
@Override
|
||||
public Long handleFDAccountPreMatureClosure(final FixedDepositAccount account, final PaymentDetail paymentDetail, final AppUser user,
|
||||
final JsonCommand command, final LocalDate tenantsTodayDate, final Map<String, Object> changes) {
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
boolean isAccountTransfer = false;
|
||||
boolean isRegularTransaction = false;
|
||||
final boolean isPreMatureClosure = true;
|
||||
@@ -277,7 +312,8 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
|
||||
Long savingsTransactionId = null;
|
||||
// post interest
|
||||
account.postPreMaturityInterest(closedDate, isPreMatureClosure);
|
||||
account.postPreMaturityInterest(closedDate, isPreMatureClosure,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
|
||||
|
||||
final Integer closureTypeValue = command.integerValueOfParameterNamed(DepositsApiConstants.onAccountClosureIdParamName);
|
||||
DepositAccountOnClosureType closureType = DepositAccountOnClosureType.fromInt(closureTypeValue);
|
||||
@@ -315,7 +351,13 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
@Override
|
||||
public Long handleRDAccountPreMatureClosure(final RecurringDepositAccount account, final PaymentDetail paymentDetail,
|
||||
final AppUser user, final JsonCommand command, final LocalDate tenantsTodayDate, final Map<String, Object> changes) {
|
||||
boolean isAccountTransfer = false;
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
boolean isAccountTransfer = false;
|
||||
final boolean isPreMatureClosure = true;
|
||||
boolean isRegularTransaction = false;
|
||||
final Set<Long> existingTransactionIds = new HashSet<>();
|
||||
@@ -327,7 +369,8 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
|
||||
final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
|
||||
Long savingsTransactionId = null;
|
||||
// post interest
|
||||
account.postPreMaturityInterest(closedDate, isPreMatureClosure);
|
||||
account.postPreMaturityInterest(closedDate, isPreMatureClosure,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
|
||||
|
||||
final Integer closureTypeValue = command.integerValueOfParameterNamed(DepositsApiConstants.onAccountClosureIdParamName);
|
||||
DepositAccountOnClosureType closureType = DepositAccountOnClosureType.fromInt(closureTypeValue);
|
||||
|
||||
+60
-24
@@ -174,7 +174,9 @@ public class FixedDepositAccount extends SavingsAccount {
|
||||
return applicableInterestRate.divide(BigDecimal.valueOf(100l), mc);
|
||||
}
|
||||
|
||||
public void updateMaturityDateAndAmountBeforeAccountActivation(final MathContext mc, final boolean isPreMatureClosure) {
|
||||
public void updateMaturityDateAndAmountBeforeAccountActivation(final MathContext mc,
|
||||
final boolean isPreMatureClosure, final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
List<SavingsAccountTransaction> allTransactions = new ArrayList<>();
|
||||
final Money transactionAmountMoney = Money.of(getCurrency(), this.accountTermAndPreClosure.depositAmount());
|
||||
final SavingsAccountTransaction transaction = SavingsAccountTransaction.deposit(null, office(), null,
|
||||
@@ -182,15 +184,20 @@ public class FixedDepositAccount extends SavingsAccount {
|
||||
transaction.updateRunningBalance(transactionAmountMoney);
|
||||
transaction.updateCumulativeBalanceAndDates(this.getCurrency(), interestCalculatedUpto());
|
||||
allTransactions.add(transaction);
|
||||
updateMaturityDateAndAmount(mc, allTransactions, isPreMatureClosure);
|
||||
updateMaturityDateAndAmount(mc, allTransactions, isPreMatureClosure,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
|
||||
}
|
||||
|
||||
public void updateMaturityDateAndAmount(final MathContext mc, final boolean isPreMatureClosure) {
|
||||
updateMaturityDateAndAmount(mc, retreiveOrderedNonInterestPostingTransactions(), isPreMatureClosure);
|
||||
public void updateMaturityDateAndAmount(final MathContext mc, final boolean isPreMatureClosure,
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
updateMaturityDateAndAmount(mc, retreiveOrderedNonInterestPostingTransactions(), isPreMatureClosure,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
|
||||
}
|
||||
|
||||
public void updateMaturityDateAndAmount(final MathContext mc, final List<SavingsAccountTransaction> transactions,
|
||||
final boolean isPreMatureClosure) {
|
||||
final boolean isPreMatureClosure, final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
final LocalDate maturityDate = calculateMaturityDate();
|
||||
final LocalDate interestCalculationUpto = maturityDate.minusDays(1);
|
||||
|
||||
@@ -198,7 +205,9 @@ public class FixedDepositAccount extends SavingsAccount {
|
||||
// calculation
|
||||
this.resetAccountTransactionsEndOfDayBalances(transactions, maturityDate);
|
||||
|
||||
final List<PostingPeriod> postingPeriods = calculateInterestPayable(mc, interestCalculationUpto, transactions, isPreMatureClosure);
|
||||
final List<PostingPeriod> postingPeriods = calculateInterestPayable(mc, interestCalculationUpto,
|
||||
transactions, isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
|
||||
// reset end of day balance back to today's date
|
||||
this.resetAccountTransactionsEndOfDayBalances(transactions, DateUtils.getLocalDateOfTenant());
|
||||
@@ -213,7 +222,8 @@ public class FixedDepositAccount extends SavingsAccount {
|
||||
this.accountTermAndPreClosure.updateMaturityDetails(maturityAmount.getAmount(), maturityDate);
|
||||
}
|
||||
|
||||
public void updateMaturityStatus() {
|
||||
public void updateMaturityStatus(final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(FIXED_DEPOSIT_ACCOUNT_RESOURCE_NAME + SavingsApiConstants.updateMaturityDetailsAction);
|
||||
@@ -228,7 +238,8 @@ public class FixedDepositAccount extends SavingsAccount {
|
||||
if (!this.maturityDate().isAfter(todayDate)) {
|
||||
// update account status
|
||||
this.status = SavingsAccountStatusType.MATURED.getValue();
|
||||
postMaturityInterest();
|
||||
postMaturityInterest(isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,7 +269,9 @@ public class FixedDepositAccount extends SavingsAccount {
|
||||
}
|
||||
|
||||
private List<PostingPeriod> calculateInterestPayable(final MathContext mc, final LocalDate maturityDate,
|
||||
final List<SavingsAccountTransaction> transactions, final boolean isPreMatureClosure) {
|
||||
final List<SavingsAccountTransaction> transactions, final boolean isPreMatureClosure,
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
|
||||
final SavingsPostingInterestPeriodType postingPeriodType = SavingsPostingInterestPeriodType.fromInt(this.interestPostingPeriodType);
|
||||
|
||||
@@ -269,7 +282,8 @@ public class FixedDepositAccount extends SavingsAccount {
|
||||
.fromInt(this.interestCalculationDaysInYearType);
|
||||
|
||||
final List<LocalDateInterval> postingPeriodIntervals = this.savingsHelper.determineInterestPostingPeriods(
|
||||
accountSubmittedOrActivationDate(), maturityDate, postingPeriodType);
|
||||
accountSubmittedOrActivationDate(), maturityDate, postingPeriodType,
|
||||
financialYearBeginningMonth);
|
||||
|
||||
final List<PostingPeriod> allPostingPeriods = new ArrayList<>();
|
||||
|
||||
@@ -284,7 +298,8 @@ public class FixedDepositAccount extends SavingsAccount {
|
||||
|
||||
final PostingPeriod postingPeriod = PostingPeriod.createFrom(periodInterval, periodStartingBalance, transactions,
|
||||
this.currency, compoundingPeriodType, interestCalculationType, interestRateAsFraction, daysInYearType.getValue(),
|
||||
maturityDate, interestPostTransactions, isInterestTransfer, minBalanceForInterestCalculation);
|
||||
maturityDate, interestPostTransactions, isInterestTransfer, minBalanceForInterestCalculation,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd);
|
||||
|
||||
periodStartingBalance = postingPeriod.closingBalance();
|
||||
|
||||
@@ -455,11 +470,14 @@ public class FixedDepositAccount extends SavingsAccount {
|
||||
// this.savingsAccountTransactionSummaryWrapper, this.transactions);
|
||||
}
|
||||
|
||||
public void postMaturityInterest() {
|
||||
public void postMaturityInterest(final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
final LocalDate interestPostingUpToDate = maturityDate();
|
||||
final MathContext mc = MathContext.DECIMAL64;
|
||||
final boolean isInterestTransfer = false;
|
||||
final List<PostingPeriod> postingPeriods = calculateInterestUsing(mc, interestPostingUpToDate, isInterestTransfer);
|
||||
final List<PostingPeriod> postingPeriods = calculateInterestUsing(mc, interestPostingUpToDate,
|
||||
isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
|
||||
Money interestPostedToDate = Money.zero(this.currency);
|
||||
|
||||
@@ -503,13 +521,17 @@ public class FixedDepositAccount extends SavingsAccount {
|
||||
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions);
|
||||
}
|
||||
|
||||
public void postPreMaturityInterest(final LocalDate accountCloseDate, final boolean isPreMatureClosure) {
|
||||
public void postPreMaturityInterest(final LocalDate accountCloseDate, final boolean isPreMatureClosure,
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
|
||||
Money interestPostedToDate = totalInterestPosted();
|
||||
// calculate interest before one day of closure date
|
||||
final LocalDate interestCalculatedToDate = accountCloseDate.minusDays(1);
|
||||
final Money interestOnMaturity = calculatePreMatureInterest(interestCalculatedToDate,
|
||||
retreiveOrderedNonInterestPostingTransactions(), isPreMatureClosure);
|
||||
retreiveOrderedNonInterestPostingTransactions(), isPreMatureClosure,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
boolean recalucateDailyBalance = false;
|
||||
|
||||
// post remaining interest
|
||||
@@ -531,12 +553,15 @@ public class FixedDepositAccount extends SavingsAccount {
|
||||
|
||||
}
|
||||
|
||||
public BigDecimal calculatePreMatureAmount(final LocalDate preMatureDate, final boolean isPreMatureClosure) {
|
||||
public BigDecimal calculatePreMatureAmount(final LocalDate preMatureDate, final boolean isPreMatureClosure,
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
|
||||
final Money interestPostedToDate = totalInterestPosted().copy();
|
||||
|
||||
final Money interestEarnedTillDate = calculatePreMatureInterest(preMatureDate, retreiveOrderedNonInterestPostingTransactions(),
|
||||
isPreMatureClosure);
|
||||
isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
|
||||
final Money accountBalance = Money.of(getCurrency(), getAccountBalance());
|
||||
final Money maturityAmount = accountBalance.minus(interestPostedToDate).plus(interestEarnedTillDate);
|
||||
@@ -545,9 +570,12 @@ public class FixedDepositAccount extends SavingsAccount {
|
||||
}
|
||||
|
||||
private Money calculatePreMatureInterest(final LocalDate preMatureDate, final List<SavingsAccountTransaction> transactions,
|
||||
final boolean isPreMatureClosure) {
|
||||
final boolean isPreMatureClosure, final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
final MathContext mc = MathContext.DECIMAL64;
|
||||
final List<PostingPeriod> postingPeriods = calculateInterestPayable(mc, preMatureDate, transactions, isPreMatureClosure);
|
||||
final List<PostingPeriod> postingPeriods = calculateInterestPayable(mc, preMatureDate, transactions,
|
||||
isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
|
||||
Money interestOnMaturity = Money.zero(this.currency);
|
||||
|
||||
@@ -560,15 +588,23 @@ public class FixedDepositAccount extends SavingsAccount {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInterest(final MathContext mc, final LocalDate postingDate, boolean isInterestTransfer) {
|
||||
public void postInterest(final MathContext mc, final LocalDate postingDate, boolean isInterestTransfer,
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
final LocalDate interestPostingUpToDate = interestPostingUpToDate(postingDate);
|
||||
super.postInterest(mc, interestPostingUpToDate, isInterestTransfer);
|
||||
}
|
||||
super.postInterest(mc, interestPostingUpToDate, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PostingPeriod> calculateInterestUsing(final MathContext mc, final LocalDate postingDate, boolean isInterestTransfer) {
|
||||
public List<PostingPeriod> calculateInterestUsing(final MathContext mc, final LocalDate postingDate,
|
||||
boolean isInterestTransfer, final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
final LocalDate interestPostingUpToDate = interestPostingUpToDate(postingDate);
|
||||
return super.calculateInterestUsing(mc, interestPostingUpToDate, isInterestTransfer);
|
||||
return super.calculateInterestUsing(mc, interestPostingUpToDate, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
}
|
||||
|
||||
private LocalDate interestPostingUpToDate(final LocalDate interestPostingDate) {
|
||||
|
||||
+45
-19
@@ -206,13 +206,16 @@ public class RecurringDepositAccount extends SavingsAccount {
|
||||
return applicableInterestRate.divide(BigDecimal.valueOf(100l), mc);
|
||||
}
|
||||
|
||||
public void updateMaturityDateAndAmount(final MathContext mc, final boolean isPreMatureClosure) {
|
||||
public void updateMaturityDateAndAmount(final MathContext mc, final boolean isPreMatureClosure,
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
final LocalDate maturityDate = calculateMaturityDate();
|
||||
final LocalDate interestCalculationUpto = maturityDate.minusDays(1);
|
||||
final List<SavingsAccountTransaction> allTransactions = generateIncludingFutureTransactions(interestCalculationUpto);
|
||||
|
||||
final List<PostingPeriod> postingPeriods = calculateInterestPayable(mc, interestCalculationUpto, allTransactions,
|
||||
isPreMatureClosure);
|
||||
isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
Money totalInterestPayable = Money.zero(getCurrency());
|
||||
Money totalDepositAmount = Money.zero(getCurrency());
|
||||
for (PostingPeriod postingPeriod : postingPeriods) {
|
||||
@@ -223,7 +226,8 @@ public class RecurringDepositAccount extends SavingsAccount {
|
||||
this.accountTermAndPreClosure.updateMaturityDetails(totalDepositAmount.getAmount(), totalInterestPayable.getAmount(), maturityDate);
|
||||
}
|
||||
|
||||
public void updateMaturityStatus() {
|
||||
public void updateMaturityStatus(final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(RECURRING_DEPOSIT_ACCOUNT_RESOURCE_NAME + SavingsApiConstants.updateMaturityDetailsAction);
|
||||
@@ -238,7 +242,8 @@ public class RecurringDepositAccount extends SavingsAccount {
|
||||
if (!this.maturityDate().isAfter(todayDate)) {
|
||||
// update account status
|
||||
this.status = SavingsAccountStatusType.MATURED.getValue();
|
||||
postMaturityInterest();
|
||||
postMaturityInterest(isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,7 +273,9 @@ public class RecurringDepositAccount extends SavingsAccount {
|
||||
}
|
||||
|
||||
private List<PostingPeriod> calculateInterestPayable(final MathContext mc, final LocalDate maturityDate,
|
||||
final List<SavingsAccountTransaction> transactions, final boolean isPreMatureClosure) {
|
||||
final List<SavingsAccountTransaction> transactions, final boolean isPreMatureClosure,
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
|
||||
// 1. default to calculate interest based on entire history OR
|
||||
// 2. determine latest 'posting period' and find interest credited to
|
||||
@@ -284,7 +291,7 @@ public class RecurringDepositAccount extends SavingsAccount {
|
||||
.fromInt(this.interestCalculationDaysInYearType);
|
||||
|
||||
final List<LocalDateInterval> postingPeriodIntervals = this.savingsHelper.determineInterestPostingPeriods(depositStartDate(),
|
||||
maturityDate, postingPeriodType);
|
||||
maturityDate, postingPeriodType, financialYearBeginningMonth);
|
||||
|
||||
final List<PostingPeriod> allPostingPeriods = new ArrayList<>();
|
||||
|
||||
@@ -298,7 +305,8 @@ public class RecurringDepositAccount extends SavingsAccount {
|
||||
for (final LocalDateInterval periodInterval : postingPeriodIntervals) {
|
||||
final PostingPeriod postingPeriod = PostingPeriod.createFrom(periodInterval, periodStartingBalance, transactions,
|
||||
this.currency, compoundingPeriodType, interestCalculationType, interestRateAsFraction, daysInYearType.getValue(),
|
||||
maturityDate, interestPostTransactions, isInterestTransfer, minBalanceForInterestCalculation);
|
||||
maturityDate, interestPostTransactions, isInterestTransfer, minBalanceForInterestCalculation,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd);
|
||||
|
||||
periodStartingBalance = postingPeriod.closingBalance();
|
||||
|
||||
@@ -560,11 +568,14 @@ public class RecurringDepositAccount extends SavingsAccount {
|
||||
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions);
|
||||
}
|
||||
|
||||
public void postMaturityInterest() {
|
||||
public void postMaturityInterest(final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
final LocalDate interestPostingUpToDate = maturityDate();
|
||||
final MathContext mc = MathContext.DECIMAL64;
|
||||
boolean isInterestTransfer = false;
|
||||
final List<PostingPeriod> postingPeriods = calculateInterestUsing(mc, interestPostingUpToDate, isInterestTransfer);
|
||||
final List<PostingPeriod> postingPeriods = calculateInterestUsing(mc, interestPostingUpToDate,
|
||||
isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
|
||||
Money interestPostedToDate = Money.zero(this.currency);
|
||||
|
||||
@@ -606,13 +617,17 @@ public class RecurringDepositAccount extends SavingsAccount {
|
||||
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions);
|
||||
}
|
||||
|
||||
public void postPreMaturityInterest(final LocalDate accountCloseDate, final boolean isPreMatureClosure) {
|
||||
public void postPreMaturityInterest(final LocalDate accountCloseDate, final boolean isPreMatureClosure,
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
|
||||
final Money interestPostedToDate = totalInterestPosted();
|
||||
// calculate interest before one day of closure date
|
||||
final LocalDate interestCalculatedToDate = accountCloseDate.minusDays(1);
|
||||
final Money interestOnMaturity = calculatePreMatureInterest(interestCalculatedToDate,
|
||||
retreiveOrderedNonInterestPostingTransactions(), isPreMatureClosure);
|
||||
retreiveOrderedNonInterestPostingTransactions(), isPreMatureClosure,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
|
||||
boolean recalucateDailyBalance = false;
|
||||
|
||||
@@ -635,12 +650,15 @@ public class RecurringDepositAccount extends SavingsAccount {
|
||||
this.accountTermAndPreClosure.updateMaturityDetails(this.getAccountBalance(), accountCloseDate);
|
||||
}
|
||||
|
||||
public BigDecimal calculatePreMatureAmount(final LocalDate preMatureDate, final boolean isPreMatureClosure) {
|
||||
public BigDecimal calculatePreMatureAmount(final LocalDate preMatureDate, final boolean isPreMatureClosure,
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
|
||||
final Money interestPostedToDate = totalInterestPosted().copy();
|
||||
|
||||
final Money interestEarnedTillDate = calculatePreMatureInterest(preMatureDate, retreiveOrderedNonInterestPostingTransactions(),
|
||||
isPreMatureClosure);
|
||||
isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
|
||||
final Money accountBalance = Money.of(getCurrency(), getAccountBalance());
|
||||
final Money maturityAmount = accountBalance.minus(interestPostedToDate).plus(interestEarnedTillDate);
|
||||
@@ -649,9 +667,12 @@ public class RecurringDepositAccount extends SavingsAccount {
|
||||
}
|
||||
|
||||
private Money calculatePreMatureInterest(final LocalDate preMatureDate, final List<SavingsAccountTransaction> transactions,
|
||||
final boolean isPreMatureClosure) {
|
||||
final boolean isPreMatureClosure, final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
final MathContext mc = MathContext.DECIMAL64;
|
||||
final List<PostingPeriod> postingPeriods = calculateInterestPayable(mc, preMatureDate, transactions, isPreMatureClosure);
|
||||
final List<PostingPeriod> postingPeriods = calculateInterestPayable(mc, preMatureDate, transactions,
|
||||
isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
|
||||
Money interestOnMaturity = Money.zero(this.currency);
|
||||
|
||||
@@ -664,15 +685,20 @@ public class RecurringDepositAccount extends SavingsAccount {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInterest(final MathContext mc, final LocalDate postingDate, final boolean isInterestTransfer) {
|
||||
public void postInterest(final MathContext mc, final LocalDate postingDate, final boolean isInterestTransfer,
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth) {
|
||||
final LocalDate interestPostingUpToDate = interestPostingUpToDate(postingDate);
|
||||
super.postInterest(mc, interestPostingUpToDate, isInterestTransfer);
|
||||
super.postInterest(mc, interestPostingUpToDate, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PostingPeriod> calculateInterestUsing(final MathContext mc, final LocalDate postingDate, boolean isInterestTransfer) {
|
||||
public List<PostingPeriod> calculateInterestUsing(final MathContext mc, final LocalDate postingDate,
|
||||
boolean isInterestTransfer, final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
final LocalDate interestPostingUpToDate = interestPostingUpToDate(postingDate);
|
||||
return super.calculateInterestUsing(mc, interestPostingUpToDate, isInterestTransfer);
|
||||
return super.calculateInterestUsing(mc, interestPostingUpToDate, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
|
||||
}
|
||||
|
||||
private LocalDate interestPostingUpToDate(final LocalDate interestPostingDate) {
|
||||
|
||||
+23
-10
@@ -417,9 +417,14 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
return SavingsAccountStatusType.fromInt(this.status).isClosed();
|
||||
}
|
||||
|
||||
public void postInterest(final MathContext mc, final LocalDate interestPostingUpToDate, final boolean isInterestTransfer) {
|
||||
public void postInterest(final MathContext mc,
|
||||
final LocalDate interestPostingUpToDate,
|
||||
final boolean isInterestTransfer,
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
|
||||
final List<PostingPeriod> postingPeriods = calculateInterestUsing(mc, interestPostingUpToDate, isInterestTransfer);
|
||||
final List<PostingPeriod> postingPeriods = calculateInterestUsing(mc, interestPostingUpToDate, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
|
||||
|
||||
Money interestPostedToDate = Money.zero(this.currency);
|
||||
|
||||
@@ -514,7 +519,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
* TODO
|
||||
*/
|
||||
public List<PostingPeriod> calculateInterestUsing(final MathContext mc, final LocalDate upToInterestCalculationDate,
|
||||
boolean isInterestTransfer) {
|
||||
boolean isInterestTransfer, final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
|
||||
// no openingBalance concept supported yet but probably will to allow
|
||||
// for migrations.
|
||||
@@ -538,7 +544,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
.fromInt(this.interestCalculationDaysInYearType);
|
||||
|
||||
final List<LocalDateInterval> postingPeriodIntervals = this.savingsHelper.determineInterestPostingPeriods(
|
||||
getStartInterestCalculationDate(), upToInterestCalculationDate, postingPeriodType);
|
||||
getStartInterestCalculationDate(), upToInterestCalculationDate, postingPeriodType,
|
||||
financialYearBeginningMonth);
|
||||
|
||||
final List<PostingPeriod> allPostingPeriods = new ArrayList<>();
|
||||
|
||||
@@ -576,7 +583,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
final PostingPeriod postingPeriod = PostingPeriod.createFrom(periodInterval, periodStartingBalance,
|
||||
retreiveOrderedNonInterestPostingTransactions(), this.currency, compoundingPeriodType, interestCalculationType,
|
||||
interestRateAsFraction, daysInYearType.getValue(), upToInterestCalculationDate, interestPostTransactions,
|
||||
isInterestTransfer, minBalanceForInterestCalculation);
|
||||
isInterestTransfer, minBalanceForInterestCalculation, isSavingsInterestPostingAtCurrentPeriodEnd);
|
||||
|
||||
periodStartingBalance = postingPeriod.closingBalance();
|
||||
|
||||
@@ -1825,7 +1832,9 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
public void processAccountUponActivation() {
|
||||
public void processAccountUponActivation(
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
|
||||
// update annual fee due date
|
||||
for (SavingsAccountCharge charge : this.charges()) {
|
||||
@@ -1833,7 +1842,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
// auto pay the activation time charges
|
||||
this.payActivationCharges();
|
||||
this.payActivationCharges(isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
// TODO : AA add activation charges to actual changes list
|
||||
}
|
||||
|
||||
@@ -1856,7 +1866,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
this.lockedInUntilDate = calculateDateAccountIsLockedUntil(getActivationLocalDate());
|
||||
}
|
||||
|
||||
private void payActivationCharges() {
|
||||
private void payActivationCharges(final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
boolean isSavingsChargeApplied = false;
|
||||
for (SavingsAccountCharge savingsAccountCharge : this.charges()) {
|
||||
if (savingsAccountCharge.isSavingsActivation()) {
|
||||
@@ -1870,10 +1881,12 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
boolean isInterestTransfer = false;
|
||||
if (this.isBeforeLastPostingPeriod(getActivationLocalDate())) {
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
this.postInterest(mc, today, isInterestTransfer);
|
||||
this.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
} else {
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
this.calculateInterestUsing(mc, today, isInterestTransfer);
|
||||
this.calculateInterestUsing(mc, today, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+26
-5
@@ -15,6 +15,7 @@ import java.util.Set;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
import org.mifosplatform.accounting.journalentry.service.JournalEntryWritePlatformService;
|
||||
import org.mifosplatform.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.mifosplatform.infrastructure.core.service.DateUtils;
|
||||
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrency;
|
||||
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper;
|
||||
@@ -34,16 +35,19 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
|
||||
private final SavingsAccountTransactionRepository savingsAccountTransactionRepository;
|
||||
private final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepositoryWrapper;
|
||||
private final JournalEntryWritePlatformService journalEntryWritePlatformService;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
|
||||
@Autowired
|
||||
public SavingsAccountDomainServiceJpa(final SavingsAccountRepositoryWrapper savingsAccountRepository,
|
||||
final SavingsAccountTransactionRepository savingsAccountTransactionRepository,
|
||||
final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepositoryWrapper,
|
||||
final JournalEntryWritePlatformService journalEntryWritePlatformService) {
|
||||
final JournalEntryWritePlatformService journalEntryWritePlatformService,
|
||||
final ConfigurationDomainService configurationDomainService) {
|
||||
this.savingsAccountRepository = savingsAccountRepository;
|
||||
this.savingsAccountTransactionRepository = savingsAccountTransactionRepository;
|
||||
this.applicationCurrencyRepositoryWrapper = applicationCurrencyRepositoryWrapper;
|
||||
this.journalEntryWritePlatformService = journalEntryWritePlatformService;
|
||||
this.configurationDomainService = configurationDomainService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -51,6 +55,11 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
|
||||
public SavingsAccountTransaction handleWithdrawal(final SavingsAccount account, final DateTimeFormatter fmt,
|
||||
final LocalDate transactionDate, final BigDecimal transactionAmount, final PaymentDetail paymentDetail,
|
||||
final SavingsTransactionBooleanValues transactionBooleanValues) {
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
if (transactionBooleanValues.isRegularTransaction() && !account.allowWithdrawal()) { throw new DepositAccountTransactionNotAllowedException(
|
||||
account.getId(), "withdraw", account.depositAccountType()); }
|
||||
@@ -64,10 +73,14 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
|
||||
final MathContext mc = MathContext.DECIMAL64;
|
||||
if (account.isBeforeLastPostingPeriod(transactionDate)) {
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
account.postInterest(mc, today, transactionBooleanValues.isInterestTransfer());
|
||||
account.postInterest(mc, today, transactionBooleanValues.isInterestTransfer(),
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
} else {
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
account.calculateInterestUsing(mc, today, transactionBooleanValues.isInterestTransfer());
|
||||
account.calculateInterestUsing(mc, today, transactionBooleanValues.isInterestTransfer(),
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
}
|
||||
account.validateAccountBalanceDoesNotBecomeNegative(transactionAmount, transactionBooleanValues.isWithdrawBalance());
|
||||
saveTransactionToGenerateTransactionId(withdrawal);
|
||||
@@ -83,6 +96,11 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
|
||||
public SavingsAccountTransaction handleDeposit(final SavingsAccount account, final DateTimeFormatter fmt,
|
||||
final LocalDate transactionDate, final BigDecimal transactionAmount, final PaymentDetail paymentDetail,
|
||||
final boolean isAccountTransfer, final boolean isRegularTransaction) {
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
if (isRegularTransaction && !account.allowDeposit()) { throw new DepositAccountTransactionNotAllowedException(account.getId(),
|
||||
"deposit", account.depositAccountType()); }
|
||||
@@ -98,10 +116,13 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
|
||||
final MathContext mc = MathContext.DECIMAL64;
|
||||
if (account.isBeforeLastPostingPeriod(transactionDate)) {
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
account.postInterest(mc, today, isInterestTransfer);
|
||||
account.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
} else {
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer);
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
}
|
||||
|
||||
saveTransactionToGenerateTransactionId(deposit);
|
||||
|
||||
+73
-46
@@ -7,9 +7,9 @@ package org.mifosplatform.portfolio.savings.domain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.core.domain.LocalDateInterval;
|
||||
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||
@@ -30,7 +30,8 @@ public final class SavingsHelper {
|
||||
private final CompoundInterestHelper compoundInterestHelper = new CompoundInterestHelper();
|
||||
|
||||
public List<LocalDateInterval> determineInterestPostingPeriods(final LocalDate startInterestCalculationLocalDate,
|
||||
final LocalDate interestPostingUpToDate, final SavingsPostingInterestPeriodType postingPeriodType) {
|
||||
final LocalDate interestPostingUpToDate, final SavingsPostingInterestPeriodType postingPeriodType,
|
||||
final Integer financialYearBeginningMonth) {
|
||||
|
||||
final List<LocalDateInterval> postingPeriods = new ArrayList<>();
|
||||
|
||||
@@ -40,14 +41,10 @@ public final class SavingsHelper {
|
||||
while (!periodStartDate.isAfter(interestPostingUpToDate) && !periodEndDate.isAfter(interestPostingUpToDate)) {
|
||||
|
||||
final LocalDate interestPostingLocalDate = determineInterestPostingPeriodEndDateFrom(periodStartDate, postingPeriodType,
|
||||
interestPostingUpToDate);
|
||||
interestPostingUpToDate, financialYearBeginningMonth);
|
||||
periodEndDate = interestPostingLocalDate.minusDays(1);
|
||||
|
||||
if (!interestPostingLocalDate.isAfter(interestPostingUpToDate)) {
|
||||
postingPeriods.add(LocalDateInterval.create(periodStartDate, periodEndDate));
|
||||
} else {
|
||||
postingPeriods.add(LocalDateInterval.create(periodStartDate, periodEndDate));
|
||||
}
|
||||
postingPeriods.add(LocalDateInterval.create(periodStartDate, periodEndDate));
|
||||
|
||||
periodEndDate = interestPostingLocalDate;
|
||||
periodStartDate = interestPostingLocalDate;
|
||||
@@ -57,46 +54,76 @@ public final class SavingsHelper {
|
||||
}
|
||||
|
||||
private LocalDate determineInterestPostingPeriodEndDateFrom(final LocalDate periodStartDate,
|
||||
final SavingsPostingInterestPeriodType interestPostingPeriodType, final LocalDate interestPostingUpToDate) {
|
||||
final SavingsPostingInterestPeriodType interestPostingPeriodType, final LocalDate interestPostingUpToDate,
|
||||
Integer financialYearBeginningMonth) {
|
||||
|
||||
LocalDate periodEndDate = interestPostingUpToDate;
|
||||
|
||||
switch (interestPostingPeriodType) {
|
||||
case INVALID:
|
||||
break;
|
||||
case MONTHLY:
|
||||
// produce period end date on last day of current month
|
||||
periodEndDate = periodStartDate.dayOfMonth().withMaximumValue();
|
||||
break;
|
||||
case QUATERLY:
|
||||
// jan 1st to mar 31st, 1st apr to jun 30, jul 1st to sept 30,
|
||||
// oct 1st to dec 31
|
||||
final int year = periodStartDate.getYearOfEra();
|
||||
final int monthofYear = periodStartDate.getMonthOfYear();
|
||||
if (monthofYear <= 3) {
|
||||
periodEndDate = new DateTime().withDate(year, 3, 31).toLocalDate();
|
||||
} else if (monthofYear <= 6) {
|
||||
periodEndDate = new DateTime().withDate(year, 6, 30).toLocalDate();
|
||||
} else if (monthofYear <= 9) {
|
||||
periodEndDate = new DateTime().withDate(year, 9, 30).toLocalDate();
|
||||
} else if (monthofYear <= 12) {
|
||||
periodEndDate = new DateTime().withDate(year, 12, 31).toLocalDate();
|
||||
}
|
||||
break;
|
||||
case BIANNUAL:
|
||||
final int byear = periodStartDate.getYearOfEra();
|
||||
final int bmonthofYear = periodStartDate.getMonthOfYear();
|
||||
if (bmonthofYear <= 6) {
|
||||
periodEndDate = new DateTime().withDate(byear, 6, 30).toLocalDate();
|
||||
} else if (bmonthofYear <= 12) {
|
||||
periodEndDate = new DateTime().withDate(byear, 12, 31).toLocalDate();
|
||||
}
|
||||
break;
|
||||
case ANNUAL:
|
||||
periodEndDate = periodStartDate.monthOfYear().withMaximumValue();
|
||||
periodEndDate = periodEndDate.dayOfMonth().withMaximumValue();
|
||||
break;
|
||||
}
|
||||
final Integer monthOfYear = periodStartDate.getMonthOfYear();
|
||||
financialYearBeginningMonth--;
|
||||
if(financialYearBeginningMonth == 0)
|
||||
financialYearBeginningMonth = 12;
|
||||
|
||||
final ArrayList<LocalDate> quarterlyDates = new ArrayList<>();
|
||||
quarterlyDates.add(periodStartDate.withMonthOfYear(financialYearBeginningMonth).dayOfMonth().withMaximumValue());
|
||||
quarterlyDates.add(periodStartDate.withMonthOfYear(financialYearBeginningMonth)
|
||||
.plusMonths(3).withYear(periodStartDate.getYear()).dayOfMonth().withMaximumValue());
|
||||
quarterlyDates.add(periodStartDate.withMonthOfYear(financialYearBeginningMonth)
|
||||
.plusMonths(6).withYear(periodStartDate.getYear()).dayOfMonth().withMaximumValue());
|
||||
quarterlyDates.add(periodStartDate.withMonthOfYear(financialYearBeginningMonth)
|
||||
.plusMonths(9).withYear(periodStartDate.getYear()).dayOfMonth().withMaximumValue());
|
||||
Collections.sort(quarterlyDates);
|
||||
|
||||
final ArrayList<LocalDate> biannualDates = new ArrayList<>();
|
||||
biannualDates.add(periodStartDate.withMonthOfYear(financialYearBeginningMonth).dayOfMonth().withMaximumValue());
|
||||
biannualDates.add(periodStartDate.withMonthOfYear(financialYearBeginningMonth).plusMonths(6)
|
||||
.withYear(periodStartDate.getYear()).dayOfMonth().withMaximumValue());
|
||||
Collections.sort(biannualDates);
|
||||
|
||||
boolean isEndDateSet = false;
|
||||
|
||||
switch (interestPostingPeriodType) {
|
||||
case INVALID:
|
||||
break;
|
||||
case MONTHLY:
|
||||
// produce period end date on last day of current month
|
||||
periodEndDate = periodStartDate.dayOfMonth().withMaximumValue();
|
||||
break;
|
||||
case QUATERLY:
|
||||
for(LocalDate quarterlyDate : quarterlyDates) {
|
||||
if(quarterlyDate.isAfter(periodStartDate)) {
|
||||
periodEndDate = quarterlyDate;
|
||||
isEndDateSet = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!isEndDateSet)
|
||||
periodEndDate = quarterlyDates.get(0).plusYears(1).dayOfMonth().withMaximumValue();
|
||||
break;
|
||||
case BIANNUAL:
|
||||
for(LocalDate biannualDate : biannualDates) {
|
||||
if(biannualDate.isAfter(periodStartDate)) {
|
||||
periodEndDate = biannualDate;
|
||||
isEndDateSet = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!isEndDateSet)
|
||||
periodEndDate = biannualDates.get(0).plusYears(1).dayOfMonth().withMaximumValue();
|
||||
break;
|
||||
case ANNUAL:
|
||||
if (financialYearBeginningMonth < monthOfYear) {
|
||||
periodEndDate = periodStartDate
|
||||
.withMonthOfYear(financialYearBeginningMonth);
|
||||
periodEndDate = periodEndDate.plusYears(1);
|
||||
} else {
|
||||
periodEndDate = periodStartDate
|
||||
.withMonthOfYear(financialYearBeginningMonth);
|
||||
}
|
||||
periodEndDate = periodEndDate.dayOfMonth().withMaximumValue();
|
||||
break;
|
||||
}
|
||||
|
||||
// interest posting always occurs on next day after the period end date.
|
||||
periodEndDate = periodEndDate.plusDays(1);
|
||||
|
||||
+9
-5
@@ -52,7 +52,7 @@ public class PostingPeriod {
|
||||
final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
|
||||
final SavingsInterestCalculationType interestCalculationType, final BigDecimal interestRateAsFraction, final long daysInYear,
|
||||
final LocalDate upToInterestCalculationDate, Collection<Long> interestPostTransactions, boolean isInterestTransfer,
|
||||
final Money minBalanceForInterestCalculation) {
|
||||
final Money minBalanceForInterestCalculation, final boolean isSavingsInterestPostingAtCurrentPeriodEnd) {
|
||||
|
||||
final List<EndOfDayBalance> accountEndOfDayBalances = new ArrayList<>();
|
||||
boolean interestTransfered = false;
|
||||
@@ -113,13 +113,14 @@ public class PostingPeriod {
|
||||
|
||||
return new PostingPeriod(periodInterval, currency, periodStartingBalance, openingDayBalance, interestCompoundingPeriodType,
|
||||
interestCalculationType, interestRateAsFraction, daysInYear, compoundingPeriods, interestTransfered,
|
||||
minBalanceForInterestCalculation);
|
||||
minBalanceForInterestCalculation, isSavingsInterestPostingAtCurrentPeriodEnd);
|
||||
}
|
||||
|
||||
private PostingPeriod(final LocalDateInterval periodInterval, final MonetaryCurrency currency, final Money openingBalance,
|
||||
final Money closingBalance, final SavingsCompoundingInterestPeriodType interestCompoundingType,
|
||||
final SavingsInterestCalculationType interestCalculationType, final BigDecimal interestRateAsFraction, final long daysInYear,
|
||||
final List<CompoundingPeriod> compoundingPeriods, boolean interestTransfered, final Money minBalanceForInterestCalculation) {
|
||||
final List<CompoundingPeriod> compoundingPeriods, boolean interestTransfered, final Money minBalanceForInterestCalculation,
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd) {
|
||||
this.periodInterval = periodInterval;
|
||||
this.currency = currency;
|
||||
this.openingBalance = openingBalance;
|
||||
@@ -129,8 +130,11 @@ public class PostingPeriod {
|
||||
this.interestRateAsFraction = interestRateAsFraction;
|
||||
this.daysInYear = daysInYear;
|
||||
this.compoundingPeriods = compoundingPeriods;
|
||||
|
||||
this.dateOfPostingTransaction = periodInterval.endDate().plusDays(1);
|
||||
|
||||
if(isSavingsInterestPostingAtCurrentPeriodEnd)
|
||||
this.dateOfPostingTransaction = periodInterval.endDate();
|
||||
else
|
||||
this.dateOfPostingTransaction = periodInterval.endDate().plusDays(1);
|
||||
this.interestTransfered = interestTransfered;
|
||||
this.minBalanceForInterestCalculation = minBalanceForInterestCalculation;
|
||||
}
|
||||
|
||||
+17
-5
@@ -12,6 +12,7 @@ import java.util.Collection;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
|
||||
import org.mifosplatform.infrastructure.codes.service.CodeValueReadPlatformService;
|
||||
import org.mifosplatform.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonQuery;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||
@@ -41,17 +42,20 @@ public class DepositAccountPreMatureCalculationPlatformServiceImpl implements De
|
||||
private final DepositAccountAssembler depositAccountAssembler;
|
||||
private final CodeValueReadPlatformService codeValueReadPlatformService;
|
||||
private final SavingsAccountReadPlatformService savingsAccountReadPlatformService;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
|
||||
@Autowired
|
||||
public DepositAccountPreMatureCalculationPlatformServiceImpl(final FromJsonHelper fromJsonHelper,
|
||||
final DepositAccountTransactionDataValidator depositAccountTransactionDataValidator,
|
||||
final DepositAccountAssembler depositAccountAssembler, final CodeValueReadPlatformService codeValueReadPlatformService,
|
||||
final SavingsAccountReadPlatformService savingsAccountReadPlatformService) {
|
||||
final SavingsAccountReadPlatformService savingsAccountReadPlatformService,
|
||||
final ConfigurationDomainService configurationDomainService) {
|
||||
this.fromJsonHelper = fromJsonHelper;
|
||||
this.depositAccountTransactionDataValidator = depositAccountTransactionDataValidator;
|
||||
this.depositAccountAssembler = depositAccountAssembler;
|
||||
this.codeValueReadPlatformService = codeValueReadPlatformService;
|
||||
this.savingsAccountReadPlatformService = savingsAccountReadPlatformService;
|
||||
this.configurationDomainService = configurationDomainService;
|
||||
|
||||
}
|
||||
|
||||
@@ -59,6 +63,12 @@ public class DepositAccountPreMatureCalculationPlatformServiceImpl implements De
|
||||
@Override
|
||||
public DepositAccountData calculatePreMatureAmount(final Long accountId, final JsonQuery query,
|
||||
final DepositAccountType depositAccountType) {
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
this.depositAccountTransactionDataValidator.validatePreMatureAmountCalculation(query.json(), depositAccountType);
|
||||
final SavingsAccount account = this.depositAccountAssembler.assembleFrom(accountId, depositAccountType);
|
||||
|
||||
@@ -79,13 +89,15 @@ public class DepositAccountPreMatureCalculationPlatformServiceImpl implements De
|
||||
if (depositAccountType.isFixedDeposit()) {
|
||||
final FixedDepositAccount fd = (FixedDepositAccount) account;
|
||||
accountData = FixedDepositAccountData.preClosureDetails(account.getId(),
|
||||
fd.calculatePreMatureAmount(interestCalculatedToDate, isPreMatureClosure), onAccountClosureOptions, paymentTypeOptions,
|
||||
savingsAccountDatas);
|
||||
fd.calculatePreMatureAmount(interestCalculatedToDate, isPreMatureClosure,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth),
|
||||
onAccountClosureOptions, paymentTypeOptions, savingsAccountDatas);
|
||||
} else if (depositAccountType.isRecurringDeposit()) {
|
||||
final RecurringDepositAccount rd = (RecurringDepositAccount) account;
|
||||
accountData = RecurringDepositAccountData.preClosureDetails(account.getId(),
|
||||
rd.calculatePreMatureAmount(interestCalculatedToDate, isPreMatureClosure), onAccountClosureOptions, paymentTypeOptions,
|
||||
savingsAccountDatas);
|
||||
rd.calculatePreMatureAmount(interestCalculatedToDate, isPreMatureClosure,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth),
|
||||
onAccountClosureOptions, paymentTypeOptions, savingsAccountDatas);
|
||||
}
|
||||
|
||||
return accountData;
|
||||
|
||||
+133
-24
@@ -27,6 +27,7 @@ import org.joda.time.LocalDate;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
import org.mifosplatform.accounting.journalentry.service.JournalEntryWritePlatformService;
|
||||
import org.mifosplatform.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
@@ -121,6 +122,7 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
private final AccountTransfersWritePlatformService accountTransfersWritePlatformService;
|
||||
private final DepositAccountReadPlatformService depositAccountReadPlatformService;
|
||||
private final CalendarInstanceRepository calendarInstanceRepository;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
|
||||
@Autowired
|
||||
public DepositAccountWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
|
||||
@@ -140,7 +142,8 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
final AccountAssociationsReadPlatformService accountAssociationsReadPlatformService,
|
||||
final AccountTransfersWritePlatformService accountTransfersWritePlatformService,
|
||||
final DepositAccountReadPlatformService depositAccountReadPlatformService,
|
||||
final CalendarInstanceRepository calendarInstanceRepository) {
|
||||
final CalendarInstanceRepository calendarInstanceRepository,
|
||||
final ConfigurationDomainService configurationDomainService) {
|
||||
|
||||
this.context = context;
|
||||
this.savingAccountRepository = savingAccountRepository;
|
||||
@@ -162,6 +165,7 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
this.accountTransfersWritePlatformService = accountTransfersWritePlatformService;
|
||||
this.depositAccountReadPlatformService = depositAccountReadPlatformService;
|
||||
this.calendarInstanceRepository = calendarInstanceRepository;
|
||||
this.configurationDomainService = configurationDomainService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -169,6 +173,11 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
public CommandProcessingResult activateFDAccount(final Long savingsId, final JsonCommand command) {
|
||||
|
||||
final AppUser user = this.context.authenticatedUser();
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
this.depositAccountTransactionDataValidator.validateActivation(command);
|
||||
final MathContext mc = MathContext.DECIMAL64;
|
||||
@@ -208,17 +217,20 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
final boolean isInterestTransfer = false;
|
||||
if (account.isBeforeLastPostingPeriod(account.getActivationLocalDate())) {
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
account.postInterest(mc, today, isInterestTransfer);
|
||||
account.postInterest(mc, today, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
|
||||
} else {
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer);
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
|
||||
}
|
||||
|
||||
updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds);
|
||||
}
|
||||
|
||||
final boolean isPreMatureClosure = false;
|
||||
account.updateMaturityDateAndAmount(mc, isPreMatureClosure);
|
||||
account.updateMaturityDateAndAmount(mc, isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
account.validateAccountBalanceDoesNotBecomeNegative(SavingsAccountTransactionType.PAY_CHARGE.name());
|
||||
this.savingAccountRepository.save(account);
|
||||
}
|
||||
@@ -241,6 +253,11 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
boolean isRegularTransaction = false;
|
||||
|
||||
final AppUser user = this.context.authenticatedUser();
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
this.depositAccountTransactionDataValidator.validateActivation(command);
|
||||
|
||||
@@ -290,7 +307,9 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
Integer frequency = CalendarUtils.getInterval(calendar.getRecurrence());
|
||||
frequency = frequency == -1 ? 1 : frequency;
|
||||
account.generateSchedule(frequencyType, frequency, calendar);
|
||||
account.updateMaturityDateAndAmount(mc, isPreMatureClosure);
|
||||
account.updateMaturityDateAndAmount(mc, isPreMatureClosure,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
}
|
||||
|
||||
final LocalDate overdueUptoDate = account.maturityDate().isAfter(DateUtils.getLocalDateOfTenant()) ? DateUtils
|
||||
@@ -299,10 +318,14 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
final boolean isInterestTransfer = false;
|
||||
if (account.isBeforeLastPostingPeriod(account.getActivationLocalDate())) {
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
account.postInterest(mc, today, isInterestTransfer);
|
||||
account.postInterest(mc, today, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
} else {
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer);
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
}
|
||||
|
||||
account.validateAccountBalanceDoesNotBecomeNegative(SavingsAccountTransactionType.PAY_CHARGE.name());
|
||||
@@ -407,6 +430,11 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
@Override
|
||||
public CommandProcessingResult calculateInterest(final Long savingsId, final DepositAccountType depositAccountType) {
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
final SavingsAccount account = this.depositAccountAssembler.assembleFrom(savingsId, depositAccountType);
|
||||
checkClientOrGroupActive(account);
|
||||
|
||||
@@ -414,7 +442,9 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
final MathContext mc = new MathContext(15, RoundingMode.HALF_EVEN);
|
||||
boolean isInterestTransfer = false;
|
||||
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer);
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
|
||||
this.savingAccountRepository.save(account);
|
||||
|
||||
@@ -445,13 +475,21 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
|
||||
@Transactional
|
||||
private void postInterest(final SavingsAccount account) {
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
final Set<Long> existingTransactionIds = new HashSet<>();
|
||||
final Set<Long> existingReversedTransactionIds = new HashSet<>();
|
||||
updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds);
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
final MathContext mc = new MathContext(10, RoundingMode.HALF_EVEN);
|
||||
boolean isInterestTransfer = false;
|
||||
account.postInterest(mc, today, isInterestTransfer);
|
||||
account.postInterest(mc, today, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
this.savingAccountRepository.save(account);
|
||||
|
||||
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds);
|
||||
@@ -487,6 +525,11 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
@Override
|
||||
public CommandProcessingResult undoRDTransaction(final Long savingsId, final Long transactionId,
|
||||
final boolean allowAccountTransferModification) {
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
final RecurringDepositAccount account = (RecurringDepositAccount) this.depositAccountAssembler.assembleFrom(savingsId,
|
||||
DepositAccountType.RECURRING_DEPOSIT);
|
||||
@@ -514,14 +557,20 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
checkClientOrGroupActive(account);
|
||||
if (savingsAccountTransaction.isPostInterestCalculationRequired()
|
||||
&& account.isBeforeLastPostingPeriod(savingsAccountTransaction.transactionLocalDate())) {
|
||||
account.postInterest(mc, today, isInterestTransfer);
|
||||
account.postInterest(mc, today, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
} else {
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer);
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
}
|
||||
account.validateAccountBalanceDoesNotBecomeNegative(SavingsApiConstants.undoTransactionAction);
|
||||
// account.activateAccountBasedOnBalance();
|
||||
final boolean isPreMatureClosure = false;
|
||||
account.updateMaturityDateAndAmount(mc, isPreMatureClosure);
|
||||
account.updateMaturityDateAndAmount(mc, isPreMatureClosure,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
|
||||
final LocalDate overdueUptoDate = account.maturityDate().isAfter(DateUtils.getLocalDateOfTenant()) ? DateUtils
|
||||
.getLocalDateOfTenant() : account.maturityDate();
|
||||
@@ -553,6 +602,11 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
@Override
|
||||
public CommandProcessingResult adjustRDTransaction(final Long savingsId, final Long transactionId, final JsonCommand command) {
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
this.depositAccountTransactionDataValidator.validate(command, DepositAccountType.RECURRING_DEPOSIT);
|
||||
|
||||
final SavingsAccountTransaction savingsAccountTransaction = this.savingsAccountTransactionRepository
|
||||
@@ -601,9 +655,13 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
boolean isInterestTransfer = false;
|
||||
if (account.isBeforeLastPostingPeriod(transactionDate)
|
||||
|| account.isBeforeLastPostingPeriod(savingsAccountTransaction.transactionLocalDate())) {
|
||||
account.postInterest(mc, today, isInterestTransfer);
|
||||
account.postInterest(mc, today, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
} else {
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer);
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
}
|
||||
|
||||
account.validateAccountBalanceDoesNotBecomeNegative(SavingsApiConstants.adjustTransactionAction);
|
||||
@@ -788,6 +846,12 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
@Override
|
||||
public SavingsAccountTransaction initiateSavingsTransfer(final Long accountId, final LocalDate transferDate,
|
||||
final DepositAccountType depositAccountType) {
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
final SavingsAccount savingsAccount = this.depositAccountAssembler.assembleFrom(accountId, depositAccountType);
|
||||
|
||||
final Set<Long> existingTransactionIds = new HashSet<>();
|
||||
@@ -800,7 +864,9 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
savingsAccount.setStatus(SavingsAccountStatusType.TRANSFER_IN_PROGRESS.getValue());
|
||||
final MathContext mc = MathContext.DECIMAL64;
|
||||
boolean isInterestTransfer = false;
|
||||
savingsAccount.calculateInterestUsing(mc, transferDate, isInterestTransfer);
|
||||
savingsAccount.calculateInterestUsing(mc, transferDate, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
|
||||
this.savingsAccountTransactionRepository.save(newTransferTransaction);
|
||||
this.savingAccountRepository.save(savingsAccount);
|
||||
@@ -813,6 +879,12 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
@Override
|
||||
public SavingsAccountTransaction withdrawSavingsTransfer(final Long accountId, final LocalDate transferDate,
|
||||
final DepositAccountType depositAccountType) {
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
final SavingsAccount savingsAccount = this.depositAccountAssembler.assembleFrom(accountId, depositAccountType);
|
||||
|
||||
final Set<Long> existingTransactionIds = new HashSet<>();
|
||||
@@ -825,7 +897,9 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
savingsAccount.setStatus(SavingsAccountStatusType.ACTIVE.getValue());
|
||||
final MathContext mc = MathContext.DECIMAL64;
|
||||
boolean isInterestTransfer = false;
|
||||
savingsAccount.calculateInterestUsing(mc, transferDate, isInterestTransfer);
|
||||
savingsAccount.calculateInterestUsing(mc, transferDate, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
|
||||
this.savingsAccountTransactionRepository.save(withdrawtransferTransaction);
|
||||
this.savingAccountRepository.save(savingsAccount);
|
||||
@@ -845,7 +919,13 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
@Override
|
||||
public SavingsAccountTransaction acceptSavingsTransfer(final Long accountId, final LocalDate transferDate,
|
||||
final Office acceptedInOffice, final Staff fieldOfficer, final DepositAccountType depositAccountType) {
|
||||
final SavingsAccount savingsAccount = this.depositAccountAssembler.assembleFrom(accountId, depositAccountType);
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
final SavingsAccount savingsAccount = this.depositAccountAssembler.assembleFrom(accountId, depositAccountType);
|
||||
|
||||
final Set<Long> existingTransactionIds = new HashSet<>();
|
||||
final Set<Long> existingReversedTransactionIds = new HashSet<>();
|
||||
@@ -860,7 +940,9 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
}
|
||||
boolean isInterestTransfer = false;
|
||||
final MathContext mc = MathContext.DECIMAL64;
|
||||
savingsAccount.calculateInterestUsing(mc, transferDate, isInterestTransfer);
|
||||
savingsAccount.calculateInterestUsing(mc, transferDate, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
|
||||
this.savingsAccountTransactionRepository.save(acceptTransferTransaction);
|
||||
this.savingAccountRepository.save(savingsAccount);
|
||||
@@ -985,6 +1067,11 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
@SuppressWarnings("unused") final DepositAccountType depositAccountType) {
|
||||
|
||||
this.context.authenticatedUser();
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
final SavingsAccountCharge savingsAccountCharge = this.savingsAccountChargeRepository.findOneWithNotFoundDetection(
|
||||
savingsAccountChargeId, savingsAccountId);
|
||||
@@ -1002,10 +1089,14 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
final MathContext mc = MathContext.DECIMAL64;
|
||||
if (account.isBeforeLastPostingPeriod(savingsAccountCharge.getDueLocalDate())) {
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
account.postInterest(mc, today, isInterestTransfer);
|
||||
account.postInterest(mc, today, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
} else {
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer);
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
}
|
||||
|
||||
account.validateAccountBalanceDoesNotBecomeNegative(SavingsApiConstants.waiveChargeTransactionAction);
|
||||
@@ -1109,6 +1200,12 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
@Transactional
|
||||
private void payCharge(final SavingsAccountCharge savingsAccountCharge, final LocalDate transactionDate, final BigDecimal amountPaid,
|
||||
final DateTimeFormatter formatter) {
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
// Get Savings account from savings charge
|
||||
final SavingsAccount account = savingsAccountCharge.savingsAccount();
|
||||
this.depositAccountAssembler.assignSavingAccountHelpers(account);
|
||||
@@ -1120,10 +1217,14 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
final MathContext mc = MathContext.DECIMAL64;
|
||||
if (account.isBeforeLastPostingPeriod(transactionDate)) {
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
account.postInterest(mc, today, isInterestTransfer);
|
||||
account.postInterest(mc, today, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
} else {
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer);
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
}
|
||||
|
||||
account.validateAccountBalanceDoesNotBecomeNegative("." + SavingsAccountTransactionType.PAY_CHARGE.getCode());
|
||||
@@ -1136,15 +1237,23 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
||||
@Transactional
|
||||
@Override
|
||||
public void updateMaturityDetails(Long depositAccountId, DepositAccountType depositAccountType) {
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
final SavingsAccount account = this.depositAccountAssembler.assembleFrom(depositAccountId, depositAccountType);
|
||||
final Set<Long> existingTransactionIds = new HashSet<>();
|
||||
final Set<Long> existingReversedTransactionIds = new HashSet<>();
|
||||
updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds);
|
||||
|
||||
if (depositAccountType.isFixedDeposit()) {
|
||||
((FixedDepositAccount) account).updateMaturityStatus();
|
||||
((FixedDepositAccount) account).updateMaturityStatus(isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
} else if (depositAccountType.isRecurringDeposit()) {
|
||||
((RecurringDepositAccount) account).updateMaturityStatus();
|
||||
((RecurringDepositAccount) account).updateMaturityStatus(isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
}
|
||||
|
||||
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds);
|
||||
|
||||
+34
-5
@@ -19,6 +19,7 @@ import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
@@ -100,6 +101,7 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
|
||||
private final AccountAssociationsRepository accountAssociationsRepository;
|
||||
private final FromJsonHelper fromJsonHelper;
|
||||
private final CalendarInstanceRepository calendarInstanceRepository;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
|
||||
@Autowired
|
||||
public DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
|
||||
@@ -113,7 +115,8 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
|
||||
final FixedDepositAccountRepository fixedDepositAccountRepository,
|
||||
final RecurringDepositAccountRepository recurringDepositAccountRepository,
|
||||
final AccountAssociationsRepository accountAssociationsRepository, final FromJsonHelper fromJsonHelper,
|
||||
final CalendarInstanceRepository calendarInstanceRepository) {
|
||||
final CalendarInstanceRepository calendarInstanceRepository,
|
||||
final ConfigurationDomainService configurationDomainService) {
|
||||
this.context = context;
|
||||
this.savingAccountRepository = savingAccountRepository;
|
||||
this.depositAccountAssembler = depositAccountAssembler;
|
||||
@@ -131,6 +134,7 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
|
||||
this.accountAssociationsRepository = accountAssociationsRepository;
|
||||
this.fromJsonHelper = fromJsonHelper;
|
||||
this.calendarInstanceRepository = calendarInstanceRepository;
|
||||
this.configurationDomainService = configurationDomainService;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -167,6 +171,11 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
|
||||
try {
|
||||
this.depositAccountDataValidator.validateFixedDepositForSubmit(command.json());
|
||||
final AppUser submittedBy = this.context.authenticatedUser();
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
final FixedDepositAccount account = (FixedDepositAccount) this.depositAccountAssembler.assembleFrom(command, submittedBy,
|
||||
DepositAccountType.FIXED_DEPOSIT);
|
||||
@@ -174,7 +183,8 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
|
||||
final MathContext mc = MathContext.DECIMAL64;
|
||||
final boolean isPreMatureClosure = false;
|
||||
|
||||
account.updateMaturityDateAndAmountBeforeAccountActivation(mc, isPreMatureClosure);
|
||||
account.updateMaturityDateAndAmountBeforeAccountActivation(mc, isPreMatureClosure,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
|
||||
this.fixedDepositAccountRepository.save(account);
|
||||
|
||||
if (account.isAccountNumberRequiresAutoGeneration()) {
|
||||
@@ -217,6 +227,11 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
|
||||
try {
|
||||
this.depositAccountDataValidator.validateRecurringDepositForSubmit(command.json());
|
||||
final AppUser submittedBy = this.context.authenticatedUser();
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
final RecurringDepositAccount account = (RecurringDepositAccount) this.depositAccountAssembler.assembleFrom(command,
|
||||
submittedBy, DepositAccountType.RECURRING_DEPOSIT);
|
||||
@@ -242,7 +257,8 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
|
||||
frequency = frequency == -1 ? 1 : frequency;
|
||||
account.generateSchedule(frequencyType, frequency, calendar);
|
||||
final boolean isPreMatureClosure = false;
|
||||
account.updateMaturityDateAndAmount(mc, isPreMatureClosure);
|
||||
account.updateMaturityDateAndAmount(mc, isPreMatureClosure,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
|
||||
account.validateApplicableInterestRate();
|
||||
this.savingAccountRepository.save(account);
|
||||
|
||||
@@ -318,6 +334,11 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
|
||||
public CommandProcessingResult modifyFDApplication(final Long accountId, final JsonCommand command) {
|
||||
try {
|
||||
this.depositAccountDataValidator.validateFixedDepositForUpdate(command.json());
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
final Map<String, Object> changes = new LinkedHashMap<>(20);
|
||||
|
||||
@@ -331,7 +352,8 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
|
||||
updateFDAndRDCommonChanges(changes, command, account);
|
||||
final MathContext mc = MathContext.DECIMAL64;
|
||||
final boolean isPreMatureClosure = false;
|
||||
account.updateMaturityDateAndAmountBeforeAccountActivation(mc, isPreMatureClosure);
|
||||
account.updateMaturityDateAndAmountBeforeAccountActivation(mc, isPreMatureClosure,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
|
||||
this.savingAccountRepository.save(account);
|
||||
}
|
||||
|
||||
@@ -355,6 +377,11 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
|
||||
public CommandProcessingResult modifyRDApplication(final Long accountId, final JsonCommand command) {
|
||||
try {
|
||||
this.depositAccountDataValidator.validateRecurringDepositForUpdate(command.json());
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
final Map<String, Object> changes = new LinkedHashMap<>(20);
|
||||
|
||||
@@ -375,7 +402,9 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
|
||||
frequency = frequency == -1 ? 1 : frequency;
|
||||
account.generateSchedule(frequencyType, frequency, calendar);
|
||||
final boolean isPreMatureClosure = false;
|
||||
account.updateMaturityDateAndAmount(mc, isPreMatureClosure);
|
||||
account.updateMaturityDateAndAmount(mc, isPreMatureClosure,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
account.validateApplicableInterestRate();
|
||||
this.savingAccountRepository.save(account);
|
||||
|
||||
|
||||
+98
-16
@@ -28,6 +28,7 @@ import org.joda.time.LocalDate;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
import org.mifosplatform.accounting.journalentry.service.JournalEntryWritePlatformService;
|
||||
import org.mifosplatform.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||
@@ -113,6 +114,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
private final SavingsAccountChargeRepositoryWrapper savingsAccountChargeRepository;
|
||||
private final HolidayWritePlatformService holidayWritePlatformService;
|
||||
private final WorkingDaysWritePlatformService workingDaysWritePlatformService;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
|
||||
@Autowired
|
||||
public SavingsAccountWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
|
||||
@@ -131,7 +133,8 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
final HolidayWritePlatformService holidayWritePlatformService,
|
||||
final WorkingDaysWritePlatformService workingDaysWritePlatformService,
|
||||
final SavingsAccountDataValidator fromApiJsonDeserializer, final SavingsAccountRepositoryWrapper savingsRepository,
|
||||
final StaffRepositoryWrapper staffRepository) {
|
||||
final StaffRepositoryWrapper staffRepository,
|
||||
final ConfigurationDomainService configurationDomainService) {
|
||||
this.context = context;
|
||||
this.savingAccountRepository = savingAccountRepository;
|
||||
this.savingsAccountTransactionRepository = savingsAccountTransactionRepository;
|
||||
@@ -152,6 +155,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
|
||||
this.savingsRepository = savingsRepository;
|
||||
this.staffRepository = staffRepository;
|
||||
this.configurationDomainService = configurationDomainService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -192,6 +196,12 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
@Override
|
||||
public void processPostActiveActions(final SavingsAccount account, final DateTimeFormatter fmt, final Set<Long> existingTransactionIds,
|
||||
final Set<Long> existingReversedTransactionIds) {
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
Money amountForDeposit = account.activateWithBalance();
|
||||
boolean isRegularTransaction = false;
|
||||
if (amountForDeposit.isGreaterThanZero()) {
|
||||
@@ -200,7 +210,8 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
null, isAccountTransfer, isRegularTransaction);
|
||||
updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds);
|
||||
}
|
||||
account.processAccountUponActivation();
|
||||
account.processAccountUponActivation(isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
account.validateAccountBalanceDoesNotBecomeNegative(SavingsAccountTransactionType.PAY_CHARGE.name());
|
||||
}
|
||||
|
||||
@@ -304,6 +315,11 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult calculateInterest(final Long savingsId) {
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
|
||||
checkClientOrGroupActive(account);
|
||||
@@ -311,7 +327,9 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
final MathContext mc = new MathContext(15, RoundingMode.HALF_EVEN);
|
||||
boolean isInterestTransfer = false;
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer);
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
|
||||
this.savingAccountRepository.save(account);
|
||||
|
||||
@@ -342,6 +360,12 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
|
||||
@Transactional
|
||||
private void postInterest(final SavingsAccount account) {
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
if (account.getNominalAnnualInterestRate().compareTo(BigDecimal.ZERO) == 1) {
|
||||
final Set<Long> existingTransactionIds = new HashSet<>();
|
||||
final Set<Long> existingReversedTransactionIds = new HashSet<>();
|
||||
@@ -349,7 +373,8 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
final MathContext mc = new MathContext(10, RoundingMode.HALF_EVEN);
|
||||
boolean isInterestTransfer = false;
|
||||
account.postInterest(mc, today, isInterestTransfer);
|
||||
account.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
|
||||
// for generating transaction id's
|
||||
List<SavingsAccountTransaction> transactions = account.getTransactions();
|
||||
@@ -379,7 +404,12 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
@Override
|
||||
public CommandProcessingResult undoTransaction(final Long savingsId, final Long transactionId,
|
||||
final boolean allowAccountTransferModification) {
|
||||
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
|
||||
final Set<Long> existingTransactionIds = new HashSet<>();
|
||||
final Set<Long> existingReversedTransactionIds = new HashSet<>();
|
||||
@@ -419,9 +449,12 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
checkClientOrGroupActive(account);
|
||||
if (savingsAccountTransaction.isPostInterestCalculationRequired()
|
||||
&& account.isBeforeLastPostingPeriod(savingsAccountTransaction.transactionLocalDate())) {
|
||||
account.postInterest(mc, today, isInterestTransfer);
|
||||
account.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
} else {
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer);
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
}
|
||||
account.validateAccountBalanceDoesNotBecomeNegative(SavingsApiConstants.undoTransactionAction);
|
||||
account.activateAccountBasedOnBalance();
|
||||
@@ -438,6 +471,11 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult adjustSavingsTransaction(final Long savingsId, final Long transactionId, final JsonCommand command) {
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
final SavingsAccountTransaction savingsAccountTransaction = this.savingsAccountTransactionRepository
|
||||
.findOneByIdAndSavingsAccountId(transactionId, savingsId);
|
||||
@@ -495,9 +533,12 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
|
||||
if (account.isBeforeLastPostingPeriod(transactionDate)
|
||||
|| account.isBeforeLastPostingPeriod(savingsAccountTransaction.transactionLocalDate())) {
|
||||
account.postInterest(mc, today, isInterestTransfer);
|
||||
account.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
} else {
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer);
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
}
|
||||
account.validateAccountBalanceDoesNotBecomeNegative(SavingsApiConstants.adjustTransactionAction);
|
||||
account.activateAccountBasedOnBalance();
|
||||
@@ -597,6 +638,12 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
|
||||
@Override
|
||||
public SavingsAccountTransaction initiateSavingsTransfer(final Long accountId, final LocalDate transferDate) {
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
final SavingsAccount savingsAccount = this.savingAccountAssembler.assembleFrom(accountId);
|
||||
|
||||
final Set<Long> existingTransactionIds = new HashSet<>();
|
||||
@@ -609,7 +656,9 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
savingsAccount.setStatus(SavingsAccountStatusType.TRANSFER_IN_PROGRESS.getValue());
|
||||
final MathContext mc = MathContext.DECIMAL64;
|
||||
boolean isInterestTransfer = false;
|
||||
savingsAccount.calculateInterestUsing(mc, transferDate, isInterestTransfer);
|
||||
savingsAccount.calculateInterestUsing(mc, transferDate, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
|
||||
this.savingsAccountTransactionRepository.save(newTransferTransaction);
|
||||
this.savingAccountRepository.save(savingsAccount);
|
||||
@@ -621,6 +670,12 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
|
||||
@Override
|
||||
public SavingsAccountTransaction withdrawSavingsTransfer(final Long accountId, final LocalDate transferDate) {
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
final SavingsAccount savingsAccount = this.savingAccountAssembler.assembleFrom(accountId);
|
||||
|
||||
final Set<Long> existingTransactionIds = new HashSet<>();
|
||||
@@ -633,7 +688,9 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
savingsAccount.setStatus(SavingsAccountStatusType.ACTIVE.getValue());
|
||||
final MathContext mc = MathContext.DECIMAL64;
|
||||
boolean isInterestTransfer = false;
|
||||
savingsAccount.calculateInterestUsing(mc, transferDate, isInterestTransfer);
|
||||
savingsAccount.calculateInterestUsing(mc, transferDate, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
|
||||
this.savingsAccountTransactionRepository.save(withdrawtransferTransaction);
|
||||
this.savingAccountRepository.save(savingsAccount);
|
||||
@@ -653,6 +710,12 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
@Override
|
||||
public SavingsAccountTransaction acceptSavingsTransfer(final Long accountId, final LocalDate transferDate,
|
||||
final Office acceptedInOffice, final Staff fieldOfficer) {
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
final SavingsAccount savingsAccount = this.savingAccountAssembler.assembleFrom(accountId);
|
||||
|
||||
final Set<Long> existingTransactionIds = new HashSet<>();
|
||||
@@ -668,7 +731,9 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
}
|
||||
boolean isInterestTransfer = false;
|
||||
final MathContext mc = MathContext.DECIMAL64;
|
||||
savingsAccount.calculateInterestUsing(mc, transferDate, isInterestTransfer);
|
||||
savingsAccount.calculateInterestUsing(mc, transferDate, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
|
||||
this.savingsAccountTransactionRepository.save(acceptTransferTransaction);
|
||||
this.savingAccountRepository.save(savingsAccount);
|
||||
@@ -792,6 +857,11 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
public CommandProcessingResult waiveCharge(final Long savingsAccountId, final Long savingsAccountChargeId) {
|
||||
|
||||
this.context.authenticatedUser();
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
final SavingsAccountCharge savingsAccountCharge = this.savingsAccountChargeRepository.findOneWithNotFoundDetection(
|
||||
savingsAccountChargeId, savingsAccountId);
|
||||
@@ -809,10 +879,13 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
final MathContext mc = MathContext.DECIMAL64;
|
||||
if (account.isBeforeLastPostingPeriod(savingsAccountCharge.getDueLocalDate())) {
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
account.postInterest(mc, today, isInterestTransfer);
|
||||
account.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
} else {
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer);
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
}
|
||||
|
||||
account.validateAccountBalanceDoesNotBecomeNegative(SavingsApiConstants.waiveChargeTransactionAction);
|
||||
@@ -914,6 +987,12 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
@Transactional
|
||||
private void payCharge(final SavingsAccountCharge savingsAccountCharge, final LocalDate transactionDate, final BigDecimal amountPaid,
|
||||
final DateTimeFormatter formatter) {
|
||||
|
||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
|
||||
.isSavingsInterestPostingAtCurrentPeriodEnd();
|
||||
final Integer financialYearBeginningMonth = this.configurationDomainService
|
||||
.retrieveFinancialYearBeginningMonth();
|
||||
|
||||
// Get Savings account from savings charge
|
||||
final SavingsAccount account = savingsAccountCharge.savingsAccount();
|
||||
this.savingAccountAssembler.assignSavingAccountHelpers(account);
|
||||
@@ -925,10 +1004,13 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
final MathContext mc = MathContext.DECIMAL64;
|
||||
if (account.isBeforeLastPostingPeriod(transactionDate)) {
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
account.postInterest(mc, today, isInterestTransfer);
|
||||
account.postInterest(mc, today, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
} else {
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer);
|
||||
account.calculateInterestUsing(mc, today, isInterestTransfer,
|
||||
isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
}
|
||||
|
||||
account.validateAccountBalanceDoesNotBecomeNegative("." + SavingsAccountTransactionType.PAY_CHARGE.getCode());
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
ALTER TABLE c_configuration ADD `description` varchar(300) DEFAULT NULL;
|
||||
|
||||
INSERT INTO `c_configuration` (`id`, `name`, `enabled`, `description`)
|
||||
VALUES (NULL, 'savings-interest-posting-current-period-end', '0', "Recommended to be changed only once during start of production. When set as false(default), interest will be posted on the first date of next period. If set as true, interest will be posted on last date of current period. There is no difference in the interest amount posted.");
|
||||
|
||||
INSERT INTO `c_configuration` (`id`, `name`, `value`, `enabled`, `description`)
|
||||
VALUES (NULL, 'financial-year-beginning-month', '1', '1', "Recommended to be changed only once during start of production. Allowed values 1 - 12 (January - December). Interest posting periods are evaluated based on this configuration.");
|
||||
Reference in New Issue
Block a user