Beispiel #1
0
 def get_billed_amount(self):
     (
         loan_type,
         calculation_slab,
         rate_of_interest,
         loan_principal,
     ) = frappe.get_value(
         "Microfinance Loan",
         self.loan,
         ["loan_type", "calculation_slab", "rate_of_interest", "loan_principal"],
     )
     if loan_type == "EMI":
         return calc_interest(loan_principal, rate_of_interest)
     outstanding_principal = get_outstanding_principal(self.loan, self.end_date)
     return calc_interest(outstanding_principal, rate_of_interest, calculation_slab)
Beispiel #2
0
def calculate_principal(income, loan_plan, end_date, execution_date):
    """
        Return a dict containing the maximum allowed principal along with the
        duration and monthly installment.

        :param income: Renumeration received by the Customer
        :param loan_plan: Name of a Loan Plan
        :param end_date: Maximum date on which the loan could end
        :param execution_date: Date on which the loan would start
    """
    plan = frappe.get_doc('Microfinance Loan Plan', loan_plan)
    if not plan.income_multiple or not plan.max_duration:
        frappe.throw('Missing values in Loan Plan', ValueError)

    recovery_amount = flt(income) * plan.income_multiple / plan.max_duration

    duration = plan.max_duration if plan.force_max_duration else min(
        plan.max_duration,
        compose(partial(month_diff, end_date), get_last_day)(execution_date),
    )

    expected_eta = compose(partial(add_months, months=duration),
                           get_last_day)(execution_date)

    principal = recovery_amount * duration
    initial_interest = calc_interest(principal, plan.rate_of_interest,
                                     plan.calculation_slab)

    return {
        'principal': rounded(principal, 2),
        'expected_eta': expected_eta,
        'duration': duration,
        'recovery_amount': rounded(recovery_amount, 2),
        'initial_interest': rounded(initial_interest, 2),
    }
 def get_billed_amount(self):
     outstanding_principal = get_outstanding_principal(
         self.loan, self.end_date)
     calculation_slab, rate_of_interest = frappe.get_value(
         'Microfinance Loan',
         self.loan,
         ['calculation_slab', 'rate_of_interest'],
     )
     return calc_interest(outstanding_principal, rate_of_interest,
                          calculation_slab)
def allocate_interests(loan, posting_date, amount_to_allocate=0, principal=0):
    periods = []
    to_allocate = amount_to_allocate

    existing_unpaid_interests = get_unpaid(loan)
    for period in map(_interest_to_period, existing_unpaid_interests):
        p = _allocate(period, to_allocate)
        periods.append(p)
        to_allocate -= p.get('allocated_amount')

    calculation_slab, loan_date, rate_of_interest = frappe.get_value(
        'Microfinance Loan',
        loan,
        ['calculation_slab', 'posting_date', 'rate_of_interest'],
    )
    outstanding_amount = get_outstanding_principal(loan, posting_date)
    interest_amount = calc_interest(outstanding_amount, rate_of_interest,
                                    calculation_slab)
    adv_interest_amount = calc_interest(outstanding_amount - principal,
                                        rate_of_interest, calculation_slab)
    last = get_last(loan)
    effective_date = frappe.get_value('Microfinance Loan Settings', None,
                                      'effective_date')
    init_date = add_days(last.get('end_date'), 1) if last \
        else max(loan_date, getdate(effective_date))
    gen_per = _generate_periods(init_date)
    while to_allocate > 0:
        per_ = gen_per.next()
        # for advance payments consider outstanding_amount to be minus
        # the current principal to be paid
        amount = adv_interest_amount \
            if _is_advance(per_, posting_date) else interest_amount
        per_.update({
            'billed_amount': amount,
            'outstanding_amount': amount,
        })
        per = _allocate(per_, to_allocate)
        periods.append(per)
        to_allocate -= per.get('allocated_amount')
    return filter(lambda x: x.get('allocated_amount') > 0, periods)
def allocate_interests(loan, posting_date, amount_to_allocate=0, principal=0):
    periods = []
    to_allocate = amount_to_allocate

    existing_unpaid_interests = get_unpaid(loan)
    for period in map(_interest_to_period, existing_unpaid_interests):
        p = _allocate(period, to_allocate)
        periods.append(p)
        to_allocate -= p.get("allocated_amount")

    calculation_slab, loan_date, rate_of_interest = frappe.get_value(
        "Microfinance Loan",
        loan,
        ["calculation_slab", "posting_date", "rate_of_interest"],
    )
    outstanding_amount = get_outstanding_principal(loan, posting_date)
    interest_amount = calc_interest(outstanding_amount, rate_of_interest,
                                    calculation_slab)
    adv_interest_amount = calc_interest(outstanding_amount - principal,
                                        rate_of_interest, calculation_slab)
    last = get_last(loan)
    effective_date = frappe.get_value("Microfinance Loan Settings", None,
                                      "effective_date")
    init_date = (add_days(last.get("end_date"), 1) if last else max(
        loan_date, getdate(effective_date)))
    gen_per = _generate_periods(init_date)
    while to_allocate > 0:
        per_ = next(gen_per)
        # for advance payments consider outstanding_amount to be minus
        # the current principal to be paid
        amount = (adv_interest_amount
                  if _is_advance(per_, posting_date) else interest_amount)
        per_.update({"billed_amount": amount, "outstanding_amount": amount})
        per = _allocate(per_, to_allocate)
        periods.append(per)
        to_allocate -= per.get("allocated_amount")
    return filter(lambda x: x.get("allocated_amount") > 0, periods)
def get_current_interest(loan, posting_date):
    calculation_slab, rate_of_interest, recovery_status = frappe.get_value(
        "Microfinance Loan",
        loan,
        ["calculation_slab", "rate_of_interest", "recovery_status"],
    )
    if recovery_status == "NPA":
        return 0
    prev_billed_amount = compose(
        partial(frappe.get_value,
                "Microfinance Loan Interest",
                fieldname="billed_amount"),
        partial(make_name, loan),
        getdate,
        partial(add_months, months=-1),
    )(posting_date)
    if prev_billed_amount:
        return prev_billed_amount
    outstanding = get_outstanding_principal(loan, posting_date)
    return calc_interest(outstanding, rate_of_interest, calculation_slab)
def get_current_interest(loan, posting_date):
    calculation_slab, rate_of_interest, recovery_status = frappe.get_value(
        'Microfinance Loan',
        loan,
        ['calculation_slab', 'rate_of_interest', 'recovery_status'],
    )
    if recovery_status == 'NPA':
        return 0
    prev_billed_amount = compose(
        partial(frappe.get_value,
                'Microfinance Loan Interest',
                fieldname='billed_amount'),
        partial(make_name, loan),
        getdate,
        partial(add_months, months=-1),
    )(posting_date)
    if prev_billed_amount:
        return prev_billed_amount
    outstanding = get_outstanding_principal(loan, posting_date)
    return calc_interest(outstanding, rate_of_interest, calculation_slab)