FINERACT-1960: GL account mappings to use Savings product with Accrual accounting
This commit is contained in:
committed by
Adam Saghy
parent
051b37c4b3
commit
6ee881b89a
+3
@@ -40,6 +40,9 @@ public class AccountingProcessorForSavingsFactory {
|
||||
if (savingsDTO.isCashBasedAccountingEnabled()) {
|
||||
accountingProcessorForSavings = this.applicationContext.getBean("cashBasedAccountingProcessorForSavings",
|
||||
AccountingProcessorForSavings.class);
|
||||
} else if (savingsDTO.isAccrualBasedAccountingEnabled()) {
|
||||
accountingProcessorForSavings = this.applicationContext.getBean("accrualBasedAccountingProcessorForSavings",
|
||||
AccountingProcessorForSavings.class);
|
||||
}
|
||||
|
||||
return accountingProcessorForSavings;
|
||||
|
||||
+108
@@ -30,6 +30,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.accounting.closure.domain.GLClosure;
|
||||
import org.apache.fineract.accounting.closure.domain.GLClosureRepository;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.AccrualAccountsForLoan;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.AccrualAccountsForSavings;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.CashAccountsForLoan;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.CashAccountsForSavings;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.CashAccountsForShares;
|
||||
@@ -573,6 +574,28 @@ public class AccountingProcessorHelper {
|
||||
paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
|
||||
}
|
||||
|
||||
public void createAccrualBasedJournalEntriesAndReversalsForSavingsTax(final Office office, final String currencyCode,
|
||||
final AccrualAccountsForSavings accountTypeToBeDebited, final AccrualAccountsForSavings accountTypeToBeCredited,
|
||||
final Long savingsProductId, final Long paymentTypeId, final Long savingsId, final String transactionId,
|
||||
final LocalDate transactionDate, final BigDecimal amount, final Boolean isReversal, final List<TaxPaymentDTO> taxDetails) {
|
||||
|
||||
for (TaxPaymentDTO taxPaymentDTO : taxDetails) {
|
||||
if (taxPaymentDTO.getAmount() != null) {
|
||||
if (taxPaymentDTO.getCreditAccountId() == null) {
|
||||
createAccrualBasedCreditJournalEntriesAndReversalsForSavings(office, currencyCode, accountTypeToBeCredited.getValue(),
|
||||
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, taxPaymentDTO.getAmount(),
|
||||
isReversal);
|
||||
} else {
|
||||
createAccrualBasedBasedCreditJournalEntriesAndReversalsForSavings(office, currencyCode,
|
||||
taxPaymentDTO.getCreditAccountId(), savingsId, transactionId, transactionDate, taxPaymentDTO.getAmount(),
|
||||
isReversal);
|
||||
}
|
||||
}
|
||||
}
|
||||
createAccrualBasedDebitJournalEntriesAndReversalsForSavings(office, currencyCode, accountTypeToBeDebited.getValue(),
|
||||
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
|
||||
}
|
||||
|
||||
public void createCashBasedDebitJournalEntriesAndReversalsForSavings(final Office office, final String currencyCode,
|
||||
final Integer accountTypeToBeDebited, final Long savingsProductId, final Long paymentTypeId, final Long savingsId,
|
||||
final String transactionId, final LocalDate transactionDate, final BigDecimal amount, final Boolean isReversal) {
|
||||
@@ -623,6 +646,56 @@ public class AccountingProcessorHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public void createAccrualBasedDebitJournalEntriesAndReversalsForSavings(final Office office, final String currencyCode,
|
||||
final Integer accountTypeToBeDebited, final Long savingsProductId, final Long paymentTypeId, final Long savingsId,
|
||||
final String transactionId, final LocalDate transactionDate, final BigDecimal amount, final Boolean isReversal) {
|
||||
// reverse debits and credits for reversals
|
||||
if (isReversal) {
|
||||
createCreditJournalEntriesForSavings(office, currencyCode, accountTypeToBeDebited, savingsProductId, paymentTypeId, savingsId,
|
||||
transactionId, transactionDate, amount);
|
||||
} else {
|
||||
createDebitJournalEntriesForSavings(office, currencyCode, accountTypeToBeDebited, savingsProductId, paymentTypeId, savingsId,
|
||||
transactionId, transactionDate, amount);
|
||||
}
|
||||
}
|
||||
|
||||
public void createAccrualBasedCreditJournalEntriesAndReversalsForSavings(final Office office, final String currencyCode,
|
||||
final Integer accountTypeToBeCredited, final Long savingsProductId, final Long paymentTypeId, final Long savingsId,
|
||||
final String transactionId, final LocalDate transactionDate, final BigDecimal amount, final Boolean isReversal) {
|
||||
// reverse debits and credits for reversals
|
||||
if (isReversal) {
|
||||
createDebitJournalEntriesForSavings(office, currencyCode, accountTypeToBeCredited, savingsProductId, paymentTypeId, savingsId,
|
||||
transactionId, transactionDate, amount);
|
||||
} else {
|
||||
createCreditJournalEntriesForSavings(office, currencyCode, accountTypeToBeCredited, savingsProductId, paymentTypeId, savingsId,
|
||||
transactionId, transactionDate, amount);
|
||||
}
|
||||
}
|
||||
|
||||
public void createAccrualBasedDebitJournalEntriesAndReversalsForSavings(final Office office, final String currencyCode,
|
||||
final Long debitAccountId, final Long savingsId, final String transactionId, final LocalDate transactionDate,
|
||||
final BigDecimal amount, final Boolean isReversal) {
|
||||
// reverse debits and credits for reversals
|
||||
final GLAccount debitAccount = getGLAccountById(debitAccountId);
|
||||
if (isReversal) {
|
||||
createCreditJournalEntryForSavings(office, currencyCode, debitAccount, savingsId, transactionId, transactionDate, amount);
|
||||
} else {
|
||||
createDebitJournalEntryForSavings(office, currencyCode, debitAccount, savingsId, transactionId, transactionDate, amount);
|
||||
}
|
||||
}
|
||||
|
||||
public void createAccrualBasedBasedCreditJournalEntriesAndReversalsForSavings(final Office office, final String currencyCode,
|
||||
final Long creditAccountId, final Long savingsId, final String transactionId, final LocalDate transactionDate,
|
||||
final BigDecimal amount, final Boolean isReversal) {
|
||||
// reverse debits and credits for reversals
|
||||
final GLAccount creditAccount = getGLAccountById(creditAccountId);
|
||||
if (isReversal) {
|
||||
createDebitJournalEntryForSavings(office, currencyCode, creditAccount, savingsId, transactionId, transactionDate, amount);
|
||||
} else {
|
||||
createCreditJournalEntryForSavings(office, currencyCode, creditAccount, savingsId, transactionId, transactionDate, amount);
|
||||
}
|
||||
}
|
||||
|
||||
private void createDebitJournalEntriesForSavings(final Office office, final String currencyCode, final int accountTypeToDebitId,
|
||||
final Long savingsProductId, final Long paymentTypeId, final Long savingsId, final String transactionId,
|
||||
final LocalDate transactionDate, final BigDecimal amount) {
|
||||
@@ -768,6 +841,41 @@ public class AccountingProcessorHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public void createAccrualBasedJournalEntriesAndReversalsForSavingsCharges(final Office office, final String currencyCode,
|
||||
final AccrualAccountsForSavings accountTypeToBeDebited, AccrualAccountsForSavings accountTypeToBeCredited,
|
||||
final Long savingsProductId, final Long paymentTypeId, final Long loanId, final String transactionId,
|
||||
final LocalDate transactionDate, final BigDecimal totalAmount, final Boolean isReversal,
|
||||
final List<ChargePaymentDTO> chargePaymentDTOs) {
|
||||
// TODO Vishwas: Remove this validation, as and when appropriate Junit
|
||||
// tests are written for accounting
|
||||
/**
|
||||
* Accounting module currently supports a single charge per transaction, throw an error if this is not the case
|
||||
* here so any developers changing the expected portfolio behavior would also take care of modifying the
|
||||
* accounting code appropriately
|
||||
**/
|
||||
if (chargePaymentDTOs.size() != 1) {
|
||||
throw new PlatformDataIntegrityException("Recent Portfolio changes w.r.t Charges for Savings have Broken the accounting code",
|
||||
"Recent Portfolio changes w.r.t Charges for Savings have Broken the accounting code");
|
||||
}
|
||||
ChargePaymentDTO chargePaymentDTO = chargePaymentDTOs.get(0);
|
||||
GLAccount chargeSpecificAccount = getLinkedGLAccountForSavingsCharges(savingsProductId, accountTypeToBeCredited.getValue(),
|
||||
chargePaymentDTO.getChargeId());
|
||||
|
||||
final GLAccount savingsControlAccount = getLinkedGLAccountForSavingsProduct(savingsProductId, accountTypeToBeDebited.getValue(),
|
||||
paymentTypeId);
|
||||
if (isReversal) {
|
||||
createDebitJournalEntryForSavings(office, currencyCode, chargeSpecificAccount, loanId, transactionId, transactionDate,
|
||||
totalAmount);
|
||||
createCreditJournalEntryForSavings(office, currencyCode, savingsControlAccount, loanId, transactionId, transactionDate,
|
||||
totalAmount);
|
||||
} else {
|
||||
createDebitJournalEntryForSavings(office, currencyCode, savingsControlAccount, loanId, transactionId, transactionDate,
|
||||
totalAmount);
|
||||
createCreditJournalEntryForSavings(office, currencyCode, chargeSpecificAccount, loanId, transactionId, transactionDate,
|
||||
totalAmount);
|
||||
}
|
||||
}
|
||||
|
||||
public LoanTransaction getLoanTransactionById(final Long loanTransactionId) {
|
||||
return this.loanTransactionRepository.getReferenceById(loanTransactionId);
|
||||
}
|
||||
|
||||
+272
@@ -0,0 +1,272 @@
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+73
-52
@@ -27,6 +27,7 @@ import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.AccrualAccountsForLoan;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.AccrualAccountsForSavings;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.CashAccountsForLoan;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.CashAccountsForSavings;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.CashAccountsForShares;
|
||||
@@ -211,6 +212,65 @@ public class ProductToGLAccountMappingWritePlatformServiceImpl implements Produc
|
||||
}
|
||||
}
|
||||
|
||||
private void saveSavingsBaseAccountMapping(final Long savingProductId, final DepositAccountType accountType, final JsonCommand command,
|
||||
final JsonElement element) {
|
||||
// asset
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToAssetAccountMapping(element,
|
||||
SavingProductAccountingParams.SAVINGS_REFERENCE.getValue(), savingProductId,
|
||||
CashAccountsForSavings.SAVINGS_REFERENCE.getValue());
|
||||
|
||||
if (!accountType.equals(DepositAccountType.RECURRING_DEPOSIT) && !accountType.equals(DepositAccountType.FIXED_DEPOSIT)) {
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToAssetAccountMapping(element,
|
||||
SavingProductAccountingParams.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), savingProductId,
|
||||
CashAccountsForSavings.OVERDRAFT_PORTFOLIO_CONTROL.getValue());
|
||||
}
|
||||
|
||||
// income
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToIncomeAccountMapping(element,
|
||||
SavingProductAccountingParams.INCOME_FROM_FEES.getValue(), savingProductId,
|
||||
CashAccountsForSavings.INCOME_FROM_FEES.getValue());
|
||||
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToIncomeAccountMapping(element,
|
||||
SavingProductAccountingParams.INCOME_FROM_PENALTIES.getValue(), savingProductId,
|
||||
CashAccountsForSavings.INCOME_FROM_PENALTIES.getValue());
|
||||
|
||||
if (!accountType.equals(DepositAccountType.RECURRING_DEPOSIT) && !accountType.equals(DepositAccountType.FIXED_DEPOSIT)) {
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToIncomeAccountMapping(element,
|
||||
SavingProductAccountingParams.INCOME_FROM_INTEREST.getValue(), savingProductId,
|
||||
CashAccountsForSavings.INCOME_FROM_INTEREST.getValue());
|
||||
}
|
||||
|
||||
// expenses
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToExpenseAccountMapping(element,
|
||||
SavingProductAccountingParams.INTEREST_ON_SAVINGS.getValue(), savingProductId,
|
||||
CashAccountsForSavings.INTEREST_ON_SAVINGS.getValue());
|
||||
|
||||
if (!accountType.equals(DepositAccountType.RECURRING_DEPOSIT) && !accountType.equals(DepositAccountType.FIXED_DEPOSIT)) {
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToExpenseAccountMapping(element,
|
||||
SavingProductAccountingParams.LOSSES_WRITTEN_OFF.getValue(), savingProductId,
|
||||
CashAccountsForSavings.LOSSES_WRITTEN_OFF.getValue());
|
||||
}
|
||||
|
||||
// liability
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToLiabilityAccountMapping(element,
|
||||
SavingProductAccountingParams.SAVINGS_CONTROL.getValue(), savingProductId,
|
||||
CashAccountsForSavings.SAVINGS_CONTROL.getValue());
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToLiabilityAccountMapping(element,
|
||||
SavingProductAccountingParams.TRANSFERS_SUSPENSE.getValue(), savingProductId,
|
||||
CashAccountsForSavings.TRANSFERS_SUSPENSE.getValue());
|
||||
|
||||
final Boolean isDormancyTrackingActive = this.fromApiJsonHelper.extractBooleanNamed(isDormancyTrackingActiveParamName, element);
|
||||
if (null != isDormancyTrackingActive && isDormancyTrackingActive) {
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToLiabilityAccountMapping(element,
|
||||
SavingProductAccountingParams.ESCHEAT_LIABILITY.getValue(), savingProductId,
|
||||
CashAccountsForSavings.ESCHEAT_LIABILITY.getValue());
|
||||
}
|
||||
|
||||
// advanced accounting mappings
|
||||
this.savingsProductToGLAccountMappingHelper.savePaymentChannelToFundSourceMappings(command, element, savingProductId, null);
|
||||
this.savingsProductToGLAccountMappingHelper.saveChargesToIncomeAccountMappings(command, element, savingProductId, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void createSavingProductToGLAccountMapping(final Long savingProductId, final JsonCommand command,
|
||||
@@ -219,67 +279,28 @@ public class ProductToGLAccountMappingWritePlatformServiceImpl implements Produc
|
||||
final Integer accountingRuleTypeId = this.fromApiJsonHelper.extractIntegerNamed(accountingRuleParamName, element,
|
||||
Locale.getDefault());
|
||||
final AccountingRuleType accountingRuleType = AccountingRuleType.fromInt(accountingRuleTypeId);
|
||||
|
||||
switch (accountingRuleType) {
|
||||
case NONE:
|
||||
break;
|
||||
case CASH_BASED:
|
||||
// asset
|
||||
saveSavingsBaseAccountMapping(savingProductId, accountType, command, element);
|
||||
break;
|
||||
|
||||
case ACCRUAL_PERIODIC:
|
||||
saveSavingsBaseAccountMapping(savingProductId, accountType, command, element);
|
||||
// assets
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToAssetAccountMapping(element,
|
||||
SavingProductAccountingParams.SAVINGS_REFERENCE.getValue(), savingProductId,
|
||||
CashAccountsForSavings.SAVINGS_REFERENCE.getValue());
|
||||
SavingProductAccountingParams.FEES_RECEIVABLE.getValue(), savingProductId,
|
||||
AccrualAccountsForSavings.FEES_RECEIVABLE.getValue());
|
||||
|
||||
if (!accountType.equals(DepositAccountType.RECURRING_DEPOSIT) && !accountType.equals(DepositAccountType.FIXED_DEPOSIT)) {
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToAssetAccountMapping(element,
|
||||
SavingProductAccountingParams.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), savingProductId,
|
||||
CashAccountsForSavings.OVERDRAFT_PORTFOLIO_CONTROL.getValue());
|
||||
}
|
||||
|
||||
// income
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToIncomeAccountMapping(element,
|
||||
SavingProductAccountingParams.INCOME_FROM_FEES.getValue(), savingProductId,
|
||||
CashAccountsForSavings.INCOME_FROM_FEES.getValue());
|
||||
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToIncomeAccountMapping(element,
|
||||
SavingProductAccountingParams.INCOME_FROM_PENALTIES.getValue(), savingProductId,
|
||||
CashAccountsForSavings.INCOME_FROM_PENALTIES.getValue());
|
||||
|
||||
if (!accountType.equals(DepositAccountType.RECURRING_DEPOSIT) && !accountType.equals(DepositAccountType.FIXED_DEPOSIT)) {
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToIncomeAccountMapping(element,
|
||||
SavingProductAccountingParams.INCOME_FROM_INTEREST.getValue(), savingProductId,
|
||||
CashAccountsForSavings.INCOME_FROM_INTEREST.getValue());
|
||||
}
|
||||
|
||||
// expenses
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToExpenseAccountMapping(element,
|
||||
SavingProductAccountingParams.INTEREST_ON_SAVINGS.getValue(), savingProductId,
|
||||
CashAccountsForSavings.INTEREST_ON_SAVINGS.getValue());
|
||||
|
||||
if (!accountType.equals(DepositAccountType.RECURRING_DEPOSIT) && !accountType.equals(DepositAccountType.FIXED_DEPOSIT)) {
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToExpenseAccountMapping(element,
|
||||
SavingProductAccountingParams.LOSSES_WRITTEN_OFF.getValue(), savingProductId,
|
||||
CashAccountsForSavings.LOSSES_WRITTEN_OFF.getValue());
|
||||
}
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToAssetAccountMapping(element,
|
||||
SavingProductAccountingParams.PENALTIES_RECEIVABLE.getValue(), savingProductId,
|
||||
AccrualAccountsForSavings.PENALTIES_RECEIVABLE.getValue());
|
||||
|
||||
// liability
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToLiabilityAccountMapping(element,
|
||||
SavingProductAccountingParams.SAVINGS_CONTROL.getValue(), savingProductId,
|
||||
CashAccountsForSavings.SAVINGS_CONTROL.getValue());
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToLiabilityAccountMapping(element,
|
||||
SavingProductAccountingParams.TRANSFERS_SUSPENSE.getValue(), savingProductId,
|
||||
CashAccountsForSavings.TRANSFERS_SUSPENSE.getValue());
|
||||
|
||||
final Boolean isDormancyTrackingActive = this.fromApiJsonHelper.extractBooleanNamed(isDormancyTrackingActiveParamName,
|
||||
element);
|
||||
if (null != isDormancyTrackingActive && isDormancyTrackingActive) {
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToLiabilityAccountMapping(element,
|
||||
SavingProductAccountingParams.ESCHEAT_LIABILITY.getValue(), savingProductId,
|
||||
CashAccountsForSavings.ESCHEAT_LIABILITY.getValue());
|
||||
}
|
||||
|
||||
// advanced accounting mappings
|
||||
this.savingsProductToGLAccountMappingHelper.savePaymentChannelToFundSourceMappings(command, element, savingProductId, null);
|
||||
this.savingsProductToGLAccountMappingHelper.saveChargesToIncomeAccountMappings(command, element, savingProductId, null);
|
||||
SavingProductAccountingParams.INTEREST_PAYABLE.getValue(), savingProductId,
|
||||
AccrualAccountsForSavings.INTEREST_PAYABLE.getValue());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
+3
-2
@@ -359,6 +359,8 @@ public class LoanScheduleAssembler {
|
||||
CalendarInstance compoundingCalendarInstance = null;
|
||||
InterestRecalculationCompoundingMethod compoundingMethod = null;
|
||||
boolean allowCompoundingOnEod = false;
|
||||
final Boolean isFloatingInterestRate = this.fromApiJsonHelper
|
||||
.extractBooleanNamed(LoanApiConstants.isFloatingInterestRateParameterName, element);
|
||||
if (isInterestRecalculationEnabled) {
|
||||
LoanProductInterestRecalculationDetails loanProductInterestRecalculationDetails = loanProduct
|
||||
.getProductInterestRecalculationDetails();
|
||||
@@ -409,8 +411,7 @@ public class LoanScheduleAssembler {
|
||||
if (loanProduct.isLinkedToFloatingInterestRate()) {
|
||||
final BigDecimal interestRateDiff = this.fromApiJsonHelper
|
||||
.extractBigDecimalWithLocaleNamed(LoanApiConstants.interestRateDifferentialParameterName, element);
|
||||
final Boolean isFloatingInterestRate = this.fromApiJsonHelper
|
||||
.extractBooleanNamed(LoanApiConstants.isFloatingInterestRateParameterName, element);
|
||||
|
||||
List<FloatingRatePeriodData> baseLendingRatePeriods = null;
|
||||
try {
|
||||
baseLendingRatePeriods = this.floatingRatesReadPlatformService.retrieveBaseLendingRate().getRatePeriods();
|
||||
|
||||
+4
-21
@@ -33,10 +33,9 @@ import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.LoanProductAccountingParams;
|
||||
import org.apache.fineract.accounting.common.AccountingRuleType;
|
||||
import org.apache.fineract.accounting.common.AccountingValidations;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
@@ -65,7 +64,6 @@ import org.apache.fineract.portfolio.loanproduct.domain.RecalculationFrequencyTy
|
||||
import org.apache.fineract.portfolio.loanproduct.exception.EqualAmortizationUnsupportedFeatureException;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
public final class LoanProductDataValidator {
|
||||
@@ -613,7 +611,8 @@ public final class LoanProductDataValidator {
|
||||
final Integer accountingRuleType = this.fromApiJsonHelper.extractIntegerNamed(ACCOUNTING_RULE, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(ACCOUNTING_RULE).value(accountingRuleType).notNull().inMinMaxRange(1, 4);
|
||||
|
||||
if (isCashBasedAccounting(accountingRuleType) || isAccrualBasedAccounting(accountingRuleType)) {
|
||||
if (AccountingValidations.isCashBasedAccounting(accountingRuleType)
|
||||
|| AccountingValidations.isAccrualBasedAccounting(accountingRuleType)) {
|
||||
|
||||
final Long fundAccountId = this.fromApiJsonHelper.extractLongNamed(LoanProductAccountingParams.FUND_SOURCE.getValue(), element);
|
||||
baseDataValidator.reset().parameter(LoanProductAccountingParams.FUND_SOURCE.getValue()).value(fundAccountId).notNull()
|
||||
@@ -709,7 +708,7 @@ public final class LoanProductDataValidator {
|
||||
|
||||
}
|
||||
|
||||
if (isAccrualBasedAccounting(accountingRuleType)) {
|
||||
if (AccountingValidations.isAccrualBasedAccounting(accountingRuleType)) {
|
||||
|
||||
final Long receivableInterestAccountId = this.fromApiJsonHelper
|
||||
.extractLongNamed(LoanProductAccountingParams.INTEREST_RECEIVABLE.getValue(), element);
|
||||
@@ -2144,22 +2143,6 @@ public final class LoanProductDataValidator {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isCashBasedAccounting(final Integer accountingRuleType) {
|
||||
return AccountingRuleType.CASH_BASED.getValue().equals(accountingRuleType);
|
||||
}
|
||||
|
||||
private boolean isAccrualBasedAccounting(final Integer accountingRuleType) {
|
||||
return isUpfrontAccrualAccounting(accountingRuleType) || isPeriodicAccounting(accountingRuleType);
|
||||
}
|
||||
|
||||
private boolean isUpfrontAccrualAccounting(final Integer accountingRuleType) {
|
||||
return AccountingRuleType.ACCRUAL_UPFRONT.getValue().equals(accountingRuleType);
|
||||
}
|
||||
|
||||
private boolean isPeriodicAccounting(final Integer accountingRuleType) {
|
||||
return AccountingRuleType.ACCRUAL_PERIODIC.getValue().equals(accountingRuleType);
|
||||
}
|
||||
|
||||
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
||||
|
||||
+22
-79
@@ -318,88 +318,31 @@ final class FixedDepositProductsApiResourceSwagger {
|
||||
public String description;
|
||||
}
|
||||
|
||||
static final class GetFixedDepositProductsGlAccount {
|
||||
|
||||
private GetFixedDepositProductsGlAccount() {}
|
||||
|
||||
@Schema(example = "12")
|
||||
public Long id;
|
||||
@Schema(example = "savings ref")
|
||||
public String name;
|
||||
@Schema(example = "20")
|
||||
public Integer glCode;
|
||||
}
|
||||
|
||||
static final class GetFixedDepositProductsProductIdAccountingMappings {
|
||||
|
||||
private GetFixedDepositProductsProductIdAccountingMappings() {}
|
||||
|
||||
static final class GetFixedDepositProductsProductIdSavingsReferenceAccount {
|
||||
|
||||
private GetFixedDepositProductsProductIdSavingsReferenceAccount() {}
|
||||
|
||||
@Schema(example = "12")
|
||||
public Long id;
|
||||
@Schema(example = "savings ref")
|
||||
public String name;
|
||||
@Schema(example = "20")
|
||||
public String glCode;
|
||||
}
|
||||
|
||||
static final class GetFixedDepositProductsProductIdIncomeFromFeeAccount {
|
||||
|
||||
private GetFixedDepositProductsProductIdIncomeFromFeeAccount() {}
|
||||
|
||||
@Schema(example = "16")
|
||||
public Long id;
|
||||
@Schema(example = "income from savings fee")
|
||||
public String name;
|
||||
@Schema(example = "24")
|
||||
public String glCode;
|
||||
}
|
||||
|
||||
static final class GetFixedDepositProductsProductIdIncomeFromPenaltyAccount {
|
||||
|
||||
private GetFixedDepositProductsProductIdIncomeFromPenaltyAccount() {}
|
||||
|
||||
@Schema(example = "17")
|
||||
public Long id;
|
||||
@Schema(example = "income from sav penalties")
|
||||
public String name;
|
||||
@Schema(example = "25")
|
||||
public String glCode;
|
||||
}
|
||||
|
||||
static final class GetFixedDepositProductsProductIdInterestOnSavingsAccount {
|
||||
|
||||
private GetFixedDepositProductsProductIdInterestOnSavingsAccount() {}
|
||||
|
||||
@Schema(example = "15")
|
||||
public Long id;
|
||||
@Schema(example = "interest on savings")
|
||||
public String name;
|
||||
@Schema(example = "23")
|
||||
public String glCode;
|
||||
}
|
||||
|
||||
static final class GetFixedDepositProductsProductIdSavingsControlAccount {
|
||||
|
||||
private GetFixedDepositProductsProductIdSavingsControlAccount() {}
|
||||
|
||||
@Schema(example = "13")
|
||||
public Long id;
|
||||
@Schema(example = "savings ref tool kit")
|
||||
public String name;
|
||||
@Schema(example = "21")
|
||||
public String glCode;
|
||||
}
|
||||
|
||||
static final class GetFixedDepositProductsProductIdTransfersInSuspenseAccount {
|
||||
|
||||
private GetFixedDepositProductsProductIdTransfersInSuspenseAccount() {}
|
||||
|
||||
@Schema(example = "14")
|
||||
public Long id;
|
||||
@Schema(example = "saving transfers")
|
||||
public String name;
|
||||
@Schema(example = "22")
|
||||
public String glCode;
|
||||
}
|
||||
|
||||
public GetFixedDepositProductsProductIdSavingsReferenceAccount savingsReferenceAccount;
|
||||
public GetFixedDepositProductsProductIdIncomeFromFeeAccount incomeFromFeeAccount;
|
||||
public GetFixedDepositProductsProductIdIncomeFromPenaltyAccount incomeFromPenaltyAccount;
|
||||
public GetFixedDepositProductsProductIdInterestOnSavingsAccount interestOnSavingsAccount;
|
||||
public GetFixedDepositProductsProductIdSavingsControlAccount savingsControlAccount;
|
||||
public GetFixedDepositProductsProductIdTransfersInSuspenseAccount transfersInSuspenseAccount;
|
||||
public GetFixedDepositProductsGlAccount savingsReferenceAccount;
|
||||
public GetFixedDepositProductsGlAccount feeReceivableAccount;
|
||||
public GetFixedDepositProductsGlAccount penaltyReceivableAccount;
|
||||
public GetFixedDepositProductsGlAccount incomeFromFeeAccount;
|
||||
public GetFixedDepositProductsGlAccount incomeFromPenaltyAccount;
|
||||
public GetFixedDepositProductsGlAccount interestOnSavingsAccount;
|
||||
public GetFixedDepositProductsGlAccount savingsControlAccount;
|
||||
public GetFixedDepositProductsGlAccount transfersInSuspenseAccount;
|
||||
public GetFixedDepositProductsGlAccount interestPayableAccount;
|
||||
}
|
||||
|
||||
static final class GetFixedDepositProductsProductIdFeeToIncomeAccountMappings {
|
||||
@@ -455,7 +398,7 @@ final class FixedDepositProductsApiResourceSwagger {
|
||||
}
|
||||
|
||||
public GetFixedDepositProductsProductIdPenaltyToIncomeAccountMappingsCharge charge;
|
||||
public GetFixedDepositProductsProductIdAccountingMappings.GetFixedDepositProductsProductIdIncomeFromPenaltyAccount incomeAccount;
|
||||
public GetFixedDepositProductsGlAccount incomeAccount;
|
||||
}
|
||||
|
||||
static final class GetFixedDepositProductsProductIdPreClosurePenalInterestOnType {
|
||||
|
||||
+21
-79
@@ -343,88 +343,30 @@ final class RecurringDepositProductsApiResourceSwagger {
|
||||
public String description;
|
||||
}
|
||||
|
||||
static final class GetRecurringDepositProductsGlAccount {
|
||||
|
||||
private GetRecurringDepositProductsGlAccount() {}
|
||||
|
||||
@Schema(example = "12")
|
||||
public Long id;
|
||||
@Schema(example = "savings control")
|
||||
public String name;
|
||||
@Schema(example = "2000001")
|
||||
public String glCode;
|
||||
}
|
||||
|
||||
static final class GetRecurringDepositProductsProductIdAccountingMappings {
|
||||
|
||||
private GetRecurringDepositProductsProductIdAccountingMappings() {}
|
||||
|
||||
static final class GetRecurringDepositProductsProductIdSavingsReferenceAccount {
|
||||
|
||||
private GetRecurringDepositProductsProductIdSavingsReferenceAccount() {}
|
||||
|
||||
@Schema(example = "12")
|
||||
public Long id;
|
||||
@Schema(example = "savings ref")
|
||||
public String name;
|
||||
@Schema(example = "20")
|
||||
public String glCode;
|
||||
}
|
||||
|
||||
static final class GetRecurringDepositProductsProductIdIncomeFromFeeAccount {
|
||||
|
||||
private GetRecurringDepositProductsProductIdIncomeFromFeeAccount() {}
|
||||
|
||||
@Schema(example = "16")
|
||||
public Long id;
|
||||
@Schema(example = "income from savings fee")
|
||||
public String name;
|
||||
@Schema(example = "24")
|
||||
public String glCode;
|
||||
}
|
||||
|
||||
static final class GetRecurringDepositProductsProductIdIncomeFromPenaltyAccount {
|
||||
|
||||
private GetRecurringDepositProductsProductIdIncomeFromPenaltyAccount() {}
|
||||
|
||||
@Schema(example = "17")
|
||||
public Long id;
|
||||
@Schema(example = "income from sav penalties")
|
||||
public String name;
|
||||
@Schema(example = "25")
|
||||
public String glCode;
|
||||
}
|
||||
|
||||
static final class GetRecurringDepositProductsProductIdInterestOnSavingsAccount {
|
||||
|
||||
private GetRecurringDepositProductsProductIdInterestOnSavingsAccount() {}
|
||||
|
||||
@Schema(example = "15")
|
||||
public Long id;
|
||||
@Schema(example = "interest on savings")
|
||||
public String name;
|
||||
@Schema(example = "23")
|
||||
public String glCode;
|
||||
}
|
||||
|
||||
static final class GetRecurringDepositProductsProductIdSavingsControlAccount {
|
||||
|
||||
private GetRecurringDepositProductsProductIdSavingsControlAccount() {}
|
||||
|
||||
@Schema(example = "13")
|
||||
public Long id;
|
||||
@Schema(example = "savings ref tool kit")
|
||||
public String name;
|
||||
@Schema(example = "21")
|
||||
public String glCode;
|
||||
}
|
||||
|
||||
static final class GetRecurringDepositProductsProductIdTransfersInSuspenseAccount {
|
||||
|
||||
private GetRecurringDepositProductsProductIdTransfersInSuspenseAccount() {}
|
||||
|
||||
@Schema(example = "14")
|
||||
public Long id;
|
||||
@Schema(example = "saving transfers")
|
||||
public String name;
|
||||
@Schema(example = "22")
|
||||
public String glCode;
|
||||
}
|
||||
|
||||
public GetRecurringDepositProductsProductIdSavingsReferenceAccount savingsReferenceAccount;
|
||||
public GetRecurringDepositProductsProductIdIncomeFromFeeAccount incomeFromFeeAccount;
|
||||
public GetRecurringDepositProductsProductIdIncomeFromPenaltyAccount incomeFromPenaltyAccount;
|
||||
public GetRecurringDepositProductsProductIdInterestOnSavingsAccount interestOnSavingsAccount;
|
||||
public GetRecurringDepositProductsProductIdSavingsControlAccount savingsControlAccount;
|
||||
public GetRecurringDepositProductsProductIdTransfersInSuspenseAccount transfersInSuspenseAccount;
|
||||
public GetRecurringDepositProductsGlAccount incomeFromFeeAccount;
|
||||
public GetRecurringDepositProductsGlAccount incomeFromPenaltyAccount;
|
||||
public GetRecurringDepositProductsGlAccount interestOnSavingsAccount;
|
||||
public GetRecurringDepositProductsGlAccount savingsControlAccount;
|
||||
public GetRecurringDepositProductsGlAccount transfersInSuspenseAccount;
|
||||
public GetRecurringDepositProductsGlAccount feeReceivableAccount;
|
||||
public GetRecurringDepositProductsGlAccount penaltyReceivableAccount;
|
||||
public GetRecurringDepositProductsGlAccount interestPayableAccount;
|
||||
}
|
||||
|
||||
static final class GetRecurringDepositProductsProductIdFeeToIncomeAccountMappings {
|
||||
@@ -480,7 +422,7 @@ final class RecurringDepositProductsApiResourceSwagger {
|
||||
}
|
||||
|
||||
public GetRecurringDepositProductsProductIdPenaltyToIncomeAccountMappingsCharge charge;
|
||||
public GetRecurringDepositProductsProductIdAccountingMappings.GetRecurringDepositProductsProductIdIncomeFromPenaltyAccount incomeAccount;
|
||||
public GetRecurringDepositProductsGlAccount incomeAccount;
|
||||
}
|
||||
|
||||
static final class GetRecurringDepositProductsProductIdPreClosurePenalInterestOnType {
|
||||
|
||||
+25
-79
@@ -226,88 +226,34 @@ final class SavingsProductsApiResourceSwagger {
|
||||
|
||||
private GetSavingsProductsProductIdResponse() {}
|
||||
|
||||
static final class GetSavingsProductsGlAccount {
|
||||
|
||||
private GetSavingsProductsGlAccount() {}
|
||||
|
||||
@Schema(example = "12")
|
||||
public Integer id;
|
||||
@Schema(example = "savings control")
|
||||
public String name;
|
||||
@Schema(example = "2000001")
|
||||
public String glCode;
|
||||
}
|
||||
|
||||
static final class GetSavingsProductsAccountingMappings {
|
||||
|
||||
private GetSavingsProductsAccountingMappings() {}
|
||||
|
||||
static final class GetSavingsProductsSavingsReferenceAccount {
|
||||
|
||||
private GetSavingsProductsSavingsReferenceAccount() {}
|
||||
|
||||
@Schema(example = "12")
|
||||
public Integer id;
|
||||
@Schema(example = "savings ref")
|
||||
public String name;
|
||||
@Schema(example = "20")
|
||||
public String glCode;
|
||||
}
|
||||
|
||||
static final class GetSavingsProductsIncomeFromFeeAccount {
|
||||
|
||||
private GetSavingsProductsIncomeFromFeeAccount() {}
|
||||
|
||||
@Schema(example = "16")
|
||||
public Integer id;
|
||||
@Schema(example = "income from savings fee")
|
||||
public String name;
|
||||
@Schema(example = "24")
|
||||
public String glCode;
|
||||
}
|
||||
|
||||
static final class GetSavingsProductsIncomeFromPenaltyAccount {
|
||||
|
||||
private GetSavingsProductsIncomeFromPenaltyAccount() {}
|
||||
|
||||
@Schema(example = "17")
|
||||
public Integer id;
|
||||
@Schema(example = "income from sav penalties")
|
||||
public String name;
|
||||
@Schema(example = "25")
|
||||
public String glCode;
|
||||
}
|
||||
|
||||
static final class GetSavingsProductsInterestOnSavingsAccount {
|
||||
|
||||
private GetSavingsProductsInterestOnSavingsAccount() {}
|
||||
|
||||
@Schema(example = "15")
|
||||
public Integer id;
|
||||
@Schema(example = "interest on savings")
|
||||
public String name;
|
||||
@Schema(example = "23")
|
||||
public String glCode;
|
||||
}
|
||||
|
||||
static final class GetSavingsProductsSavingsControlAccount {
|
||||
|
||||
private GetSavingsProductsSavingsControlAccount() {}
|
||||
|
||||
@Schema(example = "13")
|
||||
public Integer id;
|
||||
@Schema(example = "savings ref tool kit")
|
||||
public String name;
|
||||
@Schema(example = "21")
|
||||
public String glCode;
|
||||
}
|
||||
|
||||
static final class GetSavingsProductsTransfersInSuspenseAccount {
|
||||
|
||||
private GetSavingsProductsTransfersInSuspenseAccount() {}
|
||||
|
||||
@Schema(example = "14")
|
||||
public Integer id;
|
||||
@Schema(example = "saving transfers")
|
||||
public String name;
|
||||
@Schema(example = "22")
|
||||
public String glCode;
|
||||
}
|
||||
|
||||
public GetSavingsProductsSavingsReferenceAccount savingsReferenceAccount;
|
||||
public GetSavingsProductsIncomeFromFeeAccount incomeFromFeeAccount;
|
||||
public GetSavingsProductsIncomeFromPenaltyAccount incomeFromPenaltyAccount;
|
||||
public GetSavingsProductsInterestOnSavingsAccount interestOnSavingsAccount;
|
||||
public GetSavingsProductsSavingsControlAccount savingsControlAccount;
|
||||
public GetSavingsProductsTransfersInSuspenseAccount transfersInSuspenseAccount;
|
||||
public GetSavingsProductsGlAccount savingsReferenceAccount;
|
||||
public GetSavingsProductsGlAccount overdraftPortfolioControl;
|
||||
public GetSavingsProductsGlAccount feeReceivableAccount;
|
||||
public GetSavingsProductsGlAccount penaltyReceivableAccount;
|
||||
public GetSavingsProductsGlAccount incomeFromFeeAccount;
|
||||
public GetSavingsProductsGlAccount incomeFromPenaltyAccount;
|
||||
public GetSavingsProductsGlAccount incomeFromInterest;
|
||||
public GetSavingsProductsGlAccount interestOnSavingsAccount;
|
||||
public GetSavingsProductsGlAccount writeOffAccount;
|
||||
public GetSavingsProductsGlAccount savingsControlAccount;
|
||||
public GetSavingsProductsGlAccount transfersInSuspenseAccount;
|
||||
public GetSavingsProductsGlAccount interestPayableAccount;
|
||||
}
|
||||
|
||||
static final class GetSavingsProductsPaymentChannelToFundSourceMappings {
|
||||
@@ -393,7 +339,7 @@ final class SavingsProductsApiResourceSwagger {
|
||||
}
|
||||
|
||||
public GetSavingsProductsPenaltyToIncomeAccountMappingsCharge charge;
|
||||
public GetSavingsProductsAccountingMappings.GetSavingsProductsIncomeFromPenaltyAccount incomeAccount;
|
||||
public GetSavingsProductsGlAccount incomeAccount;
|
||||
}
|
||||
|
||||
@Schema(example = "1")
|
||||
|
||||
+20
-123
@@ -71,35 +71,33 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.SavingProductAccountingParams;
|
||||
import org.apache.fineract.accounting.common.AccountingRuleType;
|
||||
import org.apache.fineract.accounting.common.AccountingValidations;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.portfolio.interestratechart.data.InterestRateChartDataValidator;
|
||||
import org.apache.fineract.portfolio.savings.DepositAccountType;
|
||||
import org.apache.fineract.portfolio.savings.PreClosurePenalInterestOnType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsApiConstants;
|
||||
import org.apache.fineract.portfolio.savings.SavingsCompoundingInterestPeriodType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsInterestCalculationDaysInYearType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsInterestCalculationType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsPeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class DepositProductDataValidator {
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
private final InterestRateChartDataValidator chartDataValidator;
|
||||
|
||||
@Autowired
|
||||
public DepositProductDataValidator(FromJsonHelper fromApiJsonHelper, InterestRateChartDataValidator chartDataValidator) {
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
this.chartDataValidator = chartDataValidator;
|
||||
}
|
||||
private final SavingsProductAccountingDataValidator savingsProductAccountingDataValidator;
|
||||
|
||||
public void validateForFixedDepositCreate(final String json) {
|
||||
if (StringUtils.isBlank(json)) {
|
||||
@@ -115,7 +113,7 @@ public class DepositProductDataValidator {
|
||||
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||
|
||||
validateDepositDetailForCreate(element, this.fromApiJsonHelper, baseDataValidator);
|
||||
validateDepositDetailForCreate(element, this.fromApiJsonHelper, baseDataValidator, DepositAccountType.FIXED_DEPOSIT);
|
||||
|
||||
validatePreClosureDetailForCreate(element, baseDataValidator);
|
||||
|
||||
@@ -168,7 +166,7 @@ public class DepositProductDataValidator {
|
||||
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||
|
||||
validateDepositDetailForCreate(element, this.fromApiJsonHelper, baseDataValidator);
|
||||
validateDepositDetailForCreate(element, this.fromApiJsonHelper, baseDataValidator, DepositAccountType.RECURRING_DEPOSIT);
|
||||
|
||||
validatePreClosureDetailForCreate(element, baseDataValidator);
|
||||
|
||||
@@ -212,7 +210,7 @@ public class DepositProductDataValidator {
|
||||
}
|
||||
|
||||
private void validateDepositDetailForCreate(final JsonElement element, final FromJsonHelper fromApiJsonHelper,
|
||||
final DataValidatorBuilder baseDataValidator) {
|
||||
final DataValidatorBuilder baseDataValidator, final DepositAccountType accountType) {
|
||||
final String name = fromApiJsonHelper.extractStringNamed(nameParamName, element);
|
||||
baseDataValidator.reset().parameter(nameParamName).value(name).notBlank().notExceedingLengthOf(100);
|
||||
|
||||
@@ -258,13 +256,6 @@ public class DepositProductDataValidator {
|
||||
baseDataValidator.reset().parameter(interestCalculationDaysInYearTypeParamName).value(interestCalculationDaysInYearType).notNull()
|
||||
.isOneOfTheseValues(SavingsInterestCalculationDaysInYearType.integerValues());
|
||||
|
||||
/*
|
||||
* if (fromApiJsonHelper.parameterExists(minRequiredOpeningBalanceParamName , element)) { final BigDecimal
|
||||
* minOpeningBalance = fromApiJsonHelper.extractBigDecimalWithLocaleNamed (minRequiredOpeningBalanceParamName,
|
||||
* element); baseDataValidator.reset ().parameter(minRequiredOpeningBalanceParamName
|
||||
* ).value(minOpeningBalance).zeroOrPositiveAmount(); }
|
||||
*/
|
||||
|
||||
if (fromApiJsonHelper.parameterExists(lockinPeriodFrequencyParamName, element)) {
|
||||
|
||||
final Integer lockinPeriodFrequency = fromApiJsonHelper.extractIntegerWithLocaleNamed(lockinPeriodFrequencyParamName, element);
|
||||
@@ -302,40 +293,16 @@ public class DepositProductDataValidator {
|
||||
final Integer accountingRuleType = fromApiJsonHelper.extractIntegerNamed("accountingRule", element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("accountingRule").value(accountingRuleType).notNull().inMinMaxRange(1, 3);
|
||||
|
||||
if (isCashBasedAccounting(accountingRuleType)) {
|
||||
Boolean isDormancyActive = this.fromApiJsonHelper.extractBooleanNamed(SavingsApiConstants.isDormancyTrackingActiveParamName,
|
||||
element);
|
||||
if (isDormancyActive == null) {
|
||||
isDormancyActive = false;
|
||||
}
|
||||
|
||||
final Long savingsControlAccountId = fromApiJsonHelper
|
||||
.extractLongNamed(SavingProductAccountingParams.SAVINGS_CONTROL.getValue(), element);
|
||||
baseDataValidator.reset().parameter(SavingProductAccountingParams.SAVINGS_CONTROL.getValue()).value(savingsControlAccountId)
|
||||
.notNull().integerGreaterThanZero();
|
||||
|
||||
final Long savingsReferenceAccountId = fromApiJsonHelper
|
||||
.extractLongNamed(SavingProductAccountingParams.SAVINGS_REFERENCE.getValue(), element);
|
||||
baseDataValidator.reset().parameter(SavingProductAccountingParams.SAVINGS_REFERENCE.getValue()).value(savingsReferenceAccountId)
|
||||
.notNull().integerGreaterThanZero();
|
||||
|
||||
final Long transfersInSuspenseAccountId = fromApiJsonHelper
|
||||
.extractLongNamed(SavingProductAccountingParams.TRANSFERS_SUSPENSE.getValue(), element);
|
||||
baseDataValidator.reset().parameter(SavingProductAccountingParams.TRANSFERS_SUSPENSE.getValue())
|
||||
.value(transfersInSuspenseAccountId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long interestOnSavingsAccountId = fromApiJsonHelper
|
||||
.extractLongNamed(SavingProductAccountingParams.INTEREST_ON_SAVINGS.getValue(), element);
|
||||
baseDataValidator.reset().parameter(SavingProductAccountingParams.INTEREST_ON_SAVINGS.getValue())
|
||||
.value(interestOnSavingsAccountId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long incomeFromFeeId = fromApiJsonHelper.extractLongNamed(SavingProductAccountingParams.INCOME_FROM_FEES.getValue(),
|
||||
element);
|
||||
baseDataValidator.reset().parameter(SavingProductAccountingParams.INCOME_FROM_FEES.getValue()).value(incomeFromFeeId).notNull()
|
||||
.integerGreaterThanZero();
|
||||
|
||||
final Long incomeFromPenaltyId = fromApiJsonHelper
|
||||
.extractLongNamed(SavingProductAccountingParams.INCOME_FROM_PENALTIES.getValue(), element);
|
||||
baseDataValidator.reset().parameter(SavingProductAccountingParams.INCOME_FROM_PENALTIES.getValue()).value(incomeFromPenaltyId)
|
||||
.notNull().integerGreaterThanZero();
|
||||
|
||||
validatePaymentChannelFundSourceMappings(fromApiJsonHelper, baseDataValidator, element);
|
||||
validateChargeToIncomeAccountMappings(fromApiJsonHelper, baseDataValidator, element);
|
||||
if (AccountingValidations.isCashBasedAccounting(accountingRuleType)
|
||||
|| AccountingValidations.isAccrualPeriodicBasedAccounting(accountingRuleType)) {
|
||||
savingsProductAccountingDataValidator.evaluateProductAccountingData(accountingRuleType, isDormancyActive, element,
|
||||
baseDataValidator, accountType);
|
||||
}
|
||||
|
||||
validateTaxWithHoldingParams(baseDataValidator, element, true);
|
||||
@@ -542,8 +509,8 @@ public class DepositProductDataValidator {
|
||||
baseDataValidator.reset().parameter(SavingProductAccountingParams.INCOME_FROM_PENALTIES.getValue()).value(incomeFromPenaltyId)
|
||||
.ignoreIfNull().integerGreaterThanZero();
|
||||
|
||||
validatePaymentChannelFundSourceMappings(fromApiJsonHelper, baseDataValidator, element);
|
||||
validateChargeToIncomeAccountMappings(fromApiJsonHelper, baseDataValidator, element);
|
||||
savingsProductAccountingDataValidator.validatePaymentChannelFundSourceMappings(baseDataValidator, element);
|
||||
savingsProductAccountingDataValidator.validateChargeToIncomeAccountMappings(baseDataValidator, element);
|
||||
validateTaxWithHoldingParams(baseDataValidator, element, false);
|
||||
}
|
||||
|
||||
@@ -611,76 +578,6 @@ public class DepositProductDataValidator {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isCashBasedAccounting(final Integer accountingRuleType) {
|
||||
return AccountingRuleType.CASH_BASED.getValue().equals(accountingRuleType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validation for advanced accounting options
|
||||
*/
|
||||
private void validatePaymentChannelFundSourceMappings(final FromJsonHelper fromApiJsonHelper,
|
||||
final DataValidatorBuilder baseDataValidator, final JsonElement element) {
|
||||
if (fromApiJsonHelper.parameterExists(SavingProductAccountingParams.PAYMENT_CHANNEL_FUND_SOURCE_MAPPING.getValue(), element)) {
|
||||
final JsonArray paymentChannelMappingArray = fromApiJsonHelper
|
||||
.extractJsonArrayNamed(SavingProductAccountingParams.PAYMENT_CHANNEL_FUND_SOURCE_MAPPING.getValue(), element);
|
||||
if (paymentChannelMappingArray != null && paymentChannelMappingArray.size() > 0) {
|
||||
int i = 0;
|
||||
do {
|
||||
final JsonObject jsonObject = paymentChannelMappingArray.get(i).getAsJsonObject();
|
||||
final Long paymentTypeId = jsonObject.get(SavingProductAccountingParams.PAYMENT_TYPE.getValue()).getAsLong();
|
||||
final Long paymentSpecificFundAccountId = jsonObject.get(SavingProductAccountingParams.FUND_SOURCE.getValue())
|
||||
.getAsLong();
|
||||
baseDataValidator.reset()
|
||||
.parameter(SavingProductAccountingParams.PAYMENT_CHANNEL_FUND_SOURCE_MAPPING.getValue() + "[" + i + "]."
|
||||
+ SavingProductAccountingParams.PAYMENT_TYPE.toString())
|
||||
.value(paymentTypeId).notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset()
|
||||
.parameter(SavingProductAccountingParams.PAYMENT_CHANNEL_FUND_SOURCE_MAPPING.getValue() + "[" + i + "]."
|
||||
+ SavingProductAccountingParams.FUND_SOURCE.getValue())
|
||||
.value(paymentSpecificFundAccountId).notNull().integerGreaterThanZero();
|
||||
i++;
|
||||
} while (i < paymentChannelMappingArray.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateChargeToIncomeAccountMappings(final FromJsonHelper fromApiJsonHelper, final DataValidatorBuilder baseDataValidator,
|
||||
final JsonElement element) {
|
||||
// validate for both fee and penalty charges
|
||||
validateChargeToIncomeAccountMappings(fromApiJsonHelper, baseDataValidator, element, true);
|
||||
validateChargeToIncomeAccountMappings(fromApiJsonHelper, baseDataValidator, element, true);
|
||||
}
|
||||
|
||||
private void validateChargeToIncomeAccountMappings(final FromJsonHelper fromApiJsonHelper, final DataValidatorBuilder baseDataValidator,
|
||||
final JsonElement element, final boolean isPenalty) {
|
||||
String parameterName;
|
||||
if (isPenalty) {
|
||||
parameterName = SavingProductAccountingParams.PENALTY_INCOME_ACCOUNT_MAPPING.getValue();
|
||||
} else {
|
||||
parameterName = SavingProductAccountingParams.FEE_INCOME_ACCOUNT_MAPPING.getValue();
|
||||
}
|
||||
|
||||
if (fromApiJsonHelper.parameterExists(parameterName, element)) {
|
||||
final JsonArray chargeToIncomeAccountMappingArray = fromApiJsonHelper.extractJsonArrayNamed(parameterName, element);
|
||||
if (chargeToIncomeAccountMappingArray != null && chargeToIncomeAccountMappingArray.size() > 0) {
|
||||
int i = 0;
|
||||
do {
|
||||
final JsonObject jsonObject = chargeToIncomeAccountMappingArray.get(i).getAsJsonObject();
|
||||
final Long chargeId = fromApiJsonHelper.extractLongNamed(SavingProductAccountingParams.CHARGE_ID.getValue(),
|
||||
jsonObject);
|
||||
final Long incomeAccountId = fromApiJsonHelper
|
||||
.extractLongNamed(SavingProductAccountingParams.INCOME_ACCOUNT_ID.getValue(), jsonObject);
|
||||
baseDataValidator.reset().parameter(parameterName + "[" + i + "]." + SavingProductAccountingParams.CHARGE_ID.getValue())
|
||||
.value(chargeId).notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset()
|
||||
.parameter(parameterName + "[" + i + "]." + SavingProductAccountingParams.INCOME_ACCOUNT_ID.getValue())
|
||||
.value(incomeAccountId).notNull().integerGreaterThanZero();
|
||||
i++;
|
||||
} while (i < chargeToIncomeAccountMappingArray.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void validateRecurringDetailForCreate(JsonElement element, DataValidatorBuilder baseDataValidator) {
|
||||
|
||||
final Boolean isMandatoryDeposit = this.fromApiJsonHelper.extractBooleanNamed(isMandatoryDepositParamName, element);
|
||||
|
||||
+2
-11
@@ -43,6 +43,7 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
@@ -55,15 +56,14 @@ import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.portfolio.savings.SavingsApiConstants;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountAssembler;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountSubStatusEnum;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountTransaction;
|
||||
import org.apache.fineract.portfolio.savings.exception.TransactionBeforePivotDateNotAllowed;
|
||||
import org.apache.fineract.useradministration.domain.AppUser;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class SavingsAccountTransactionDataValidator {
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
@@ -71,15 +71,6 @@ public class SavingsAccountTransactionDataValidator {
|
||||
Arrays.asList(transactionDateParamName, SavingsApiConstants.dateFormatParamName, SavingsApiConstants.localeParamName,
|
||||
transactionAmountParamName, lienAllowedParamName, SavingsApiConstants.reasonForBlockParamName));
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
private final SavingsAccountAssembler savingAccountAssembler;
|
||||
|
||||
@Autowired
|
||||
public SavingsAccountTransactionDataValidator(final FromJsonHelper fromApiJsonHelper,
|
||||
final ConfigurationDomainService configurationDomainService, final SavingsAccountAssembler savingAccountAssembler) {
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
this.configurationDomainService = configurationDomainService;
|
||||
this.savingAccountAssembler = savingAccountAssembler;
|
||||
}
|
||||
|
||||
public void validateTransactionWithPivotDate(final LocalDate transactionDate, final SavingsAccount savingsAccount) {
|
||||
final boolean backdatedTxnsAllowedTill = this.configurationDomainService.retrievePivotDateConfig();
|
||||
|
||||
-1
@@ -99,7 +99,6 @@ import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
|
||||
public class DepositAccountReadPlatformServiceImpl implements DepositAccountReadPlatformService {
|
||||
|
||||
private static final FixedDepositAccountMapper FIXED_DEPOSIT_ACCOUNT_MAPPER = new FixedDepositAccountMapper();
|
||||
|
||||
+2
-82
@@ -611,7 +611,6 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
final BigDecimal outstandingChargeAmount = null;
|
||||
final BigDecimal runningBalance = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "runningBalance");
|
||||
final boolean reversed = rs.getBoolean("reversed");
|
||||
final boolean isManualTransaction = rs.getBoolean("manualTransaction");
|
||||
final Long officeId = rs.getLong("officeId");
|
||||
final BigDecimal cumulativeBalance = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "cumulativeBalance");
|
||||
|
||||
@@ -684,59 +683,6 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
}
|
||||
return savingsAccountDataList;
|
||||
|
||||
// final String productName = rs.getString("productName");
|
||||
|
||||
// final String fieldOfficerName = rs.getString("fieldOfficerName");
|
||||
|
||||
// final String submittedByUsername = rs.getString("submittedByUsername");
|
||||
// final String submittedByFirstname = rs.getString("submittedByFirstname");
|
||||
// final String submittedByLastname = rs.getString("submittedByLastname");
|
||||
//
|
||||
|
||||
// final String rejectedByUsername = rs.getString("rejectedByUsername");
|
||||
// final String rejectedByFirstname = rs.getString("rejectedByFirstname");
|
||||
// final String rejectedByLastname = rs.getString("rejectedByLastname");
|
||||
//
|
||||
|
||||
// final String withdrawnByUsername = rs.getString("withdrawnByUsername");
|
||||
// final String withdrawnByFirstname = rs.getString("withdrawnByFirstname");
|
||||
// final String withdrawnByLastname = rs.getString("withdrawnByLastname");
|
||||
|
||||
// final String approvedByUsername = rs.getString("approvedByUsername");
|
||||
// final String approvedByFirstname = rs.getString("approvedByFirstname");
|
||||
// final String approvedByLastname = rs.getString("approvedByLastname");
|
||||
|
||||
// final String activatedByUsername = rs.getString("activatedByUsername");
|
||||
// final String activatedByFirstname = rs.getString("activatedByFirstname");
|
||||
// final String activatedByLastname = rs.getString("activatedByLastname");
|
||||
|
||||
// final String closedByUsername = rs.getString("closedByUsername");
|
||||
// final String closedByFirstname = rs.getString("closedByFirstname");
|
||||
// final String closedByLastname = rs.getString("closedByLastname");
|
||||
|
||||
// final String currencyName = rs.getString("currencyName");
|
||||
// final String currencyNameCode = rs.getString("currencyNameCode");
|
||||
// final String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
|
||||
|
||||
/*
|
||||
* final BigDecimal withdrawalFeeAmount = rs.getBigDecimal("withdrawalFeeAmount");
|
||||
*
|
||||
* EnumOptionData withdrawalFeeType = null; final Integer withdrawalFeeTypeValue =
|
||||
* JdbcSupport.getInteger(rs, "withdrawalFeeTypeEnum"); if (withdrawalFeeTypeValue != null) {
|
||||
* withdrawalFeeType = SavingsEnumerations.withdrawalFeeType(withdrawalFeeTypeValue); }
|
||||
*/
|
||||
|
||||
/*
|
||||
* final BigDecimal annualFeeAmount = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "annualFeeAmount");
|
||||
*
|
||||
* MonthDay annualFeeOnMonthDay = null; final Integer annualFeeOnMonth = JdbcSupport.getInteger(rs,
|
||||
* "annualFeeOnMonth"); final Integer annualFeeOnDay = JdbcSupport.getInteger(rs, "annualFeeOnDay"); if
|
||||
* (annualFeeAmount != null && annualFeeOnDay != null) { annualFeeOnMonthDay = new
|
||||
* MonthDay(annualFeeOnMonth, annualFeeOnDay); }
|
||||
*
|
||||
* final LocalDate annualFeeNextDueDate = JdbcSupport.getLocalDate(rs, "annualFeeNextDueDate");
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -792,20 +738,12 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
sqlBuilder.append("sa.min_required_opening_balance as minRequiredOpeningBalance, ");
|
||||
sqlBuilder.append("sa.lockin_period_frequency as lockinPeriodFrequency,");
|
||||
sqlBuilder.append("sa.lockin_period_frequency_enum as lockinPeriodFrequencyType, ");
|
||||
// sqlBuilder.append("sa.withdrawal_fee_amount as
|
||||
// withdrawalFeeAmount,");
|
||||
// sqlBuilder.append("sa.withdrawal_fee_type_enum as
|
||||
// withdrawalFeeTypeEnum, ");
|
||||
|
||||
sqlBuilder.append("sa.allow_overdraft as allowOverdraft, ");
|
||||
sqlBuilder.append("sa.overdraft_limit as overdraftLimit, ");
|
||||
sqlBuilder.append("sa.nominal_annual_interest_rate_overdraft as nominalAnnualInterestRateOverdraft, ");
|
||||
sqlBuilder.append("sa.min_overdraft_for_interest_calculation as minOverdraftForInterestCalculation, ");
|
||||
// sqlBuilder.append("sa.annual_fee_amount as annualFeeAmount,");
|
||||
// sqlBuilder.append("sa.annual_fee_on_month as annualFeeOnMonth,
|
||||
// ");
|
||||
// sqlBuilder.append("sa.annual_fee_on_day as annualFeeOnDay, ");
|
||||
// sqlBuilder.append("sa.annual_fee_next_due_date as
|
||||
// annualFeeNextDueDate, ");
|
||||
|
||||
sqlBuilder.append("sa.total_deposits_derived as totalDeposits, ");
|
||||
sqlBuilder.append("sa.total_withdrawals_derived as totalWithdrawals, ");
|
||||
sqlBuilder.append("sa.total_withdrawal_fees_derived as totalWithdrawalFees, ");
|
||||
@@ -981,14 +919,6 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
lockinPeriodFrequencyType = SavingsEnumerations.lockinPeriodFrequencyType(lockinPeriodType);
|
||||
}
|
||||
|
||||
/*
|
||||
* final BigDecimal withdrawalFeeAmount = rs.getBigDecimal("withdrawalFeeAmount");
|
||||
*
|
||||
* EnumOptionData withdrawalFeeType = null; final Integer withdrawalFeeTypeValue =
|
||||
* JdbcSupport.getInteger(rs, "withdrawalFeeTypeEnum"); if (withdrawalFeeTypeValue != null) {
|
||||
* withdrawalFeeType = SavingsEnumerations.withdrawalFeeType(withdrawalFeeTypeValue); }
|
||||
*/
|
||||
|
||||
final boolean withdrawalFeeForTransfers = rs.getBoolean("withdrawalFeeForTransfers");
|
||||
|
||||
final boolean allowOverdraft = rs.getBoolean("allowOverdraft");
|
||||
@@ -1004,16 +934,6 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
final BigDecimal maxAllowedLienLimit = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "maxAllowedLienLimit");
|
||||
final boolean lienAllowed = rs.getBoolean("lienAllowed");
|
||||
|
||||
/*
|
||||
* final BigDecimal annualFeeAmount = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "annualFeeAmount");
|
||||
*
|
||||
* MonthDay annualFeeOnMonthDay = null; final Integer annualFeeOnMonth = JdbcSupport.getInteger(rs,
|
||||
* "annualFeeOnMonth"); final Integer annualFeeOnDay = JdbcSupport.getInteger(rs, "annualFeeOnDay"); if
|
||||
* (annualFeeAmount != null && annualFeeOnDay != null) { annualFeeOnMonthDay = new
|
||||
* MonthDay(annualFeeOnMonth, annualFeeOnDay); }
|
||||
*
|
||||
* final LocalDate annualFeeNextDueDate = JdbcSupport.getLocalDate(rs, "annualFeeNextDueDate");
|
||||
*/
|
||||
final BigDecimal totalDeposits = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalDeposits");
|
||||
final BigDecimal totalWithdrawals = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalWithdrawals");
|
||||
final BigDecimal totalWithdrawalFees = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalWithdrawalFees");
|
||||
|
||||
+1
-5
@@ -59,11 +59,7 @@ public class SavingsDropdownReadPlatformServiceImpl implements SavingsDropdownRe
|
||||
SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.MONTHLY),
|
||||
SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.QUATERLY),
|
||||
SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.BI_ANNUAL),
|
||||
SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.ANNUAL)
|
||||
// //
|
||||
// SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.NO_COMPOUNDING_SIMPLE_INTEREST)
|
||||
// //
|
||||
);
|
||||
SavingsEnumerations.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.ANNUAL));
|
||||
|
||||
return allowedOptions;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user