formatting savings classes

This commit is contained in:
Vishwas Babu A J
2014-12-06 10:23:22 -08:00
parent c7f3f416ad
commit cb48a79e24
9 changed files with 1179 additions and 1572 deletions
@@ -50,7 +50,7 @@ public class DepositAccountOnHoldTransaction extends AbstractPersistable<Long> {
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created_date", nullable = false)
private Date createdDate;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "depositAccountOnHoldTransaction", optional = true, orphanRemoval = true)
private GuarantorFundingTransaction guarantorFundingTransaction;
@@ -8,8 +8,7 @@ package org.mifosplatform.portfolio.savings.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface DepositAccountOnHoldTransactionRepository extends JpaRepository<DepositAccountOnHoldTransaction ,Long>,
JpaSpecificationExecutor<DepositAccountOnHoldTransaction>{
public interface DepositAccountOnHoldTransactionRepository extends JpaRepository<DepositAccountOnHoldTransaction, Long>,
JpaSpecificationExecutor<DepositAccountOnHoldTransaction> {
}
@@ -174,25 +174,33 @@ public class FixedDepositAccount extends SavingsAccount {
return applicableInterestRate.divide(BigDecimal.valueOf(100l), mc);
}
public void updateMaturityDateAndAmountBeforeAccountActivation(final MathContext mc,
final boolean isPreMatureClosure, final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
final Integer financialYearBeginningMonth) {
public void updateMaturityDateAndAmountBeforeAccountActivation(final MathContext mc, final boolean isPreMatureClosure,
final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth) {
List<SavingsAccountTransaction> allTransactions = new ArrayList<>();
final Money transactionAmountMoney = Money.of(getCurrency(), this.accountTermAndPreClosure.depositAmount());
final SavingsAccountTransaction transaction = SavingsAccountTransaction.deposit(null, office(), null,
this.accountSubmittedOrActivationDate(), transactionAmountMoney, new Date(), null); // TODO: verify if it is ok to pass null for AppUser
this.accountSubmittedOrActivationDate(), transactionAmountMoney, new Date(), null); // TODO:
// verify
// if
// it
// is
// ok
// to
// pass
// null
// for
// AppUser
transaction.updateRunningBalance(transactionAmountMoney);
transaction.updateCumulativeBalanceAndDates(this.getCurrency(), interestCalculatedUpto());
allTransactions.add(transaction);
updateMaturityDateAndAmount(mc, allTransactions, isPreMatureClosure,
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
updateMaturityDateAndAmount(mc, allTransactions, isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd,
financialYearBeginningMonth);
}
public void updateMaturityDateAndAmount(final MathContext mc, final boolean isPreMatureClosure,
final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
final Integer financialYearBeginningMonth) {
final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth) {
updateMaturityDateAndAmount(mc, retreiveOrderedNonInterestPostingTransactions(), isPreMatureClosure,
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
}
public void updateMaturityDateAndAmount(final MathContext mc, final List<SavingsAccountTransaction> transactions,
@@ -205,9 +213,8 @@ public class FixedDepositAccount extends SavingsAccount {
// calculation
this.resetAccountTransactionsEndOfDayBalances(transactions, maturityDate);
final List<PostingPeriod> postingPeriods = calculateInterestPayable(mc, interestCalculationUpto,
transactions, isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd,
financialYearBeginningMonth);
final List<PostingPeriod> postingPeriods = calculateInterestPayable(mc, interestCalculationUpto, transactions, isPreMatureClosure,
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
// reset end of day balance back to today's date
this.resetAccountTransactionsEndOfDayBalances(transactions, DateUtils.getLocalDateOfTenant());
@@ -222,8 +229,7 @@ public class FixedDepositAccount extends SavingsAccount {
this.accountTermAndPreClosure.updateMaturityDetails(maturityAmount.getAmount(), maturityDate);
}
public void updateMaturityStatus(final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
final Integer financialYearBeginningMonth) {
public void updateMaturityStatus(final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth) {
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(FIXED_DEPOSIT_ACCOUNT_RESOURCE_NAME + SavingsApiConstants.updateMaturityDetailsAction);
@@ -238,8 +244,7 @@ public class FixedDepositAccount extends SavingsAccount {
if (!this.maturityDate().isAfter(todayDate)) {
// update account status
this.status = SavingsAccountStatusType.MATURED.getValue();
postMaturityInterest(isSavingsInterestPostingAtCurrentPeriodEnd,
financialYearBeginningMonth);
postMaturityInterest(isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
}
}
@@ -270,8 +275,7 @@ public class FixedDepositAccount extends SavingsAccount {
private List<PostingPeriod> calculateInterestPayable(final MathContext mc, final LocalDate maturityDate,
final List<SavingsAccountTransaction> transactions, final boolean isPreMatureClosure,
final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
final Integer financialYearBeginningMonth) {
final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth) {
final SavingsPostingInterestPeriodType postingPeriodType = SavingsPostingInterestPeriodType.fromInt(this.interestPostingPeriodType);
@@ -282,8 +286,7 @@ public class FixedDepositAccount extends SavingsAccount {
.fromInt(this.interestCalculationDaysInYearType);
final List<LocalDateInterval> postingPeriodIntervals = this.savingsHelper.determineInterestPostingPeriods(
accountSubmittedOrActivationDate(), maturityDate, postingPeriodType,
financialYearBeginningMonth);
accountSubmittedOrActivationDate(), maturityDate, postingPeriodType, financialYearBeginningMonth);
final List<PostingPeriod> allPostingPeriods = new ArrayList<>();
@@ -470,14 +473,12 @@ public class FixedDepositAccount extends SavingsAccount {
// this.savingsAccountTransactionSummaryWrapper, this.transactions);
}
public void postMaturityInterest(final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
final Integer financialYearBeginningMonth) {
public void postMaturityInterest(final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth) {
final LocalDate interestPostingUpToDate = maturityDate();
final MathContext mc = MathContext.DECIMAL64;
final boolean isInterestTransfer = false;
final List<PostingPeriod> postingPeriods = calculateInterestUsing(mc, interestPostingUpToDate,
isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
financialYearBeginningMonth);
final List<PostingPeriod> postingPeriods = calculateInterestUsing(mc, interestPostingUpToDate, isInterestTransfer,
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
Money interestPostedToDate = Money.zero(this.currency);
@@ -522,15 +523,13 @@ public class FixedDepositAccount extends SavingsAccount {
}
public void postPreMaturityInterest(final LocalDate accountCloseDate, final boolean isPreMatureClosure,
final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
final Integer financialYearBeginningMonth) {
final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth) {
Money interestPostedToDate = totalInterestPosted();
// calculate interest before one day of closure date
final LocalDate interestCalculatedToDate = accountCloseDate.minusDays(1);
final Money interestOnMaturity = calculatePreMatureInterest(interestCalculatedToDate,
retreiveOrderedNonInterestPostingTransactions(), isPreMatureClosure,
isSavingsInterestPostingAtCurrentPeriodEnd,
retreiveOrderedNonInterestPostingTransactions(), isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd,
financialYearBeginningMonth);
boolean recalucateDailyBalance = false;
@@ -554,14 +553,12 @@ public class FixedDepositAccount extends SavingsAccount {
}
public BigDecimal calculatePreMatureAmount(final LocalDate preMatureDate, final boolean isPreMatureClosure,
final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
final Integer financialYearBeginningMonth) {
final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth) {
final Money interestPostedToDate = totalInterestPosted().copy();
final Money interestEarnedTillDate = calculatePreMatureInterest(preMatureDate, retreiveOrderedNonInterestPostingTransactions(),
isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd,
financialYearBeginningMonth);
isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
final Money accountBalance = Money.of(getCurrency(), getAccountBalance());
final Money maturityAmount = accountBalance.minus(interestPostedToDate).plus(interestEarnedTillDate);
@@ -573,9 +570,8 @@ public class FixedDepositAccount extends SavingsAccount {
final boolean isPreMatureClosure, final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
final Integer financialYearBeginningMonth) {
final MathContext mc = MathContext.DECIMAL64;
final List<PostingPeriod> postingPeriods = calculateInterestPayable(mc, preMatureDate, transactions,
isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd,
financialYearBeginningMonth);
final List<PostingPeriod> postingPeriods = calculateInterestPayable(mc, preMatureDate, transactions, isPreMatureClosure,
isSavingsInterestPostingAtCurrentPeriodEnd, financialYearBeginningMonth);
Money interestOnMaturity = Money.zero(this.currency);
@@ -589,22 +585,18 @@ public class FixedDepositAccount extends SavingsAccount {
@Override
public void postInterest(final MathContext mc, final LocalDate postingDate, boolean isInterestTransfer,
final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
final Integer financialYearBeginningMonth) {
final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth) {
final LocalDate interestPostingUpToDate = interestPostingUpToDate(postingDate);
super.postInterest(mc, interestPostingUpToDate, isInterestTransfer,
isSavingsInterestPostingAtCurrentPeriodEnd,
financialYearBeginningMonth);
}
super.postInterest(mc, interestPostingUpToDate, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
financialYearBeginningMonth);
}
@Override
public List<PostingPeriod> calculateInterestUsing(final MathContext mc, final LocalDate postingDate,
boolean isInterestTransfer, final boolean isSavingsInterestPostingAtCurrentPeriodEnd,
final Integer financialYearBeginningMonth) {
public List<PostingPeriod> calculateInterestUsing(final MathContext mc, final LocalDate postingDate, boolean isInterestTransfer,
final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth) {
final LocalDate interestPostingUpToDate = interestPostingUpToDate(postingDate);
return super.calculateInterestUsing(mc, interestPostingUpToDate, isInterestTransfer,
isSavingsInterestPostingAtCurrentPeriodEnd,
financialYearBeginningMonth);
return super.calculateInterestUsing(mc, interestPostingUpToDate, isInterestTransfer, isSavingsInterestPostingAtCurrentPeriodEnd,
financialYearBeginningMonth);
}
private LocalDate interestPostingUpToDate(final LocalDate interestPostingDate) {
@@ -229,7 +229,7 @@ public class SavingsAccountAssembler {
} else {
enforceMinRequiredBalance = product.isMinRequiredBalanceEnforced();
}
BigDecimal minRequiredBalance = null;
if (command.parameterExists(minRequiredBalanceParamName)) {
minRequiredBalance = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(minRequiredBalanceParamName);
@@ -97,7 +97,7 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created_date", nullable = false)
private final Date createdDate;
@ManyToOne
@JoinColumn(name = "appuser_id", nullable = true)
private AppUser appUser;
@@ -157,8 +157,8 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
isReversed, appUser);
}
public static SavingsAccountTransaction initiateTransfer(final SavingsAccount savingsAccount, final Office office, final LocalDate date,
final AppUser appUser) {
public static SavingsAccountTransaction initiateTransfer(final SavingsAccount savingsAccount, final Office office,
final LocalDate date, final AppUser appUser) {
final boolean isReversed = false;
final PaymentDetail paymentDetail = null;
return new SavingsAccountTransaction(savingsAccount, office, paymentDetail,
@@ -167,7 +167,7 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
}
public static SavingsAccountTransaction approveTransfer(final SavingsAccount savingsAccount, final Office office, final LocalDate date,
final AppUser appUser) {
final AppUser appUser) {
final boolean isReversed = false;
final PaymentDetail paymentDetail = null;
return new SavingsAccountTransaction(savingsAccount, office, paymentDetail,
@@ -175,8 +175,8 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
.getAccountBalance(), isReversed, appUser);
}
public static SavingsAccountTransaction withdrawTransfer(final SavingsAccount savingsAccount, final Office office, final LocalDate date,
final AppUser appUser) {
public static SavingsAccountTransaction withdrawTransfer(final SavingsAccount savingsAccount, final Office office,
final LocalDate date, final AppUser appUser) {
final boolean isReversed = false;
final PaymentDetail paymentDetail = null;
return new SavingsAccountTransaction(savingsAccount, office, paymentDetail,
@@ -196,8 +196,8 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
}
private SavingsAccountTransaction(final SavingsAccount savingsAccount, final Office office, final PaymentDetail paymentDetail,
final Integer typeOf, final LocalDate transactionLocalDate, final Date createdDate, final Money amount, final boolean isReversed,
final AppUser appUser) {
final Integer typeOf, final LocalDate transactionLocalDate, final Date createdDate, final Money amount,
final boolean isReversed, final AppUser appUser) {
this(savingsAccount, office, paymentDetail, typeOf, transactionLocalDate, createdDate, amount.getAmount(), isReversed, appUser);
}
@@ -60,70 +60,65 @@ public final class SavingsHelper {
LocalDate periodEndDate = interestPostingUpToDate;
final Integer monthOfYear = periodStartDate.getMonthOfYear();
financialYearBeginningMonth--;
if(financialYearBeginningMonth == 0)
financialYearBeginningMonth = 12;
final ArrayList<LocalDate> quarterlyDates = new ArrayList<>();
quarterlyDates.add(periodStartDate.withMonthOfYear(financialYearBeginningMonth).dayOfMonth().withMaximumValue());
quarterlyDates.add(periodStartDate.withMonthOfYear(financialYearBeginningMonth)
.plusMonths(3).withYear(periodStartDate.getYear()).dayOfMonth().withMaximumValue());
quarterlyDates.add(periodStartDate.withMonthOfYear(financialYearBeginningMonth)
.plusMonths(6).withYear(periodStartDate.getYear()).dayOfMonth().withMaximumValue());
quarterlyDates.add(periodStartDate.withMonthOfYear(financialYearBeginningMonth)
.plusMonths(9).withYear(periodStartDate.getYear()).dayOfMonth().withMaximumValue());
Collections.sort(quarterlyDates);
final ArrayList<LocalDate> biannualDates = new ArrayList<>();
biannualDates.add(periodStartDate.withMonthOfYear(financialYearBeginningMonth).dayOfMonth().withMaximumValue());
biannualDates.add(periodStartDate.withMonthOfYear(financialYearBeginningMonth).plusMonths(6)
.withYear(periodStartDate.getYear()).dayOfMonth().withMaximumValue());
Collections.sort(biannualDates);
boolean isEndDateSet = false;
switch (interestPostingPeriodType) {
case INVALID:
break;
case MONTHLY:
// produce period end date on last day of current month
periodEndDate = periodStartDate.dayOfMonth().withMaximumValue();
break;
case QUATERLY:
for(LocalDate quarterlyDate : quarterlyDates) {
if(quarterlyDate.isAfter(periodStartDate)) {
periodEndDate = quarterlyDate;
isEndDateSet = true;
break;
}
}
if(!isEndDateSet)
periodEndDate = quarterlyDates.get(0).plusYears(1).dayOfMonth().withMaximumValue();
break;
case BIANNUAL:
for(LocalDate biannualDate : biannualDates) {
if(biannualDate.isAfter(periodStartDate)) {
periodEndDate = biannualDate;
isEndDateSet = true;
break;
}
}
if(!isEndDateSet)
periodEndDate = biannualDates.get(0).plusYears(1).dayOfMonth().withMaximumValue();
break;
case ANNUAL:
if (financialYearBeginningMonth < monthOfYear) {
periodEndDate = periodStartDate
.withMonthOfYear(financialYearBeginningMonth);
periodEndDate = periodEndDate.plusYears(1);
} else {
periodEndDate = periodStartDate
.withMonthOfYear(financialYearBeginningMonth);
}
periodEndDate = periodEndDate.dayOfMonth().withMaximumValue();
break;
}
if (financialYearBeginningMonth == 0) financialYearBeginningMonth = 12;
final ArrayList<LocalDate> quarterlyDates = new ArrayList<>();
quarterlyDates.add(periodStartDate.withMonthOfYear(financialYearBeginningMonth).dayOfMonth().withMaximumValue());
quarterlyDates.add(periodStartDate.withMonthOfYear(financialYearBeginningMonth).plusMonths(3).withYear(periodStartDate.getYear())
.dayOfMonth().withMaximumValue());
quarterlyDates.add(periodStartDate.withMonthOfYear(financialYearBeginningMonth).plusMonths(6).withYear(periodStartDate.getYear())
.dayOfMonth().withMaximumValue());
quarterlyDates.add(periodStartDate.withMonthOfYear(financialYearBeginningMonth).plusMonths(9).withYear(periodStartDate.getYear())
.dayOfMonth().withMaximumValue());
Collections.sort(quarterlyDates);
final ArrayList<LocalDate> biannualDates = new ArrayList<>();
biannualDates.add(periodStartDate.withMonthOfYear(financialYearBeginningMonth).dayOfMonth().withMaximumValue());
biannualDates.add(periodStartDate.withMonthOfYear(financialYearBeginningMonth).plusMonths(6).withYear(periodStartDate.getYear())
.dayOfMonth().withMaximumValue());
Collections.sort(biannualDates);
boolean isEndDateSet = false;
switch (interestPostingPeriodType) {
case INVALID:
break;
case MONTHLY:
// produce period end date on last day of current month
periodEndDate = periodStartDate.dayOfMonth().withMaximumValue();
break;
case QUATERLY:
for (LocalDate quarterlyDate : quarterlyDates) {
if (quarterlyDate.isAfter(periodStartDate)) {
periodEndDate = quarterlyDate;
isEndDateSet = true;
break;
}
}
if (!isEndDateSet) periodEndDate = quarterlyDates.get(0).plusYears(1).dayOfMonth().withMaximumValue();
break;
case BIANNUAL:
for (LocalDate biannualDate : biannualDates) {
if (biannualDate.isAfter(periodStartDate)) {
periodEndDate = biannualDate;
isEndDateSet = true;
break;
}
}
if (!isEndDateSet) periodEndDate = biannualDates.get(0).plusYears(1).dayOfMonth().withMaximumValue();
break;
case ANNUAL:
if (financialYearBeginningMonth < monthOfYear) {
periodEndDate = periodStartDate.withMonthOfYear(financialYearBeginningMonth);
periodEndDate = periodEndDate.plusYears(1);
} else {
periodEndDate = periodStartDate.withMonthOfYear(financialYearBeginningMonth);
}
periodEndDate = periodEndDate.dayOfMonth().withMaximumValue();
break;
}
// interest posting always occurs on next day after the period end date.
periodEndDate = periodEndDate.plusDays(1);
@@ -32,7 +32,7 @@ public class SavingsOfficerAssignmentHistory extends AbstractAuditableCustom<App
@ManyToOne
@JoinColumn(name = "savings_officer_id", nullable = true)
private Staff savingsOfficer;
@Temporal(TemporalType.DATE)
@Column(name = "start_date")
private Date startDate;
@@ -41,15 +41,17 @@ public class SavingsOfficerAssignmentHistory extends AbstractAuditableCustom<App
@Column(name = "end_date")
private Date endDate;
public static SavingsOfficerAssignmentHistory createNew(final SavingsAccount account, final Staff savingsOfficer,final LocalDate assignmentDate) {
return new SavingsOfficerAssignmentHistory(account, savingsOfficer,assignmentDate.toDate(),null);
public static SavingsOfficerAssignmentHistory createNew(final SavingsAccount account, final Staff savingsOfficer,
final LocalDate assignmentDate) {
return new SavingsOfficerAssignmentHistory(account, savingsOfficer, assignmentDate.toDate(), null);
}
protected SavingsOfficerAssignmentHistory() {
//
}
private SavingsOfficerAssignmentHistory(final SavingsAccount account, final Staff savingsOfficer,final Date startDate, final Date endDate) {
private SavingsOfficerAssignmentHistory(final SavingsAccount account, final Staff savingsOfficer, final Date startDate,
final Date endDate) {
this.savingsAccount = account;
this.savingsOfficer = savingsOfficer;
this.startDate = startDate;
@@ -63,7 +65,6 @@ public class SavingsOfficerAssignmentHistory extends AbstractAuditableCustom<App
public boolean isSameSavingsOfficer(final Staff staff) {
return this.savingsOfficer.identifiedBy(staff);
}
public void updateStartDate(final LocalDate startDate) {
this.startDate = startDate.toDate();
@@ -103,4 +104,4 @@ public class SavingsOfficerAssignmentHistory extends AbstractAuditableCustom<App
return (LocalDate) ObjectUtils.defaultIfNull(new LocalDate(this.endDate), null);
}
}
}
@@ -130,11 +130,11 @@ public class PostingPeriod {
this.interestRateAsFraction = interestRateAsFraction;
this.daysInYear = daysInYear;
this.compoundingPeriods = compoundingPeriods;
if(isSavingsInterestPostingAtCurrentPeriodEnd)
this.dateOfPostingTransaction = periodInterval.endDate();
if (isSavingsInterestPostingAtCurrentPeriodEnd)
this.dateOfPostingTransaction = periodInterval.endDate();
else
this.dateOfPostingTransaction = periodInterval.endDate().plusDays(1);
this.dateOfPostingTransaction = periodInterval.endDate().plusDays(1);
this.interestTransfered = interestTransfered;
this.minBalanceForInterestCalculation = minBalanceForInterestCalculation;
}