MIFOSX-1522 : added outstanding running balance for transactions

This commit is contained in:
Pramod Nuthakki
2014-09-04 13:41:03 +05:30
parent 821a879610
commit d846886508
7 changed files with 69 additions and 21 deletions
@@ -0,0 +1,2 @@
ALTER TABLE `m_loan_transaction`
ADD COLUMN `outstanding_loan_balance_derived` DECIMAL(19,6) NULL DEFAULT NULL AFTER `overpayment_portion_derived`;
@@ -827,7 +827,7 @@ public class DataValidatorBuilder {
if (this.value != null && date != null) {
final LocalDate dateVal = (LocalDate) this.value;
if (!date.isAfter(dateVal)) {
if (dateVal.isAfter(date)) {
final StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(this.resource).append(".")
.append(this.parameter).append(".is.greater.than.date");
final StringBuilder defaultEnglishMessage = new StringBuilder("The ").append(this.parameter)
@@ -39,6 +39,7 @@ public class LoanTransactionData {
private final String externalId;
private final AccountTransferData transfer;
private final BigDecimal fixedEmiAmount;
private final BigDecimal outstandingLoanBalance;
// templates
final Collection<CodeValueData> paymentTypeOptions;
@@ -49,16 +50,18 @@ public class LoanTransactionData {
loanTransactionData.type, loanTransactionData.paymentDetailData, loanTransactionData.currency, loanTransactionData.date,
loanTransactionData.amount, loanTransactionData.principalPortion, loanTransactionData.interestPortion,
loanTransactionData.feeChargesPortion, loanTransactionData.penaltyChargesPortion, loanTransactionData.overpaymentPortion,
paymentTypeOptions, loanTransactionData.externalId, loanTransactionData.transfer, loanTransactionData.fixedEmiAmount);
paymentTypeOptions, loanTransactionData.externalId, loanTransactionData.transfer, loanTransactionData.fixedEmiAmount,
loanTransactionData.outstandingLoanBalance);
}
public LoanTransactionData(final Long id, final Long officeId, final String officeName, final LoanTransactionEnumData transactionType,
final PaymentDetailData paymentDetailData, final CurrencyData currency, final LocalDate date, final BigDecimal amount,
final BigDecimal principalPortion, final BigDecimal interestPortion, final BigDecimal feeChargesPortion,
final BigDecimal penaltyChargesPortion, final BigDecimal overpaymentPortion, final String externalId,
final AccountTransferData transfer, BigDecimal fixedEmiAmount) {
final AccountTransferData transfer, BigDecimal fixedEmiAmount, BigDecimal outstandingLoanBalance) {
this(id, officeId, officeName, transactionType, paymentDetailData, currency, date, amount, principalPortion, interestPortion,
feeChargesPortion, penaltyChargesPortion, overpaymentPortion, null, externalId, transfer, fixedEmiAmount);
feeChargesPortion, penaltyChargesPortion, overpaymentPortion, null, externalId, transfer, fixedEmiAmount,
outstandingLoanBalance);
}
public LoanTransactionData(final Long id, final Long officeId, final String officeName, final LoanTransactionEnumData transactionType,
@@ -66,7 +69,7 @@ public class LoanTransactionData {
final BigDecimal principalPortion, final BigDecimal interestPortion, final BigDecimal feeChargesPortion,
final BigDecimal penaltyChargesPortion, final BigDecimal overpaymentPortion,
final Collection<CodeValueData> paymentTypeOptions, final String externalId, final AccountTransferData transfer,
final BigDecimal fixedEmiAmount) {
final BigDecimal fixedEmiAmount, BigDecimal outstandingLoanBalance) {
this.id = id;
this.officeId = officeId;
this.officeName = officeName;
@@ -84,6 +87,7 @@ public class LoanTransactionData {
this.transfer = transfer;
this.overpaymentPortion = overpaymentPortion;
this.fixedEmiAmount = fixedEmiAmount;
this.outstandingLoanBalance = outstandingLoanBalance;
}
public LocalDate dateOf() {
@@ -1044,6 +1044,7 @@ public class Loan extends AbstractPersistable<Long> {
if (this.summaryArrearsAging.isNotInArrears(loanCurrency())) {
this.summaryArrearsAging = null;
}
updateLoanOutstandingBalaces();
}
}
@@ -2504,6 +2505,18 @@ public class Loan extends AbstractPersistable<Long> {
return repaymentsOrWaivers;
}
private List<LoanTransaction> retreiveListOfTransactionsExcludeAccruals() {
final List<LoanTransaction> repaymentsOrWaivers = new ArrayList<>();
for (final LoanTransaction transaction : this.loanTransactions) {
if (transaction.isNotReversed() && !transaction.isAccrual()) {
repaymentsOrWaivers.add(transaction);
}
}
final LoanTransactionComparator transactionComparator = new LoanTransactionComparator();
Collections.sort(repaymentsOrWaivers, transactionComparator);
return repaymentsOrWaivers;
}
private void doPostLoanTransactionChecks(final LocalDate transactionDate, final LoanLifecycleStateMachine loanLifecycleStateMachine) {
if (isOverPaid()) {
@@ -4169,9 +4182,6 @@ public class Loan extends AbstractPersistable<Long> {
final InterestMethod interestMethod = this.loanRepaymentScheduleDetail.getInterestMethod();
final LoanScheduleGenerator loanScheduleGenerator = loanScheduleFactory.create(interestMethod);
final RoundingMode roundingMode = RoundingMode.HALF_EVEN;
final MathContext mc = new MathContext(8, roundingMode);
final Integer loanTermFrequency = this.termFrequency;
final PeriodFrequencyType loanTermPeriodFrequencyType = PeriodFrequencyType.fromInt(this.termPeriodFrequencyType);
final List<DisbursementData> disbursementData = new ArrayList<>();
@@ -4233,4 +4243,19 @@ public class Loan extends AbstractPersistable<Long> {
}
return accruedTill;
}
private void updateLoanOutstandingBalaces() {
Money outstanding = Money.zero(getCurrency());
List<LoanTransaction> loanTransactions = retreiveListOfTransactionsExcludeAccruals();
for (LoanTransaction loanTransaction : loanTransactions) {
if (loanTransaction.isDisbursement()) {
outstanding = outstanding.plus(loanTransaction.getAmount(getCurrency()));
loanTransaction.updateOutstandingLoanBalance(outstanding.getAmount());
} else {
outstanding = outstanding.minus(loanTransaction.getPrincipalPortion(getCurrency()));
loanTransaction.updateOutstandingLoanBalance(outstanding.getAmount());
}
}
}
}
@@ -95,6 +95,9 @@ public final class LoanTransaction extends AbstractPersistable<Long> {
@OneToMany(cascade = CascadeType.ALL, mappedBy = "loanTransaction", orphanRemoval = true)
private Set<LoanChargePaidBy> loanChargesPaid = new HashSet<>();
@Column(name = "outstanding_loan_balance_derived", scale = 6, precision = 19, nullable = true)
private BigDecimal outstandingLoanBalance;
protected LoanTransaction() {
this.loan = null;
this.dateOf = null;
@@ -264,6 +267,7 @@ public final class LoanTransaction extends AbstractPersistable<Long> {
this.feeChargesPortion = null;
this.penaltyChargesPortion = null;
this.overPaymentPortion = null;
this.outstandingLoanBalance = null;
}
public void updateLoan(final Loan loan) {
@@ -462,7 +466,7 @@ public final class LoanTransaction extends AbstractPersistable<Long> {
}
return new LoanTransactionData(getId(), this.office.getId(), this.office.getName(), transactionType, paymentDetailData,
currencyData, getTransactionDate(), this.amount, this.principalPortion, this.interestPortion, this.feeChargesPortion,
this.penaltyChargesPortion, this.overPaymentPortion, this.externalId, transfer, null);
this.penaltyChargesPortion, this.overPaymentPortion, this.externalId, transfer, null, outstandingLoanBalance);
}
public Map<String, Object> toMapData(final CurrencyData currencyData) {
@@ -532,4 +536,8 @@ public final class LoanTransaction extends AbstractPersistable<Long> {
return LoanTransactionType.ACCRUAL.equals(getTypeOf()) && isNotReversed();
}
public void updateOutstandingLoanBalance(BigDecimal outstandingLoanBalance) {
this.outstandingLoanBalance = outstandingLoanBalance;
}
}
@@ -123,7 +123,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
transactionstoBeProcessed.add(loanTransaction);
}
}
for (final LoanTransaction loanTransaction : transactionstoBeProcessed) {
if (loanTransaction.isRepayment() || loanTransaction.isInterestWaiver() || loanTransaction.isRecoveryRepayment()) {
@@ -361,11 +361,13 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
final LoanTransactionEnumData transactionType = LoanEnumerations.transactionType(LoanTransactionType.REPAYMENT);
final Collection<CodeValueData> paymentOptions = this.codeValueReadPlatformService
.retrieveCodeValuesByCode(PaymentDetailConstants.paymentTypeCodeName);
final BigDecimal outstandingLoanBalance = null;
return new LoanTransactionData(null, null, null, transactionType, null, currencyData, earliestUnpaidInstallmentDate,
loanRepaymentScheduleInstallment.getTotalOutstanding(currency).getAmount(), loanRepaymentScheduleInstallment
.getPrincipalOutstanding(currency).getAmount(), loanRepaymentScheduleInstallment.getInterestOutstanding(currency)
.getAmount(), loanRepaymentScheduleInstallment.getFeeChargesOutstanding(currency).getAmount(),
loanRepaymentScheduleInstallment.getPenaltyChargesOutstanding(currency).getAmount(), null, paymentOptions, null, null, null);
loanRepaymentScheduleInstallment.getPenaltyChargesOutstanding(currency).getAmount(), null, paymentOptions, null, null,
null, outstandingLoanBalance);
}
@Override
@@ -387,11 +389,13 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
final LoanTransactionEnumData transactionType = LoanEnumerations.transactionType(LoanTransactionType.REPAYMENT);
final Collection<CodeValueData> paymentOptions = this.codeValueReadPlatformService
.retrieveCodeValuesByCode(PaymentDetailConstants.paymentTypeCodeName);
final BigDecimal outstandingLoanBalance = loanRepaymentScheduleInstallment.getPrincipalOutstanding(currency).getAmount();
return new LoanTransactionData(null, null, null, transactionType, null, currencyData, earliestUnpaidInstallmentDate,
loanRepaymentScheduleInstallment.getTotalOutstanding(currency).getAmount(), loanRepaymentScheduleInstallment
.getPrincipalOutstanding(currency).getAmount(), loanRepaymentScheduleInstallment.getInterestOutstanding(currency)
.getAmount(), loanRepaymentScheduleInstallment.getFeeChargesOutstanding(currency).getAmount(),
loanRepaymentScheduleInstallment.getPenaltyChargesOutstanding(currency).getAmount(), null, paymentOptions, null, null, null);
loanRepaymentScheduleInstallment.getPenaltyChargesOutstanding(currency).getAmount(), null, paymentOptions, null, null,
null, outstandingLoanBalance);
}
@Override
@@ -414,18 +418,19 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
final LoanTransactionEnumData transactionType = LoanEnumerations.transactionType(LoanTransactionType.WAIVE_INTEREST);
final BigDecimal amount = waiveOfInterest.getAmount(currency).getAmount();
final BigDecimal outstandingLoanBalance = null;
return new LoanTransactionData(null, null, null, transactionType, null, currencyData, waiveOfInterest.getTransactionDate(), amount,
null, null, null, null, null, null, null, null);
null, null, null, null, null, null, null, null, outstandingLoanBalance);
}
@Override
public LoanTransactionData retrieveNewClosureDetails() {
this.context.authenticatedUser();
final BigDecimal outstandingLoanBalance = null;
final LoanTransactionEnumData transactionType = LoanEnumerations.transactionType(LoanTransactionType.WRITEOFF);
return new LoanTransactionData(null, null, null, transactionType, null, null, DateUtils.getLocalDateOfTenant(), null, null, null,
null, null, null, null, null, null);
null, null, null, null, null, null, outstandingLoanBalance);
}
@Override
@@ -437,8 +442,10 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
if (paymentDetailsRequired) {
paymentOptions = this.codeValueReadPlatformService.retrieveCodeValuesByCode(PaymentDetailConstants.paymentTypeCodeName);
}
final BigDecimal outstandingLoanBalance = null;
return new LoanTransactionData(null, null, null, transactionType, null, null, loan.getExpectedDisbursedOnLocalDateForTemplate(),
loan.getDisburseAmountForTemplate(), null, null, null, null, null, paymentOptions, null, null, loan.retriveLastEmiAmount());
loan.getDisburseAmountForTemplate(), null, null, null, null, null, paymentOptions, null, null, loan.retriveLastEmiAmount(),
outstandingLoanBalance);
}
@Override
@@ -1047,7 +1054,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
return " tr.id as id, tr.transaction_type_enum as transactionType, tr.transaction_date as `date`, tr.amount as total, "
+ " tr.principal_portion_derived as principal, tr.interest_portion_derived as interest, "
+ " tr.fee_charges_portion_derived as fees, tr.penalty_charges_portion_derived as penalties, "
+ " tr.overpayment_portion_derived as overpayment, "
+ " tr.overpayment_portion_derived as overpayment, tr.outstanding_loan_balance_derived as outstandingLoanBalance, "
+ " pd.payment_type_cv_id as paymentType,pd.account_number as accountNumber,pd.check_number as checkNumber, "
+ " pd.receipt_number as receiptNumber, pd.bank_number as bankNumber,pd.routing_code as routingCode, "
+ " l.currency_code as currencyCode, l.currency_digits as currencyDigits, l.currency_multiplesof as inMultiplesOf, rc.`name` as currencyName, "
@@ -1108,6 +1115,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
final BigDecimal feeChargesPortion = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "fees");
final BigDecimal penaltyChargesPortion = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "penalties");
final BigDecimal overPaymentPortion = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "overpayment");
final BigDecimal outstandingLoanBalance = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "outstandingLoanBalance");
final String externalId = rs.getString("externalId");
AccountTransferData transfer = null;
@@ -1133,7 +1141,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
return new LoanTransactionData(id, officeId, officeName, transactionType, paymentDetailData, currencyData, date, totalAmount,
principalPortion, interestPortion, feeChargesPortion, penaltyChargesPortion, overPaymentPortion, externalId, transfer,
null);
null, outstandingLoanBalance);
}
}
@@ -1559,8 +1567,9 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
final LoanTransactionEnumData transactionType = LoanEnumerations.transactionType(LoanTransactionType.RECOVERY_REPAYMENT);
final Collection<CodeValueData> paymentOptions = this.codeValueReadPlatformService
.retrieveCodeValuesByCode(PaymentDetailConstants.paymentTypeCodeName);
BigDecimal outstandingLoanBalance = null;
return new LoanTransactionData(null, null, null, transactionType, null, null, null, loan.getTotalWrittenOff(), null, null, null,
null, null, paymentOptions, null, null, null);
null, null, paymentOptions, null, null, null, outstandingLoanBalance);
}
@@ -1568,10 +1577,10 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
public LoanTransactionData retrieveLoanWriteoffTemplate(final Long loanId) {
final LoanAccountData loan = this.retrieveOne(loanId);
final BigDecimal outstandingLoanBalance = null;
final LoanTransactionEnumData transactionType = LoanEnumerations.transactionType(LoanTransactionType.WRITEOFF);
return new LoanTransactionData(null, null, null, transactionType, null, loan.currency(), DateUtils.getLocalDateOfTenant(),
loan.getTotalOutstandingAmount(), null, null, null, null, null, null, null, null);
loan.getTotalOutstandingAmount(), null, null, null, null, null, null, null, null, outstandingLoanBalance);
}
@Override