blob: 4aa1b935bd8f158f9f5209fea0cb933d122f7741 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.accounting.journalentry.service;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.accounting.closure.domain.GLClosure;
import org.apache.fineract.accounting.common.AccountingConstants.AccrualAccountsForSavings;
import org.apache.fineract.accounting.common.AccountingConstants.FinancialActivity;
import org.apache.fineract.accounting.journalentry.data.ChargePaymentDTO;
import org.apache.fineract.accounting.journalentry.data.SavingsDTO;
import org.apache.fineract.accounting.journalentry.data.SavingsTransactionDTO;
import org.apache.fineract.organisation.office.domain.Office;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class AccrualBasedAccountingProcessorForSavings implements AccountingProcessorForSavings {
private final AccountingProcessorHelper helper;
@Override
public void createJournalEntriesForSavings(final SavingsDTO savingsDTO) {
final GLClosure latestGLClosure = this.helper.getLatestClosureByBranch(savingsDTO.getOfficeId());
final Long savingsProductId = savingsDTO.getSavingsProductId();
final Long savingsId = savingsDTO.getSavingsId();
final String currencyCode = savingsDTO.getCurrencyCode();
for (final SavingsTransactionDTO savingsTransactionDTO : savingsDTO.getNewSavingsTransactions()) {
final LocalDate transactionDate = savingsTransactionDTO.getTransactionDate();
final String transactionId = savingsTransactionDTO.getTransactionId();
final Office office = this.helper.getOfficeById(savingsTransactionDTO.getOfficeId());
final Long paymentTypeId = savingsTransactionDTO.getPaymentTypeId();
final boolean isReversal = savingsTransactionDTO.isReversed();
final BigDecimal amount = savingsTransactionDTO.getAmount();
final BigDecimal overdraftAmount = savingsTransactionDTO.getOverdraftAmount();
final List<ChargePaymentDTO> feePayments = savingsTransactionDTO.getFeePayments();
final List<ChargePaymentDTO> penaltyPayments = savingsTransactionDTO.getPenaltyPayments();
this.helper.checkForBranchClosures(latestGLClosure, transactionDate);
if (savingsTransactionDTO.getTransactionType().isWithdrawal() && savingsTransactionDTO.isOverdraftTransaction()) {
boolean isPositive = amount.subtract(overdraftAmount).compareTo(BigDecimal.ZERO) > 0;
if (savingsTransactionDTO.isAccountTransfer()) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
AccrualAccountsForSavings.OVERDRAFT_PORTFOLIO_CONTROL.getValue(),
FinancialActivity.LIABILITY_TRANSFER.getValue(), savingsProductId, paymentTypeId, savingsId, transactionId,
transactionDate, overdraftAmount, isReversal);
if (isPositive) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
AccrualAccountsForSavings.SAVINGS_CONTROL.getValue(), FinancialActivity.LIABILITY_TRANSFER.getValue(),
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate,
amount.subtract(overdraftAmount), isReversal);
}
} else {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
AccrualAccountsForSavings.OVERDRAFT_PORTFOLIO_CONTROL.getValue(),
AccrualAccountsForSavings.SAVINGS_REFERENCE.getValue(), savingsProductId, paymentTypeId, savingsId,
transactionId, transactionDate, overdraftAmount, isReversal);
if (isPositive) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
AccrualAccountsForSavings.SAVINGS_CONTROL.getValue(),
AccrualAccountsForSavings.SAVINGS_REFERENCE.getValue(), savingsProductId, paymentTypeId, savingsId,
transactionId, transactionDate, amount.subtract(overdraftAmount), isReversal);
}
}
}
else if (savingsTransactionDTO.getTransactionType().isDeposit() && savingsTransactionDTO.isOverdraftTransaction()) {
boolean isPositive = amount.subtract(overdraftAmount).compareTo(BigDecimal.ZERO) > 0;
if (savingsTransactionDTO.isAccountTransfer()) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
FinancialActivity.LIABILITY_TRANSFER.getValue(),
AccrualAccountsForSavings.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), savingsProductId, paymentTypeId, savingsId,
transactionId, transactionDate, overdraftAmount, isReversal);
if (isPositive) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
FinancialActivity.LIABILITY_TRANSFER.getValue(), AccrualAccountsForSavings.SAVINGS_CONTROL.getValue(),
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate,
amount.subtract(overdraftAmount), isReversal);
}
} else {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
AccrualAccountsForSavings.SAVINGS_REFERENCE.getValue(),
AccrualAccountsForSavings.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), savingsProductId, paymentTypeId, savingsId,
transactionId, transactionDate, overdraftAmount, isReversal);
if (isPositive) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
AccrualAccountsForSavings.SAVINGS_REFERENCE.getValue(),
AccrualAccountsForSavings.SAVINGS_CONTROL.getValue(), savingsProductId, paymentTypeId, savingsId,
transactionId, transactionDate, amount.subtract(overdraftAmount), isReversal);
}
}
}
/** Handle Deposits and reversals of deposits **/
else if (savingsTransactionDTO.getTransactionType().isDeposit()) {
if (savingsTransactionDTO.isAccountTransfer()) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
FinancialActivity.LIABILITY_TRANSFER.getValue(), AccrualAccountsForSavings.SAVINGS_CONTROL.getValue(),
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
} else {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
AccrualAccountsForSavings.SAVINGS_REFERENCE.getValue(), AccrualAccountsForSavings.SAVINGS_CONTROL.getValue(),
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
}
}
/** Handle Deposits and reversals of Dividend pay outs **/
else if (savingsTransactionDTO.getTransactionType().isDividendPayout()) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
FinancialActivity.PAYABLE_DIVIDENDS.getValue(), AccrualAccountsForSavings.SAVINGS_CONTROL.getValue(),
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
}
/** Handle withdrawals and reversals of withdrawals **/
else if (savingsTransactionDTO.getTransactionType().isWithdrawal()) {
if (savingsTransactionDTO.isAccountTransfer()) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
AccrualAccountsForSavings.SAVINGS_CONTROL.getValue(), FinancialActivity.LIABILITY_TRANSFER.getValue(),
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
} else {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
AccrualAccountsForSavings.SAVINGS_CONTROL.getValue(), AccrualAccountsForSavings.SAVINGS_REFERENCE.getValue(),
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
}
}
else if (savingsTransactionDTO.getTransactionType().isEscheat()) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
AccrualAccountsForSavings.SAVINGS_CONTROL.getValue(), AccrualAccountsForSavings.ESCHEAT_LIABILITY.getValue(),
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
}
/**
* Handle Interest Applications and reversals of Interest Applications
**/
else if (savingsTransactionDTO.getTransactionType().isInterestPosting() && savingsTransactionDTO.isOverdraftTransaction()) {
boolean isPositive = amount.subtract(overdraftAmount).compareTo(BigDecimal.ZERO) > 0;
// Post journal entry if earned interest amount is greater than
// zero
if (savingsTransactionDTO.getAmount().compareTo(BigDecimal.ZERO) > 0) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
AccrualAccountsForSavings.INTEREST_ON_SAVINGS.getValue(),
AccrualAccountsForSavings.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), savingsProductId, paymentTypeId, savingsId,
transactionId, transactionDate, overdraftAmount, isReversal);
if (isPositive) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
AccrualAccountsForSavings.INTEREST_ON_SAVINGS.getValue(),
AccrualAccountsForSavings.SAVINGS_CONTROL.getValue(), savingsProductId, paymentTypeId, savingsId,
transactionId, transactionDate, amount.subtract(overdraftAmount), isReversal);
}
}
}
else if (savingsTransactionDTO.getTransactionType().isInterestPosting()) {
// Post journal entry if earned interest amount is greater than
// zero
if (savingsTransactionDTO.getAmount().compareTo(BigDecimal.ZERO) > 0) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
AccrualAccountsForSavings.INTEREST_PAYABLE.getValue(), AccrualAccountsForSavings.SAVINGS_CONTROL.getValue(),
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
}
}
else if (savingsTransactionDTO.getTransactionType().isAccrual()) {
// Post journal entry for Accrual Recognition
if (savingsTransactionDTO.getAmount().compareTo(BigDecimal.ZERO) > 0) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
AccrualAccountsForSavings.INTEREST_ON_SAVINGS.getValue(), AccrualAccountsForSavings.INTEREST_PAYABLE.getValue(),
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
}
}
else if (savingsTransactionDTO.getTransactionType().isWithholdTax()) {
this.helper.createAccrualBasedJournalEntriesAndReversalsForSavingsTax(office, currencyCode,
AccrualAccountsForSavings.SAVINGS_CONTROL, AccrualAccountsForSavings.SAVINGS_REFERENCE, savingsProductId,
paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal,
savingsTransactionDTO.getTaxPayments());
}
/** Handle Fees Deductions and reversals of Fees Deductions **/
else if (savingsTransactionDTO.getTransactionType().isFeeDeduction() && savingsTransactionDTO.isOverdraftTransaction()) {
boolean isPositive = amount.subtract(overdraftAmount).compareTo(BigDecimal.ZERO) > 0;
// Is the Charge a penalty?
if (penaltyPayments.size() > 0) {
this.helper.createAccrualBasedJournalEntriesAndReversalsForSavingsCharges(office, currencyCode,
AccrualAccountsForSavings.OVERDRAFT_PORTFOLIO_CONTROL, AccrualAccountsForSavings.INCOME_FROM_PENALTIES,
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, overdraftAmount, isReversal,
penaltyPayments);
if (isPositive) {
this.helper.createAccrualBasedJournalEntriesAndReversalsForSavingsCharges(office, currencyCode,
AccrualAccountsForSavings.SAVINGS_CONTROL, AccrualAccountsForSavings.INCOME_FROM_PENALTIES,
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate,
amount.subtract(overdraftAmount), isReversal, penaltyPayments);
}
} else {
this.helper.createAccrualBasedJournalEntriesAndReversalsForSavingsCharges(office, currencyCode,
AccrualAccountsForSavings.OVERDRAFT_PORTFOLIO_CONTROL, AccrualAccountsForSavings.INCOME_FROM_FEES,
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, overdraftAmount, isReversal,
feePayments);
if (isPositive) {
this.helper.createAccrualBasedJournalEntriesAndReversalsForSavingsCharges(office, currencyCode,
AccrualAccountsForSavings.SAVINGS_CONTROL, AccrualAccountsForSavings.INCOME_FROM_FEES, savingsProductId,
paymentTypeId, savingsId, transactionId, transactionDate, amount.subtract(overdraftAmount), isReversal,
feePayments);
}
}
}
else if (savingsTransactionDTO.getTransactionType().isFeeDeduction()) {
// Is the Charge a penalty?
if (penaltyPayments.size() > 0) {
this.helper.createAccrualBasedJournalEntriesAndReversalsForSavingsCharges(office, currencyCode,
AccrualAccountsForSavings.SAVINGS_CONTROL, AccrualAccountsForSavings.INCOME_FROM_PENALTIES, savingsProductId,
paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal, penaltyPayments);
} else {
this.helper.createAccrualBasedJournalEntriesAndReversalsForSavingsCharges(office, currencyCode,
AccrualAccountsForSavings.SAVINGS_CONTROL, AccrualAccountsForSavings.INCOME_FROM_FEES, savingsProductId,
paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal, feePayments);
}
}
/** Handle Transfers proposal **/
else if (savingsTransactionDTO.getTransactionType().isInitiateTransfer()) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
AccrualAccountsForSavings.SAVINGS_CONTROL.getValue(), AccrualAccountsForSavings.TRANSFERS_SUSPENSE.getValue(),
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
}
/** Handle Transfer Withdrawal or Acceptance **/
else if (savingsTransactionDTO.getTransactionType().isWithdrawTransfer()
|| savingsTransactionDTO.getTransactionType().isApproveTransfer()) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
AccrualAccountsForSavings.TRANSFERS_SUSPENSE.getValue(), AccrualAccountsForSavings.SAVINGS_CONTROL.getValue(),
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
}
/** overdraft **/
else if (savingsTransactionDTO.getTransactionType().isOverdraftInterest()) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
AccrualAccountsForSavings.SAVINGS_REFERENCE.getValue(), AccrualAccountsForSavings.INCOME_FROM_INTEREST.getValue(),
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
} else if (savingsTransactionDTO.getTransactionType().isWrittenoff()) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
AccrualAccountsForSavings.LOSSES_WRITTEN_OFF.getValue(),
AccrualAccountsForSavings.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), savingsProductId, paymentTypeId, savingsId,
transactionId, transactionDate, amount, isReversal);
} else if (savingsTransactionDTO.getTransactionType().isOverdraftFee()) {
this.helper.createAccrualBasedJournalEntriesAndReversalsForSavingsCharges(office, currencyCode,
AccrualAccountsForSavings.SAVINGS_REFERENCE, AccrualAccountsForSavings.INCOME_FROM_FEES, savingsProductId,
paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal, feePayments);
}
}
}
}