+5
@@ -0,0 +1,5 @@
|
||||
/***Set defaults for income from Penalties for existing Saving Products**/
|
||||
INSERT INTO `acc_product_mapping` (`gl_account_id`,`product_id`,`product_type`,`payment_type`,`charge_id`,`financial_account_type`)
|
||||
select mapping.gl_account_id,mapping.product_id,mapping.product_type,mapping.payment_type,mapping.charge_id, 5
|
||||
from acc_product_mapping mapping
|
||||
where mapping.financial_account_type = 4 and mapping.product_type=2;
|
||||
+7
-4
@@ -108,7 +108,8 @@ public class AccountingConstants {
|
||||
|
||||
/*** Accounting placeholders for cash based accounting for savings products ***/
|
||||
public static enum CASH_ACCOUNTS_FOR_SAVINGS {
|
||||
SAVINGS_REFERENCE(1), SAVINGS_CONTROL(2), INTEREST_ON_SAVINGS(3), INCOME_FROM_FEES(4), TRANSFERS_SUSPENSE(10);
|
||||
SAVINGS_REFERENCE(1), SAVINGS_CONTROL(2), INTEREST_ON_SAVINGS(3), INCOME_FROM_FEES(4), INCOME_FROM_PENALTIES(5), TRANSFERS_SUSPENSE(
|
||||
10);
|
||||
|
||||
private final Integer value;
|
||||
|
||||
@@ -144,9 +145,11 @@ public class AccountingConstants {
|
||||
***/
|
||||
public static enum SAVINGS_PRODUCT_ACCOUNTING_PARAMS {
|
||||
SAVINGS_REFERENCE("savingsReferenceAccountId"), SAVINGS_CONTROL("savingsControlAccountId"), INCOME_FROM_FEES(
|
||||
"incomeFromFeeAccountId"), INTEREST_ON_SAVINGS("interestOnSavingsAccountId"), PAYMENT_CHANNEL_FUND_SOURCE_MAPPING(
|
||||
"paymentChannelToFundSourceMappings"), PAYMENT_TYPE("paymentTypeId"), FUND_SOURCE("fundSourceAccountId"), TRANSFERS_SUSPENSE(
|
||||
"transfersInSuspenseAccountId");
|
||||
"incomeFromFeeAccountId"), INCOME_FROM_PENALTIES("incomeFromPenaltyAccountId"), INTEREST_ON_SAVINGS(
|
||||
"interestOnSavingsAccountId"), PAYMENT_CHANNEL_FUND_SOURCE_MAPPING("paymentChannelToFundSourceMappings"), PAYMENT_TYPE(
|
||||
"paymentTypeId"), FUND_SOURCE("fundSourceAccountId"), TRANSFERS_SUSPENSE("transfersInSuspenseAccountId"), FEE_INCOME_ACCOUNT_MAPPING(
|
||||
"feeToIncomeAccountMappings"), PENALTY_INCOME_ACCOUNT_MAPPING("penaltyToIncomeAccountMappings"), CHARGE_ID("chargeId"), INCOME_ACCOUNT_ID(
|
||||
"incomeAccountId");
|
||||
|
||||
private final String value;
|
||||
|
||||
|
||||
+17
-1
@@ -7,6 +7,7 @@ package org.mifosplatform.accounting.journalentry.data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionEnumData;
|
||||
|
||||
@@ -23,14 +24,21 @@ public class SavingsTransactionDTO {
|
||||
/*** Boolean values determines if the transaction is reversed ***/
|
||||
private final boolean reversed;
|
||||
|
||||
/** Breakdowns of fees and penalties this Transaction pays **/
|
||||
private final List<ChargePaymentDTO> penaltyPayments;
|
||||
private final List<ChargePaymentDTO> feePayments;
|
||||
|
||||
public SavingsTransactionDTO(final Long officeId, final Long paymentTypeId, final String transactionId, final Date transactionDate,
|
||||
final SavingsAccountTransactionEnumData transactionType, final BigDecimal amount, final boolean reversed) {
|
||||
final SavingsAccountTransactionEnumData transactionType, final BigDecimal amount, final boolean reversed,
|
||||
final List<ChargePaymentDTO> feePayments, final List<ChargePaymentDTO> penaltyPayments) {
|
||||
this.paymentTypeId = paymentTypeId;
|
||||
this.transactionId = transactionId;
|
||||
this.transactionDate = transactionDate;
|
||||
this.amount = amount;
|
||||
this.reversed = reversed;
|
||||
this.transactionType = transactionType;
|
||||
this.feePayments = feePayments;
|
||||
this.penaltyPayments = penaltyPayments;
|
||||
this.officeId = officeId;
|
||||
}
|
||||
|
||||
@@ -62,4 +70,12 @@ public class SavingsTransactionDTO {
|
||||
return this.reversed;
|
||||
}
|
||||
|
||||
public List<ChargePaymentDTO> getPenaltyPayments() {
|
||||
return this.penaltyPayments;
|
||||
}
|
||||
|
||||
public List<ChargePaymentDTO> getFeePayments() {
|
||||
return this.feePayments;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+101
-3
@@ -92,7 +92,7 @@ public class AccountingProcessorHelper {
|
||||
final List<Map<String, Object>> loanChargesPaidData = (List<Map<String, Object>>) map.get("loanChargesPaid");
|
||||
for (final Map<String, Object> loanChargePaid : loanChargesPaidData) {
|
||||
final Long chargeId = (Long) loanChargePaid.get("chargeId");
|
||||
final Long loanChargeId = (Long) loanChargePaid.get("chargeId");
|
||||
final Long loanChargeId = (Long) loanChargePaid.get("loanChargeId");
|
||||
final boolean isPenalty = (Boolean) loanChargePaid.get("isPenalty");
|
||||
final BigDecimal chargeAmountPaid = (BigDecimal) loanChargePaid.get("amount");
|
||||
final ChargePaymentDTO chargePaymentDTO = new ChargePaymentDTO(chargeId, loanChargeId, chargeAmountPaid);
|
||||
@@ -135,8 +135,28 @@ public class AccountingProcessorHelper {
|
||||
final boolean reversed = (Boolean) map.get("reversed");
|
||||
final Long paymentTypeId = (Long) map.get("paymentTypeId");
|
||||
|
||||
final List<ChargePaymentDTO> feePayments = new ArrayList<ChargePaymentDTO>();
|
||||
final List<ChargePaymentDTO> penaltyPayments = new ArrayList<ChargePaymentDTO>();
|
||||
// extract charge payment details (if exists)
|
||||
if (map.containsKey("savingsChargesPaid")) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<Map<String, Object>> savingsChargesPaidData = (List<Map<String, Object>>) map.get("savingsChargesPaid");
|
||||
for (final Map<String, Object> loanChargePaid : savingsChargesPaidData) {
|
||||
final Long chargeId = (Long) loanChargePaid.get("chargeId");
|
||||
final Long loanChargeId = (Long) loanChargePaid.get("savingsChargeId");
|
||||
final boolean isPenalty = (Boolean) loanChargePaid.get("isPenalty");
|
||||
final BigDecimal chargeAmountPaid = (BigDecimal) loanChargePaid.get("amount");
|
||||
final ChargePaymentDTO chargePaymentDTO = new ChargePaymentDTO(chargeId, loanChargeId, chargeAmountPaid);
|
||||
if (isPenalty) {
|
||||
penaltyPayments.add(chargePaymentDTO);
|
||||
} else {
|
||||
feePayments.add(chargePaymentDTO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final SavingsTransactionDTO transaction = new SavingsTransactionDTO(transactionOfficeId, paymentTypeId, transactionId,
|
||||
transactionDate, transactionType, amount, reversed);
|
||||
transactionDate, transactionType, amount, reversed, feePayments, penaltyPayments);
|
||||
|
||||
newSavingsTransactions.add(transaction);
|
||||
|
||||
@@ -378,6 +398,61 @@ public class AccountingProcessorHelper {
|
||||
totalCreditedAmount, totalAmount); }
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that creates a pair of related Debits and Credits for
|
||||
* Cash Based accounting.
|
||||
*
|
||||
* The target accounts for debits and credits are switched in case of a
|
||||
* reversal
|
||||
*
|
||||
* @param office
|
||||
* @param accountTypeToBeDebited
|
||||
* Enum of the placeholder GLAccount to be debited
|
||||
* @param accountTypeToBeCredited
|
||||
* Enum of the placeholder of the GLAccount to be credited
|
||||
* @param savingsProductId
|
||||
* @param paymentTypeId
|
||||
* @param loanId
|
||||
* @param transactionId
|
||||
* @param transactionDate
|
||||
* @param amount
|
||||
* @param isReversal
|
||||
*/
|
||||
public void createCashBasedJournalEntriesAndReversalsForSavingsCharges(final Office office, final String currencyCode,
|
||||
final CASH_ACCOUNTS_FOR_SAVINGS accountTypeToBeDebited, final CASH_ACCOUNTS_FOR_SAVINGS accountTypeToBeCredited,
|
||||
final Long savingsProductId, final Long paymentTypeId, final Long loanId, final String transactionId,
|
||||
final Date 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);
|
||||
|
||||
final 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);
|
||||
}
|
||||
}
|
||||
|
||||
private void createCreditJournalEntryOrReversalForLoan(final Office office, final String currencyCode, final int accountMappingTypeId,
|
||||
final Long loanProductId, final Long paymentTypeId, final Long loanId, final String transactionId, final Date transactionDate,
|
||||
final BigDecimal amount, final Boolean isReversal) {
|
||||
@@ -464,6 +539,29 @@ public class AccountingProcessorHelper {
|
||||
return accountMapping.getGlAccount();
|
||||
}
|
||||
|
||||
private GLAccount getLinkedGLAccountForSavingsCharges(final Long savingsProductId, final int accountMappingTypeId, final Long chargeId) {
|
||||
ProductToGLAccountMapping accountMapping = this.accountMappingRepository.findCoreProductToFinAccountMapping(savingsProductId,
|
||||
PortfolioProductType.SAVING.getValue(), accountMappingTypeId);
|
||||
/*****
|
||||
* Get more specific mappings for Charges and penalties (based on the
|
||||
* actual charge /penalty coupled with the loan product). Note the
|
||||
* income from fees and income from penalties placeholder ID would be
|
||||
* the same for both cash and accrual based accounts
|
||||
*****/
|
||||
|
||||
// Vishwas TODO: remove this condition as it should always be true
|
||||
if (accountMappingTypeId == CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_FEES.getValue()
|
||||
|| accountMappingTypeId == CASH_ACCOUNTS_FOR_LOAN.INCOME_FROM_PENALTIES.getValue()) {
|
||||
final ProductToGLAccountMapping chargeSpecificIncomeAccountMapping = this.accountMappingRepository
|
||||
.findByProductIdAndProductTypeAndFinancialAccountTypeAndChargeId(savingsProductId,
|
||||
PortfolioProductType.SAVING.getValue(), accountMappingTypeId, chargeId);
|
||||
if (chargeSpecificIncomeAccountMapping != null) {
|
||||
accountMapping = chargeSpecificIncomeAccountMapping;
|
||||
}
|
||||
}
|
||||
return accountMapping.getGlAccount();
|
||||
}
|
||||
|
||||
private GLAccount getLinkedGLAccountForSavingsProduct(final Long savingsProductId, final int accountMappingTypeId,
|
||||
final Long paymentTypeId) {
|
||||
ProductToGLAccountMapping accountMapping = this.accountMappingRepository.findCoreProductToFinAccountMapping(savingsProductId,
|
||||
@@ -473,7 +571,7 @@ public class AccountingProcessorHelper {
|
||||
* channels). Note that fund source placeholder ID would be same for
|
||||
* both cash and accrual accounts
|
||||
***/
|
||||
if (accountMappingTypeId == CASH_ACCOUNTS_FOR_LOAN.FUND_SOURCE.getValue()) {
|
||||
if (accountMappingTypeId == CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE.getValue()) {
|
||||
final ProductToGLAccountMapping paymentChannelSpecificAccountMapping = this.accountMappingRepository
|
||||
.findByProductIdAndProductTypeAndFinancialAccountTypeAndPaymentTypeId(savingsProductId,
|
||||
PortfolioProductType.SAVING.getValue(), accountMappingTypeId, paymentTypeId);
|
||||
|
||||
+14
-3
@@ -7,9 +7,11 @@ package org.mifosplatform.accounting.journalentry.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.mifosplatform.accounting.closure.domain.GLClosure;
|
||||
import org.mifosplatform.accounting.common.AccountingConstants.CASH_ACCOUNTS_FOR_SAVINGS;
|
||||
import org.mifosplatform.accounting.journalentry.data.ChargePaymentDTO;
|
||||
import org.mifosplatform.accounting.journalentry.data.SavingsDTO;
|
||||
import org.mifosplatform.accounting.journalentry.data.SavingsTransactionDTO;
|
||||
import org.mifosplatform.organisation.office.domain.Office;
|
||||
@@ -39,6 +41,8 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
|
||||
final Long paymentTypeId = savingsTransactionDTO.getPaymentTypeId();
|
||||
final boolean isReversal = savingsTransactionDTO.isReversed();
|
||||
final BigDecimal amount = savingsTransactionDTO.getAmount();
|
||||
final List<ChargePaymentDTO> feePayments = savingsTransactionDTO.getFeePayments();
|
||||
final List<ChargePaymentDTO> penaltyPayments = savingsTransactionDTO.getPenaltyPayments();
|
||||
|
||||
this.helper.checkForBranchClosures(latestGLClosure, transactionDate);
|
||||
|
||||
@@ -68,9 +72,16 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
|
||||
|
||||
/** Handle Fees Deductions and reversals of Fees Deductions **/
|
||||
else if (savingsTransactionDTO.getTransactionType().isFeeDeduction()) {
|
||||
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_FEES, savingsProductId,
|
||||
paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal);
|
||||
// Is the Charge a penalty?
|
||||
if (penaltyPayments.size() > 0) {
|
||||
this.helper.createCashBasedJournalEntriesAndReversalsForSavingsCharges(office, currencyCode,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_PENALTIES, savingsProductId,
|
||||
paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal, penaltyPayments);
|
||||
} else {
|
||||
this.helper.createCashBasedJournalEntriesAndReversalsForSavingsCharges(office, currencyCode,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_FEES, savingsProductId,
|
||||
paymentTypeId, savingsId, transactionId, transactionDate, amount, isReversal, feePayments);
|
||||
}
|
||||
}
|
||||
|
||||
/** Handle Transfers proposal **/
|
||||
|
||||
+5
@@ -176,6 +176,11 @@ public final class ProductToGLAccountMappingFromApiJsonDeserializer {
|
||||
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue()).value(incomeFromFeeId)
|
||||
.notNull().integerGreaterThanZero();
|
||||
|
||||
final Long incomeFromPenaltyId = this.fromApiJsonHelper.extractLongNamed(
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), element);
|
||||
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue())
|
||||
.value(incomeFromPenaltyId).notNull().integerGreaterThanZero();
|
||||
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
|
||||
+4
@@ -24,5 +24,9 @@ public interface ProductToGLAccountMappingReadPlatformService {
|
||||
public Map<String, Object> fetchAccountMappingDetailsForSavingsProduct(final Long savingsProductId, final Integer accountingType);
|
||||
|
||||
public List<PaymentTypeToGLAccountMapper> fetchPaymentTypeToFundSourceMappingsForSavingsProduct(final Long savingsProductId);
|
||||
|
||||
public List<ChargeToGLAccountMapper> fetchFeeToIncomeAccountMappingsForSavingsProduct(final Long savingsProductId);
|
||||
|
||||
public List<ChargeToGLAccountMapper> fetchPenaltyToIncomeAccountMappingsForSavingsProduct(final Long savingsProductId);
|
||||
|
||||
}
|
||||
+13
@@ -169,6 +169,8 @@ public class ProductToGLAccountMappingReadPlatformServiceImpl implements Product
|
||||
accountMappingDetails.put(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_CONTROL.getValue(), glAccountId);
|
||||
} else if (glAccountForSavings.equals(CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_FEES)) {
|
||||
accountMappingDetails.put(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), glAccountId);
|
||||
} else if (glAccountForSavings.equals(CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_PENALTIES)) {
|
||||
accountMappingDetails.put(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), glAccountId);
|
||||
} else if (glAccountForSavings.equals(CASH_ACCOUNTS_FOR_SAVINGS.TRANSFERS_SUSPENSE)) {
|
||||
accountMappingDetails.put(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.TRANSFERS_SUSPENSE.getValue(), glAccountId);
|
||||
} else if (glAccountForSavings.equals(CASH_ACCOUNTS_FOR_SAVINGS.INTEREST_ON_SAVINGS)) {
|
||||
@@ -225,6 +227,16 @@ public class ProductToGLAccountMappingReadPlatformServiceImpl implements Product
|
||||
return fetchChargeToIncomeAccountMappings(PortfolioProductType.LOAN, loanProductId, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ChargeToGLAccountMapper> fetchFeeToIncomeAccountMappingsForSavingsProduct(Long savingsProductId) {
|
||||
return fetchChargeToIncomeAccountMappings(PortfolioProductType.SAVING, savingsProductId, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ChargeToGLAccountMapper> fetchPenaltyToIncomeAccountMappingsForSavingsProduct(Long savingsProductId) {
|
||||
return fetchChargeToIncomeAccountMappings(PortfolioProductType.SAVING, savingsProductId, true);
|
||||
}
|
||||
|
||||
private List<ChargeToGLAccountMapper> fetchChargeToIncomeAccountMappings(final PortfolioProductType portfolioProductType,
|
||||
final Long loanProductId, final boolean penalty) {
|
||||
final ProductToGLAccountMappingMapper rm = new ProductToGLAccountMappingMapper();
|
||||
@@ -249,4 +261,5 @@ public class ProductToGLAccountMappingReadPlatformServiceImpl implements Product
|
||||
}
|
||||
return chargeToGLAccountMappers;
|
||||
}
|
||||
|
||||
}
|
||||
+6
@@ -154,6 +154,10 @@ public class ProductToGLAccountMappingWritePlatformServiceImpl implements Produc
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), savingProductId,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_FEES.getValue());
|
||||
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToIncomeAccountMapping(element,
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), savingProductId,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_PENALTIES.getValue());
|
||||
|
||||
// expenses
|
||||
this.savingsProductToGLAccountMappingHelper.saveSavingsToExpenseAccountMapping(element,
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_SAVINGS.getValue(), savingProductId,
|
||||
@@ -169,6 +173,7 @@ public class ProductToGLAccountMappingWritePlatformServiceImpl implements Produc
|
||||
|
||||
// advanced accounting mappings
|
||||
this.savingsProductToGLAccountMappingHelper.savePaymentChannelToFundSourceMappings(command, element, savingProductId, null);
|
||||
this.savingsProductToGLAccountMappingHelper.saveChargesToIncomeAccountMappings(command, element, savingProductId, null);
|
||||
break;
|
||||
/*** Do not have accrual based accounting for now ***/
|
||||
case ACCRUAL_BASED:
|
||||
@@ -236,6 +241,7 @@ public class ProductToGLAccountMappingWritePlatformServiceImpl implements Produc
|
||||
element, accountingRuleType);
|
||||
this.savingsProductToGLAccountMappingHelper.updatePaymentChannelToFundSourceMappings(command, element, savingsProductId,
|
||||
changes);
|
||||
this.savingsProductToGLAccountMappingHelper.updateChargesToIncomeAccountMappings(command, element, savingsProductId, changes);
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
+21
@@ -94,6 +94,20 @@ public class SavingsProductToGLAccountMappingHelper extends ProductToGLAccountMa
|
||||
updatePaymentChannelToFundSourceMappings(command, element, productId, changes, PortfolioProductType.SAVING);
|
||||
}
|
||||
|
||||
public void saveChargesToIncomeAccountMappings(final JsonCommand command, final JsonElement element, final Long productId,
|
||||
final Map<String, Object> changes) {
|
||||
// save both fee and penalty charges
|
||||
saveChargesToIncomeAccountMappings(command, element, productId, changes, PortfolioProductType.SAVING, true);
|
||||
saveChargesToIncomeAccountMappings(command, element, productId, changes, PortfolioProductType.SAVING, false);
|
||||
}
|
||||
|
||||
public void updateChargesToIncomeAccountMappings(final JsonCommand command, final JsonElement element, final Long productId,
|
||||
final Map<String, Object> changes) {
|
||||
// update both fee and penalty charges
|
||||
updateChargeToIncomeAccountMappings(command, element, productId, changes, PortfolioProductType.SAVING, true);
|
||||
updateChargeToIncomeAccountMappings(command, element, productId, changes, PortfolioProductType.SAVING, false);
|
||||
}
|
||||
|
||||
public Map<String, Object> populateChangesForNewSavingsProductToGLAccountMappingCreation(final JsonElement element,
|
||||
final AccountingRuleType accountingRuleType) {
|
||||
final Map<String, Object> changes = new HashMap<String, Object>();
|
||||
@@ -102,6 +116,8 @@ public class SavingsProductToGLAccountMappingHelper extends ProductToGLAccountMa
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_REFERENCE.getValue(), element);
|
||||
final Long incomeFromFeesId = this.fromApiJsonHelper.extractLongNamed(
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), element);
|
||||
final Long incomeFromPenaltiesId = this.fromApiJsonHelper.extractLongNamed(
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), element);
|
||||
final Long interestOnSavingsId = this.fromApiJsonHelper.extractLongNamed(
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_SAVINGS.getValue(), element);
|
||||
final Long savingsControlId = this.fromApiJsonHelper.extractLongNamed(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_CONTROL.getValue(),
|
||||
@@ -117,6 +133,7 @@ public class SavingsProductToGLAccountMappingHelper extends ProductToGLAccountMa
|
||||
changes.put(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_REFERENCE.getValue(), savingsReferenceId);
|
||||
changes.put(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_SAVINGS.getValue(), interestOnSavingsId);
|
||||
changes.put(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), incomeFromFeesId);
|
||||
changes.put(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), incomeFromPenaltiesId);
|
||||
changes.put(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.TRANSFERS_SUSPENSE.getValue(), transfersInSuspenseAccountId);
|
||||
break;
|
||||
case ACCRUAL_BASED:
|
||||
@@ -150,6 +167,10 @@ public class SavingsProductToGLAccountMappingHelper extends ProductToGLAccountMa
|
||||
savingsProductId, CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_FEES.getValue(),
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_FEES.toString(), changes);
|
||||
|
||||
mergeSavingsToIncomeAccountMappingChanges(element, SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(),
|
||||
savingsProductId, CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_PENALTIES.getValue(),
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_PENALTIES.toString(), changes);
|
||||
|
||||
// expenses
|
||||
mergeSavingsToExpenseAccountMappingChanges(element, SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_SAVINGS.getValue(),
|
||||
savingsProductId, CASH_ACCOUNTS_FOR_SAVINGS.INTEREST_ON_SAVINGS.getValue(),
|
||||
|
||||
+4
-1
@@ -128,10 +128,13 @@ public class SavingsApiConstants {
|
||||
withdrawalFeeAmountParamName, withdrawalFeeTypeParamName, withdrawalFeeForTransfersParamName, annualFeeAmountParamName,
|
||||
annualFeeOnMonthDayParamName, accountingRuleParamName, chargesParamName,
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(),
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(),
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_SAVINGS.getValue(),
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.PAYMENT_CHANNEL_FUND_SOURCE_MAPPING.getValue(),
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_CONTROL.getValue(), SAVINGS_PRODUCT_ACCOUNTING_PARAMS.TRANSFERS_SUSPENSE.getValue(),
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_REFERENCE.getValue()));
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_REFERENCE.getValue(),
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.FEE_INCOME_ACCOUNT_MAPPING.getValue(),
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.PENALTY_INCOME_ACCOUNT_MAPPING.getValue()));
|
||||
|
||||
/**
|
||||
* These parameters will match the class level parameters of
|
||||
|
||||
+6
-1
@@ -26,6 +26,7 @@ import org.mifosplatform.accounting.common.AccountingDropdownReadPlatformService
|
||||
import org.mifosplatform.accounting.common.AccountingEnumerations;
|
||||
import org.mifosplatform.accounting.common.AccountingRuleType;
|
||||
import org.mifosplatform.accounting.glaccount.data.GLAccountData;
|
||||
import org.mifosplatform.accounting.producttoaccountmapping.data.ChargeToGLAccountMapper;
|
||||
import org.mifosplatform.accounting.producttoaccountmapping.data.PaymentTypeToGLAccountMapper;
|
||||
import org.mifosplatform.accounting.producttoaccountmapping.service.ProductToGLAccountMappingReadPlatformService;
|
||||
import org.mifosplatform.commands.domain.CommandWrapper;
|
||||
@@ -159,8 +160,12 @@ public class SavingsProductsApiResource {
|
||||
.fetchAccountMappingDetailsForSavingsProduct(productId, savingProductData.accountingRuleTypeId());
|
||||
final Collection<PaymentTypeToGLAccountMapper> paymentChannelToFundSourceMappings = this.accountMappingReadPlatformService
|
||||
.fetchPaymentTypeToFundSourceMappingsForSavingsProduct(productId);
|
||||
Collection<ChargeToGLAccountMapper> feeToGLAccountMappings = this.accountMappingReadPlatformService
|
||||
.fetchFeeToIncomeAccountMappingsForSavingsProduct(productId);
|
||||
Collection<ChargeToGLAccountMapper> penaltyToGLAccountMappings = this.accountMappingReadPlatformService
|
||||
.fetchPenaltyToIncomeAccountMappingsForSavingsProduct(productId);
|
||||
savingProductData = SavingsProductData.withAccountingDetails(savingProductData, accountingMappings,
|
||||
paymentChannelToFundSourceMappings);
|
||||
paymentChannelToFundSourceMappings, feeToGLAccountMappings, penaltyToGLAccountMappings);
|
||||
}
|
||||
|
||||
if (settings.isTemplate()) {
|
||||
|
||||
+31
-8
@@ -13,6 +13,7 @@ import java.util.Map;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.accounting.common.AccountingRuleType;
|
||||
import org.mifosplatform.accounting.glaccount.data.GLAccountData;
|
||||
import org.mifosplatform.accounting.producttoaccountmapping.data.ChargeToGLAccountMapper;
|
||||
import org.mifosplatform.accounting.producttoaccountmapping.data.PaymentTypeToGLAccountMapper;
|
||||
import org.mifosplatform.infrastructure.codes.data.CodeValueData;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
@@ -46,6 +47,8 @@ public class SavingsProductData {
|
||||
private final EnumOptionData accountingRule;
|
||||
private final Map<String, Object> accountingMappings;
|
||||
private final Collection<PaymentTypeToGLAccountMapper> paymentChannelToFundSourceMappings;
|
||||
private final Collection<ChargeToGLAccountMapper> feeToIncomeAccountMappings;
|
||||
private final Collection<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings;
|
||||
|
||||
// charges
|
||||
private final Collection<ChargeData> charges;
|
||||
@@ -91,6 +94,8 @@ public class SavingsProductData {
|
||||
final Map<String, Object> accountingMappings = null;
|
||||
final Collection<PaymentTypeToGLAccountMapper> paymentChannelToFundSourceMappings = null;
|
||||
final Collection<ChargeData> charges = null;
|
||||
final Collection<ChargeToGLAccountMapper> feeToIncomeAccountMappings = null;
|
||||
final Collection<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings = null;
|
||||
|
||||
return new SavingsProductData(id, name, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
@@ -98,7 +103,8 @@ public class SavingsProductData {
|
||||
accountingRule, annualFeeAmount, annualFeeMonthDay, accountingMappings, paymentChannelToFundSourceMappings,
|
||||
currencyOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions,
|
||||
accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions);
|
||||
accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings,
|
||||
penaltyToIncomeAccountMappings);
|
||||
}
|
||||
|
||||
public static SavingsProductData withCharges(final SavingsProductData product, final Collection<ChargeData> charges) {
|
||||
@@ -111,7 +117,8 @@ public class SavingsProductData {
|
||||
product.interestCompoundingPeriodTypeOptions, product.interestPostingPeriodTypeOptions,
|
||||
product.interestCalculationTypeOptions, product.interestCalculationDaysInYearTypeOptions,
|
||||
product.lockinPeriodFrequencyTypeOptions, product.withdrawalFeeTypeOptions, product.paymentTypeOptions,
|
||||
product.accountingRuleOptions, product.accountingMappingOptions, charges, product.chargeOptions, product.penaltyOptions);
|
||||
product.accountingRuleOptions, product.accountingMappingOptions, charges, product.chargeOptions, product.penaltyOptions,
|
||||
product.feeToIncomeAccountMappings, product.penaltyToIncomeAccountMappings);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -138,11 +145,15 @@ public class SavingsProductData {
|
||||
existingProduct.paymentChannelToFundSourceMappings, currencyOptions, interestCompoundingPeriodTypeOptions,
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions,
|
||||
accountingMappingOptions, existingProduct.charges, chargeOptions, penaltyOptions);
|
||||
accountingMappingOptions, existingProduct.charges, chargeOptions, penaltyOptions,
|
||||
existingProduct.feeToIncomeAccountMappings, existingProduct.penaltyToIncomeAccountMappings);
|
||||
}
|
||||
|
||||
public static SavingsProductData withAccountingDetails(final SavingsProductData existingProduct,
|
||||
final Map<String, Object> accountingMappings, final Collection<PaymentTypeToGLAccountMapper> paymentChannelToFundSourceMappings) {
|
||||
final Map<String, Object> accountingMappings,
|
||||
final Collection<PaymentTypeToGLAccountMapper> paymentChannelToFundSourceMappings,
|
||||
final Collection<ChargeToGLAccountMapper> feeToIncomeAccountMappings,
|
||||
final Collection<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings) {
|
||||
|
||||
final Collection<CurrencyData> currencyOptions = null;
|
||||
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
|
||||
@@ -167,7 +178,8 @@ public class SavingsProductData {
|
||||
paymentChannelToFundSourceMappings, currencyOptions, interestCompoundingPeriodTypeOptions,
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions,
|
||||
accountingMappingOptions, existingProduct.charges, chargeOptions, penaltyOptions);
|
||||
accountingMappingOptions, existingProduct.charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings,
|
||||
penaltyToIncomeAccountMappings);
|
||||
}
|
||||
|
||||
public static SavingsProductData instance(final Long id, final String name, final String description, final CurrencyData currency,
|
||||
@@ -194,6 +206,8 @@ public class SavingsProductData {
|
||||
final Collection<ChargeData> chargeOptions = null;
|
||||
final Collection<ChargeData> penaltyOptions = null;
|
||||
final Collection<ChargeData> charges = null;
|
||||
final Collection<ChargeToGLAccountMapper> feeToIncomeAccountMappings = null;
|
||||
final Collection<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings = null;
|
||||
|
||||
return new SavingsProductData(id, name, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
@@ -201,7 +215,8 @@ public class SavingsProductData {
|
||||
accountingType, annualFeeAmount, annualFeeOnMonthDay, accountingMappings, paymentChannelToFundSourceMappings,
|
||||
currencyOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions,
|
||||
accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions);
|
||||
accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings,
|
||||
penaltyToIncomeAccountMappings);
|
||||
}
|
||||
|
||||
public static SavingsProductData lookup(final Long id, final String name) {
|
||||
@@ -238,6 +253,8 @@ public class SavingsProductData {
|
||||
final Collection<ChargeData> charges = null;
|
||||
final Collection<ChargeData> chargeOptions = null;
|
||||
final Collection<ChargeData> penaltyOptions = null;
|
||||
final Collection<ChargeToGLAccountMapper> feeToIncomeAccountMappings = null;
|
||||
final Collection<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings = null;
|
||||
|
||||
return new SavingsProductData(id, name, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
@@ -245,7 +262,8 @@ public class SavingsProductData {
|
||||
accountingType, annualFeeAmount, annualFeeMonthDay, accountingMappings, paymentChannelToFundSourceMappings,
|
||||
currencyOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions,
|
||||
accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions);
|
||||
accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings,
|
||||
penaltyToIncomeAccountMappings);
|
||||
}
|
||||
|
||||
private SavingsProductData(final Long id, final String name, final String description, final CurrencyData currency,
|
||||
@@ -263,7 +281,9 @@ public class SavingsProductData {
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, final Collection<EnumOptionData> withdrawalFeeTypeOptions,
|
||||
final Collection<CodeValueData> paymentTypeOptions, final Collection<EnumOptionData> accountingRuleOptions,
|
||||
final Map<String, List<GLAccountData>> accountingMappingOptions, final Collection<ChargeData> charges,
|
||||
final Collection<ChargeData> chargeOptions, final Collection<ChargeData> penaltyOptions) {
|
||||
final Collection<ChargeData> chargeOptions, final Collection<ChargeData> penaltyOptions,
|
||||
final Collection<ChargeToGLAccountMapper> feeToIncomeAccountMappings,
|
||||
final Collection<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
@@ -306,6 +326,9 @@ public class SavingsProductData {
|
||||
// Savings product
|
||||
this.penaltyOptions = penaltyOptions;// penalties available for adding
|
||||
// to Savings product
|
||||
|
||||
this.feeToIncomeAccountMappings = feeToIncomeAccountMappings;
|
||||
this.penaltyToIncomeAccountMappings = penaltyToIncomeAccountMappings;
|
||||
}
|
||||
|
||||
public boolean hasAccountingEnabled() {
|
||||
|
||||
+49
@@ -235,7 +235,13 @@ public class SavingsProductDataValidator {
|
||||
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue()).value(incomeFromFeeId)
|
||||
.notNull().integerGreaterThanZero();
|
||||
|
||||
final Long incomeFromPenaltyId = this.fromApiJsonHelper.extractLongNamed(
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), element);
|
||||
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue())
|
||||
.value(incomeFromPenaltyId).notNull().integerGreaterThanZero();
|
||||
|
||||
validatePaymentChannelFundSourceMappings(baseDataValidator, element);
|
||||
validateChargeToIncomeAccountMappings(baseDataValidator, element);
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
@@ -380,7 +386,13 @@ public class SavingsProductDataValidator {
|
||||
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue()).value(incomeFromFeeId)
|
||||
.ignoreIfNull().integerGreaterThanZero();
|
||||
|
||||
final Long incomeFromPenaltyId = this.fromApiJsonHelper.extractLongNamed(
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue(), element);
|
||||
baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_PENALTIES.getValue()).value(incomeFromPenaltyId)
|
||||
.ignoreIfNull().integerGreaterThanZero();
|
||||
|
||||
validatePaymentChannelFundSourceMappings(baseDataValidator, element);
|
||||
validateChargeToIncomeAccountMappings(baseDataValidator, element);
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
@@ -425,4 +437,41 @@ public class SavingsProductDataValidator {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateChargeToIncomeAccountMappings(final DataValidatorBuilder baseDataValidator, final JsonElement element) {
|
||||
// validate for both fee and penalty charges
|
||||
validateChargeToIncomeAccountMappings(baseDataValidator, element, true);
|
||||
validateChargeToIncomeAccountMappings(baseDataValidator, element, true);
|
||||
}
|
||||
|
||||
private void validateChargeToIncomeAccountMappings(final DataValidatorBuilder baseDataValidator, final JsonElement element,
|
||||
final boolean isPenalty) {
|
||||
String parameterName;
|
||||
if (isPenalty) {
|
||||
parameterName = SAVINGS_PRODUCT_ACCOUNTING_PARAMS.PENALTY_INCOME_ACCOUNT_MAPPING.getValue();
|
||||
} else {
|
||||
parameterName = SAVINGS_PRODUCT_ACCOUNTING_PARAMS.FEE_INCOME_ACCOUNT_MAPPING.getValue();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(parameterName, element)) {
|
||||
final JsonArray chargeToIncomeAccountMappingArray = this.fromApiJsonHelper.extractJsonArrayNamed(parameterName, element);
|
||||
if (chargeToIncomeAccountMappingArray != null && chargeToIncomeAccountMappingArray.size() > 0) {
|
||||
int i = 0;
|
||||
do {
|
||||
final JsonObject jsonObject = chargeToIncomeAccountMappingArray.get(i).getAsJsonObject();
|
||||
final Long chargeId = this.fromApiJsonHelper.extractLongNamed(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.CHARGE_ID.getValue(),
|
||||
jsonObject);
|
||||
final Long incomeAccountId = this.fromApiJsonHelper.extractLongNamed(
|
||||
SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_ACCOUNT_ID.getValue(), jsonObject);
|
||||
baseDataValidator.reset()
|
||||
.parameter(parameterName + "[" + i + "]." + SAVINGS_PRODUCT_ACCOUNTING_PARAMS.CHARGE_ID.getValue())
|
||||
.value(chargeId).notNull().integerGreaterThanZero();
|
||||
baseDataValidator.reset()
|
||||
.parameter(parameterName + "[" + i + "]." + SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_ACCOUNT_ID.getValue())
|
||||
.value(incomeAccountId).notNull().integerGreaterThanZero();
|
||||
i++;
|
||||
} while (i < chargeToIncomeAccountMappingArray.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+21
@@ -6,9 +6,11 @@
|
||||
package org.mifosplatform.portfolio.savings.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -315,6 +317,25 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
||||
thisTransactionData.put("paymentTypeId", this.paymentDetail.getPaymentType().getId());
|
||||
}
|
||||
|
||||
/***
|
||||
* Sending data in a map, though in savings we currently expect a transaction to
|
||||
* always repay a single charge (or may repay a part of a single charge
|
||||
* too)
|
||||
***/
|
||||
if (!this.savingsAccountChargesPaid.isEmpty()) {
|
||||
final List<Map<String, Object>> savingsChargesPaidData = new ArrayList<Map<String, Object>>();
|
||||
for (final SavingsAccountChargePaidBy chargePaidBy : this.savingsAccountChargesPaid) {
|
||||
final Map<String, Object> savingChargePaidData = new LinkedHashMap<String, Object>();
|
||||
savingChargePaidData.put("chargeId", chargePaidBy.getSavingsAccountCharge().getCharge().getId());
|
||||
savingChargePaidData.put("isPenalty", chargePaidBy.getSavingsAccountCharge().getCharge().isPenalty());
|
||||
savingChargePaidData.put("savingsChargeId", chargePaidBy.getSavingsAccountCharge().getId());
|
||||
savingChargePaidData.put("amount", chargePaidBy.getAmount());
|
||||
|
||||
savingsChargesPaidData.add(savingChargePaidData);
|
||||
}
|
||||
thisTransactionData.put("savingsChargesPaid", savingsChargesPaidData);
|
||||
}
|
||||
|
||||
return thisTransactionData;
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -787,6 +787,8 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
savingsAccount.payCharge(savingsAccountChargeId, chargeAmount, transactionDate, fmt, existingTransactionIds, existingReversedTransactionIds);
|
||||
|
||||
this.savingAccountRepository.saveAndFlush(savingsAccount);
|
||||
|
||||
postJournalEntries(savingsAccount, existingTransactionIds, existingReversedTransactionIds);
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withEntityId(savingsAccountChargeId) //
|
||||
|
||||
Reference in New Issue
Block a user