Search in sources :

Example 6 with AccountFeesEntity

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)));
}
Also used : OriginalLoanScheduleEntity(org.mifos.accounts.loan.business.OriginalLoanScheduleEntity) LoanScheduleEntity(org.mifos.accounts.loan.business.LoanScheduleEntity) OriginalLoanScheduleEntity(org.mifos.accounts.loan.business.OriginalLoanScheduleEntity) OriginalLoanFeeScheduleEntityMatcher(org.mifos.accounts.loan.business.matchers.OriginalLoanFeeScheduleEntityMatcher) ArrayList(java.util.ArrayList) Date(java.sql.Date) OriginalLoanScheduleEntitiesMatcher(org.mifos.accounts.loan.business.matchers.OriginalLoanScheduleEntitiesMatcher) OriginalLoanFeeScheduleEntity(org.mifos.accounts.loan.business.OriginalLoanFeeScheduleEntity) FeeBO(org.mifos.accounts.fees.business.FeeBO) LoanFeeScheduleEntity(org.mifos.accounts.loan.business.LoanFeeScheduleEntity) OriginalLoanFeeScheduleEntity(org.mifos.accounts.loan.business.OriginalLoanFeeScheduleEntity) AccountFeesEntity(org.mifos.accounts.business.AccountFeesEntity) Test(org.junit.Test)

Example 7 with AccountFeesEntity

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);
        }
    }
}
Also used : ArrayList(java.util.ArrayList) DefaultLoanScheduleRounderHelper(org.mifos.clientportfolio.newloan.domain.DefaultLoanScheduleRounderHelper) Money(org.mifos.framework.util.helpers.Money) AccountActionDateEntity(org.mifos.accounts.business.AccountActionDateEntity) AccountException(org.mifos.accounts.exceptions.AccountException) LegacyAccountDao(org.mifos.accounts.persistence.LegacyAccountDao) FirstInstallmentRoudingDifferenceLoanScheduleRounder(org.mifos.clientportfolio.newloan.domain.FirstInstallmentRoudingDifferenceLoanScheduleRounder) LoanScheduleRounder(org.mifos.clientportfolio.newloan.domain.LoanScheduleRounder) DefaultLoanScheduleRounder(org.mifos.clientportfolio.newloan.domain.DefaultLoanScheduleRounder) PersistenceException(org.mifos.framework.exceptions.PersistenceException) FeeBO(org.mifos.accounts.fees.business.FeeBO) RateFeeBO(org.mifos.accounts.fees.business.RateFeeBO) DefaultLoanScheduleRounderHelper(org.mifos.clientportfolio.newloan.domain.DefaultLoanScheduleRounderHelper) LoanScheduleRounderHelper(org.mifos.clientportfolio.newloan.domain.LoanScheduleRounderHelper) AccountFeesEntity(org.mifos.accounts.business.AccountFeesEntity)

Example 8 with AccountFeesEntity

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;
}
Also used : RateAmountFlag(org.mifos.accounts.fees.util.helpers.RateAmountFlag) ArrayList(java.util.ArrayList) InstallmentFeeCalculator(org.mifos.clientportfolio.newloan.domain.InstallmentFeeCalculator) InstallmentDate(org.mifos.accounts.util.helpers.InstallmentDate) Money(org.mifos.framework.util.helpers.Money) FeeInstallment(org.mifos.accounts.util.helpers.FeeInstallment) InstallmentFeeCalculatorFactoryImpl(org.mifos.clientportfolio.newloan.domain.InstallmentFeeCalculatorFactoryImpl) InstallmentPrincipalAndInterest(org.mifos.accounts.loan.util.helpers.InstallmentPrincipalAndInterest) AccountFeesEntity(org.mifos.accounts.business.AccountFeesEntity) InstallmentFeeCalculatorFactory(org.mifos.clientportfolio.newloan.domain.InstallmentFeeCalculatorFactory)

Example 9 with AccountFeesEntity

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);
}
Also used : AccountActionDateEntity(org.mifos.accounts.business.AccountActionDateEntity) ScheduledEvent(org.mifos.schedule.ScheduledEvent) Money(org.mifos.framework.util.helpers.Money) FeeInstallment(org.mifos.accounts.util.helpers.FeeInstallment) ArrayList(java.util.ArrayList) AccountFeesEntity(org.mifos.accounts.business.AccountFeesEntity) LinkedHashSet(java.util.LinkedHashSet) HashSet(java.util.HashSet) InstallmentDate(org.mifos.accounts.util.helpers.InstallmentDate)

Example 10 with AccountFeesEntity

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;
}
Also used : Money(org.mifos.framework.util.helpers.Money) AccountFeesEntity(org.mifos.accounts.business.AccountFeesEntity)

Aggregations

AccountFeesEntity (org.mifos.accounts.business.AccountFeesEntity)118 ArrayList (java.util.ArrayList)78 Test (org.junit.Test)65 CenterBuilder (org.mifos.domain.builders.CenterBuilder)46 DateTime (org.joda.time.DateTime)42 MeetingBO (org.mifos.application.meeting.business.MeetingBO)42 CenterBO (org.mifos.customers.center.business.CenterBO)39 MeetingBuilder (org.mifos.domain.builders.MeetingBuilder)38 FeeBO (org.mifos.accounts.fees.business.FeeBO)25 Money (org.mifos.framework.util.helpers.Money)25 AmountFeeBO (org.mifos.accounts.fees.business.AmountFeeBO)24 UserContext (org.mifos.security.util.UserContext)22 LocalDate (org.joda.time.LocalDate)21 AccountActionDateEntity (org.mifos.accounts.business.AccountActionDateEntity)21 CustomerAccountBO (org.mifos.customers.business.CustomerAccountBO)18 FeeInstallment (org.mifos.accounts.util.helpers.FeeInstallment)17 OfficeBO (org.mifos.customers.office.business.OfficeBO)17 PersonnelBO (org.mifos.customers.personnel.business.PersonnelBO)17 MifosUser (org.mifos.security.MifosUser)16 AccountException (org.mifos.accounts.exceptions.AccountException)14