Search in sources :

Example 1 with InstallmentPrincipalAndInterest

use of org.mifos.accounts.loan.util.helpers.InstallmentPrincipalAndInterest 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 2 with InstallmentPrincipalAndInterest

use of org.mifos.accounts.loan.util.helpers.InstallmentPrincipalAndInterest in project head by mifos.

the class FlatLoanPrincipalWithInterestGenerator method generateFlatInstallmentsAfterInterestOnlyGraceInstallments_v2.

/**
     * Calculate the installments after grace period, in the case of principal-only grace type for a flat-interest loan.
     * Divide interest evenly among all installments, but divide principle evenly among installments after the grace
     * period.
     */
private List<InstallmentPrincipalAndInterest> generateFlatInstallmentsAfterInterestOnlyGraceInstallments_v2(final Money loanInterest, Money loanAmount, Integer numberOfInstallments, Integer gracePeriodDuration) {
    List<InstallmentPrincipalAndInterest> emiInstallments = new ArrayList<InstallmentPrincipalAndInterest>();
    Money principalPerInstallment = loanAmount.divide(numberOfInstallments - gracePeriodDuration);
    Money interestPerInstallment = loanInterest.divide(numberOfInstallments);
    for (int i = gracePeriodDuration; i < numberOfInstallments; i++) {
        InstallmentPrincipalAndInterest installment = new InstallmentPrincipalAndInterest(principalPerInstallment, interestPerInstallment);
        emiInstallments.add(installment);
    }
    return emiInstallments;
}
Also used : Money(org.mifos.framework.util.helpers.Money) ArrayList(java.util.ArrayList) InstallmentPrincipalAndInterest(org.mifos.accounts.loan.util.helpers.InstallmentPrincipalAndInterest)

Example 3 with InstallmentPrincipalAndInterest

use of org.mifos.accounts.loan.util.helpers.InstallmentPrincipalAndInterest in project head by mifos.

the class DecliningBalancePrincipalWithInterestGenerator method generateEqualInstallments.

@Override
public List<InstallmentPrincipalAndInterest> generateEqualInstallments(LoanInterestCalculationDetails loanInterestCalculationDetails) {
    GraceType graceType = loanInterestCalculationDetails.getGraceType();
    Integer gracePeriodDuration = loanInterestCalculationDetails.getGracePeriodDuration();
    Money loanAmount = loanInterestCalculationDetails.getLoanAmount();
    Integer numberOfInstallments = loanInterestCalculationDetails.getNumberOfInstallments();
    Double interestFractionalRatePerInstallment = loanInterestCalculationDetails.getInterestFractionalRatePerInstallment();
    Double interestRate = loanInterestCalculationDetails.getInterestRate();
    int prorateValue = 0;
    List<InstallmentPrincipalAndInterest> lstInstallmntPricplIntrst = null;
    LocalDate disbursalDateWithLocalDate = loanInterestCalculationDetails.getDisbursementDate();
    DateTime disbursalDate = disbursalDateWithLocalDate.toDateTimeAtStartOfDay();
    List<DateTime> dates = loanInterestCalculationDetails.getLoanScheduleDates();
    if (dates.size() > 1) {
        //check whether loanscheduledDates are there
        DateTime firstRepaymentDay = dates.get(0);
        long differenceOfTwoDatesinMilliseconds = (firstRepaymentDay.toDate().getTime() - disbursalDate.toDate().getTime());
        long noOfDays = differenceOfTwoDatesinMilliseconds / (1000 * 60 * 60 * 24);
        int noOfDaysBetweenFirstRepaymentDayAndDisbursalDate = (int) noOfDays;
        DateTime secondRepaymentDay = dates.get(1);
        long duration = (secondRepaymentDay.toDate().getTime() - firstRepaymentDay.toDate().getTime()) / (1000 * 60 * 60 * 24);
        int noOfDaysInOneSchedule = (int) duration;
        prorateValue = new ConfigurationPersistence().getConfigurationValueInteger(PRORATE_RULE);
        if (prorateValue == 1)
            lstInstallmntPricplIntrst = allDecliningInstallments_v2(loanAmount, numberOfInstallments, graceType, gracePeriodDuration, interestFractionalRatePerInstallment, interestRate, noOfDaysBetweenFirstRepaymentDayAndDisbursalDate, noOfDaysInOneSchedule);
    }
    if (prorateValue != 1) {
        lstInstallmntPricplIntrst = allDecliningInstallments_v2(loanAmount, numberOfInstallments, graceType, gracePeriodDuration, interestFractionalRatePerInstallment, interestRate);
    }
    return lstInstallmntPricplIntrst;
}
Also used : Money(org.mifos.framework.util.helpers.Money) GraceType(org.mifos.accounts.productdefinition.util.helpers.GraceType) ConfigurationPersistence(org.mifos.config.persistence.ConfigurationPersistence) InstallmentPrincipalAndInterest(org.mifos.accounts.loan.util.helpers.InstallmentPrincipalAndInterest) LocalDate(org.joda.time.LocalDate) DateTime(org.joda.time.DateTime)

