Search in sources :

Example 46 with LoanScheduleEntity

use of org.mifos.accounts.loan.business.LoanScheduleEntity in project head by mifos.

the class DefaultLoanScheduleRounder method round.

@Override
public List<LoanScheduleEntity> round(GraceType graceType, Short gracePeriodDuration, Money loanAmount, InterestType interestType, List<LoanScheduleEntity> unroundedLoanSchedules, List<LoanScheduleEntity> allExistingLoanSchedules) {
    Collections.sort(unroundedLoanSchedules);
    List<LoanScheduleEntity> roundedLoanSchedules = new ArrayList<LoanScheduleEntity>();
    RepaymentTotals totals = loanScheduleInstallmentRounder.calculateInitialTotals_v2(unroundedLoanSchedules, loanAmount, allExistingLoanSchedules);
    int installmentNum = 0;
    for (Iterator<LoanScheduleEntity> it = unroundedLoanSchedules.iterator(); it.hasNext(); ) {
        LoanScheduleEntity currentInstallment = it.next();
        LoanScheduleEntity roundedInstallment = currentInstallment;
        installmentNum++;
        if (it.hasNext()) {
            // handle all but the last installment
            if (loanScheduleInstallmentRounder.isGraceInstallment_v2(installmentNum, graceType, gracePeriodDuration)) {
                roundedInstallment = loanScheduleInstallmentRounder.roundAndAdjustGraceInstallment_v2(roundedInstallment);
            } else if (interestType.equals(InterestType.DECLINING_EPI)) {
                loanScheduleInstallmentRounder.roundAndAdjustNonGraceInstallmentForDecliningEPI_v2(roundedInstallment);
            } else {
                loanScheduleInstallmentRounder.roundAndAdjustButLastNonGraceInstallment_v2(roundedInstallment);
            }
            loanScheduleInstallmentRounder.updateRunningTotals_v2(totals, roundedInstallment);
        } else {
            loanScheduleInstallmentRounder.roundAndAdjustLastInstallment_v2(roundedInstallment, totals);
        }
        roundedLoanSchedules.add(roundedInstallment);
    }
    // for
    return roundedLoanSchedules;
}
Also used : LoanScheduleEntity(org.mifos.accounts.loan.business.LoanScheduleEntity) RepaymentTotals(org.mifos.accounts.loan.business.RepaymentTotals) ArrayList(java.util.ArrayList)

Example 47 with LoanScheduleEntity

use of org.mifos.accounts.loan.business.LoanScheduleEntity in project head by mifos.

the class LoanBusinessService method applyPayment.

public void applyPayment(PaymentData paymentData, LoanBO loanBO, AccountPaymentEntity accountPaymentEntity) {
    Money balance = paymentData.getTotalAmount();
    PersonnelBO personnel = paymentData.getPersonnel();
    Date transactionDate = paymentData.getTransactionDate();
    if (configService.isRecalculateInterestEnabled() && loanBO.isDecliningBalanceEqualPrincipleCalculation())
        scheduleCalculatorAdaptor.applyPayment(loanBO, balance, transactionDate, personnel, accountPaymentEntity, paymentData.isAdjustment());
    else if (loanBO.isDecliningBalanceInterestRecalculation()) {
        scheduleCalculatorAdaptor.applyPayment(loanBO, balance, transactionDate, personnel, accountPaymentEntity, paymentData.isAdjustment());
    } else {
        if (AccountingRules.isOverdueInterestPaidFirst()) {
            for (AccountActionDateEntity accountActionDate : loanBO.getDetailsOfInstallmentsInArrearsOn(new LocalDate(transactionDate))) {
                balance = ((LoanScheduleEntity) accountActionDate).applyPaymentToInterest(accountPaymentEntity, balance, personnel, transactionDate);
            }
        }
        for (AccountActionDateEntity accountActionDate : loanBO.getAccountActionDatesSortedByInstallmentId()) {
            balance = ((LoanScheduleEntity) accountActionDate).applyPayment(accountPaymentEntity, balance, personnel, transactionDate);
        }
    }
}
Also used : OriginalLoanScheduleEntity(org.mifos.accounts.loan.business.OriginalLoanScheduleEntity) LoanScheduleEntity(org.mifos.accounts.loan.business.LoanScheduleEntity) Money(org.mifos.framework.util.helpers.Money) AccountActionDateEntity(org.mifos.accounts.business.AccountActionDateEntity) PersonnelBO(org.mifos.customers.personnel.business.PersonnelBO) LocalDate(org.joda.time.LocalDate) Date(java.util.Date) LocalDate(org.joda.time.LocalDate)

