MIFOSX-1270 : corrected accounting for activation charge
This commit is contained in:
+46
-2
@@ -77,7 +77,7 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
|
||||
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
|
||||
ORGANIZATION_ACCOUNTS.LIABILITY_TRANSFER_SUSPENSE.getValue(),
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), savingsProductId, paymentTypeId, savingsId,
|
||||
transactionId, transactionDate, amount, isReversal);
|
||||
transactionId, transactionDate, overdraftAmount, isReversal);
|
||||
if (amount.subtract(overdraftAmount).compareTo(BigDecimal.ZERO) == 1) {
|
||||
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
|
||||
ORGANIZATION_ACCOUNTS.LIABILITY_TRANSFER_SUSPENSE.getValue(),
|
||||
@@ -88,7 +88,7 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
|
||||
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE.getValue(),
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), savingsProductId, paymentTypeId, savingsId,
|
||||
transactionId, transactionDate, amount, isReversal);
|
||||
transactionId, transactionDate, overdraftAmount, isReversal);
|
||||
if (amount.subtract(overdraftAmount).compareTo(BigDecimal.ZERO) == 1) {
|
||||
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE.getValue(),
|
||||
@@ -130,6 +130,23 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
|
||||
* Handle Interest Applications and reversals of Interest
|
||||
* Applications
|
||||
**/
|
||||
else if (savingsTransactionDTO.getTransactionType().isInterestPosting() && savingsTransactionDTO.isOverdraftTransaction()) {
|
||||
// Post journal entry if earned interest amount is greater than
|
||||
// zero
|
||||
if (savingsTransactionDTO.getAmount().compareTo(BigDecimal.ZERO) == 1) {
|
||||
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.INTEREST_ON_SAVINGS.getValue(),
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), savingsProductId, paymentTypeId, savingsId,
|
||||
transactionId, transactionDate, overdraftAmount, isReversal);
|
||||
if (amount.subtract(overdraftAmount).compareTo(BigDecimal.ZERO) == 1) {
|
||||
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.INTEREST_ON_SAVINGS.getValue(),
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.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
|
||||
@@ -141,6 +158,33 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
|
||||
}
|
||||
|
||||
/** Handle Fees Deductions and reversals of Fees Deductions **/
|
||||
else if (savingsTransactionDTO.getTransactionType().isFeeDeduction() && savingsTransactionDTO.isOverdraftTransaction()) {
|
||||
// Is the Charge a penalty?
|
||||
if (penaltyPayments.size() > 0) {
|
||||
this.helper.createCashBasedJournalEntriesAndReversalsForSavingsCharges(office, currencyCode,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL, CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_PENALTIES,
|
||||
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, overdraftAmount, isReversal,
|
||||
penaltyPayments);
|
||||
if (amount.subtract(overdraftAmount).compareTo(BigDecimal.ZERO) == 1) {
|
||||
this.helper.createCashBasedJournalEntriesAndReversalsForSavingsCharges(office, currencyCode,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_PENALTIES,
|
||||
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate,
|
||||
amount.subtract(overdraftAmount), isReversal, penaltyPayments);
|
||||
}
|
||||
} else {
|
||||
this.helper.createCashBasedJournalEntriesAndReversalsForSavingsCharges(office, currencyCode,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL, CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_FEES,
|
||||
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, overdraftAmount, isReversal,
|
||||
feePayments);
|
||||
if (amount.subtract(overdraftAmount).compareTo(BigDecimal.ZERO) == 1) {
|
||||
this.helper.createCashBasedJournalEntriesAndReversalsForSavingsCharges(office, currencyCode,
|
||||
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, CASH_ACCOUNTS_FOR_SAVINGS.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) {
|
||||
|
||||
+35
-19
@@ -449,9 +449,12 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
* calculate the amount of interest due at the end of each 'crediting'
|
||||
* period check if an existing 'interest posting' transaction exists for
|
||||
* date and matches the amount posted
|
||||
* @param isInterestTransfer TODO
|
||||
*
|
||||
* @param isInterestTransfer
|
||||
* TODO
|
||||
*/
|
||||
public List<PostingPeriod> calculateInterestUsing(final MathContext mc, final LocalDate upToInterestCalculationDate, boolean isInterestTransfer) {
|
||||
public List<PostingPeriod> calculateInterestUsing(final MathContext mc, final LocalDate upToInterestCalculationDate,
|
||||
boolean isInterestTransfer) {
|
||||
|
||||
// no openingBalance concept supported yet but probably will to allow
|
||||
// for migrations.
|
||||
@@ -488,7 +491,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
|
||||
final PostingPeriod postingPeriod = PostingPeriod.createFrom(periodInterval, periodStartingBalance,
|
||||
retreiveOrderedNonInterestPostingTransactions(), this.currency, compoundingPeriodType, interestCalculationType,
|
||||
interestRateAsFraction, daysInYearType.getValue(), upToInterestCalculationDate, interestPostTransactions, isInterestTransfer);
|
||||
interestRateAsFraction, daysInYearType.getValue(), upToInterestCalculationDate, interestPostTransactions,
|
||||
isInterestTransfer);
|
||||
|
||||
periodStartingBalance = postingPeriod.closingBalance();
|
||||
|
||||
@@ -587,9 +591,10 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
}
|
||||
resetAccountTransactionsEndOfDayBalances(accountTransactionsSorted, interestPostingUpToDate);
|
||||
}
|
||||
|
||||
protected void resetAccountTransactionsEndOfDayBalances(final List<SavingsAccountTransaction> accountTransactionsSorted, final LocalDate interestPostingUpToDate) {
|
||||
// loop over transactions in reverse
|
||||
|
||||
protected void resetAccountTransactionsEndOfDayBalances(final List<SavingsAccountTransaction> accountTransactionsSorted,
|
||||
final LocalDate interestPostingUpToDate) {
|
||||
// loop over transactions in reverse
|
||||
LocalDate endOfBalanceDate = interestPostingUpToDate;
|
||||
for (int i = accountTransactionsSorted.size() - 1; i >= 0; i--) {
|
||||
final SavingsAccountTransaction transaction = accountTransactionsSorted.get(i);
|
||||
@@ -618,8 +623,9 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
|
||||
if (isDateInTheFuture(transactionDTO.getTransactionDate())) {
|
||||
final String defaultUserMessage = "Transaction date cannot be in the future.";
|
||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg." + resourceTypeName + ".transaction.in.the.future",
|
||||
defaultUserMessage, "transactionDate", transactionDTO.getTransactionDate().toString(transactionDTO.getFormatter()));
|
||||
final ApiParameterError error = ApiParameterError.parameterError(
|
||||
"error.msg." + resourceTypeName + ".transaction.in.the.future", defaultUserMessage, "transactionDate", transactionDTO
|
||||
.getTransactionDate().toString(transactionDTO.getFormatter()));
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
dataValidationErrors.add(error);
|
||||
@@ -790,8 +796,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
if (runningBalance.isLessThanZero()) {
|
||||
//
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(depositAccountType().resourceName() + transactionAction);
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource(depositAccountType()
|
||||
.resourceName() + transactionAction);
|
||||
|
||||
if (this.allowOverdraft) {
|
||||
Money limit = runningBalance.zero();
|
||||
@@ -1316,7 +1322,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
if (transactionToUndo == null) { throw new SavingsAccountTransactionNotFoundException(this.getId(), transactionId); }
|
||||
|
||||
|
||||
validateAttemptToUndoTransferRelatedTransactions(transactionToUndo);
|
||||
validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_UNDO_TRANSACTION, transactionToUndo.transactionLocalDate());
|
||||
transactionToUndo.reverse();
|
||||
@@ -1480,8 +1486,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>();
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(depositAccountType().resourceName() + SavingsApiConstants.activateAction);
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource(depositAccountType()
|
||||
.resourceName() + SavingsApiConstants.activateAction);
|
||||
|
||||
final SavingsAccountStatusType currentStatus = SavingsAccountStatusType.fromInt(this.status);
|
||||
if (!SavingsAccountStatusType.APPROVED.hasStateOf(currentStatus)) {
|
||||
@@ -1553,10 +1559,6 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
}
|
||||
validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_ACTIVATE, activationDate);
|
||||
|
||||
// auto enter deposit for minimum required opening balance when
|
||||
// activating account.
|
||||
processAccountUponActivation();
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
@@ -1592,11 +1594,25 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
private void payActivationCharges() {
|
||||
boolean isSavingsChargeApplied = false;
|
||||
for (SavingsAccountCharge savingsAccountCharge : this.charges()) {
|
||||
if (savingsAccountCharge.isSavingsActivation()) {
|
||||
isSavingsChargeApplied = true;
|
||||
payCharge(savingsAccountCharge, savingsAccountCharge.getAmountOutstanding(getCurrency()), getActivationLocalDate());
|
||||
}
|
||||
}
|
||||
|
||||
if (isSavingsChargeApplied) {
|
||||
final MathContext mc = MathContext.DECIMAL64;
|
||||
boolean isInterestTransfer = false;
|
||||
if (this.isBeforeLastPostingPeriod(getActivationLocalDate())) {
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
this.postInterest(mc, today, isInterestTransfer);
|
||||
} else {
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
this.calculateInterestUsing(mc, today, isInterestTransfer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Object> close(final AppUser currentUser, final JsonCommand command, final LocalDate tenantsTodayDate) {
|
||||
@@ -2027,7 +2043,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
baseDataValidator.reset().parameter(SavingsApiConstants.overdraftLimitParamName).value(this.overdraftLimit)
|
||||
.failWithCode("cannot.exceed.product.value");
|
||||
}
|
||||
|
||||
|
||||
validateInterestPostingAndCompoundingPeriodTypes(baseDataValidator);
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
@@ -2054,7 +2070,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
return getActivationLocalDate().isEqual(getSubmittedOnLocalDate());
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void validateInterestPostingAndCompoundingPeriodTypes(final DataValidatorBuilder baseDataValidator) {
|
||||
Map<SavingsPostingInterestPeriodType, List<SavingsCompoundingInterestPeriodType>> postingtoCompoundMap = new HashMap<SavingsPostingInterestPeriodType, List<SavingsCompoundingInterestPeriodType>>();
|
||||
postingtoCompoundMap.put(
|
||||
|
||||
Reference in New Issue
Block a user