Example 4 with InstallmentPrincipalAndInterest

use of org.mifos.accounts.loan.util.helpers.InstallmentPrincipalAndInterest in project head by mifos.

the class LoanBO method regeneratePaymentSchedule.

/**
     * pull this logic out of LoanBO entity and reuse LoanSchedule behaviour used from service facades at a service level
     */
@Deprecated
private void regeneratePaymentSchedule(final boolean isRepaymentIndepOfMeetingEnabled, final MeetingBO newMeetingForRepaymentDay) throws AccountException {
    Money miscFee = getMiscFee();
    Money miscPenalty = getMiscPenalty();
    try {
        getlegacyLoanDao().deleteInstallments(this.getAccountActionDates());
    } catch (PersistenceException e) {
        throw new AccountException(e);
    }
    // Delete previous loan meeting if loan is parent account and set individual loans(if any) loanMeeting same as parent 
    if (isRepaymentIndepOfMeetingEnabled && newMeetingForRepaymentDay != null && !this.getLoanMeeting().equals(newMeetingForRepaymentDay)) {
        if (null != this.getLoanMeeting() && !this.isIndividualLoan()) {
            this.delete(this.getLoanMeeting());
        }
        setLoanMeeting(newMeetingForRepaymentDay);
        if (this.hasMemberAccounts()) {
            for (LoanBO individualLoanBO : this.getMemberAccounts()) {
                individualLoanBO.setLoanMeeting(newMeetingForRepaymentDay);
            }
        }
    }
    this.resetAccountActionDates();
    loanMeeting.setMeetingStartDate(disbursementDate);
    RecurringScheduledEventFactory scheduledEventFactory = new RecurringScheduledEventFactoryImpl();
    ScheduledEvent meetingScheduledEvent = scheduledEventFactory.createScheduledEventFrom(this.loanMeeting);
    LoanInstallmentFactory loanInstallmentFactory = new LoanInstallmentFactoryImpl(scheduledEventFactory);
    LoanInstallmentGenerator loanInstallmentGenerator = loanInstallmentFactory.create(this.getLoanMeeting(), isRepaymentIndepOfMeetingEnabled);
    LocalDate actualDisbursementDate = new LocalDate(this.disbursementDate);
    List<InstallmentDate> installmentDates = loanInstallmentGenerator.generate(actualDisbursementDate, this.noOfInstallments, this.gracePeriodType.asEnum(), this.gracePeriodDuration, this.office.getOfficeId());
    Integer numberOfInstallments = installmentDates.size();
    GraceType graceType = this.gracePeriodType.asEnum();
    InterestType interestType = InterestType.fromInt(this.interestType.getId());
    Integer interestDays = AccountingRules.getNumberOfInterestDays().intValue();
    LoanDecliningInterestAnnualPeriodCalculator decliningInterestAnnualPeriodCalculator = new LoanDecliningInterestAnnualPeriodCalculatorFactory().create(loanMeeting.getRecurrenceType());
    Double decliningInterestAnnualPeriod = decliningInterestAnnualPeriodCalculator.calculate(loanMeeting.getRecurAfter().intValue(), interestDays);
    Double interestFractionalRatePerInstallment = interestRate / decliningInterestAnnualPeriod / 100;
    LoanDurationInAccountingYearsCalculator loanDurationInAccountingYearsCalculator = new LoanDurationInAccountingYearsCalculatorFactory().create(loanMeeting.getRecurrenceType());
    Double durationInYears = loanDurationInAccountingYearsCalculator.calculate(loanMeeting.getRecurAfter().intValue(), numberOfInstallments, interestDays);
    List<DateTime> scheduledInstallments = new ArrayList<DateTime>();
    for (InstallmentDate installmentDate : installmentDates) {
        scheduledInstallments.add(new DateTime(installmentDate.getInstallmentDueDate()));
    }
    LoanInterestCalculationDetails loanInterestCalculationDetails = new LoanInterestCalculationDetails(loanAmount, interestRate, graceType, gracePeriodDuration.intValue(), numberOfInstallments, durationInYears, interestFractionalRatePerInstallment, actualDisbursementDate, scheduledInstallments);
    LoanInterestCalculatorFactory loanInterestCalculatorFactory = new LoanInterestCalculatorFactoryImpl();
    LoanInterestCalculator loanInterestCalculator = loanInterestCalculatorFactory.create(interestType, this.loanOffering.isVariableInstallmentsAllowed());
    Money loanInterest = loanInterestCalculator.calculate(loanInterestCalculationDetails);
    EqualInstallmentGeneratorFactory equalInstallmentGeneratorFactory = new EqualInstallmentGeneratorFactoryImpl();
    PrincipalWithInterestGenerator equalInstallmentGenerator = equalInstallmentGeneratorFactory.create(interestType, loanInterest, this.loanOffering.isVariableInstallmentsAllowed());
    List<InstallmentPrincipalAndInterest> principalWithInterestInstallments = equalInstallmentGenerator.generateEqualInstallments(loanInterestCalculationDetails);
    List<LoanScheduleEntity> unroundedLoanSchedules = createUnroundedLoanSchedulesFromInstallments(installmentDates, loanInterest, this.loanAmount, meetingScheduledEvent, principalWithInterestInstallments, this.getAccountFees());
    Money rawAmount = calculateTotalFeesAndInterestForLoanSchedules(unroundedLoanSchedules);
    if (loanSummary == null) {
        // save it to LoanBO first and when loan summary is created it will
        // be retrieved and save to loan summary
        setRawAmountTotal(rawAmount);
    } else {
        loanSummary.setRawAmountTotal(rawAmount);
    }
    List<LoanScheduleEntity> allExistingLoanSchedules = new ArrayList<LoanScheduleEntity>();
    LoanScheduleRounderHelper loanScheduleRounderHelper = new DefaultLoanScheduleRounderHelper();
    LoanScheduleRounder loanScheduleInstallmentRounder = getLoanScheduleRounder(loanScheduleRounderHelper);
    List<LoanScheduleEntity> roundedLoanSchedules = loanScheduleInstallmentRounder.round(graceType, gracePeriodDuration, loanAmount, interestType, unroundedLoanSchedules, allExistingLoanSchedules);
    for (LoanScheduleEntity roundedLoanSchedule : roundedLoanSchedules) {
        addAccountActionDate(roundedLoanSchedule);
    }
    LoanScheduleEntity loanScheduleEntity = (LoanScheduleEntity) getAccountActionDate((short) 1);
    loanScheduleEntity.setMiscFee(miscFee);
    loanScheduleEntity.setMiscPenalty(miscPenalty);
    Money interest = new Money(getCurrency());
    Money fees = new Money(getCurrency());
    Money penalty = new Money(getCurrency());
    Money principal = new Money(getCurrency());
    Set<AccountActionDateEntity> actionDates = getAccountActionDates();
    if (actionDates != null && actionDates.size() > 0) {
        for (AccountActionDateEntity accountActionDate : actionDates) {
            LoanScheduleEntity loanSchedule = (LoanScheduleEntity) accountActionDate;
            principal = principal.add(loanSchedule.getPrincipal());
            interest = interest.add(loanSchedule.getInterest());
            fees = fees.add(loanSchedule.getTotalFeesDueWithMiscFee());
            penalty = penalty.add(loanSchedule.getTotalPenalty());
        }
    }
    fees = fees.add(getDisbursementFeeAmount());
    loanSummary.setOriginalInterest(interest);
    loanSummary.setOriginalFees(fees);
    loanSummary.setOriginalPenalty(penalty);
}
Also used : PrincipalWithInterestGenerator(org.mifos.clientportfolio.newloan.domain.PrincipalWithInterestGenerator) EqualInstallmentGeneratorFactoryImpl(org.mifos.clientportfolio.newloan.domain.EqualInstallmentGeneratorFactoryImpl) LoanInstallmentFactory(org.mifos.clientportfolio.newloan.domain.LoanInstallmentFactory) ArrayList(java.util.ArrayList) LoanDecliningInterestAnnualPeriodCalculatorFactory(org.mifos.clientportfolio.newloan.domain.LoanDecliningInterestAnnualPeriodCalculatorFactory) DefaultLoanScheduleRounderHelper(org.mifos.clientportfolio.newloan.domain.DefaultLoanScheduleRounderHelper) LoanInterestCalculatorFactory(org.mifos.clientportfolio.newloan.domain.LoanInterestCalculatorFactory) LocalDate(org.joda.time.LocalDate) DateTime(org.joda.time.DateTime) InstallmentDate(org.mifos.accounts.util.helpers.InstallmentDate) LoanInstallmentGenerator(org.mifos.clientportfolio.newloan.domain.LoanInstallmentGenerator) Money(org.mifos.framework.util.helpers.Money) AccountActionDateEntity(org.mifos.accounts.business.AccountActionDateEntity) GraceType(org.mifos.accounts.productdefinition.util.helpers.GraceType) LoanInstallmentFactoryImpl(org.mifos.clientportfolio.newloan.domain.LoanInstallmentFactoryImpl) LoanInterestCalculator(org.mifos.clientportfolio.newloan.domain.LoanInterestCalculator) DefaultLoanScheduleRounderHelper(org.mifos.clientportfolio.newloan.domain.DefaultLoanScheduleRounderHelper) LoanScheduleRounderHelper(org.mifos.clientportfolio.newloan.domain.LoanScheduleRounderHelper) RecurringScheduledEventFactoryImpl(org.mifos.clientportfolio.newloan.domain.RecurringScheduledEventFactoryImpl) ScheduledEvent(org.mifos.schedule.ScheduledEvent) LoanDurationInAccountingYearsCalculator(org.mifos.clientportfolio.newloan.domain.LoanDurationInAccountingYearsCalculator) LoanInterestCalculationDetails(org.mifos.clientportfolio.newloan.domain.LoanInterestCalculationDetails) EqualInstallmentGeneratorFactory(org.mifos.clientportfolio.newloan.domain.EqualInstallmentGeneratorFactory) RecurringScheduledEventFactory(org.mifos.clientportfolio.newloan.domain.RecurringScheduledEventFactory) InterestType(org.mifos.accounts.productdefinition.util.helpers.InterestType) LoanDecliningInterestAnnualPeriodCalculator(org.mifos.clientportfolio.newloan.domain.LoanDecliningInterestAnnualPeriodCalculator) AccountException(org.mifos.accounts.exceptions.AccountException) 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) LoanInterestCalculatorFactoryImpl(org.mifos.clientportfolio.newloan.domain.LoanInterestCalculatorFactoryImpl) InstallmentPrincipalAndInterest(org.mifos.accounts.loan.util.helpers.InstallmentPrincipalAndInterest) LoanDurationInAccountingYearsCalculatorFactory(org.mifos.clientportfolio.newloan.domain.LoanDurationInAccountingYearsCalculatorFactory)