Example 48 with LoanScheduleEntity

use of org.mifos.accounts.loan.business.LoanScheduleEntity in project head by mifos.

the class LoanBusinessService method persistOriginalSchedule.

public void persistOriginalSchedule(LoanBO loan) throws PersistenceException {
    Collection<LoanScheduleEntity> loanScheduleEntities = loan.getLoanScheduleEntities();
    Collection<OriginalLoanScheduleEntity> originalLoanScheduleEntities = new ArrayList<OriginalLoanScheduleEntity>();
    for (LoanScheduleEntity loanScheduleEntity : loanScheduleEntities) {
        originalLoanScheduleEntities.add(new OriginalLoanScheduleEntity(loanScheduleEntity));
    }
    this.getlegacyLoanDao().saveOriginalSchedule(originalLoanScheduleEntities);
}
Also used : OriginalLoanScheduleEntity(org.mifos.accounts.loan.business.OriginalLoanScheduleEntity) LoanScheduleEntity(org.mifos.accounts.loan.business.LoanScheduleEntity) OriginalLoanScheduleEntity(org.mifos.accounts.loan.business.OriginalLoanScheduleEntity) ArrayList(java.util.ArrayList)

Example 49 with LoanScheduleEntity

use of org.mifos.accounts.loan.business.LoanScheduleEntity in project head by mifos.

the class IndividualLoanScheduleFactory method create.

