Example #1
0
def list(loan, from_date, to_date):
    if getdate(to_date) < getdate(from_date):
        return frappe.throw('To date cannot be less than From date')

    conds = [
        "loan = '{}'".format(loan),
        "docstatus = 1",
        "start_date BETWEEN '{}' AND '{}'".format(from_date, to_date),
    ]
    existing = frappe.db.sql(
        """
            SELECT
                name, status,
                period, posting_date, start_date,
                billed_amount, paid_amount, fine_amount
            FROM `tabMicrofinance Loan Interest` WHERE {conds}
        """.format(conds=join(" AND ")(conds)),
        as_dict=True,
    )
    existing_dict = dict((row.name, row) for row in existing)

    get_item = compose(existing_dict.get, partial(make_name, loan))
    make_item = compose(_make_list_item, get_item)
    loan_end_date, loan_start_date = frappe.get_value(
        'Microfinance Loan', loan, ['clear_date', 'posting_date'])

    def make_empty(d):
        return {
            'name': make_name(loan, d),
            'period': d.strftime('%b %Y'),
            'start_date': max(loan_start_date, d),
            'status': 'Unbilled'
        }

    effective_date = frappe.get_value('Microfinance Loan Settings', None,
                                      'effective_date')
    is_not_sys_mgr = 'System Manager' not in frappe.permissions.get_roles()

    def change_status(row):
        start_date = row.get('start_date')
        status = 'Clear' \
            if is_not_sys_mgr \
            and getdate(effective_date) > getdate(start_date) \
            else row.get('status')
        return update({
            'status': status,
        })(row)

    fd = compose(partial(max, loan_start_date), getdate)
    td = compose(partial(min, loan_end_date), getdate) \
        if loan_end_date else getdate
    dates = _gen_dates(fd(from_date), td(to_date))

    return compose(
        partial(map, change_status),
        partial(map, lambda x: make_item(x) if get_item(x) else make_empty(x)),
    )(dates)
Example #2
0
 def get_sum_of(doctype, field):
     def fn(loan):
         return frappe.get_all(
             doctype,
             filters={'docstatus': 1, 'loan': loan},
             fields=field,
         )
     return compose(sum, partial(map, pick(field)), fn)
Example #3
0
def create(loan, period, start_date, billed_amount=None):
    if 'System Manager' not in frappe.permissions.get_roles():
        prev = compose(
            partial(frappe.db.exists, 'Microfinance Loan Interest'),
            partial(make_name, loan),
            getdate,
            partial(add_months, months=-1),
        )(start_date)
        if not prev:
            return frappe.throw(
                'Interest for previous interval does not exists')
    end_date = compose(get_last_day, getdate)(start_date)
    interest = frappe.get_doc({
        'doctype': 'Microfinance Loan Interest',
        'loan': loan,
        'posting_date': add_days(end_date, 1),
        'period': period,
        'start_date': getdate(start_date),
        'end_date': end_date,
        'billed_amount': billed_amount,
    })
    interest.insert()
    interest.submit()
    return interest
Example #4
0
def fine(name):
    interest = frappe.get_doc('Microfinance Loan Interest', name)
    loan_start_date = frappe.get_value('Microfinance Loan', interest.loan,
                                       'posting_date')
    prev_status = compose(
        partial(frappe.get_value,
                'Microfinance Loan Interest',
                fieldname='status'),
        partial(make_name, interest.loan),
        partial(add_months, months=-1),
    )(interest.end_date) if interest.start_date > loan_start_date else 'Clear'
    if prev_status not in ['Clear', 'Fined']:
        return frappe.throw('Previous interest is not cleared or fined')
    if _has_next_interest(interest):
        return frappe.throw('Interest for next interval already exists')
    interest.run_method('set_fine_amount')
    return interest
Example #5
0
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)
Example #6
0
from loan_management.loan_management.utils.fp import compose, join
from loan_management.loan_management.api.loan import get_outstanding_principal


def _accum_reducer(acc, row):
    return acc + [row[:-1] + (acc[-1][5] + row[4], ) + row[-1:]]


def _col_sum(idx):
    def fn(rows):
        return reduce(lambda a, x: a + x[idx], rows, 0)

    return fn


_stringify_accounts = compose(join(', '),
                              partial(map, lambda x: "'{}'".format(x)))


def execute(filters={}):
    columns = [
        _("Posting Date") + ":Date:90",
        _("Account") + ":Link/Account:240",
        _("Credit") + ":Currency/currency:90",
        _("Debit") + ":Currency/currency:90",
        _("Amount") + ":Currency/currency:90",
        _("Cummulative") + ":Currency/currency:90",
        _("Remarks") + "::240",
    ]

    loan_account = frappe.get_value('Customer Loan Application',
                                    filters.get('loan'),
Example #7
0
def _is_advance(per, posting_date):
    scheduled_pd = compose(
        partial(add_days, days=1),
        per.get,
    )('end_date')
    return getdate(posting_date) < getdate(scheduled_pd)
Example #8
0
def _has_next_interest(interest):
    return compose(
        partial(frappe.db.exists, 'Microfinance Loan Interest'),
        partial(make_name, interest.loan),
        partial(add_months, months=1),
    )(interest.start_date)