Example 5 with InstallmentPrincipalAndInterest

use of org.mifos.accounts.loan.util.helpers.InstallmentPrincipalAndInterest in project head by mifos.

the class DecliningBalancePrincipalWithInterestGenerator method allDecliningInstallments_v2.

//for M5193
private List<InstallmentPrincipalAndInterest> allDecliningInstallments_v2(Money loanAmount, Integer numberOfInstallments, GraceType graceType, Integer gracePeriodDuration, Double interestFractionalRatePerInstallment, Double interestRate, Integer days, Integer durationInDays) {
    List<InstallmentPrincipalAndInterest> emiInstallments = new ArrayList<InstallmentPrincipalAndInterest>();
    if (graceType == GraceType.NONE || graceType == GraceType.GRACEONALLREPAYMENTS) {
        Money paymentPerPeriod = getPaymentPerPeriodForDecliningInterest_v2(numberOfInstallments, interestRate, loanAmount, interestFractionalRatePerInstallment);
        emiInstallments = generateDecliningInstallmentsNoGrace_v2(numberOfInstallments, loanAmount, interestFractionalRatePerInstallment, paymentPerPeriod);
    } else {
        // getGraceType() == GraceType.PRINCIPALONLYGRACE which is disabled.
        emiInstallments = generateDecliningInstallmentsInterestOnly_v2(loanAmount, gracePeriodDuration, interestFractionalRatePerInstallment, days, durationInDays);
        int nonGraceInstallments = (numberOfInstallments - gracePeriodDuration);
        Money paymentPerPeriod = getPaymentPerPeriodForDecliningInterest_v2(nonGraceInstallments, interestRate, loanAmount, interestFractionalRatePerInstallment);
        emiInstallments.addAll(generateDecliningInstallmentsNoGrace_v2(nonGraceInstallments, loanAmount, interestFractionalRatePerInstallment, paymentPerPeriod));
    }
    return emiInstallments;
}
Also used : Money(org.mifos.framework.util.helpers.Money) ArrayList(java.util.ArrayList) InstallmentPrincipalAndInterest(org.mifos.accounts.loan.util.helpers.InstallmentPrincipalAndInterest)