@Override
public LoanSchedule create(LocalDate disbursementDate, List<DateTime> loanScheduleDates, List<Number> totalInstallmentAmounts, LoanOfferingBO loanProduct, CustomerBO customer, MeetingBO loanMeeting, Money loanAmount, Double interestRate, Integer interestDays, Integer gracePeriodDuration, List<AccountFeesEntity> accountFees) {
    GraceType graceType = loanProduct.getGraceType();
    InterestType interestType = loanProduct.getInterestType();
    boolean variableInstallmentLoanProduct = loanProduct.isVariableInstallmentsAllowed();
    boolean roundingDifferenceInFirstPayment = loanProduct.isRoundingDifferenceInFirstPayment();
    Integer numberOfInstallments = loanScheduleDates.size();
    RecurringScheduledEventFactory scheduledEventFactory = new RecurringScheduledEventFactoryImpl();
    ScheduledEvent meetingScheduledEvent = scheduledEventFactory.createScheduledEventFrom(loanMeeting);
    Integer installmentNumber = 1;
    List<InstallmentDate> dueInstallmentDates = new ArrayList<InstallmentDate>();
    for (DateTime scheduledDate : loanScheduleDates) {
        dueInstallmentDates.add(new InstallmentDate(installmentNumber.shortValue(), scheduledDate.toLocalDate().toDateMidnight().toDate()));
        installmentNumber++;
    }
    if (loanProduct.isPrinDueLastInst()) {
        // Principal due on last installment has been cut, so throw an exception if we reach this code.
        throw new BusinessRuleException(AccountConstants.NOT_SUPPORTED_EMI_GENERATION);
    }
    // loan interest calculation for various interest calculation algorithms
    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<Money> totalInstallmentAmountsAsMoney = new ArrayList<Money>();
    for (Number totalInstallmentAmount : totalInstallmentAmounts) {
        Money totalAmount = new Money(loanAmount.getCurrency(), BigDecimal.valueOf(totalInstallmentAmount.doubleValue()));
        totalInstallmentAmountsAsMoney.add(totalAmount);
    }
    LoanInterestCalculationDetails loanInterestCalculationDetails = new LoanInterestCalculationDetails(loanAmount, interestRate, graceType, gracePeriodDuration, numberOfInstallments, durationInYears, interestFractionalRatePerInstallment, disbursementDate, loanScheduleDates);
    loanInterestCalculationDetails.setTotalInstallmentAmounts(totalInstallmentAmountsAsMoney);
    LoanInterestCalculatorFactory loanInterestCalculatorFactory = new LoanInterestCalculatorFactoryImpl();
    LoanInterestCalculator loanInterestCalculator = loanInterestCalculatorFactory.create(interestType, variableInstallmentLoanProduct);
    Money loanInterest = loanInterestCalculator.calculate(loanInterestCalculationDetails);
    // end of loan Interest creation
    EqualInstallmentGeneratorFactory equalInstallmentGeneratorFactory = new EqualInstallmentGeneratorFactoryImpl();
    PrincipalWithInterestGenerator equalInstallmentGenerator = equalInstallmentGeneratorFactory.create(interestType, loanInterest, variableInstallmentLoanProduct);
    List<InstallmentPrincipalAndInterest> EMIInstallments = equalInstallmentGenerator.generateEqualInstallments(loanInterestCalculationDetails);
    List<LoanScheduleEntity> unroundedLoanSchedules = createUnroundedLoanSchedulesFromInstallments(dueInstallmentDates, loanInterest, loanAmount, meetingScheduledEvent, EMIInstallments, accountFees, customer);
    Money rawAmount = calculateTotalFeesAndInterestForLoanSchedules(unroundedLoanSchedules, loanAmount.getCurrency(), accountFees);
    List<LoanScheduleEntity> allExistingLoanSchedules = new ArrayList<LoanScheduleEntity>();
    List<LoanScheduleEntity> finalisedLoanSchedules = new ArrayList<LoanScheduleEntity>(unroundedLoanSchedules);
    if (variableInstallmentLoanProduct && totalInstallmentAmounts.isEmpty()) {
        // only round inital loan schedule of variable installments product.
        LoanScheduleRounder loanScheduleInstallmentRounder = new VariableInstallmentLoanScheduleRounder();
        finalisedLoanSchedules = loanScheduleInstallmentRounder.round(graceType, gracePeriodDuration.shortValue(), loanAmount, interestType, unroundedLoanSchedules, allExistingLoanSchedules);
    } else if (!variableInstallmentLoanProduct && roundingDifferenceInFirstPayment) {
        LoanScheduleRounderHelper loanScheduleRounderHelper = new DefaultLoanScheduleRounderHelper();
        LoanScheduleRounder loanScheduleInstallmentRounder = new FirstInstallmentRoudingDifferenceLoanScheduleRounder(loanScheduleRounderHelper);
        finalisedLoanSchedules = loanScheduleInstallmentRounder.round(graceType, gracePeriodDuration.shortValue(), loanAmount, interestType, unroundedLoanSchedules, allExistingLoanSchedules);
    } else if (!variableInstallmentLoanProduct) {
        LoanScheduleRounderHelper loanScheduleRounderHelper = new DefaultLoanScheduleRounderHelper();
        LoanScheduleRounder loanScheduleInstallmentRounder = new DefaultLoanScheduleRounder(loanScheduleRounderHelper);
        finalisedLoanSchedules = loanScheduleInstallmentRounder.round(graceType, gracePeriodDuration.shortValue(), loanAmount, interestType, unroundedLoanSchedules, allExistingLoanSchedules);
    }
    return new LoanSchedule(finalisedLoanSchedules, rawAmount);
}
Also used : LoanScheduleEntity(org.mifos.accounts.loan.business.LoanScheduleEntity) ArrayList(java.util.ArrayList) DateTime(org.joda.time.DateTime) InstallmentDate(org.mifos.accounts.util.helpers.InstallmentDate) Money(org.mifos.framework.util.helpers.Money) BusinessRuleException(org.mifos.service.BusinessRuleException) GraceType(org.mifos.accounts.productdefinition.util.helpers.GraceType) ScheduledEvent(org.mifos.schedule.ScheduledEvent) InterestType(org.mifos.accounts.productdefinition.util.helpers.InterestType) InstallmentPrincipalAndInterest(org.mifos.accounts.loan.util.helpers.InstallmentPrincipalAndInterest)

Example 50 with LoanScheduleEntity

use of org.mifos.accounts.loan.business.LoanScheduleEntity in project head by mifos.

the class IndividualLoanScheduleFactory method createUnroundedLoanSchedulesFromInstallments.

