FINERACT-1939: Hold Amount - should be debit

This commit is contained in:
jmarta
2023-08-07 13:42:30 +02:00
committed by Adam Saghy
parent 53ebbc6c46
commit 5b3d088f7b
11 changed files with 212 additions and 156 deletions
@@ -0,0 +1,54 @@
/**
* 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.portfolio;
public enum TransactionEntryType {
CREDIT(1, "transactionEntryType.credit"), //
DEBIT(2, "transactionEntryType.debit"), //
;
private final Integer value;
private final String code;
TransactionEntryType(final Integer value, final String code) {
this.value = value;
this.code = code;
}
public Integer getValue() {
return this.value;
}
public String getCode() {
return this.code;
}
public boolean isCredit() {
return this == CREDIT;
}
public boolean isDebit() {
return this == DEBIT;
}
public TransactionEntryType getReversal() {
return this == CREDIT ? DEBIT : CREDIT;
}
}
@@ -18,34 +18,60 @@
*/ */
package org.apache.fineract.portfolio.savings; package org.apache.fineract.portfolio.savings;
import jakarta.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.apache.fineract.portfolio.TransactionEntryType;
/** /**
* An enumeration of different transactions that can occur on a {@link SavingsAccount}. * An enumeration of different transactions that can occur on a {@link SavingsAccount}.
*/ */
public enum SavingsAccountTransactionType { public enum SavingsAccountTransactionType {
INVALID(0, "savingsAccountTransactionType.invalid"), // INVALID(0, "savingsAccountTransactionType.invalid"), //
DEPOSIT(1, "savingsAccountTransactionType.deposit"), // DEPOSIT(1, "savingsAccountTransactionType.deposit", TransactionEntryType.CREDIT), //
WITHDRAWAL(2, "savingsAccountTransactionType.withdrawal"), // WITHDRAWAL(2, "savingsAccountTransactionType.withdrawal", TransactionEntryType.DEBIT), //
INTEREST_POSTING(3, "savingsAccountTransactionType.interestPosting"), // INTEREST_POSTING(3, "savingsAccountTransactionType.interestPosting", TransactionEntryType.CREDIT), //
WITHDRAWAL_FEE(4, "savingsAccountTransactionType.withdrawalFee"), // WITHDRAWAL_FEE(4, "savingsAccountTransactionType.withdrawalFee", TransactionEntryType.DEBIT), //
ANNUAL_FEE(5, "savingsAccountTransactionType.annualFee"), // ANNUAL_FEE(5, "savingsAccountTransactionType.annualFee", TransactionEntryType.DEBIT), //
WAIVE_CHARGES(6, "savingsAccountTransactionType.waiveCharge"), // WAIVE_CHARGES(6, "savingsAccountTransactionType.waiveCharge"), //
PAY_CHARGE(7, "savingsAccountTransactionType.payCharge"), // PAY_CHARGE(7, "savingsAccountTransactionType.payCharge", TransactionEntryType.DEBIT), //
DIVIDEND_PAYOUT(8, "savingsAccountTransactionType.dividendPayout"), // DIVIDEND_PAYOUT(8, "savingsAccountTransactionType.dividendPayout", TransactionEntryType.CREDIT), //
INITIATE_TRANSFER(12, "savingsAccountTransactionType.initiateTransfer"), // INITIATE_TRANSFER(12, "savingsAccountTransactionType.initiateTransfer"), //
APPROVE_TRANSFER(13, "savingsAccountTransactionType.approveTransfer"), // APPROVE_TRANSFER(13, "savingsAccountTransactionType.approveTransfer"), //
WITHDRAW_TRANSFER(14, "savingsAccountTransactionType.withdrawTransfer"), // WITHDRAW_TRANSFER(14, "savingsAccountTransactionType.withdrawTransfer"), //
REJECT_TRANSFER(15, "savingsAccountTransactionType.rejectTransfer"), WRITTEN_OFF(16, "savingsAccountTransactionType.writtenoff"), // REJECT_TRANSFER(15, "savingsAccountTransactionType.rejectTransfer"), //
OVERDRAFT_INTEREST(17, "savingsAccountTransactionType.overdraftInterest"), // WRITTEN_OFF(16, "savingsAccountTransactionType.writtenoff"), //
WITHHOLD_TAX(18, "savingsAccountTransactionType.withholdTax"), ESCHEAT(19, "savingsAccountTransactionType.escheat"), AMOUNT_HOLD(20, OVERDRAFT_INTEREST(17, "savingsAccountTransactionType.overdraftInterest", TransactionEntryType.DEBIT), //
"savingsAccountTransactionType.onHold"), AMOUNT_RELEASE(21, "savingsAccountTransactionType.release"); WITHHOLD_TAX(18, "savingsAccountTransactionType.withholdTax", TransactionEntryType.DEBIT), //
ESCHEAT(19, "savingsAccountTransactionType.escheat", TransactionEntryType.DEBIT), //
AMOUNT_HOLD(20, "savingsAccountTransactionType.onHold", TransactionEntryType.DEBIT), //
AMOUNT_RELEASE(21, "savingsAccountTransactionType.release", TransactionEntryType.CREDIT); //
private final Integer value; public static final SavingsAccountTransactionType[] VALUES = values();
private static final Map<Integer, SavingsAccountTransactionType> BY_ID = Arrays.stream(VALUES)
.collect(Collectors.toMap(SavingsAccountTransactionType::getValue, v -> v));
private final int value;
private final String code; private final String code;
private final TransactionEntryType entryType;
SavingsAccountTransactionType(final Integer value, final String code) { SavingsAccountTransactionType(final Integer value, final String code, TransactionEntryType entryType) {
this.value = value; this.value = value;
this.code = code; this.code = code;
this.entryType = entryType;
}
SavingsAccountTransactionType(final Integer value, final String code) {
this(value, code, null);
}
public int getId() {
return this.value;
} }
public Integer getValue() { public Integer getValue() {
@@ -56,102 +82,53 @@ public enum SavingsAccountTransactionType {
return this.code; return this.code;
} }
public static SavingsAccountTransactionType fromInt(final Integer transactionType) { public TransactionEntryType getEntryType() {
return entryType;
}
if (transactionType == null) { public boolean isCreditEntryType() {
return SavingsAccountTransactionType.INVALID; return entryType != null && entryType.isCredit();
} }
SavingsAccountTransactionType savingsAccountTransactionType = SavingsAccountTransactionType.INVALID; public boolean isDebitEntryType() {
switch (transactionType) { return entryType != null && entryType.isDebit();
case 1: }
savingsAccountTransactionType = SavingsAccountTransactionType.DEPOSIT;
break; public static SavingsAccountTransactionType fromInt(final Integer value) {
case 2: SavingsAccountTransactionType transactionType = BY_ID.get(value);
savingsAccountTransactionType = SavingsAccountTransactionType.WITHDRAWAL; return transactionType == null ? INVALID : transactionType;
break;
case 3:
savingsAccountTransactionType = SavingsAccountTransactionType.INTEREST_POSTING;
break;
case 4:
savingsAccountTransactionType = SavingsAccountTransactionType.WITHDRAWAL_FEE;
break;
case 5:
savingsAccountTransactionType = SavingsAccountTransactionType.ANNUAL_FEE;
break;
case 6:
savingsAccountTransactionType = SavingsAccountTransactionType.WAIVE_CHARGES;
break;
case 7:
savingsAccountTransactionType = SavingsAccountTransactionType.PAY_CHARGE;
break;
case 8:
savingsAccountTransactionType = SavingsAccountTransactionType.DIVIDEND_PAYOUT;
break;
case 12:
savingsAccountTransactionType = SavingsAccountTransactionType.INITIATE_TRANSFER;
break;
case 13:
savingsAccountTransactionType = SavingsAccountTransactionType.APPROVE_TRANSFER;
break;
case 14:
savingsAccountTransactionType = SavingsAccountTransactionType.WITHDRAW_TRANSFER;
break;
case 15:
savingsAccountTransactionType = SavingsAccountTransactionType.REJECT_TRANSFER;
break;
case 16:
savingsAccountTransactionType = SavingsAccountTransactionType.WRITTEN_OFF;
break;
case 17:
savingsAccountTransactionType = SavingsAccountTransactionType.OVERDRAFT_INTEREST;
break;
case 18:
savingsAccountTransactionType = SavingsAccountTransactionType.WITHHOLD_TAX;
break;
case 19:
savingsAccountTransactionType = SavingsAccountTransactionType.ESCHEAT;
break;
case 20:
savingsAccountTransactionType = SavingsAccountTransactionType.AMOUNT_HOLD;
break;
case 21:
savingsAccountTransactionType = SavingsAccountTransactionType.AMOUNT_RELEASE;
break;
}
return savingsAccountTransactionType;
} }
public boolean isDeposit() { public boolean isDeposit() {
return this.value.equals(SavingsAccountTransactionType.DEPOSIT.getValue()); return this == DEPOSIT;
} }
public boolean isWithdrawal() { public boolean isWithdrawal() {
return this.value.equals(SavingsAccountTransactionType.WITHDRAWAL.getValue()); return this == WITHDRAWAL;
} }
public boolean isInterestPosting() { public boolean isInterestPosting() {
return this.value.equals(SavingsAccountTransactionType.INTEREST_POSTING.getValue()); return this == INTEREST_POSTING;
} }
public boolean isOverDraftInterestPosting() { public boolean isOverDraftInterestPosting() {
return this.value.equals(SavingsAccountTransactionType.OVERDRAFT_INTEREST.getValue()); return this == OVERDRAFT_INTEREST;
} }
public boolean isWithHoldTax() { public boolean isWithHoldTax() {
return this.value.equals(SavingsAccountTransactionType.WITHHOLD_TAX.getValue()); return this == WITHHOLD_TAX;
} }
public boolean isWithdrawalFee() { public boolean isWithdrawalFee() {
return this.value.equals(SavingsAccountTransactionType.WITHDRAWAL_FEE.getValue()); return this == WITHDRAWAL_FEE;
} }
public boolean isAnnualFee() { public boolean isAnnualFee() {
return this.value.equals(SavingsAccountTransactionType.ANNUAL_FEE.getValue()); return this == ANNUAL_FEE;
} }
public boolean isPayCharge() { public boolean isPayCharge() {
return this.value.equals(SavingsAccountTransactionType.PAY_CHARGE.getValue()); return this == PAY_CHARGE;
} }
public boolean isChargeTransaction() { public boolean isChargeTransaction() {
@@ -159,55 +136,61 @@ public enum SavingsAccountTransactionType {
} }
public boolean isWaiveCharge() { public boolean isWaiveCharge() {
return this.value.equals(SavingsAccountTransactionType.WAIVE_CHARGES.getValue()); return this == WAIVE_CHARGES;
} }
public boolean isTransferInitiation() { public boolean isTransferInitiation() {
return this.value.equals(SavingsAccountTransactionType.INITIATE_TRANSFER.getValue()); return this == INITIATE_TRANSFER;
} }
public boolean isTransferApproval() { public boolean isTransferApproval() {
return this.value.equals(SavingsAccountTransactionType.APPROVE_TRANSFER.getValue()); return this == APPROVE_TRANSFER;
} }
public boolean isTransferRejection() { public boolean isTransferRejection() {
return this.value.equals(SavingsAccountTransactionType.REJECT_TRANSFER.getValue()); return this == REJECT_TRANSFER;
} }
public boolean isTransferWithdrawal() { public boolean isTransferWithdrawal() {
return this.value.equals(SavingsAccountTransactionType.WITHDRAW_TRANSFER.getValue()); return this == WITHDRAW_TRANSFER;
} }
public boolean isWrittenoff() { public boolean isWrittenoff() {
return this.value.equals(SavingsAccountTransactionType.WRITTEN_OFF.getValue()); return this == WRITTEN_OFF;
} }
public boolean isDividendPayout() { public boolean isDividendPayout() {
return this.value.equals(SavingsAccountTransactionType.DIVIDEND_PAYOUT.getValue()); return this == DIVIDEND_PAYOUT;
} }
public boolean isIncomeFromInterest() { public boolean isIncomeFromInterest() {
return this.value.equals(SavingsAccountTransactionType.OVERDRAFT_INTEREST.getValue()); return this == OVERDRAFT_INTEREST;
} }
public boolean isEscheat() { public boolean isEscheat() {
return this.value.equals(SavingsAccountTransactionType.ESCHEAT.getValue()); return this == ESCHEAT;
} }
public boolean isAmountOnHold() { public boolean isAmountOnHold() {
return this.value.equals(SavingsAccountTransactionType.AMOUNT_HOLD.getValue()); return this == AMOUNT_HOLD;
} }
public boolean isAmountRelease() { public boolean isAmountRelease() {
return this.value.equals(SavingsAccountTransactionType.AMOUNT_RELEASE.getValue()); return this == AMOUNT_RELEASE;
}
public boolean isDebit() {
return isWithdrawal() || isWithdrawalFee() || isAnnualFee() || isPayCharge() || isIncomeFromInterest() || isWithHoldTax()
|| isEscheat();
} }
public boolean isCredit() { public boolean isCredit() {
return isDeposit() || isInterestPosting() || isDividendPayout(); // AMOUNT_RELEASE is not credit, because the account balance is not changed
return isCreditEntryType() && !isAmountRelease();
}
public boolean isDebit() {
// AMOUNT_HOLD, ESCHEAT are not debit, because the account balance is not changed
return isDebitEntryType() && !isAmountOnHold() && !isEscheat();
}
@NotNull
public static List<SavingsAccountTransactionType> getFiltered(Predicate<SavingsAccountTransactionType> filter) {
return Arrays.stream(VALUES).filter(filter).toList();
} }
} }
@@ -36,6 +36,7 @@ import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.organisation.monetary.data.CurrencyData; import org.apache.fineract.organisation.monetary.data.CurrencyData;
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
import org.apache.fineract.organisation.monetary.domain.Money; import org.apache.fineract.organisation.monetary.domain.Money;
import org.apache.fineract.portfolio.TransactionEntryType;
import org.apache.fineract.portfolio.account.data.AccountTransferData; import org.apache.fineract.portfolio.account.data.AccountTransferData;
import org.apache.fineract.portfolio.paymentdetail.data.PaymentDetailData; import org.apache.fineract.portfolio.paymentdetail.data.PaymentDetailData;
import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeData; import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeData;
@@ -55,6 +56,8 @@ public final class SavingsAccountTransactionData implements Serializable {
private Long id; private Long id;
private final SavingsAccountTransactionEnumData transactionType; private final SavingsAccountTransactionEnumData transactionType;
private final TransactionEntryType entryType;
private final Long accountId; private final Long accountId;
private final String accountNo; private final String accountNo;
private final LocalDate date; private final LocalDate date;
@@ -144,9 +147,12 @@ public final class SavingsAccountTransactionData implements Serializable {
return this.transactionType.isIncomeFromInterest() && isNotReversed(); return this.transactionType.isIncomeFromInterest() && isNotReversed();
} }
public boolean isCredit() {
return transactionType.getTransactionTypeEnum().isCredit() && isNotReversed() && !isReversalTransaction();
}
public boolean isDebit() { public boolean isDebit() {
return isWithdrawal() || isWithdrawalFeeAndNotReversed() || isAnnualFeeAndNotReversed() || isPayCharge() return transactionType.getTransactionTypeEnum().isDebit() && isNotReversed() && !isReversalTransaction();
|| isOverdraftInterestAndNotReversed() || isWithHoldTaxAndNotReversed();
} }
public boolean isWithdrawalFeeAndNotReversed() { public boolean isWithdrawalFeeAndNotReversed() {
@@ -286,10 +292,6 @@ public final class SavingsAccountTransactionData implements Serializable {
return this.transactionType.isAmountRelease(); return this.transactionType.isAmountRelease();
} }
public boolean isCredit() {
return isDeposit() || isInterestPostingAndNotReversed() || isDividendPayoutAndNotReversed();
}
public boolean isDeposit() { public boolean isDeposit() {
return this.transactionType.isDeposit(); return this.transactionType.isDeposit();
} }
@@ -308,6 +310,7 @@ public final class SavingsAccountTransactionData implements Serializable {
this.savingsAccountId = savingsId; this.savingsAccountId = savingsId;
this.paymentDetailData = paymentDetailData; this.paymentDetailData = paymentDetailData;
this.transactionType = savingsAccountTransactionType; this.transactionType = savingsAccountTransactionType;
this.entryType = transactionType == null ? null : transactionType.getTransactionTypeEnum().getEntryType();
this.transactionDate = transactionDate; this.transactionDate = transactionDate;
this.submittedOnDate = createdDate; this.submittedOnDate = createdDate;
this.amount = amount; this.amount = amount;
@@ -509,6 +512,7 @@ public final class SavingsAccountTransactionData implements Serializable {
final Boolean lienTransaction) { final Boolean lienTransaction) {
this.id = null; this.id = null;
this.transactionType = transactionType; this.transactionType = transactionType;
this.entryType = transactionType == null ? null : transactionType.getTransactionTypeEnum().getEntryType();
this.accountId = null; this.accountId = null;
this.accountNo = null; this.accountNo = null;
this.date = transactionDate; this.date = transactionDate;
@@ -550,6 +554,7 @@ public final class SavingsAccountTransactionData implements Serializable {
final Boolean lienTransaction) { final Boolean lienTransaction) {
this.id = null; this.id = null;
this.transactionType = transactionType; this.transactionType = transactionType;
this.entryType = transactionType == null ? null : transactionType.getTransactionTypeEnum().getEntryType();
this.accountId = null; this.accountId = null;
this.accountNo = null; this.accountNo = null;
this.date = null; this.date = null;
@@ -638,6 +643,7 @@ public final class SavingsAccountTransactionData implements Serializable {
this.id = id; this.id = id;
this.transactionDate = date; this.transactionDate = date;
this.transactionType = transactionType; this.transactionType = transactionType;
this.entryType = transactionType == null ? null : transactionType.getTransactionTypeEnum().getEntryType();
this.paymentDetailData = paymentDetailData; this.paymentDetailData = paymentDetailData;
this.accountId = savingsId; this.accountId = savingsId;
this.accountNo = savingsAccountNo; this.accountNo = savingsAccountNo;
@@ -744,6 +750,12 @@ public final class SavingsAccountTransactionData implements Serializable {
final String reasonForBlock) { final String reasonForBlock) {
this.id = id; this.id = id;
this.transactionType = transactionType; this.transactionType = transactionType;
TransactionEntryType entryType = null;
if (transactionType != null) {
entryType = transactionType.getTransactionTypeEnum().getEntryType();
entryType = Boolean.TRUE.equals(isReversal) ? entryType.getReversal() : entryType;
}
this.entryType = entryType;
this.paymentDetailData = paymentDetailData; this.paymentDetailData = paymentDetailData;
this.accountId = savingsId; this.accountId = savingsId;
this.accountNo = savingsAccountNo; this.accountNo = savingsAccountNo;
@@ -801,4 +813,8 @@ public final class SavingsAccountTransactionData implements Serializable {
public boolean isIsManualTransaction() { public boolean isIsManualTransaction() {
return isManualTransaction; return isManualTransaction;
} }
public TransactionEntryType getEntryType() {
return entryType;
}
} }
@@ -100,4 +100,7 @@ public class SavingsAccountTransactionEnumData implements Serializable {
return Long.valueOf(SavingsAccountTransactionType.WITHDRAWAL_FEE.getValue()).equals(this.id); return Long.valueOf(SavingsAccountTransactionType.WITHDRAWAL_FEE.getValue()).equals(this.id);
} }
public SavingsAccountTransactionType getTransactionTypeEnum() {
return SavingsAccountTransactionType.fromInt(id.intValue());
}
} }
@@ -101,7 +101,7 @@ public class InteropTransactionData extends CommandProcessingResult {
SavingsAccount savingsAccount = transaction.getSavingsAccount(); SavingsAccount savingsAccount = transaction.getSavingsAccount();
String transactionId = transaction.getId().toString(); String transactionId = transaction.getId().toString();
SavingsAccountTransactionType transactionType = SavingsAccountTransactionType.fromInt(transaction.getTypeOf()); SavingsAccountTransactionType transactionType = transaction.getTransactionType();
BigDecimal amount = transaction.getAmount(); BigDecimal amount = transaction.getAmount();
BigDecimal chargeAmount = null; BigDecimal chargeAmount = null;
@@ -233,7 +233,7 @@ public class InteropServiceImpl implements InteropService {
SavingsAccount savingsAccount = validateAndGetSavingAccount(accountId); SavingsAccount savingsAccount = validateAndGetSavingAccount(accountId);
Predicate<SavingsAccountTransaction> transFilter = t -> { Predicate<SavingsAccountTransaction> transFilter = t -> {
SavingsAccountTransactionType transactionType = SavingsAccountTransactionType.fromInt(t.getTypeOf()); SavingsAccountTransactionType transactionType = t.getTransactionType();
if (debit != transactionType.isDebit() && credit != transactionType.isCredit()) { if (debit != transactionType.isDebit() && credit != transactionType.isCredit()) {
return false; return false;
} }
@@ -23,6 +23,7 @@ import java.math.BigDecimal;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import org.apache.fineract.portfolio.TransactionEntryType;
final class SavingsAccountTransactionsApiResourceSwagger { final class SavingsAccountTransactionsApiResourceSwagger {
@@ -147,6 +148,8 @@ final class SavingsAccountTransactionsApiResourceSwagger {
@Schema(example = "1") @Schema(example = "1")
public Long id; public Long id;
public GetTranscationEnumData transactionType; public GetTranscationEnumData transactionType;
@Schema(example = "CREDIT")
public TransactionEntryType entryType;
@Schema(example = "1") @Schema(example = "1")
public Long accountId; public Long accountId;
@Schema(example = "000000001") @Schema(example = "000000001")
@@ -405,7 +405,6 @@ public class RecurringDepositAccount extends SavingsAccount {
if (transaction.isReversed()) { if (transaction.isReversed()) {
transaction.zeroBalanceFields(); transaction.zeroBalanceFields();
} else { } else {
Money transactionAmount = Money.zero(this.currency); Money transactionAmount = Money.zero(this.currency);
if (transaction.isCredit()) { if (transaction.isCredit()) {
transactionAmount = transactionAmount.plus(transaction.getAmount(this.currency)); transactionAmount = transactionAmount.plus(transaction.getAmount(this.currency));
@@ -28,7 +28,6 @@ import java.util.List;
import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
import org.apache.fineract.organisation.monetary.domain.Money; import org.apache.fineract.organisation.monetary.domain.Money;
import org.apache.fineract.portfolio.savings.SavingsAccountTransactionType;
import org.apache.fineract.portfolio.savings.domain.interest.PostingPeriod; import org.apache.fineract.portfolio.savings.domain.interest.PostingPeriod;
/** /**
@@ -106,7 +105,6 @@ public final class SavingsAccountSummary {
this.totalOverdraftInterestDerived = wrapper.calculateTotalOverdraftInterest(currency, transactions); this.totalOverdraftInterestDerived = wrapper.calculateTotalOverdraftInterest(currency, transactions);
this.totalWithholdTax = wrapper.calculateTotalWithholdTaxWithdrawal(currency, transactions); this.totalWithholdTax = wrapper.calculateTotalWithholdTaxWithdrawal(currency, transactions);
// boolean isUpdated = false;
updateRunningBalanceAndPivotDate(false, transactions, null, null, null, currency); updateRunningBalanceAndPivotDate(false, transactions, null, null, null, currency);
this.accountBalance = Money.of(currency, this.totalDeposits).plus(this.totalInterestPosted).minus(this.totalWithdrawals) this.accountBalance = Money.of(currency, this.totalDeposits).plus(this.totalInterestPosted).minus(this.totalWithdrawals)
@@ -122,7 +120,7 @@ public final class SavingsAccountSummary {
return; return;
} }
Money transactionAmount = Money.of(currency, transaction.getAmount()); Money transactionAmount = Money.of(currency, transaction.getAmount());
switch (SavingsAccountTransactionType.fromInt(transaction.getTypeOf())) { switch (transaction.getTransactionType()) {
case DEPOSIT: case DEPOSIT:
if (transaction.isDepositAndNotReversed() || transaction.isDividendPayoutAndNotReversed()) { if (transaction.isDepositAndNotReversed() || transaction.isDividendPayoutAndNotReversed()) {
this.totalDeposits = Money.of(currency, this.totalDeposits).plus(transactionAmount).getAmount(); this.totalDeposits = Money.of(currency, this.totalDeposits).plus(transactionAmount).getAmount();
@@ -185,7 +183,7 @@ public final class SavingsAccountSummary {
break; break;
} }
} else { } else {
// boolean isUpdated = false; // INTEREST_POSTING
Money interestTotal = Money.zero(currency); Money interestTotal = Money.zero(currency);
Money withHoldTaxTotal = Money.zero(currency); Money withHoldTaxTotal = Money.zero(currency);
Money overdraftInterestTotal = Money.zero(currency); Money overdraftInterestTotal = Money.zero(currency);
@@ -418,23 +418,23 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom {
} }
public boolean isDeposit() { public boolean isDeposit() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isDeposit(); return getTransactionType().isDeposit();
} }
public boolean isDepositAndNotReversed() { public boolean isDepositAndNotReversed() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isDeposit() && isNotReversed(); return getTransactionType().isDeposit() && isNotReversed();
} }
public boolean isDividendPayout() { public boolean isDividendPayout() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isDividendPayout(); return getTransactionType().isDividendPayout();
} }
public boolean isDividendPayoutAndNotReversed() { public boolean isDividendPayoutAndNotReversed() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isDividendPayout() && isNotReversed(); return getTransactionType().isDividendPayout() && isNotReversed();
} }
public boolean isWithdrawal() { public boolean isWithdrawal() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isWithdrawal(); return getTransactionType().isWithdrawal();
} }
public boolean isPostInterestCalculationRequired() { public boolean isPostInterestCalculationRequired() {
@@ -442,20 +442,19 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom {
} }
public boolean isInterestPostingAndNotReversed() { public boolean isInterestPostingAndNotReversed() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isInterestPosting() && isNotReversed(); return getTransactionType().isInterestPosting() && isNotReversed();
} }
public boolean isInterestPosting() { public boolean isInterestPosting() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isInterestPosting() return getTransactionType().isInterestPosting() || getTransactionType().isOverDraftInterestPosting();
|| SavingsAccountTransactionType.fromInt(this.typeOf).isOverDraftInterestPosting();
} }
public boolean isWithdrawalFeeAndNotReversed() { public boolean isWithdrawalFeeAndNotReversed() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isWithdrawalFee() && isNotReversed(); return getTransactionType().isWithdrawalFee() && isNotReversed();
} }
public boolean isWithdrawalFee() { public boolean isWithdrawalFee() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isWithdrawalFee(); return getTransactionType().isWithdrawalFee();
} }
public boolean isAnnualFeeAndNotReversed() { public boolean isAnnualFeeAndNotReversed() {
@@ -463,7 +462,7 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom {
} }
public boolean isAnnualFee() { public boolean isAnnualFee() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isAnnualFee(); return getTransactionType().isAnnualFee();
} }
public boolean isNotReversed() { public boolean isNotReversed() {
@@ -475,19 +474,19 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom {
} }
public boolean isTransferInitiation() { public boolean isTransferInitiation() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isTransferInitiation(); return getTransactionType().isTransferInitiation();
} }
public boolean isTransferApproval() { public boolean isTransferApproval() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isTransferApproval(); return getTransactionType().isTransferApproval();
} }
public boolean isTransferRejection() { public boolean isTransferRejection() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isTransferRejection(); return getTransactionType().isTransferRejection();
} }
public boolean isTransferWithdrawal() { public boolean isTransferWithdrawal() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isTransferWithdrawal(); return getTransactionType().isTransferWithdrawal();
} }
public boolean isTransferRelatedTransaction() { public boolean isTransferRelatedTransaction() {
@@ -722,49 +721,56 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom {
} }
public boolean isCredit() { public boolean isCredit() {
return isDeposit() || isInterestPostingAndNotReversed() || isDividendPayoutAndNotReversed(); return isCreditType() && !isReversed() && !isReversalTransaction();
}
public boolean isCreditType() {
return getTransactionType().isCredit();
} }
public boolean isDebit() { public boolean isDebit() {
return isWithdrawal() || isWithdrawalFeeAndNotReversed() || isAnnualFeeAndNotReversed() || isPayCharge() return isDebitType() && !isReversed() && !isReversalTransaction();
|| isOverdraftInterestAndNotReversed() || isWithHoldTaxAndNotReversed(); }
public boolean isDebitType() {
return getTransactionType().isDebit();
} }
public boolean isWithHoldTaxAndNotReversed() { public boolean isWithHoldTaxAndNotReversed() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isWithHoldTax() && isNotReversed(); return getTransactionType().isWithHoldTax() && isNotReversed();
} }
public boolean isOverdraftInterestAndNotReversed() { public boolean isOverdraftInterestAndNotReversed() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isIncomeFromInterest() && isNotReversed(); return getTransactionType().isIncomeFromInterest() && isNotReversed();
} }
public boolean isPayCharge() { public boolean isPayCharge() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isPayCharge(); return getTransactionType().isPayCharge();
} }
public boolean isChargeTransaction() { public boolean isChargeTransaction() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isChargeTransaction(); return getTransactionType().isChargeTransaction();
} }
public boolean isChargeTransactionAndNotReversed() { public boolean isChargeTransactionAndNotReversed() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isChargeTransaction() && isNotReversed(); return getTransactionType().isChargeTransaction() && isNotReversed();
} }
public boolean isWaiveCharge() { public boolean isWaiveCharge() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isWaiveCharge(); return getTransactionType().isWaiveCharge();
} }
public boolean isAmountOnHold() { public boolean isAmountOnHold() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isAmountOnHold(); return getTransactionType().isAmountOnHold();
} }
public boolean isAmountRelease() { public boolean isAmountRelease() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isAmountRelease(); return getTransactionType().isAmountRelease();
} }
private boolean canOverriteSavingAccountRules() { private boolean canOverriteSavingAccountRules() {
final SavingsAccountChargePaidBy chargePaidBy = getSavingsAccountChargePaidBy(); final SavingsAccountChargePaidBy chargePaidBy = getSavingsAccountChargePaidBy();
return (isChargeTransaction() && chargePaidBy != null) ? chargePaidBy.canOverriteSavingAccountRules() : false; return isChargeTransaction() && chargePaidBy != null && chargePaidBy.canOverriteSavingAccountRules();
} }
public boolean canProcessBalanceCheck() { public boolean canProcessBalanceCheck() {
@@ -773,12 +779,12 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom {
public boolean isFeeCharge() { public boolean isFeeCharge() {
final SavingsAccountChargePaidBy chargePaidBy = getSavingsAccountChargePaidBy(); final SavingsAccountChargePaidBy chargePaidBy = getSavingsAccountChargePaidBy();
return (isPayCharge() && chargePaidBy != null) ? chargePaidBy.isFeeCharge() : false; return isPayCharge() && chargePaidBy != null && chargePaidBy.isFeeCharge();
} }
public boolean isPenaltyCharge() { public boolean isPenaltyCharge() {
final SavingsAccountChargePaidBy chargePaidBy = getSavingsAccountChargePaidBy(); final SavingsAccountChargePaidBy chargePaidBy = getSavingsAccountChargePaidBy();
return (isPayCharge() && chargePaidBy != null) ? chargePaidBy.isPenaltyCharge() : false; return isPayCharge() && chargePaidBy != null && chargePaidBy.isPenaltyCharge();
} }
public boolean isFeeChargeAndNotReversed() { public boolean isFeeChargeAndNotReversed() {
@@ -791,12 +797,12 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom {
public boolean isWaiveFeeCharge() { public boolean isWaiveFeeCharge() {
final SavingsAccountChargePaidBy chargePaidBy = getSavingsAccountChargePaidBy(); final SavingsAccountChargePaidBy chargePaidBy = getSavingsAccountChargePaidBy();
return (isWaiveCharge() && chargePaidBy != null) ? chargePaidBy.isFeeCharge() : false; return isWaiveCharge() && chargePaidBy != null && chargePaidBy.isFeeCharge();
} }
public boolean isWaivePenaltyCharge() { public boolean isWaivePenaltyCharge() {
final SavingsAccountChargePaidBy chargePaidBy = getSavingsAccountChargePaidBy(); final SavingsAccountChargePaidBy chargePaidBy = getSavingsAccountChargePaidBy();
return (isWaiveCharge() && chargePaidBy != null) ? chargePaidBy.isPenaltyCharge() : false; return isWaiveCharge() && chargePaidBy != null && chargePaidBy.isPenaltyCharge();
} }
public boolean isWaiveFeeChargeAndNotReversed() { public boolean isWaiveFeeChargeAndNotReversed() {
@@ -827,18 +833,8 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom {
} }
public boolean isPaymentForCurrentCharge(final SavingsAccountCharge savingsAccountCharge) { public boolean isPaymentForCurrentCharge(final SavingsAccountCharge savingsAccountCharge) {
final SavingsAccountChargePaidBy chargePaidBy = getSavingsAccountChargePaidBy(); final SavingsAccountChargePaidBy chargePaidBy = getSavingsAccountChargePaidBy();
final boolean isChargePaidForCurrentCharge; return chargePaidBy != null && chargePaidBy.getSavingsAccountCharge().equals(savingsAccountCharge);
if (chargePaidBy == null) {
isChargePaidForCurrentCharge = false;
} else if (chargePaidBy.getSavingsAccountCharge().equals(savingsAccountCharge)) {
isChargePaidForCurrentCharge = true;
} else {
isChargePaidForCurrentCharge = false;
}
return isChargePaidForCurrentCharge;
} }
public BigDecimal getAmount() { public BigDecimal getAmount() {
@@ -861,6 +857,10 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom {
return this.typeOf; return this.typeOf;
} }
public SavingsAccountTransactionType getTransactionType() {
return SavingsAccountTransactionType.fromInt(this.typeOf);
}
public SavingsAccount getSavingsAccount() { public SavingsAccount getSavingsAccount() {
return this.savingsAccount; return this.savingsAccount;
} }
@@ -434,7 +434,7 @@ public class SavingsAccountInterestPostingServiceImpl implements SavingsAccountI
} }
runningBalance = runningBalance.plus(transactionAmount); runningBalance = runningBalance.plus(transactionAmount);
if (!transaction.getRunningBalance(transactionAmount.getCurrency()).isEqualTo(transactionAmount)) { if (!transaction.getRunningBalance(transactionAmount.getCurrency()).isEqualTo(runningBalance)) {
transaction.updateRunningBalance(runningBalance); transaction.updateRunningBalance(runningBalance);
} }
// transaction.updateRunningBalance(runningBalance); // transaction.updateRunningBalance(runningBalance);