Skip to content

Commit 25f4aef

Browse files
committed
FINERACT-2312: Accruals added for savings accounts (apache#4885)
1 parent 314f28e commit 25f4aef

File tree

24 files changed

+1073
-5
lines changed

24 files changed

+1073
-5
lines changed

fineract-core/src/main/java/org/apache/fineract/infrastructure/jobs/service/JobName.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public enum JobName {
5858
PURGE_EXTERNAL_EVENTS("Purge External Events"), //
5959
PURGE_PROCESSED_COMMANDS("Purge Processed Commands"), //
6060
ACCRUAL_ACTIVITY_POSTING("Accrual Activity Posting"), //
61-
;
61+
ADD_PERIODIC_ACCRUAL_ENTRIES_FOR_SAVINGS_WITH_INCOME_POSTED_AS_TRANSACTIONS("Add Accrual Transactions For Savings"); //
6262

6363
private final String name;
6464

fineract-core/src/main/java/org/apache/fineract/portfolio/savings/SavingsApiConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ public class SavingsApiConstants {
104104
public static final String activeParamName = "active";
105105
public static final String nameParamName = "name";
106106
public static final String shortNameParamName = "shortName";
107+
public static final String interestReceivableAccount = "interestReceivableAccountId";
107108
public static final String descriptionParamName = "description";
108109
public static final String currencyCodeParamName = "currencyCode";
109110
public static final String digitsAfterDecimalParamName = "digitsAfterDecimal";

fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/interest/PostingPeriod.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ public final class PostingPeriod {
6464

6565
private Integer financialYearBeginningMonth;
6666

67+
public void setOverdraftInterestRateAsFraction(BigDecimal overdraftInterestRateAsFraction) {
68+
this.overdraftInterestRateAsFraction = overdraftInterestRateAsFraction;
69+
}
70+
6771
public static PostingPeriod createFrom(final LocalDateInterval periodInterval, final Money periodStartingBalance,
6872
final List<SavingsAccountTransactionDetailsForPostingPeriod> orderedListOfTransactions, final MonetaryCurrency currency,
6973
final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
@@ -545,4 +549,10 @@ public Integer getFinancialYearBeginningMonth() {
545549
return this.financialYearBeginningMonth;
546550
}
547551

552+
// public List<CompoundingPeriod> getCompoundingPeriods() {return compoundingPeriods;}
553+
554+
public Money getClosingBalance() {
555+
return closingBalance;
556+
}
557+
548558
}

fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccrualBasedAccountingProcessorForSavings.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.apache.fineract.accounting.journalentry.data.ChargePaymentDTO;
2929
import org.apache.fineract.accounting.journalentry.data.SavingsDTO;
3030
import org.apache.fineract.accounting.journalentry.data.SavingsTransactionDTO;
31+
import org.apache.fineract.infrastructure.core.service.MathUtil;
3132
import org.apache.fineract.organisation.office.domain.Office;
3233
import org.springframework.stereotype.Component;
3334

@@ -182,9 +183,21 @@ else if (savingsTransactionDTO.getTransactionType().isInterestPosting()) {
182183
else if (savingsTransactionDTO.getTransactionType().isAccrual()) {
183184
// Post journal entry for Accrual Recognition
184185
if (savingsTransactionDTO.getAmount().compareTo(BigDecimal.ZERO) > 0) {
185-
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
186-
AccrualAccountsForSavings.INTEREST_ON_SAVINGS.getValue(), AccrualAccountsForSavings.INTEREST_PAYABLE.getValue(),
187-
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
186+
if (MathUtil.isGreaterThanZero(overdraftAmount)) {
187+
this.helper.createAccrualBasedDebitJournalEntriesAndReversalsForSavings(office, currencyCode,
188+
AccrualAccountsForSavings.INTEREST_ON_SAVINGS.getValue(), savingsProductId, paymentTypeId, savingsId,
189+
transactionId, transactionDate, amount, isReversal);
190+
this.helper.createAccrualBasedCreditJournalEntriesAndReversalsForSavings(office, currencyCode,
191+
AccrualAccountsForSavings.INTEREST_PAYABLE.getValue(), savingsProductId, paymentTypeId, savingsId,
192+
transactionId, transactionDate, amount, isReversal);
193+
} else {
194+
this.helper.createAccrualBasedDebitJournalEntriesAndReversalsForSavings(office, currencyCode,
195+
AccrualAccountsForSavings.INTEREST_RECEIVABLE.getValue(), savingsProductId, paymentTypeId, savingsId,
196+
transactionId, transactionDate, amount, isReversal);
197+
this.helper.createAccrualBasedCreditJournalEntriesAndReversalsForSavings(office, currencyCode,
198+
AccrualAccountsForSavings.INCOME_FROM_INTEREST.getValue(), savingsProductId, paymentTypeId, savingsId,
199+
transactionId, transactionDate, amount, isReversal);
200+
}
188201
}
189202
}
190203

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.fineract.portfolio.savings.jobs.addaccrualtransactionforsavings;
20+
21+
import org.apache.fineract.infrastructure.jobs.service.JobName;
22+
import org.apache.fineract.portfolio.savings.service.SavingsAccrualWritePlatformService;
23+
import org.springframework.batch.core.Job;
24+
import org.springframework.batch.core.Step;
25+
import org.springframework.batch.core.job.builder.JobBuilder;
26+
import org.springframework.batch.core.launch.support.RunIdIncrementer;
27+
import org.springframework.batch.core.repository.JobRepository;
28+
import org.springframework.batch.core.step.builder.StepBuilder;
29+
import org.springframework.beans.factory.annotation.Autowired;
30+
import org.springframework.context.annotation.Bean;
31+
import org.springframework.context.annotation.Configuration;
32+
import org.springframework.transaction.PlatformTransactionManager;
33+
34+
@Configuration
35+
public class AddAccrualTransactionForSavingsConfig {
36+
37+
@Autowired
38+
private JobRepository jobRepository;
39+
@Autowired
40+
private PlatformTransactionManager transactionManager;
41+
@Autowired
42+
private SavingsAccrualWritePlatformService savingsAccrualWritePlatformService;
43+
44+
@Bean
45+
protected Step addAccrualTransactionForSavingsStep() {
46+
return new StepBuilder(JobName.ADD_PERIODIC_ACCRUAL_ENTRIES_FOR_SAVINGS_WITH_INCOME_POSTED_AS_TRANSACTIONS.name(), jobRepository)
47+
.tasklet(addAccrualTransactionForSavingsTasklet(), transactionManager).build();
48+
}
49+
50+
@Bean
51+
public Job addAccrualTransactionForSavingsJob() {
52+
return new JobBuilder(JobName.ADD_PERIODIC_ACCRUAL_ENTRIES_FOR_SAVINGS_WITH_INCOME_POSTED_AS_TRANSACTIONS.name(), jobRepository)
53+
.start(addAccrualTransactionForSavingsStep()).incrementer(new RunIdIncrementer()).build();
54+
}
55+
56+
@Bean
57+
public AddAccrualTransactionForSavingsTasklet addAccrualTransactionForSavingsTasklet() {
58+
return new AddAccrualTransactionForSavingsTasklet(savingsAccrualWritePlatformService);
59+
}
60+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.fineract.portfolio.savings.jobs.addaccrualtransactionforsavings;
20+
21+
import java.time.LocalDate;
22+
import lombok.RequiredArgsConstructor;
23+
import org.apache.fineract.infrastructure.core.exception.MultiException;
24+
import org.apache.fineract.infrastructure.core.service.DateUtils;
25+
import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
26+
import org.apache.fineract.portfolio.savings.service.SavingsAccrualWritePlatformService;
27+
import org.springframework.batch.core.StepContribution;
28+
import org.springframework.batch.core.scope.context.ChunkContext;
29+
import org.springframework.batch.core.step.tasklet.Tasklet;
30+
import org.springframework.batch.repeat.RepeatStatus;
31+
32+
@RequiredArgsConstructor
33+
public class AddAccrualTransactionForSavingsTasklet implements Tasklet {
34+
35+
private final SavingsAccrualWritePlatformService savingsAccrualWritePlatformService;
36+
37+
@Override
38+
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
39+
try {
40+
addPeriodicAccruals(DateUtils.getBusinessLocalDate());
41+
} catch (MultiException e) {
42+
throw new JobExecutionException(e);
43+
}
44+
return RepeatStatus.FINISHED;
45+
}
46+
47+
private void addPeriodicAccruals(final LocalDate tilldate) throws MultiException {
48+
savingsAccrualWritePlatformService.addAccrualEntries(tilldate);
49+
}
50+
}

fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@
6464
import org.apache.fineract.portfolio.savings.data.SavingsAccountSummaryData;
6565
import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionData;
6666
import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionEnumData;
67+
import org.apache.fineract.portfolio.savings.data.SavingsAccrualData;
6768
import org.apache.fineract.portfolio.savings.data.SavingsProductData;
69+
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
6870
import org.apache.fineract.portfolio.savings.domain.SavingsAccountAssembler;
6971
import org.apache.fineract.portfolio.savings.domain.SavingsAccountChargesPaidByData;
7072
import org.apache.fineract.portfolio.savings.domain.SavingsAccountRepositoryWrapper;
@@ -1386,4 +1388,13 @@ public List<Long> getAccountsIdsByStatusPaged(Integer status, int pageSize, Long
13861388
public Long retrieveAccountIdByExternalId(final ExternalId externalId) {
13871389
return savingsAccountRepositoryWrapper.findIdByExternalId(externalId);
13881390
}
1391+
1392+
@Override
1393+
public List<SavingsAccrualData> retrievePeriodicAccrualData(LocalDate tillDate, SavingsAccount savings) {
1394+
Long savingsId = (savings != null) ? savings.getId() : null;
1395+
Integer status = SavingsAccountStatusType.ACTIVE.getValue();
1396+
Integer accountingRule = AccountingRuleType.ACCRUAL_PERIODIC.getValue();
1397+
1398+
return this.savingsAccountRepositoryWrapper.findAccrualData(tillDate, savingsId, status, accountingRule);
1399+
}
13891400
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.fineract.portfolio.savings.service;
20+
21+
import java.time.LocalDate;
22+
import org.apache.fineract.infrastructure.core.exception.MultiException;
23+
24+
public interface SavingsAccrualWritePlatformService {
25+
26+
void addAccrualEntries(LocalDate tillDate) throws MultiException;
27+
28+
}

0 commit comments

Comments
 (0)