Accounts Receivable report based on payment terms
This commit is contained in:
parent
a78947f2de
commit
a8ab9b5c3d
@ -107,6 +107,11 @@ frappe.query_reports["Accounts Receivable"] = {
|
|||||||
"label": __("Show PDC in Print"),
|
"label": __("Show PDC in Print"),
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"based_on_payment_terms",
|
||||||
|
"label": __("Based On Payment Terms"),
|
||||||
|
"fieldtype": "Check",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldname":"tax_id",
|
"fieldname":"tax_id",
|
||||||
"label": __("Tax Id"),
|
"label": __("Tax Id"),
|
||||||
|
@ -152,106 +152,139 @@ class ReceivablePayableReport(object):
|
|||||||
def get_data(self, party_naming_by, args):
|
def get_data(self, party_naming_by, args):
|
||||||
from erpnext.accounts.utils import get_currency_precision
|
from erpnext.accounts.utils import get_currency_precision
|
||||||
currency_precision = get_currency_precision() or 2
|
currency_precision = get_currency_precision() or 2
|
||||||
dr_or_cr = "debit" if args.get("party_type") == "Customer" else "credit"
|
self.dr_or_cr = "debit" if args.get("party_type") == "Customer" else "credit"
|
||||||
|
|
||||||
future_vouchers = self.get_entries_after(self.filters.report_date, args.get("party_type"))
|
future_vouchers = self.get_entries_after(self.filters.report_date, args.get("party_type"))
|
||||||
|
|
||||||
if not self.filters.get("company"):
|
if not self.filters.get("company"):
|
||||||
self.filters["company"] = frappe.db.get_single_value('Global Defaults', 'default_company')
|
self.filters["company"] = frappe.db.get_single_value('Global Defaults', 'default_company')
|
||||||
|
|
||||||
company_currency = frappe.get_cached_value('Company', self.filters.get("company"), "default_currency")
|
self.company_currency = frappe.get_cached_value('Company', self.filters.get("company"), "default_currency")
|
||||||
|
|
||||||
return_entries = self.get_return_entries(args.get("party_type"))
|
return_entries = self.get_return_entries(args.get("party_type"))
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
pdc_details = get_pdc_details(args.get("party_type"), self.filters.report_date)
|
self.pdc_details = get_pdc_details(args.get("party_type"), self.filters.report_date)
|
||||||
gl_entries_data = self.get_entries_till(self.filters.report_date, args.get("party_type"))
|
gl_entries_data = self.get_entries_till(self.filters.report_date, args.get("party_type"))
|
||||||
|
|
||||||
if gl_entries_data:
|
if gl_entries_data:
|
||||||
voucher_nos = [d.voucher_no for d in gl_entries_data] or []
|
voucher_nos = [d.voucher_no for d in gl_entries_data] or []
|
||||||
dn_details = get_dn_details(args.get("party_type"), voucher_nos)
|
dn_details = get_dn_details(args.get("party_type"), voucher_nos)
|
||||||
voucher_details = get_voucher_details(args.get("party_type"), voucher_nos, dn_details)
|
self.voucher_details = get_voucher_details(args.get("party_type"), voucher_nos, dn_details)
|
||||||
|
|
||||||
|
if self.filters.based_on_payment_terms:
|
||||||
|
self.payment_term_map = self.get_payment_term_detail(voucher_nos)
|
||||||
|
|
||||||
for gle in gl_entries_data:
|
for gle in gl_entries_data:
|
||||||
if self.is_receivable_or_payable(gle, dr_or_cr, future_vouchers):
|
if self.is_receivable_or_payable(gle, self.dr_or_cr, future_vouchers):
|
||||||
outstanding_amount, credit_note_amount = self.get_outstanding_amount(gle,
|
if self.filters.based_on_payment_terms and self.payment_term_map.get(gle.voucher_no):
|
||||||
self.filters.report_date, dr_or_cr, return_entries, currency_precision)
|
outstanding_amount, credit_note_amount, payment_amount = self.get_outstanding_amount(
|
||||||
if abs(outstanding_amount) > 0.1/10**currency_precision:
|
gle,self.filters.report_date, self.dr_or_cr, return_entries, currency_precision)
|
||||||
row = [gle.posting_date, gle.party]
|
if abs(outstanding_amount) > 0.1/10**currency_precision:
|
||||||
|
for d in self.payment_term_map.get(gle.voucher_no):
|
||||||
|
if payment_amount >= d[1]:
|
||||||
|
payment_amount -= d[1]
|
||||||
|
else:
|
||||||
|
outstanding_amount = d[1] - payment_amount
|
||||||
|
row = self.prepare_row(party_naming_by, args, gle, outstanding_amount,
|
||||||
|
credit_note_amount, d[0], payment_amount )
|
||||||
|
payment_amount = 0
|
||||||
|
data.append(row)
|
||||||
|
else:
|
||||||
|
outstanding_amount, credit_note_amount, payment_amount = self.get_outstanding_amount(
|
||||||
|
gle,self.filters.report_date, self.dr_or_cr, return_entries, currency_precision)
|
||||||
|
if abs(outstanding_amount) > 0.1/10**currency_precision:
|
||||||
|
row = self.prepare_row(party_naming_by, args, gle, outstanding_amount, credit_note_amount)
|
||||||
|
data.append(row)
|
||||||
|
return data
|
||||||
|
|
||||||
# customer / supplier name
|
def prepare_row(self, party_naming_by, args, gle, outstanding_amount, credit_note_amount,
|
||||||
if party_naming_by == "Naming Series":
|
due_date=None, paid_amt=None):
|
||||||
row += [self.get_party_name(gle.party_type, gle.party)]
|
row = [gle.posting_date, gle.party]
|
||||||
|
|
||||||
# get due date
|
# customer / supplier name
|
||||||
due_date = voucher_details.get(gle.voucher_no, {}).get("due_date", "")
|
if party_naming_by == "Naming Series":
|
||||||
bill_date = voucher_details.get(gle.voucher_no, {}).get("bill_date", "")
|
row += [self.get_party_name(gle.party_type, gle.party)]
|
||||||
|
|
||||||
row += [gle.voucher_type, gle.voucher_no, due_date]
|
# get due date
|
||||||
|
if not due_date:
|
||||||
|
due_date = self.voucher_details.get(gle.voucher_no, {}).get("due_date", "")
|
||||||
|
bill_date = self.voucher_details.get(gle.voucher_no, {}).get("bill_date", "")
|
||||||
|
|
||||||
# get supplier bill details
|
row += [gle.voucher_type, gle.voucher_no, due_date]
|
||||||
if args.get("party_type") == "Supplier":
|
|
||||||
row += [
|
|
||||||
voucher_details.get(gle.voucher_no, {}).get("bill_no", ""),
|
|
||||||
voucher_details.get(gle.voucher_no, {}).get("bill_date", "")
|
|
||||||
]
|
|
||||||
|
|
||||||
# invoiced and paid amounts
|
# get supplier bill details
|
||||||
invoiced_amount = gle.get(dr_or_cr) if (gle.get(dr_or_cr) > 0) else 0
|
if args.get("party_type") == "Supplier":
|
||||||
paid_amt = invoiced_amount - outstanding_amount - credit_note_amount
|
row += [
|
||||||
row += [invoiced_amount, paid_amt, credit_note_amount, outstanding_amount]
|
self.voucher_details.get(gle.voucher_no, {}).get("bill_no", ""),
|
||||||
|
self.voucher_details.get(gle.voucher_no, {}).get("bill_date", "")
|
||||||
|
]
|
||||||
|
|
||||||
# ageing data
|
# invoiced and paid amounts
|
||||||
if self.filters.ageing_based_on == "Due Date":
|
invoiced_amount = gle.get(self.dr_or_cr) if (gle.get(self.dr_or_cr) > 0) else 0
|
||||||
entry_date = due_date
|
|
||||||
elif self.filters.ageing_based_on == "Supplier Invoice Date":
|
|
||||||
entry_date = bill_date
|
|
||||||
else:
|
|
||||||
entry_date = gle.posting_date
|
|
||||||
|
|
||||||
row += get_ageing_data(cint(self.filters.range1), cint(self.filters.range2),
|
if not self.filters.based_on_payment_terms:
|
||||||
cint(self.filters.range3), self.age_as_on, entry_date, outstanding_amount)
|
paid_amt = invoiced_amount - outstanding_amount - credit_note_amount
|
||||||
|
row += [invoiced_amount, paid_amt, credit_note_amount, outstanding_amount]
|
||||||
|
|
||||||
|
# ageing data
|
||||||
|
if self.filters.ageing_based_on == "Due Date":
|
||||||
|
entry_date = due_date
|
||||||
|
elif self.filters.ageing_based_on == "Supplier Invoice Date":
|
||||||
|
entry_date = bill_date
|
||||||
|
else:
|
||||||
|
entry_date = gle.posting_date
|
||||||
|
|
||||||
|
row += get_ageing_data(cint(self.filters.range1), cint(self.filters.range2),
|
||||||
|
cint(self.filters.range3), self.age_as_on, entry_date, outstanding_amount)
|
||||||
|
|
||||||
|
|
||||||
# issue 6371-Ageing buckets should not have amounts if due date is not reached
|
# issue 6371-Ageing buckets should not have amounts if due date is not reached
|
||||||
if self.filters.ageing_based_on == "Due Date" \
|
if self.filters.ageing_based_on == "Due Date" \
|
||||||
and getdate(due_date) > getdate(self.filters.report_date):
|
and getdate(due_date) > getdate(self.filters.report_date):
|
||||||
row[-1]=row[-2]=row[-3]=row[-4]=0
|
row[-1]=row[-2]=row[-3]=row[-4]=0
|
||||||
|
|
||||||
if self.filters.ageing_based_on == "Supplier Invoice Date" \
|
if self.filters.ageing_based_on == "Supplier Invoice Date" \
|
||||||
and getdate(bill_date) > getdate(self.filters.report_date):
|
and getdate(bill_date) > getdate(self.filters.report_date):
|
||||||
|
|
||||||
row[-1]=row[-2]=row[-3]=row[-4]=0
|
row[-1]=row[-2]=row[-3]=row[-4]=0
|
||||||
|
|
||||||
if self.filters.get(scrub(args.get("party_type"))):
|
if self.filters.get(scrub(args.get("party_type"))):
|
||||||
row.append(gle.account_currency)
|
row.append(gle.account_currency)
|
||||||
else:
|
else:
|
||||||
row.append(company_currency)
|
row.append(self.company_currency)
|
||||||
|
|
||||||
pdc = pdc_details.get((gle.voucher_no, gle.party), {})
|
pdc = self.pdc_details.get((gle.voucher_no, gle.party), {})
|
||||||
|
|
||||||
remaining_balance = outstanding_amount - flt(pdc.get("pdc_amount"))
|
remaining_balance = outstanding_amount - flt(pdc.get("pdc_amount"))
|
||||||
row += [pdc.get("pdc_date"), pdc.get("pdc_ref"),
|
row += [pdc.get("pdc_date"), pdc.get("pdc_ref"),
|
||||||
flt(pdc.get("pdc_amount")), remaining_balance]
|
flt(pdc.get("pdc_amount")), remaining_balance]
|
||||||
|
|
||||||
if args.get('party_type') == 'Customer':
|
|
||||||
# customer LPO
|
|
||||||
row += [voucher_details.get(gle.voucher_no, {}).get("po_no")]
|
|
||||||
|
|
||||||
# Delivery Note
|
|
||||||
row += [voucher_details.get(gle.voucher_no, {}).get("delivery_note")]
|
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
# customer territory / supplier group
|
# customer territory / supplier group
|
||||||
if args.get("party_type") == "Customer":
|
if args.get("party_type") == "Customer":
|
||||||
row += [self.get_territory(gle.party), self.get_customer_group(gle.party),
|
row += [self.get_territory(gle.party), self.get_customer_group(gle.party),
|
||||||
voucher_details.get(gle.voucher_no, {}).get("sales_person")]
|
voucher_details.get(gle.voucher_no, {}).get("sales_person")]
|
||||||
if args.get("party_type") == "Supplier":
|
if args.get("party_type") == "Supplier":
|
||||||
row += [self.get_supplier_group(gle.party)]
|
row += [self.get_supplier_group(gle.party)]
|
||||||
|
=======
|
||||||
|
if args.get('party_type') == 'Customer':
|
||||||
|
# customer LPO
|
||||||
|
row += [self.voucher_details.get(gle.voucher_no, {}).get("po_no")]
|
||||||
|
>>>>>>> Accounts Receivable report based on payment terms
|
||||||
|
|
||||||
row.append(gle.remarks)
|
# Delivery Note
|
||||||
data.append(row)
|
row += [self.voucher_details.get(gle.voucher_no, {}).get("delivery_note")]
|
||||||
|
|
||||||
return data
|
# customer territory / supplier group
|
||||||
|
if args.get("party_type") == "Customer":
|
||||||
|
row += [self.get_territory(gle.party), self.get_customer_group(gle.party)]
|
||||||
|
if args.get("party_type") == "Supplier":
|
||||||
|
row += [self.get_supplier_group(gle.party)]
|
||||||
|
|
||||||
|
row.append(gle.remarks)
|
||||||
|
|
||||||
|
return row
|
||||||
|
|
||||||
def get_entries_after(self, report_date, party_type):
|
def get_entries_after(self, report_date, party_type):
|
||||||
# returns a distinct list
|
# returns a distinct list
|
||||||
@ -298,7 +331,7 @@ class ReceivablePayableReport(object):
|
|||||||
|
|
||||||
credit_note_amount = flt(credit_note_amount, currency_precision)
|
credit_note_amount = flt(credit_note_amount, currency_precision)
|
||||||
|
|
||||||
return outstanding_amount, credit_note_amount
|
return outstanding_amount, credit_note_amount, payment_amount
|
||||||
|
|
||||||
def get_party_name(self, party_type, party_name):
|
def get_party_name(self, party_type, party_name):
|
||||||
return self.get_party_map(party_type).get(party_name, {}).get("customer_name" if party_type == "Customer" else "supplier_name") or ""
|
return self.get_party_map(party_type).get(party_name, {}).get("customer_name" if party_type == "Customer" else "supplier_name") or ""
|
||||||
@ -432,6 +465,20 @@ class ReceivablePayableReport(object):
|
|||||||
.get(against_voucher_type, {})\
|
.get(against_voucher_type, {})\
|
||||||
.get(against_voucher, [])
|
.get(against_voucher, [])
|
||||||
|
|
||||||
|
def get_payment_term_detail(self, voucher_nos):
|
||||||
|
payment_term_map = frappe._dict()
|
||||||
|
for d in frappe.db.sql(""" select si.name, si.payment_terms_template, ps.due_date, ps.payment_amount
|
||||||
|
from `tabSales Invoice` si, `tabPayment Schedule` ps
|
||||||
|
where si.name = ps.parent and
|
||||||
|
si.docstatus = 1 and si.company = '%s' and
|
||||||
|
si.name in (%s) order by ps.due_date"""
|
||||||
|
% (self.filters.company, ','.join(['%s'] *len(voucher_nos))), (tuple(voucher_nos)), as_dict = 1):
|
||||||
|
if d.payment_terms_template:
|
||||||
|
payment_term_map.setdefault(d.name,[])
|
||||||
|
payment_term_map[d.name].append((d.due_date,d.payment_amount))
|
||||||
|
|
||||||
|
return payment_term_map
|
||||||
|
|
||||||
def get_chart_data(self, columns, data):
|
def get_chart_data(self, columns, data):
|
||||||
ageing_columns = columns[self.ageing_col_idx_start : self.ageing_col_idx_start+4]
|
ageing_columns = columns[self.ageing_col_idx_start : self.ageing_col_idx_start+4]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user