Aggregations

InstallmentPrincipalAndInterest (org.mifos.accounts.loan.util.helpers.InstallmentPrincipalAndInterest)17 Money (org.mifos.framework.util.helpers.Money)16 ArrayList (java.util.ArrayList)15 DateTime (org.joda.time.DateTime)6 LocalDate (org.joda.time.LocalDate)5 GraceType (org.mifos.accounts.productdefinition.util.helpers.GraceType)4 InstallmentDate (org.mifos.accounts.util.helpers.InstallmentDate)4 AccountFeesEntity (org.mifos.accounts.business.AccountFeesEntity)2 RateAmountFlag (org.mifos.accounts.fees.util.helpers.RateAmountFlag)2 LoanScheduleEntity (org.mifos.accounts.loan.business.LoanScheduleEntity)2 InterestType (org.mifos.accounts.productdefinition.util.helpers.InterestType)2 FeeInstallment (org.mifos.accounts.util.helpers.FeeInstallment)2 ConfigurationPersistence (org.mifos.config.persistence.ConfigurationPersistence)2 ScheduledEvent (org.mifos.schedule.ScheduledEvent)2 BigDecimal (java.math.BigDecimal)1 AccountActionDateEntity (org.mifos.accounts.business.AccountActionDateEntity)1 AccountException (org.mifos.accounts.exceptions.AccountException)1 LoanFeeScheduleEntity (org.mifos.accounts.loan.business.LoanFeeScheduleEntity)1 DefaultLoanScheduleRounder (org.mifos.clientportfolio.newloan.domain.DefaultLoanScheduleRounder)1 DefaultLoanScheduleRounderHelper (org.mifos.clientportfolio.newloan.domain.DefaultLoanScheduleRounderHelper)1