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)
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)