Package org.mifosplatform.portfolio.savings.domain.interest

Source Code of org.mifosplatform.portfolio.savings.domain.interest.EndOfDayBalance

/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.savings.domain.interest;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;

import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.domain.LocalDateInterval;
import org.mifosplatform.organisation.monetary.domain.Money;

public class EndOfDayBalance {

    private final LocalDate date;
    private final Money openingBalance;
    private final Money endOfDayBalance;
    private final int numberOfDays;

    public static EndOfDayBalance from(final LocalDate date, final Money openingBalance, final Money endOfDayBalance, final int numberOfDays) {
        return new EndOfDayBalance(date, openingBalance, endOfDayBalance, numberOfDays);
    }

    public EndOfDayBalance(final LocalDate date, final Money openingBalance, final Money endOfDayBalance, final int numberOfDays) {
        this.date = date;
        this.openingBalance = openingBalance;
        this.endOfDayBalance = endOfDayBalance;
        this.numberOfDays = numberOfDays;
    }

    public LocalDate date() {
        return this.date;
    }

    public Money closingBalance() {
        return this.endOfDayBalance;
    }

    public BigDecimal cumulativeBalance(final BigDecimal interestToCompound) {
        final BigDecimal daysAsBigDecimal = BigDecimal.valueOf(this.numberOfDays);
        final BigDecimal realBalanceForInterestCalculation = this.endOfDayBalance.getAmount().add(interestToCompound);
        return realBalanceForInterestCalculation.multiply(daysAsBigDecimal, MathContext.DECIMAL64).setScale(9, RoundingMode.HALF_EVEN);
    }

    public BigDecimal calculateInterestOnBalance(final BigDecimal interestToCompound, final BigDecimal interestRateAsFraction,
            final long daysInYear, final BigDecimal minBalanceForInterestCalculation) {

        final BigDecimal multiplicand = BigDecimal.ONE.divide(BigDecimal.valueOf(daysInYear), MathContext.DECIMAL64);
        final BigDecimal dailyInterestRate = interestRateAsFraction.multiply(multiplicand, MathContext.DECIMAL64);
        final BigDecimal periodicInterestRate = dailyInterestRate.multiply(BigDecimal.valueOf(this.numberOfDays), MathContext.DECIMAL64);

        final BigDecimal realBalanceForInterestCalculation = this.endOfDayBalance.getAmount().add(interestToCompound);
        BigDecimal interest = BigDecimal.ZERO.setScale(9, RoundingMode.HALF_EVEN);
        if (realBalanceForInterestCalculation.compareTo(minBalanceForInterestCalculation) >= 0) {
            interest = realBalanceForInterestCalculation.multiply(periodicInterestRate, MathContext.DECIMAL64).setScale(9,
                    RoundingMode.HALF_EVEN);
        }
        return interest;
    }

    /**
     * Future Value (FV) = PV x (1+r)^n
     *
     * Interest = FV - PV PV = Principal or the Account Balance r = rate per
     * compounding period (so for daily, r = nominalInterestRateAsFraction x
     * 1/365 n = number of periods rate is compounded
     */
    public BigDecimal calculateInterestOnBalanceAndInterest(final BigDecimal interestToCompound, final BigDecimal interestRateAsFraction,
            final long daysInYear, final BigDecimal minBalanceForInterestCalculation) {
        final BigDecimal multiplicand = BigDecimal.ONE.divide(BigDecimal.valueOf(daysInYear), MathContext.DECIMAL64);

        final BigDecimal presentValue = this.endOfDayBalance.getAmount().add(interestToCompound);

        final BigDecimal r = interestRateAsFraction.multiply(multiplicand);

        final BigDecimal interestRateForCompoundingPeriodPlusOne = BigDecimal.ONE.add(r);

        final double interestRateForCompoundingPeriodPowered = Math.pow(interestRateForCompoundingPeriodPlusOne.doubleValue(), Integer
                .valueOf(this.numberOfDays).doubleValue());
        BigDecimal futureValue = presentValue.setScale(9, RoundingMode.HALF_EVEN);
        if (presentValue.compareTo(minBalanceForInterestCalculation) >= 0) {
            futureValue = presentValue.multiply(BigDecimal.valueOf(interestRateForCompoundingPeriodPowered), MathContext.DECIMAL64)
                    .setScale(9, RoundingMode.HALF_EVEN);
        }
        return futureValue.subtract(presentValue);
    }

    /**
     * @param compoundingPeriodInterval
     * @param upToInterestCalculationDate
     *            : For calculating maturity details in advance
     *            upToInterestCalculationDate will be maturity date else it will
     *            be DateUtils.getLocalDateOfTenant().
     * @return
     */
    public EndOfDayBalance upTo(final LocalDateInterval compoundingPeriodInterval, final LocalDate upToInterestCalculationDate) {

        Money startingBalance = this.openingBalance;
        LocalDate balanceStartDate = this.date;

        LocalDate oldBalanceEndDate = this.date.plusDays(this.numberOfDays - 1);

        int daysOfBalance = this.numberOfDays;

        if (this.date.isBefore(compoundingPeriodInterval.startDate())) {
            balanceStartDate = compoundingPeriodInterval.startDate();
            startingBalance = this.endOfDayBalance;
            final LocalDateInterval balancePeriodInterval = LocalDateInterval.create(balanceStartDate, oldBalanceEndDate);
            daysOfBalance = balancePeriodInterval.daysInPeriodInclusiveOfEndDate();
        }

        LocalDate balanceEndDate = balanceStartDate.plusDays(daysOfBalance - 1);
        if (balanceEndDate.isAfter(compoundingPeriodInterval.endDate())) {
            balanceEndDate = compoundingPeriodInterval.endDate();
            final LocalDateInterval balancePeriodInterval = LocalDateInterval.create(balanceStartDate, balanceEndDate);
            daysOfBalance = balancePeriodInterval.daysInPeriodInclusiveOfEndDate();
        }
        if (balanceEndDate.isAfter(upToInterestCalculationDate)) {
            balanceEndDate = upToInterestCalculationDate;
            final LocalDateInterval balancePeriodInterval = LocalDateInterval.create(balanceStartDate, balanceEndDate);
            daysOfBalance = balancePeriodInterval.daysInPeriodInclusiveOfEndDate();
        }

        return new EndOfDayBalance(balanceStartDate, startingBalance, this.endOfDayBalance, daysOfBalance);
    }

    public boolean contains(final LocalDateInterval compoundingPeriodInterval) {

        final LocalDate balanceUpToDate = this.date.plusDays(this.numberOfDays - 1);

        final LocalDateInterval balanceInterval = LocalDateInterval.create(this.date, balanceUpToDate);
        return balanceInterval.containsPortionOf(compoundingPeriodInterval);
    }

    public Integer getNumberOfDays() {
        return Integer.valueOf(this.numberOfDays);
    }
}
TOP

Related Classes of org.mifosplatform.portfolio.savings.domain.interest.EndOfDayBalance

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.