use of org.mifos.accounts.business.AccountFeesEntity in project head by mifos.
the class LegacyLoanDaoIntegrationTest method testSaveAndGetOriginalLoanScheduleEntityWithFees.
@Test
public void testSaveAndGetOriginalLoanScheduleEntityWithFees() throws PersistenceException {
ArrayList<OriginalLoanScheduleEntity> originalLoanScheduleEntities = new ArrayList<OriginalLoanScheduleEntity>();
Date date = new Date(new java.util.Date().getTime());
Short installmentId = new Short("1");
FeeBO upfrontFee = TestObjectFactory.createOneTimeRateFee("Upfront Fee", FeeCategory.LOAN, Double.valueOf("20"), FeeFormula.AMOUNT, FeePayment.UPFRONT, null);
AccountFeesEntity accountUpfrontFee = new AccountFeesEntity(goodAccount, upfrontFee, new Double("20.0"), FeeStatus.ACTIVE.getValue(), null, date);
AccountTestUtils.addAccountFees(accountUpfrontFee, goodAccount);
TestObjectFactory.updateObject(goodAccount);
goodAccount = (LoanBO) TestObjectFactory.getObject(AccountBO.class, goodAccount.getAccountId());
LoanScheduleEntity loanScheduleEntity = new LoanScheduleEntity(goodAccount, group, installmentId, date, PaymentStatus.UNPAID, Money.zero(), Money.zero());
LoanFeeScheduleEntity feesEntity = new LoanFeeScheduleEntity(loanScheduleEntity, upfrontFee, accountUpfrontFee, Money.zero());
loanScheduleEntity.addAccountFeesAction(feesEntity);
OriginalLoanScheduleEntity originalLoanScheduleEntity = new OriginalLoanScheduleEntity(loanScheduleEntity);
OriginalLoanFeeScheduleEntity scheduleEntityFee = new OriginalLoanFeeScheduleEntity(feesEntity, originalLoanScheduleEntity);
originalLoanScheduleEntities.add(originalLoanScheduleEntity);
legacyLoanDao.saveOriginalSchedule(originalLoanScheduleEntities);
List<OriginalLoanScheduleEntity> actual = legacyLoanDao.getOriginalLoanScheduleEntity(goodAccount.getAccountId());
List<OriginalLoanFeeScheduleEntity> fees = new ArrayList<OriginalLoanFeeScheduleEntity>(actual.get(0).getAccountFeesActionDetails());
Assert.assertEquals(1, actual.size());
Assert.assertEquals(1, fees.size());
assertThat(actual, is(new OriginalLoanScheduleEntitiesMatcher(originalLoanScheduleEntities)));
assertThat(fees.get(0), is(new OriginalLoanFeeScheduleEntityMatcher(scheduleEntityFee)));
}
use of org.mifos.accounts.business.AccountFeesEntity in project head by mifos.
the class LoanBO method removeFeesAssociatedWithUpcomingAndAllKnownFutureInstallments.
/**
* Remove the fee from all unpaid current or future installments, and update the loan accordingly.
*/
@Override
public final void removeFeesAssociatedWithUpcomingAndAllKnownFutureInstallments(final Short feeId, final Short personnelId) throws AccountException {
List<Short> installmentIds = getApplicableInstallmentIdsForRemoveFees();
Money totalFeeAmount;
if (installmentIds != null && installmentIds.size() != 0 && isFeeActive(feeId)) {
FeeBO fee = getAccountFeesObject(feeId);
if (havePaymentsBeenMade() && fee.doesFeeInvolveFractionalAmounts()) {
throw new AccountException(AccountExceptionConstants.CANT_REMOVE_FEE_EXCEPTION);
}
if (fee.isTimeOfDisbursement()) {
AccountFeesEntity accountFee = getAccountFees(feeId);
totalFeeAmount = accountFee.getAccountFeeAmount();
removeAccountFee(accountFee);
this.delete(accountFee);
} else {
totalFeeAmount = updateAccountActionDateEntity(installmentIds, feeId);
updateAccountFeesEntity(feeId);
}
updateTotalFeeAmount(totalFeeAmount);
String description = fee.getFeeName() + " " + AccountConstants.FEES_REMOVED;
updateAccountActivity(null, null, totalFeeAmount, null, personnelId, description);
if (!havePaymentsBeenMade()) {
LoanScheduleRounderHelper loanScheduleRounderHelper = new DefaultLoanScheduleRounderHelper();
LoanScheduleRounder loanScheduleInstallmentRounder = getLoanScheduleRounder(loanScheduleRounderHelper);
List<LoanScheduleEntity> unroundedLoanSchedules = new ArrayList<LoanScheduleEntity>();
List<LoanScheduleEntity> allExistingLoanSchedules = new ArrayList<LoanScheduleEntity>();
List<AccountActionDateEntity> installmentsToRound = getInstallmentsToRound();
for (AccountActionDateEntity installment : installmentsToRound) {
unroundedLoanSchedules.add((LoanScheduleEntity) installment);
}
List<AccountActionDateEntity> allExistingInstallments = this.getAllInstallments();
for (AccountActionDateEntity installment : allExistingInstallments) {
allExistingLoanSchedules.add((LoanScheduleEntity) installment);
}
List<LoanScheduleEntity> roundedLoanSchedules = loanScheduleInstallmentRounder.round(this.gracePeriodType.asEnum(), this.gracePeriodDuration, this.loanAmount, this.interestType.asEnum(), unroundedLoanSchedules, allExistingLoanSchedules);
// applyRounding_v2();
}
try {
ApplicationContextProvider.getBean(LegacyAccountDao.class).createOrUpdate(this);
} catch (PersistenceException e) {
throw new AccountException(e);
}
}
}
use of org.mifos.accounts.business.AccountFeesEntity in project head by mifos.
the class LoanBO method createUnroundedLoanSchedulesFromInstallments.
private List<LoanScheduleEntity> createUnroundedLoanSchedulesFromInstallments(List<InstallmentDate> installmentDates, Money loanInterest, Money loanAmount, ScheduledEvent meetingScheduledEvent, List<InstallmentPrincipalAndInterest> principalWithInterestInstallments, Set<AccountFeesEntity> accountFees) {
List<LoanScheduleEntity> unroundedLoanSchedules = new ArrayList<LoanScheduleEntity>();
List<FeeInstallment> feeInstallments = new ArrayList<FeeInstallment>();
if (!getAccountFees().isEmpty()) {
InstallmentFeeCalculatorFactory installmentFeeCalculatorFactory = new InstallmentFeeCalculatorFactoryImpl();
for (AccountFeesEntity accountFeesEntity : accountFees) {
RateAmountFlag feeType = accountFeesEntity.getFees().getFeeType();
InstallmentFeeCalculator installmentFeeCalculator = installmentFeeCalculatorFactory.create(getFeeDao(), feeType);
Double feeAmount = accountFeesEntity.getFeeAmount();
Money accountFeeAmount = installmentFeeCalculator.calculate(feeAmount, loanAmount, loanInterest, accountFeesEntity.getFees());
accountFeesEntity.setAccountFeeAmount(accountFeeAmount);
}
feeInstallments = FeeInstallment.createMergedFeeInstallments(meetingScheduledEvent, accountFees, installmentDates.size());
}
int installmentIndex = 0;
for (InstallmentDate installmentDate1 : installmentDates) {
InstallmentPrincipalAndInterest em = principalWithInterestInstallments.get(installmentIndex);
LoanScheduleEntity loanScheduleEntity = new LoanScheduleEntity(this, getCustomer(), installmentDate1.getInstallmentId(), new java.sql.Date(installmentDate1.getInstallmentDueDate().getTime()), PaymentStatus.UNPAID, em.getPrincipal(), em.getInterest());
for (FeeInstallment feeInstallment : feeInstallments) {
if (feeInstallment.getInstallmentId().equals(installmentDate1.getInstallmentId()) && !feeInstallment.getAccountFeesEntity().getFees().isTimeOfDisbursement()) {
LoanFeeScheduleEntity loanFeeScheduleEntity = new LoanFeeScheduleEntity(loanScheduleEntity, feeInstallment.getAccountFeesEntity().getFees(), feeInstallment.getAccountFeesEntity(), feeInstallment.getAccountFee());
loanScheduleEntity.addAccountFeesAction(loanFeeScheduleEntity);
} else if (feeInstallment.getInstallmentId().equals(installmentDate1.getInstallmentId()) && isInterestDeductedAtDisbursement() && feeInstallment.getAccountFeesEntity().getFees().isTimeOfDisbursement()) {
// FIXME - keithw - isInterestDeductedAtDisbursement is not relevant but one integration test fails
// when this is removed. leaving in but test is most likely wrong. LoanBOIntegrationTest.testRemoveLoanDisbursalFee
LoanFeeScheduleEntity loanFeeScheduleEntity = new LoanFeeScheduleEntity(loanScheduleEntity, feeInstallment.getAccountFeesEntity().getFees(), feeInstallment.getAccountFeesEntity(), feeInstallment.getAccountFee());
loanScheduleEntity.addAccountFeesAction(loanFeeScheduleEntity);
}
}
unroundedLoanSchedules.add(loanScheduleEntity);
installmentIndex++;
}
return unroundedLoanSchedules;
}
use of org.mifos.accounts.business.AccountFeesEntity in project head by mifos.
the class LoanBO method applyPeriodicFee.
/**
* The fee (new or to be updated) is applied to the given list of AccountActionDateEntity(s). Note that the entities
* are the actual entity objects referenced by the loan, so this method acts by side-effect, adding fees to the
* given entities.
*
* @param fee
* the periodic FeeBO to apply to the given AccountActionDateEntity(s)
* @param charge
* the
* @param dueInstallments
* @throws AccountException
* @throws PersistenceException
*/
private void applyPeriodicFee(final FeeBO fee, final Double charge, final List<AccountActionDateEntity> dueInstallments) throws AccountException {
// Create an AccountFeesEntity linking the loan to the given fee fee and charge if the fee hasn't been applied,
// or
// update the applied fee's AccountFeesEntity.feeAmount with the given charge. Then set the
// AccountFeeEntity.accountFeeAmount to this loan's originalInterest.
AccountFeesEntity accountFee = getAccountFee(fee, charge);
Set<AccountFeesEntity> accountFeeSet = new HashSet<AccountFeesEntity>();
accountFeeSet.add(accountFee);
populateAccountFeeAmount(accountFeeSet, loanSummary.getOriginalInterest());
// Extract the list of InstallmentDate(s) from the given AccountActionDateEntity(s). Note that
// the installmentId(s) likely do not start with 1 since the fee may be applied after some
// installment dates have passed.
List<InstallmentDate> installmentDates = new ArrayList<InstallmentDate>();
for (AccountActionDateEntity accountActionDateEntity : dueInstallments) {
installmentDates.add(new InstallmentDate(accountActionDateEntity.getInstallmentId(), accountActionDateEntity.getActionDate()));
}
// Get the full list of all loan InstallmentDate(s), past, present and future, without adjusting for holidays.
// This will work correctly only if adjusting periodic fees is done when no installments have been paid
// boolean isRepaymentIndepOfMeetingEnabled = new ConfigurationPersistence().isRepaymentIndepOfMeetingEnabled();
// List<InstallmentDate> nonAdjustedInstallmentDates = getInstallmentDates(getLoanMeeting(), noOfInstallments,
// getInstallmentSkipToStartRepayment(), isRepaymentIndepOfMeetingEnabled,
// false);
// Use handlePeriodic to adjust fee installments for holiday periods and combine multiple fee installments due
// for the
// same loan installment. Finally, apply these updated fees to the given dueInstallments list and update
// loan summary and activity tables.
/*
* old way List<FeeInstallment> feeInstallmentList = mergeFeeInstallments(handlePeriodic(accountFee,
* installmentDates, nonAdjustedInstallmentDates));
*/
// new way
ScheduledEvent loanScheduledEvent = ScheduledEventFactory.createScheduledEventFrom(this.getMeetingForAccount());
List<FeeInstallment> feeInstallmentList = FeeInstallment.createMergedFeeInstallmentsForOneFeeStartingWith(loanScheduledEvent, accountFee, dueInstallments.size(), dueInstallments.get(0).getInstallmentId());
Money totalFeeAmountApplied = applyFeeToInstallments(feeInstallmentList, dueInstallments);
updateLoanSummary(fee.getFeeId(), totalFeeAmountApplied);
updateLoanActivity(fee.getFeeId(), totalFeeAmountApplied, fee.getFeeName() + AccountConstants.APPLIED);
}
use of org.mifos.accounts.business.AccountFeesEntity in project head by mifos.
the class LoanBO method calculateTotalFeesAndInterestForLoanSchedules.
private Money calculateTotalFeesAndInterestForLoanSchedules(List<LoanScheduleEntity> unroundedLoanSchedules) {
Money zero = new Money(getCurrency());
Money interest = zero;
Money fees = zero;
for (LoanScheduleEntity unroundedLoanSchedule : unroundedLoanSchedules) {
interest = interest.add(unroundedLoanSchedule.getInterest());
fees = fees.add(unroundedLoanSchedule.getTotalFeesDueWithMiscFee());
}
Money feeDisbursementAmount = zero;
for (AccountFeesEntity accountFeesEntity : this.getAccountFees()) {
if (accountFeesEntity.getFees().isTimeOfDisbursement()) {
feeDisbursementAmount = fees.add(accountFeesEntity.getAccountFeeAmount());
}
}
fees = fees.add(feeDisbursementAmount);
fees = MoneyUtils.currencyRound(fees);
interest = MoneyUtils.currencyRound(interest);
Money rawAmount = interest.add(fees);
return rawAmount;
}
Aggregations