added support for undo savings fees
This commit is contained in:
+4
@@ -63,4 +63,8 @@ public class DateUtils {
|
|||||||
final String formattedSqlDate = df.format(date);
|
final String formattedSqlDate = df.format(date);
|
||||||
return formattedSqlDate;
|
return formattedSqlDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isInFuture(final LocalDate date){
|
||||||
|
return date.isAfter(getLocalDateOfTenant());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -19,7 +19,7 @@ public enum SavingsAccountTransactionType {
|
|||||||
INTEREST_POSTING(3, "savingsAccountTransactionType.interestPosting"), //
|
INTEREST_POSTING(3, "savingsAccountTransactionType.interestPosting"), //
|
||||||
WITHDRAWAL_FEE(4, "savingsAccountTransactionType.withdrawalFee"), //
|
WITHDRAWAL_FEE(4, "savingsAccountTransactionType.withdrawalFee"), //
|
||||||
ANNUAL_FEE(5, "savingsAccountTransactionType.annualFee"), //
|
ANNUAL_FEE(5, "savingsAccountTransactionType.annualFee"), //
|
||||||
WAIVE_CHARGES(6, "savingsAccountTransactionType.waiveCharges"), //
|
WAIVE_CHARGES(6, "savingsAccountTransactionType.waiveCharge"), //
|
||||||
PAY_CHARGE(7, "savingsAccountTransactionType.payCharge"), //
|
PAY_CHARGE(7, "savingsAccountTransactionType.payCharge"), //
|
||||||
INITIATE_TRANSFER(12, "savingsAccountTransactionType.initiateTransfer"), //
|
INITIATE_TRANSFER(12, "savingsAccountTransactionType.initiateTransfer"), //
|
||||||
APPROVE_TRANSFER(13, "savingsAccountTransactionType.approveTransfer"), //
|
APPROVE_TRANSFER(13, "savingsAccountTransactionType.approveTransfer"), //
|
||||||
|
|||||||
+1
@@ -34,6 +34,7 @@ public class SavingsApiConstants {
|
|||||||
public static String adjustTransactionAction = ".adjusttransaction";
|
public static String adjustTransactionAction = ".adjusttransaction";
|
||||||
public static String closeAction = ".close";
|
public static String closeAction = ".close";
|
||||||
public static String payChargeTransactionAction = ".paycharge";
|
public static String payChargeTransactionAction = ".paycharge";
|
||||||
|
public static String waiveChargeTransactionAction = ".waivecharge";
|
||||||
|
|
||||||
// command
|
// command
|
||||||
public static String COMMAND_UNDO_TRANSACTION = "undo";
|
public static String COMMAND_UNDO_TRANSACTION = "undo";
|
||||||
|
|||||||
+73
-76
@@ -8,13 +8,13 @@ package org.mifosplatform.portfolio.savings.domain;
|
|||||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME;
|
||||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeAmountParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeAmountParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeOnMonthDayParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.annualFeeOnMonthDayParamName;
|
||||||
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.dueAsOfDateParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.localeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.localeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeAmountParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeAmountParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeTypeParamName;
|
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.dueAsOfDateParamName;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.MathContext;
|
import java.math.MathContext;
|
||||||
@@ -1497,15 +1497,18 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
.withMonthOfYear(this.annualFeeOnMonth).withDayOfMonth(this.annualFeeOnDay).plusYears(1);
|
.withMonthOfYear(this.annualFeeOnMonth).withDayOfMonth(this.annualFeeOnDay).plusYears(1);
|
||||||
this.annualFeeNextDueDate = newAnnualFeeNextDueDate.toDate();
|
this.annualFeeNextDueDate = newAnnualFeeNextDueDate.toDate();
|
||||||
}
|
}
|
||||||
} else if (transactionToUndo.isCharge()) {
|
} else if (transactionToUndo.isCharge() || transactionToUndo.isWaiveCharge()) {
|
||||||
// undo charge
|
// undo charge
|
||||||
final Set<SavingsAccountChargePaidBy> chargesPaidBy = transactionToUndo.getSavingsAccountChargesPaid();
|
final Set<SavingsAccountChargePaidBy> chargesPaidBy = transactionToUndo.getSavingsAccountChargesPaid();
|
||||||
for (final SavingsAccountChargePaidBy savingsAccountChargePaidBy : chargesPaidBy) {
|
for (final SavingsAccountChargePaidBy savingsAccountChargePaidBy : chargesPaidBy) {
|
||||||
final SavingsAccountCharge chargeToUndo = savingsAccountChargePaidBy.getSavingsAccountCharge();
|
final SavingsAccountCharge chargeToUndo = savingsAccountChargePaidBy.getSavingsAccountCharge();
|
||||||
chargeToUndo.resetPaidAmount(this.currency);
|
if(transactionToUndo.isCharge()){
|
||||||
|
chargeToUndo.undoPayment(this.getCurrency(), transactionToUndo.getAmount(this.getCurrency()));
|
||||||
|
}else if (transactionToUndo.isWaiveCharge()){
|
||||||
|
chargeToUndo.undoWaiver(this.getCurrency(), transactionToUndo.getAmount(this.getCurrency()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1899,6 +1902,20 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void removeCharge(final SavingsAccountCharge charge) {
|
public void removeCharge(final SavingsAccountCharge charge) {
|
||||||
|
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||||
|
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||||
|
.resource(SAVINGS_ACCOUNT_RESOURCE_NAME);
|
||||||
|
|
||||||
|
if (isClosed()) {
|
||||||
|
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("delete.transaction.invalid.account.is.closed");
|
||||||
|
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isActive() || isApproved()) {
|
||||||
|
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("delete.transaction.invalid.account.is.active");
|
||||||
|
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||||
|
}
|
||||||
|
|
||||||
this.charges.remove(charge);
|
this.charges.remove(charge);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1936,15 +1953,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
// waive charge
|
// waive charge
|
||||||
final Money amountWaived = savingsAccountCharge.waive(getCurrency());
|
final Money amountWaived = savingsAccountCharge.waive(getCurrency());
|
||||||
|
|
||||||
// persist an entry in transaction details
|
handleWaiverChargeTransactions(savingsAccountCharge, amountWaived);
|
||||||
final SavingsAccountTransaction chargeTransaction = SavingsAccountTransaction.charge(this, office(),
|
|
||||||
savingsAccountCharge.getDueLocalDate(), amountWaived);
|
|
||||||
|
|
||||||
this.transactions.add(chargeTransaction);
|
|
||||||
|
|
||||||
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions);
|
|
||||||
final MathContext mc = MathContext.DECIMAL64;
|
|
||||||
calculateInterestUsing(mc, savingsAccountCharge.getDueLocalDate());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addCharge(final DateTimeFormatter formatter, final SavingsAccountCharge savingsAccountCharge, final Charge chargeDefinition) {
|
public void addCharge(final DateTimeFormatter formatter, final SavingsAccountCharge savingsAccountCharge, final Charge chargeDefinition) {
|
||||||
@@ -1966,10 +1975,16 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
final LocalDate chargeDueDate = savingsAccountCharge.getDueLocalDate();
|
final LocalDate chargeDueDate = savingsAccountCharge.getDueLocalDate();
|
||||||
|
|
||||||
if (chargeDueDate != null && chargeDueDate.isBefore(getActivationLocalDate())) {
|
if (savingsAccountCharge.isOnSpecifiedDueDate()){
|
||||||
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(getActivationLocalDate().toString(formatter))
|
if(getActivationLocalDate() != null && chargeDueDate.isBefore(getActivationLocalDate())){
|
||||||
.failWithCodeNoParameterAddedToErrorCode("before.activationDate");
|
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(getActivationLocalDate().toString(formatter))
|
||||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
.failWithCodeNoParameterAddedToErrorCode("before.activationDate");
|
||||||
|
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||||
|
}else if(getSubmittedOnLocalDate() != null && chargeDueDate.isBefore(getSubmittedOnLocalDate())){
|
||||||
|
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(getSubmittedOnLocalDate().toString(formatter))
|
||||||
|
.failWithCodeNoParameterAddedToErrorCode("before.submittedOnDate");
|
||||||
|
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_APPLY_CHARGE, chargeDueDate);
|
validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_APPLY_CHARGE, chargeDueDate);
|
||||||
@@ -1979,7 +1994,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void payCharge(final Long savingsAccountChargeId, final BigDecimal amountPaid, final LocalDate transactionDate,
|
public void payCharge(final SavingsAccountCharge savingsAccountCharge, final BigDecimal amountPaid, final LocalDate transactionDate,
|
||||||
final DateTimeFormatter formatter, final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds) {
|
final DateTimeFormatter formatter, final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds) {
|
||||||
|
|
||||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||||
@@ -1996,13 +2011,23 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transactionDate != null && transactionDate.isBefore(getActivationLocalDate())) {
|
if (savingsAccountCharge.isOnSpecifiedDueDate()){
|
||||||
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(getActivationLocalDate().toString(formatter))
|
if(getActivationLocalDate() != null && transactionDate.isBefore(getActivationLocalDate())){
|
||||||
.failWithCodeNoParameterAddedToErrorCode("before.activationDate");
|
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(getActivationLocalDate().toString(formatter))
|
||||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
.failWithCodeNoParameterAddedToErrorCode("transaction.before.activationDate");
|
||||||
|
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||||
|
}else if(getSubmittedOnLocalDate() != null && transactionDate.isBefore(getSubmittedOnLocalDate())){
|
||||||
|
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(getSubmittedOnLocalDate().toString(formatter))
|
||||||
|
.failWithCodeNoParameterAddedToErrorCode("transaction.before.submittedOnDate");
|
||||||
|
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final SavingsAccountCharge savingsAccountCharge = getCharge(savingsAccountChargeId);
|
if (DateUtils.isInFuture(transactionDate)){
|
||||||
|
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(getSubmittedOnLocalDate().toString(formatter))
|
||||||
|
.failWithCodeNoParameterAddedToErrorCode("transaction.is.futureDate");
|
||||||
|
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||||
|
}
|
||||||
|
|
||||||
// validate charge is not already paid or waived
|
// validate charge is not already paid or waived
|
||||||
if (savingsAccountCharge.isWaived()) {
|
if (savingsAccountCharge.isWaived()) {
|
||||||
@@ -2012,9 +2037,9 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("transaction.invalid.account.charge.is.paid");
|
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("transaction.invalid.account.charge.is.paid");
|
||||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||||
}
|
}
|
||||||
|
|
||||||
final Money amountPaidMoney = Money.of(currency, amountPaid);
|
final Money amountPaidMoney = Money.of(currency, amountPaid);
|
||||||
if (!savingsAccountCharge.getAmountOutstanding(getCurrency()).isGreaterThanOrEqualTo(amountPaidMoney)){
|
if (!savingsAccountCharge.getAmountOutstanding(getCurrency()).isGreaterThanOrEqualTo(amountPaidMoney)) {
|
||||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("transaction.invalid.charge.amount.paid.in.access");
|
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("transaction.invalid.charge.amount.paid.in.access");
|
||||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||||
}
|
}
|
||||||
@@ -2022,61 +2047,33 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
existingTransactionIds.addAll(findExistingTransactionIds());
|
existingTransactionIds.addAll(findExistingTransactionIds());
|
||||||
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
|
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
|
||||||
|
|
||||||
final Money chargePaid = savingsAccountCharge.pay(getCurrency(), amountPaidMoney);
|
savingsAccountCharge.pay(getCurrency(), amountPaidMoney);
|
||||||
|
|
||||||
// persist transaction details
|
|
||||||
final SavingsAccountTransaction chargeTransaction = SavingsAccountTransaction.charge(this, office(), transactionDate, chargePaid);
|
|
||||||
|
|
||||||
final SavingsAccountChargePaidBy chargePaidBy = SavingsAccountChargePaidBy.instance(chargeTransaction, savingsAccountCharge,
|
|
||||||
amountPaid);
|
|
||||||
chargeTransaction.getSavingsAccountChargesPaid().add(chargePaidBy);
|
|
||||||
this.transactions.add(chargeTransaction);
|
|
||||||
|
|
||||||
final MathContext mc = MathContext.DECIMAL64;
|
|
||||||
if (isBeforeLastPostingPeriod(savingsAccountCharge.getDueLocalDate())) {
|
|
||||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
|
||||||
postInterest(mc, today, existingTransactionIds, existingReversedTransactionIds);
|
|
||||||
} else {
|
|
||||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
|
||||||
calculateInterestUsing(mc, today);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions);
|
|
||||||
|
|
||||||
validateAccountBalanceDoesNotBecomeNegative(SavingsApiConstants.payChargeTransactionAction);
|
|
||||||
|
|
||||||
|
handlePayChargeTransactions(savingsAccountCharge, amountPaidMoney, transactionDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void payDueCharge(final SavingsAccountCharge savingsAccountCharge, final LocalDate transactionDate, final List<Long> existingTransactionIds,
|
private void handlePayChargeTransactions(SavingsAccountCharge savingsAccountCharge, Money transactionAmount,
|
||||||
final List<Long> existingReversedTransactionIds) {
|
final LocalDate transactionDate) {
|
||||||
|
final SavingsAccountTransaction chargeTransaction = SavingsAccountTransaction.charge(this, office(), transactionDate,
|
||||||
existingTransactionIds.addAll(findExistingTransactionIds());
|
transactionAmount);
|
||||||
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
|
handleChargeTransactions(savingsAccountCharge, chargeTransaction);
|
||||||
final Money amountPaid = savingsAccountCharge.payDueCharge(getCurrency());
|
|
||||||
|
|
||||||
// persist transaction details
|
|
||||||
final SavingsAccountTransaction chargeTransaction = SavingsAccountTransaction.charge(this, office(), transactionDate, amountPaid);
|
|
||||||
|
|
||||||
final SavingsAccountChargePaidBy chargePaidBy = SavingsAccountChargePaidBy.instance(chargeTransaction, savingsAccountCharge,
|
|
||||||
amountPaid.getAmount());
|
|
||||||
|
|
||||||
chargeTransaction.getSavingsAccountChargesPaid().add(chargePaidBy);
|
|
||||||
|
|
||||||
this.transactions.add(chargeTransaction);
|
|
||||||
|
|
||||||
final MathContext mc = MathContext.DECIMAL64;
|
|
||||||
if (isBeforeLastPostingPeriod(savingsAccountCharge.getDueLocalDate())) {
|
|
||||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
|
||||||
postInterest(mc, today, existingTransactionIds, existingReversedTransactionIds);
|
|
||||||
} else {
|
|
||||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
|
||||||
calculateInterestUsing(mc, today);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions);
|
|
||||||
validateAccountBalanceDoesNotBecomeNegative(amountPaid.getAmount());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleWaiverChargeTransactions(SavingsAccountCharge savingsAccountCharge, Money transactionAmount) {
|
||||||
|
final SavingsAccountTransaction chargeTransaction = SavingsAccountTransaction.waiver(this, office(),
|
||||||
|
DateUtils.getLocalDateOfTenant(), transactionAmount);
|
||||||
|
handleChargeTransactions(savingsAccountCharge, chargeTransaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleChargeTransactions(final SavingsAccountCharge savingsAccountCharge, final SavingsAccountTransaction transaction) {
|
||||||
|
// Provide a link between transaction and savings charge for which
|
||||||
|
// amount is waived.
|
||||||
|
final SavingsAccountChargePaidBy chargePaidBy = SavingsAccountChargePaidBy.instance(transaction, savingsAccountCharge, transaction
|
||||||
|
.getAmount(this.getCurrency()).getAmount());
|
||||||
|
transaction.getSavingsAccountChargesPaid().add(chargePaidBy);
|
||||||
|
this.getTransactions().add(transaction);
|
||||||
|
}
|
||||||
|
|
||||||
private SavingsAccountCharge getCharge(final Long savingsAccountChargeId) {
|
private SavingsAccountCharge getCharge(final Long savingsAccountChargeId) {
|
||||||
SavingsAccountCharge charge = null;
|
SavingsAccountCharge charge = null;
|
||||||
for (final SavingsAccountCharge existingCharge : this.charges) {
|
for (final SavingsAccountCharge existingCharge : this.charges) {
|
||||||
|
|||||||
+17
-17
@@ -214,8 +214,10 @@ public class SavingsAccountCharge extends AbstractPersistable<Long> {
|
|||||||
this.waived = false;
|
this.waived = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resetPaidAmount(final MonetaryCurrency currency) {
|
public void undoPayment(final MonetaryCurrency currency, final Money transactionAmount) {
|
||||||
this.amountPaid = BigDecimal.ZERO;
|
Money amountPaid = getAmountPaid(currency);
|
||||||
|
amountPaid = amountPaid.minus(transactionAmount);
|
||||||
|
this.amountPaid = amountPaid.getAmount();
|
||||||
this.amountOutstanding = calculateAmountOutstanding(currency);
|
this.amountOutstanding = calculateAmountOutstanding(currency);
|
||||||
this.paid = false;
|
this.paid = false;
|
||||||
}
|
}
|
||||||
@@ -223,10 +225,17 @@ public class SavingsAccountCharge extends AbstractPersistable<Long> {
|
|||||||
public Money waive(final MonetaryCurrency currency) {
|
public Money waive(final MonetaryCurrency currency) {
|
||||||
this.amountWaived = this.amountOutstanding;
|
this.amountWaived = this.amountOutstanding;
|
||||||
this.amountOutstanding = BigDecimal.ZERO;
|
this.amountOutstanding = BigDecimal.ZERO;
|
||||||
this.paid = false;
|
|
||||||
this.waived = true;
|
this.waived = true;
|
||||||
return getAmountWaived(currency);
|
return getAmountWaived(currency);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void undoWaiver(final MonetaryCurrency currency, final Money transactionAmount) {
|
||||||
|
Money amountWaived = getAmountWaived(currency);
|
||||||
|
amountWaived = amountWaived.minus(transactionAmount);
|
||||||
|
this.amountWaived = amountWaived.getAmount();
|
||||||
|
this.amountOutstanding = calculateAmountOutstanding(currency);
|
||||||
|
this.waived = false;
|
||||||
|
}
|
||||||
|
|
||||||
public Money pay(final MonetaryCurrency currency, final Money amountPaid) {
|
public Money pay(final MonetaryCurrency currency, final Money amountPaid) {
|
||||||
|
|
||||||
@@ -237,20 +246,7 @@ public class SavingsAccountCharge extends AbstractPersistable<Long> {
|
|||||||
this.amountPaid = amountPaidToDate.getAmount();
|
this.amountPaid = amountPaidToDate.getAmount();
|
||||||
this.amountOutstanding = amountOutstanding.getAmount();
|
this.amountOutstanding = amountOutstanding.getAmount();
|
||||||
this.paid = determineIfFullyPaid();
|
this.paid = determineIfFullyPaid();
|
||||||
return amountPaid;
|
return amountOutstanding;
|
||||||
}
|
|
||||||
|
|
||||||
public Money payDueCharge(final MonetaryCurrency currency) {
|
|
||||||
|
|
||||||
Money amountPaidToDate = Money.of(currency, this.amountPaid);
|
|
||||||
Money amountOutstanding = Money.of(currency, this.amountOutstanding);
|
|
||||||
final Money amountPaid = Money.of(currency, this.amountOutstanding);;
|
|
||||||
amountPaidToDate = amountPaidToDate.plus(amountPaid);
|
|
||||||
amountOutstanding = amountOutstanding.minus(amountPaid);
|
|
||||||
this.amountPaid = amountPaidToDate.getAmount();
|
|
||||||
this.amountOutstanding = amountOutstanding.getAmount();
|
|
||||||
this.paid = determineIfFullyPaid();
|
|
||||||
return amountPaid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private BigDecimal calculateAmountOutstanding(final MonetaryCurrency currency) {
|
private BigDecimal calculateAmountOutstanding(final MonetaryCurrency currency) {
|
||||||
@@ -409,6 +405,10 @@ public class SavingsAccountCharge extends AbstractPersistable<Long> {
|
|||||||
public BigDecimal amount() {
|
public BigDecimal amount() {
|
||||||
return this.amount;
|
return this.amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BigDecimal amoutOutstanding(){
|
||||||
|
return this.amountOutstanding;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isFeeCharge() {
|
public boolean isFeeCharge() {
|
||||||
return !this.penaltyCharge;
|
return !this.penaltyCharge;
|
||||||
|
|||||||
+1
-1
@@ -18,6 +18,6 @@ public interface SavingsAccountChargeRepository extends JpaRepository<SavingsAcc
|
|||||||
|
|
||||||
SavingsAccountCharge findByIdAndSavingsAccountId(Long id, Long savingsAccountId);
|
SavingsAccountCharge findByIdAndSavingsAccountId(Long id, Long savingsAccountId);
|
||||||
|
|
||||||
@Query("from SavingsAccountCharge sac where sac.dueDate <=:transactionDate and sac.waived = 0 and sac.paid=0")
|
@Query("from SavingsAccountCharge sac where sac.dueDate <=:transactionDate and sac.waived = 0 and sac.paid=0 order by sac.dueDate")
|
||||||
List<SavingsAccountCharge> findPendingCharges(@Param("transactionDate") Date transactionDate);
|
List<SavingsAccountCharge> findPendingCharges(@Param("transactionDate") Date transactionDate);
|
||||||
}
|
}
|
||||||
|
|||||||
-1
@@ -5,7 +5,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.portfolio.savings.domain;
|
package org.mifosplatform.portfolio.savings.domain;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|||||||
+4
@@ -210,6 +210,10 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
|||||||
return SavingsAccountTransactionType.fromInt(this.typeOf).isWithdrawal();
|
return SavingsAccountTransactionType.fromInt(this.typeOf).isWithdrawal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPostInterestCalculationRequired(){
|
||||||
|
return this.isDeposit() || this.isWithdrawal() || this.isCharge();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isInterestPostingAndNotReversed() {
|
public boolean isInterestPostingAndNotReversed() {
|
||||||
return SavingsAccountTransactionType.fromInt(this.typeOf).isInterestPosting() && isNotReversed();
|
return SavingsAccountTransactionType.fromInt(this.typeOf).isInterestPosting() && isNotReversed();
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -52,5 +52,5 @@ public interface SavingsAccountWritePlatformService {
|
|||||||
|
|
||||||
CommandProcessingResult payCharge(Long savingsAccountId, Long savingsAccountChargeId, JsonCommand command);
|
CommandProcessingResult payCharge(Long savingsAccountId, Long savingsAccountChargeId, JsonCommand command);
|
||||||
|
|
||||||
void payDueCharges();
|
void processDueCharges();
|
||||||
}
|
}
|
||||||
+74
-54
@@ -353,7 +353,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
}
|
}
|
||||||
account.undoTransaction(transactionId, reversedTransactionIds);
|
account.undoTransaction(transactionId, reversedTransactionIds);
|
||||||
checkClientOrGroupActive(account);
|
checkClientOrGroupActive(account);
|
||||||
if ((savingsAccountTransaction.isDeposit() || savingsAccountTransaction.isWithdrawal())
|
if (savingsAccountTransaction.isPostInterestCalculationRequired()
|
||||||
&& account.isBeforeLastPostingPeriod(savingsAccountTransaction.transactionLocalDate())) {
|
&& account.isBeforeLastPostingPeriod(savingsAccountTransaction.transactionLocalDate())) {
|
||||||
account.postInterest(mc, today, newTransactionIds, reversedTransactionIds);
|
account.postInterest(mc, today, newTransactionIds, reversedTransactionIds);
|
||||||
} else {
|
} else {
|
||||||
@@ -606,7 +606,8 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
final SavingsAccount savingsAccount = this.savingAccountAssembler.assembleFrom(savingsAccountId);
|
final SavingsAccount savingsAccount = this.savingAccountAssembler.assembleFrom(savingsAccountId);
|
||||||
checkClientOrGroupActive(savingsAccount);
|
checkClientOrGroupActive(savingsAccount);
|
||||||
|
|
||||||
final DateTimeFormatter fmt = DateTimeFormat.forPattern("dd MM yyyy");
|
final Locale locale = command.extractLocale();
|
||||||
|
final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
|
||||||
|
|
||||||
final Long chargeDefinitionId = command.longValueOfParameterNamed(chargeIdParamName);
|
final Long chargeDefinitionId = command.longValueOfParameterNamed(chargeIdParamName);
|
||||||
final Charge chargeDefinition = this.chargeRepository.findOneWithNotFoundDetection(chargeDefinitionId);
|
final Charge chargeDefinition = this.chargeRepository.findOneWithNotFoundDetection(chargeDefinitionId);
|
||||||
@@ -635,12 +636,11 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
this.savingAccountRepository.saveAndFlush(savingsAccount);
|
this.savingAccountRepository.saveAndFlush(savingsAccount);
|
||||||
|
|
||||||
return new CommandProcessingResultBuilder() //
|
return new CommandProcessingResultBuilder() //
|
||||||
.withCommandId(command.commandId()) //
|
|
||||||
.withEntityId(savingsAccountCharge.getId()) //
|
.withEntityId(savingsAccountCharge.getId()) //
|
||||||
.withOfficeId(savingsAccount.officeId()) //
|
.withOfficeId(savingsAccount.officeId()) //
|
||||||
.withClientId(savingsAccount.clientId()) //
|
.withClientId(savingsAccount.clientId()) //
|
||||||
.withGroupId(savingsAccount.groupId()) //
|
.withGroupId(savingsAccount.groupId()) //
|
||||||
.withLoanId(savingsAccountId) //
|
.withSavingsId(savingsAccountId) //
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -688,11 +688,11 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
this.savingsAccountChargeRepository.saveAndFlush(savingsAccountCharge);
|
this.savingsAccountChargeRepository.saveAndFlush(savingsAccountCharge);
|
||||||
|
|
||||||
return new CommandProcessingResultBuilder() //
|
return new CommandProcessingResultBuilder() //
|
||||||
.withEntityId(savingsChargeId) //
|
.withEntityId(savingsAccountCharge.getId()) //
|
||||||
// .withOfficeId(savings) //
|
.withOfficeId(savingsAccountCharge.savingsAccount().officeId()) //
|
||||||
// .withClientId(loan.getClientId()) //
|
.withClientId(savingsAccountCharge.savingsAccount().clientId()) //
|
||||||
// .withGroupId(loan.getGroupId()) //
|
.withGroupId(savingsAccountCharge.savingsAccount().groupId()) //
|
||||||
// .withLoanId(savingsAccountId) //
|
.withSavingsId(savingsAccountCharge.savingsAccount().getId()) //
|
||||||
.with(changes) //
|
.with(changes) //
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
@@ -702,22 +702,37 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
public CommandProcessingResult waiveCharge(final Long savingsAccountId, final Long savingsAccountChargeId) {
|
public CommandProcessingResult waiveCharge(final Long savingsAccountId, final Long savingsAccountChargeId) {
|
||||||
|
|
||||||
this.context.authenticatedUser();
|
this.context.authenticatedUser();
|
||||||
|
|
||||||
|
final SavingsAccountCharge savingsAccountCharge = this.savingsAccountChargeRepository.findOneWithNotFoundDetection(
|
||||||
|
savingsAccountChargeId, savingsAccountId);
|
||||||
|
|
||||||
|
// Get Savings account from savings charge
|
||||||
|
final SavingsAccount account = savingsAccountCharge.savingsAccount();
|
||||||
|
this.savingAccountAssembler.assignSavingAccountHelpers(account);
|
||||||
|
|
||||||
final List<Long> existingTransactionIds = new ArrayList<Long>();
|
final List<Long> existingTransactionIds = new ArrayList<Long>();
|
||||||
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
|
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
|
||||||
|
|
||||||
final SavingsAccount savingsAccount = this.savingAccountAssembler.assembleFrom(savingsAccountId);
|
account.waiveCharge(savingsAccountChargeId, existingTransactionIds, existingReversedTransactionIds);
|
||||||
checkClientOrGroupActive(savingsAccount);
|
|
||||||
|
|
||||||
savingsAccount.waiveCharge(savingsAccountChargeId, existingTransactionIds, existingReversedTransactionIds);
|
final MathContext mc = MathContext.DECIMAL64;
|
||||||
|
if (account.isBeforeLastPostingPeriod(savingsAccountCharge.getDueLocalDate())) {
|
||||||
|
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||||
|
account.postInterest(mc, today, existingTransactionIds, existingReversedTransactionIds);
|
||||||
|
} else {
|
||||||
|
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||||
|
account.calculateInterestUsing(mc, today);
|
||||||
|
}
|
||||||
|
|
||||||
this.savingAccountRepository.saveAndFlush(savingsAccount);
|
account.validateAccountBalanceDoesNotBecomeNegative(SavingsApiConstants.waiveChargeTransactionAction);
|
||||||
|
|
||||||
|
this.savingAccountRepository.saveAndFlush(account);
|
||||||
|
|
||||||
return new CommandProcessingResultBuilder() //
|
return new CommandProcessingResultBuilder() //
|
||||||
.withEntityId(savingsAccountChargeId) //
|
.withEntityId(savingsAccountChargeId) //
|
||||||
.withOfficeId(savingsAccount.officeId()) //
|
.withOfficeId(account.officeId()) //
|
||||||
.withClientId(savingsAccount.clientId()) //
|
.withClientId(account.clientId()) //
|
||||||
.withGroupId(savingsAccount.groupId()) //
|
.withGroupId(account.groupId()) //
|
||||||
.withSavingsId(savingsAccountId) //
|
.withSavingsId(savingsAccountId) //
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
@@ -733,8 +748,6 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
final SavingsAccountCharge savingsAccountCharge = this.savingsAccountChargeRepository.findOneWithNotFoundDetection(
|
final SavingsAccountCharge savingsAccountCharge = this.savingsAccountChargeRepository.findOneWithNotFoundDetection(
|
||||||
savingsAccountChargeId, savingsAccountId);
|
savingsAccountChargeId, savingsAccountId);
|
||||||
|
|
||||||
// TODO AA: validate before deleting a charge
|
|
||||||
|
|
||||||
savingsAccount.removeCharge(savingsAccountCharge);
|
savingsAccount.removeCharge(savingsAccountCharge);
|
||||||
this.savingAccountRepository.saveAndFlush(savingsAccount);
|
this.savingAccountRepository.saveAndFlush(savingsAccount);
|
||||||
|
|
||||||
@@ -747,31 +760,25 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult payCharge(final Long savingsAccountId, final Long savingsAccountChargeId, final JsonCommand command) {
|
public CommandProcessingResult payCharge(final Long savingsAccountId, final Long savingsAccountChargeId, final JsonCommand command) {
|
||||||
|
|
||||||
this.context.authenticatedUser();
|
this.context.authenticatedUser();
|
||||||
this.savingsAccountChargeDataValidator.validatePayCharge(command.json());
|
this.savingsAccountChargeDataValidator.validatePayCharge(command.json());
|
||||||
|
|
||||||
final List<Long> existingTransactionIds = new ArrayList<Long>();
|
|
||||||
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
|
|
||||||
|
|
||||||
final Locale locale = command.extractLocale();
|
final Locale locale = command.extractLocale();
|
||||||
final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
|
final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
|
||||||
|
final BigDecimal amountPaid = command.bigDecimalValueOfParameterNamed(amountParamName);
|
||||||
final SavingsAccount savingsAccount = this.savingAccountAssembler.assembleFrom(savingsAccountId);
|
|
||||||
checkClientOrGroupActive(savingsAccount);
|
|
||||||
|
|
||||||
final BigDecimal chargeAmount = command.bigDecimalValueOfParameterNamed(amountParamName);
|
|
||||||
final LocalDate transactionDate = command.localDateValueOfParameterNamed(dueAsOfDateParamName);
|
final LocalDate transactionDate = command.localDateValueOfParameterNamed(dueAsOfDateParamName);
|
||||||
|
|
||||||
|
final SavingsAccountCharge savingsAccountCharge = this.savingsAccountChargeRepository.findOneWithNotFoundDetection(
|
||||||
|
savingsAccountChargeId, savingsAccountId);
|
||||||
|
|
||||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource(SAVINGS_ACCOUNT_RESOURCE_NAME);
|
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource(SAVINGS_ACCOUNT_RESOURCE_NAME);
|
||||||
|
|
||||||
//transaction date should not be on a holiday or non working day
|
//transaction date should not be on a holiday or non working day
|
||||||
if (!this.holidayWritePlatformService.isTransactionAllowedOnHoliday()
|
if (!this.holidayWritePlatformService.isTransactionAllowedOnHoliday()
|
||||||
&& this.holidayWritePlatformService.isHoliday(savingsAccount.officeId(), transactionDate)) {
|
&& this.holidayWritePlatformService.isHoliday(savingsAccountCharge.savingsAccount().officeId(), transactionDate)) {
|
||||||
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(transactionDate.toString(fmt))
|
baseDataValidator.reset().parameter(dueAsOfDateParamName).value(transactionDate.toString(fmt))
|
||||||
.failWithCodeNoParameterAddedToErrorCode("transaction.not.allowed.transaction.date.is.on.holiday");
|
.failWithCodeNoParameterAddedToErrorCode("transaction.not.allowed.transaction.date.is.on.holiday");
|
||||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||||
@@ -783,50 +790,63 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
|||||||
.failWithCodeNoParameterAddedToErrorCode("transaction.not.allowed.transaction.date.is.a.nonworking.day");
|
.failWithCodeNoParameterAddedToErrorCode("transaction.not.allowed.transaction.date.is.a.nonworking.day");
|
||||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||||
}
|
}
|
||||||
|
|
||||||
savingsAccount.payCharge(savingsAccountChargeId, chargeAmount, transactionDate, fmt, existingTransactionIds, existingReversedTransactionIds);
|
|
||||||
|
|
||||||
this.savingAccountRepository.saveAndFlush(savingsAccount);
|
|
||||||
|
|
||||||
postJournalEntries(savingsAccount, existingTransactionIds, existingReversedTransactionIds);
|
this.payCharge(savingsAccountCharge, transactionDate, amountPaid, fmt);
|
||||||
|
|
||||||
return new CommandProcessingResultBuilder() //
|
return new CommandProcessingResultBuilder() //
|
||||||
.withEntityId(savingsAccountChargeId) //
|
.withEntityId(savingsAccountCharge.getId()) //
|
||||||
.withOfficeId(savingsAccount.officeId()) //
|
.withOfficeId(savingsAccountCharge.savingsAccount().officeId()) //
|
||||||
.withClientId(savingsAccount.clientId()) //
|
.withClientId(savingsAccountCharge.savingsAccount().clientId()) //
|
||||||
.withGroupId(savingsAccount.groupId()) //
|
.withGroupId(savingsAccountCharge.savingsAccount().groupId()) //
|
||||||
.withSavingsId(savingsAccountId) //
|
.withSavingsId(savingsAccountCharge.savingsAccount().getId()) //
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
|
||||||
@Override
|
@Override
|
||||||
@CronTarget(jobName = JobName.PAY_DUE_SAVINGS_CHARGES)
|
@CronTarget(jobName = JobName.PAY_DUE_SAVINGS_CHARGES)
|
||||||
public void payDueCharges() {
|
public void processDueCharges() {
|
||||||
//always use current date as transaction date for batch job
|
//always use current date as transaction date for batch job
|
||||||
final LocalDate transactionDate = DateUtils.getLocalDateOfTenant();
|
final LocalDate transactionDate = DateUtils.getLocalDateOfTenant();
|
||||||
final List<SavingsAccountCharge> pendingCharges = this.savingsAccountChargeRepository.findPendingCharges(transactionDate.toDate());
|
final List<SavingsAccountCharge> pendingCharges = this.savingsAccountChargeRepository.findPendingCharges(transactionDate.toDate());
|
||||||
final List<SavingsAccountCharge> paidCharges = new ArrayList<SavingsAccountCharge>(pendingCharges.size());
|
//final List<SavingsAccountCharge> paidCharges = new ArrayList<SavingsAccountCharge>(pendingCharges.size());
|
||||||
|
final DateTimeFormatter fmt = DateTimeFormat.forPattern("dd MM yyyy");
|
||||||
for (SavingsAccountCharge savingsAccountCharge : pendingCharges) {
|
for (SavingsAccountCharge savingsAccountCharge : pendingCharges) {
|
||||||
// Get Savings account from savings charge
|
|
||||||
final SavingsAccount account = savingsAccountCharge.savingsAccount();
|
|
||||||
this.savingAccountAssembler.assignSavingAccountHelpers(account);
|
|
||||||
final List<Long> existingTransactionIds = new ArrayList<Long>();
|
|
||||||
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
account.payDueCharge(savingsAccountCharge, transactionDate, existingTransactionIds, existingReversedTransactionIds);
|
payCharge(savingsAccountCharge, transactionDate, savingsAccountCharge.amoutOutstanding(), fmt);
|
||||||
paidCharges.add(savingsAccountCharge);
|
|
||||||
} catch (InsufficientAccountBalanceException isab) {
|
} catch (InsufficientAccountBalanceException isab) {
|
||||||
// TODO: AA - provide a meaningful error with failed
|
// TODO: AA - provide a meaningful error with failed
|
||||||
// transactions list
|
// transactions list
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.savingsAccountChargeRepository.save(paidCharges);
|
// this.savingsAccountChargeRepository.save(paidCharges);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
private void payCharge(final SavingsAccountCharge savingsAccountCharge, final LocalDate transactionDate, final BigDecimal amountPaid,
|
||||||
|
final DateTimeFormatter formatter) {
|
||||||
|
// Get Savings account from savings charge
|
||||||
|
final SavingsAccount account = savingsAccountCharge.savingsAccount();
|
||||||
|
this.savingAccountAssembler.assignSavingAccountHelpers(account);
|
||||||
|
final List<Long> existingTransactionIds = new ArrayList<Long>();
|
||||||
|
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
|
||||||
|
account.payCharge(savingsAccountCharge, amountPaid, transactionDate, formatter, existingTransactionIds,
|
||||||
|
existingReversedTransactionIds);
|
||||||
|
|
||||||
|
final MathContext mc = MathContext.DECIMAL64;
|
||||||
|
if (account.isBeforeLastPostingPeriod(savingsAccountCharge.getDueLocalDate())) {
|
||||||
|
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||||
|
account.postInterest(mc, today, existingTransactionIds, existingReversedTransactionIds);
|
||||||
|
} else {
|
||||||
|
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||||
|
account.calculateInterestUsing(mc, today);
|
||||||
|
}
|
||||||
|
|
||||||
|
account.validateAccountBalanceDoesNotBecomeNegative(amountPaid);
|
||||||
|
|
||||||
|
this.savingAccountRepository.save(account);
|
||||||
|
|
||||||
|
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user