private List<LoanScheduleEntity> createUnroundedLoanSchedulesFromInstallments(List<InstallmentDate> installmentDates, Money loanInterest, Money loanAmount, ScheduledEvent meetingScheduledEvent, List<InstallmentPrincipalAndInterest> principalWithInterestInstallments, List<AccountFeesEntity> accountFees, CustomerBO customer) {
    List<LoanScheduleEntity> unroundedLoanSchedules = new ArrayList<LoanScheduleEntity>();
    List<AccountFeesEntity> accountFeesWithNoTimeOfDibursementFees = new ArrayList<AccountFeesEntity>();
    List<FeeInstallment> feeInstallments = new ArrayList<FeeInstallment>();
    if (!accountFees.isEmpty()) {
        InstallmentFeeCalculatorFactory installmentFeeCalculatorFactory = new InstallmentFeeCalculatorFactoryImpl();
        for (AccountFeesEntity accountFeesEntity : accountFees) {
            RateAmountFlag feeType = accountFeesEntity.getFees().getFeeType();
            InstallmentFeeCalculator installmentFeeCalculator = installmentFeeCalculatorFactory.create(this.feeDao, feeType);
            Double feeAmountOrRate = accountFeesEntity.getFeeAmount();
            Money accountFeeAmount = installmentFeeCalculator.calculate(feeAmountOrRate, loanAmount, loanInterest, accountFeesEntity.getFees());
            accountFeesEntity.setAccountFeeAmount(accountFeeAmount);
            if (!accountFeesEntity.isTimeOfDisbursement()) {
                accountFeesWithNoTimeOfDibursementFees.add(accountFeesEntity);
            }
        }
        feeInstallments = FeeInstallment.createMergedFeeInstallments(meetingScheduledEvent, accountFeesWithNoTimeOfDibursementFees, installmentDates.size());
    }
    int installmentIndex = 0;
    for (InstallmentDate installmentDate1 : installmentDates) {
        InstallmentPrincipalAndInterest em = principalWithInterestInstallments.get(installmentIndex);
        LoanScheduleEntity loanScheduleEntity = new LoanScheduleEntity(null, customer, 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())) {
                LoanFeeScheduleEntity loanFeeScheduleEntity = new LoanFeeScheduleEntity(loanScheduleEntity, feeInstallment.getAccountFeesEntity().getFees(), feeInstallment.getAccountFeesEntity(), feeInstallment.getAccountFee());
                loanScheduleEntity.addAccountFeesAction(loanFeeScheduleEntity);
            }
        }
        unroundedLoanSchedules.add(loanScheduleEntity);
        installmentIndex++;
    }
    return unroundedLoanSchedules;
}
Also used : LoanScheduleEntity(org.mifos.accounts.loan.business.LoanScheduleEntity) RateAmountFlag(org.mifos.accounts.fees.util.helpers.RateAmountFlag) ArrayList(java.util.ArrayList) InstallmentDate(org.mifos.accounts.util.helpers.InstallmentDate) Money(org.mifos.framework.util.helpers.Money) FeeInstallment(org.mifos.accounts.util.helpers.FeeInstallment) LoanFeeScheduleEntity(org.mifos.accounts.loan.business.LoanFeeScheduleEntity) InstallmentPrincipalAndInterest(org.mifos.accounts.loan.util.helpers.InstallmentPrincipalAndInterest) AccountFeesEntity(org.mifos.accounts.business.AccountFeesEntity)

Aggregations

LoanScheduleEntity (org.mifos.accounts.loan.business.LoanScheduleEntity)54 Money (org.mifos.framework.util.helpers.Money)32 ArrayList (java.util.ArrayList)19 OriginalLoanScheduleEntity (org.mifos.accounts.loan.business.OriginalLoanScheduleEntity)18 Test (org.junit.Test)16 AccountActionDateEntity (org.mifos.accounts.business.AccountActionDateEntity)14 BigDecimal (java.math.BigDecimal)11 AccountFeesActionDetailEntity (org.mifos.accounts.business.AccountFeesActionDetailEntity)8 LoanBO (org.mifos.accounts.loan.business.LoanBO)8 AccountFeesEntity (org.mifos.accounts.business.AccountFeesEntity)7 Date (java.util.Date)5 CustomerBO (org.mifos.customers.business.CustomerBO)5 UserContext (org.mifos.security.util.UserContext)5 LocalDate (org.joda.time.LocalDate)4 AccountPenaltiesEntity (org.mifos.accounts.business.AccountPenaltiesEntity)4 OriginalLoanScheduleEntitiesMatcher (org.mifos.accounts.loan.business.matchers.OriginalLoanScheduleEntitiesMatcher)4 InstallmentDetailsDto (org.mifos.dto.domain.InstallmentDetailsDto)4 LoanInstallmentDetailsDto (org.mifos.dto.domain.LoanInstallmentDetailsDto)4 MifosUser (org.mifos.security.MifosUser)4 Date (java.sql.Date)3