Skip to content

Commit

Permalink
feat: Provision to send Accounts Receivable Reports using Process SOA (
Browse files Browse the repository at this point in the history
…#35789)

* feat: Provision to send Accounts Receivable Reports using Process Statement of Accounts

Issue #35707

(cherry picked from commit b3d565c)

# Conflicts:
#	erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py

* fix: add patch for setting default value of report field

(cherry picked from commit 555c126)

# Conflicts:
#	erpnext/patches.txt

* fix: modify patch

(cherry picked from commit cde82bc)

* chore: update typo in patch

(cherry picked from commit 4de7a4c)

* chore: Resolve conflicts

---------

Co-authored-by: Gursheen Anand <gursheen@frappe.io>
Co-authored-by: Deepesh Garg <deepeshgarg6@gmail.com>
  • Loading branch information
3 people authored Jun 25, 2023
1 parent 4a7d75b commit 21d560c
Show file tree
Hide file tree
Showing 8 changed files with 560 additions and 75 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div class="page-break">
<div id="header-html" class="hidden-pdf">
{% if letter_head %}
{% if letter_head.content %}
<div class="letter-head text-center">{{ letter_head.content }}</div>
<hr style="height:2px;border-width:0;color:black;background-color:black;">
{% endif %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,20 @@ frappe.ui.form.on('Process Statement Of Accounts', {
frm.set_value('to_date', frappe.datetime.get_today());
}
},
report: function(frm){
let filters = {
'company': frm.doc.company,
}
if(frm.doc.report == 'Accounts Receivable'){
filters['account_type'] = 'Receivable';
}
frm.set_query("account", function() {
return {
filters: filters
};
});

},
customer_collection: function(frm){
frm.set_value('collection_name', '');
if(frm.doc.customer_collection){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,24 @@
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"report",
"section_break_11",
"from_date",
"posting_date",
"company",
"account",
"group_by",
"cost_center",
"territory",
"column_break_14",
"to_date",
"finance_book",
"currency",
"project",
"payment_terms_template",
"sales_partner",
"sales_person",
"based_on_payment_terms",
"section_break_3",
"customer_collection",
"collection_name",
Expand Down Expand Up @@ -65,14 +72,14 @@
"reqd": 1
},
{
"depends_on": "eval:doc.enable_auto_email == 0;",
"depends_on": "eval:(doc.enable_auto_email == 0 && doc.report == 'General Ledger');",
"fieldname": "from_date",
"fieldtype": "Date",
"label": "From Date",
"mandatory_depends_on": "eval:doc.frequency == '';"
},
{
"depends_on": "eval:doc.enable_auto_email == 0;",
"depends_on": "eval:(doc.enable_auto_email == 0 && doc.report == 'General Ledger');",
"fieldname": "to_date",
"fieldtype": "Date",
"label": "To Date",
Expand All @@ -85,6 +92,7 @@
"options": "PSOA Cost Center"
},
{
"depends_on": "eval: (doc.report == 'General Ledger');",
"fieldname": "project",
"fieldtype": "Table MultiSelect",
"label": "Project",
Expand All @@ -102,7 +110,7 @@
{
"fieldname": "section_break_11",
"fieldtype": "Section Break",
"label": "General Ledger Filters"
"label": "Report Filters"
},
{
"fieldname": "column_break_14",
Expand Down Expand Up @@ -162,12 +170,14 @@
},
{
"default": "Group by Voucher (Consolidated)",
"depends_on": "eval:(doc.report == 'General Ledger');",
"fieldname": "group_by",
"fieldtype": "Select",
"label": "Group By",
"options": "\nGroup by Voucher\nGroup by Voucher (Consolidated)"
},
{
"depends_on": "eval: (doc.report == 'General Ledger');",
"fieldname": "currency",
"fieldtype": "Link",
"label": "Currency",
Expand Down Expand Up @@ -295,6 +305,7 @@
},
{
"default": "0",
"depends_on": "eval: (doc.report == 'General Ledger');",
"fieldname": "show_net_values_in_party_account",
"fieldtype": "Check",
"label": "Show Net Values in Party Account"
Expand All @@ -308,10 +319,59 @@
{
"fieldname": "column_break_ocfq",
"fieldtype": "Column Break"
},
{
"fieldname": "report",
"fieldtype": "Select",
"label": "Report",
"options": "General Ledger\nAccounts Receivable",
"reqd": 1
},
{
"default": "Today",
"depends_on": "eval:(doc.report == 'Accounts Receivable');",
"fieldname": "posting_date",
"fieldtype": "Date",
"label": "Posting Date"
},
{
"depends_on": "eval: (doc.report == 'Accounts Receivable');",
"fieldname": "payment_terms_template",
"fieldtype": "Link",
"label": "Payment Terms Template",
"options": "Payment Terms Template"
},
{
"depends_on": "eval: (doc.report == 'Accounts Receivable');",
"fieldname": "sales_partner",
"fieldtype": "Link",
"label": "Sales Partner",
"options": "Sales Partner"
},
{
"depends_on": "eval: (doc.report == 'Accounts Receivable');",
"fieldname": "sales_person",
"fieldtype": "Link",
"label": "Sales Person",
"options": "Sales Person"
},
{
"depends_on": "eval: (doc.report == 'Accounts Receivable');",
"fieldname": "territory",
"fieldtype": "Link",
"label": "Territory",
"options": "Territory"
},
{
"default": "0",
"depends_on": "eval:(doc.report == 'Accounts Receivable');",
"fieldname": "based_on_payment_terms",
"fieldtype": "Check",
"label": "Based On Payment Terms"
}
],
"links": [],
"modified": "2023-04-26 12:46:43.645455",
"modified": "2023-06-23 10:13:15.051950",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Process Statement Of Accounts",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from erpnext import get_company_currency
from erpnext.accounts.party import get_party_account_currency
from erpnext.accounts.report.accounts_receivable.accounts_receivable import execute as get_ar_soa
from erpnext.accounts.report.accounts_receivable_summary.accounts_receivable_summary import (
execute as get_ageing,
)
Expand Down Expand Up @@ -42,89 +43,36 @@ def validate(self):
def get_report_pdf(doc, consolidated=True):
statement_dict = {}
ageing = ""
base_template_path = "frappe/www/printview.html"
template_path = (
"erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html"
)

for entry in doc.customers:
if doc.include_ageing:
ageing_filters = frappe._dict(
{
"company": doc.company,
"report_date": doc.to_date,
"ageing_based_on": doc.ageing_based_on,
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
"customer": entry.customer,
}
)
col1, ageing = get_ageing(ageing_filters)

if ageing:
ageing[0]["ageing_based_on"] = doc.ageing_based_on
ageing = set_ageing(doc, entry)

tax_id = frappe.get_doc("Customer", entry.customer).tax_id
presentation_currency = (
get_party_account_currency("Customer", entry.customer, doc.company)
or doc.currency
or get_company_currency(doc.company)
)
if doc.letter_head:
from frappe.www.printview import get_letter_head

letter_head = get_letter_head(doc, 0)
filters = get_common_filters(doc)

filters = frappe._dict(
{
"from_date": doc.from_date,
"to_date": doc.to_date,
"company": doc.company,
"finance_book": doc.finance_book if doc.finance_book else None,
"account": [doc.account] if doc.account else None,
"party_type": "Customer",
"party": [entry.customer],
"party_name": [entry.customer_name] if entry.customer_name else None,
"presentation_currency": presentation_currency,
"group_by": doc.group_by,
"currency": doc.currency,
"cost_center": [cc.cost_center_name for cc in doc.cost_center],
"project": [p.project_name for p in doc.project],
"show_opening_entries": 0,
"include_default_book_entries": 0,
"tax_id": tax_id if tax_id else None,
}
)
col, res = get_soa(filters)

for x in [0, -2, -1]:
res[x]["account"] = res[x]["account"].replace("'", "")

if len(res) == 3:
continue
if doc.report == "General Ledger":
filters.update(get_gl_filters(doc, entry, tax_id, presentation_currency))
else:
filters.update(get_ar_filters(doc, entry))

html = frappe.render_template(
template_path,
{
"filters": filters,
"data": res,
"ageing": ageing[0] if (doc.include_ageing and ageing) else None,
"letter_head": letter_head if doc.letter_head else None,
"terms_and_conditions": frappe.db.get_value(
"Terms and Conditions", doc.terms_and_conditions, "terms"
)
if doc.terms_and_conditions
else None,
},
)
if doc.report == "General Ledger":
col, res = get_soa(filters)
for x in [0, -2, -1]:
res[x]["account"] = res[x]["account"].replace("'", "")
if len(res) == 3:
continue
else:
ar_res = get_ar_soa(filters)
col, res = ar_res[0], ar_res[1]

html = frappe.render_template(
base_template_path,
{"body": html, "css": get_print_style(), "title": "Statement For " + entry.customer},
)
statement_dict[entry.customer] = html
statement_dict[entry.customer] = get_html(doc, filters, entry, col, res, ageing)

if not bool(statement_dict):
return False
Expand All @@ -137,6 +85,110 @@ def get_report_pdf(doc, consolidated=True):
return statement_dict


def set_ageing(doc, entry):
ageing_filters = frappe._dict(
{
"company": doc.company,
"report_date": doc.to_date,
"ageing_based_on": doc.ageing_based_on,
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
"customer": entry.customer,
}
)
col1, ageing = get_ageing(ageing_filters)

if ageing:
ageing[0]["ageing_based_on"] = doc.ageing_based_on

return ageing


def get_common_filters(doc):
return frappe._dict(
{
"company": doc.company,
"finance_book": doc.finance_book if doc.finance_book else None,
"account": [doc.account] if doc.account else None,
"cost_center": [cc.cost_center_name for cc in doc.cost_center],
}
)


def get_gl_filters(doc, entry, tax_id, presentation_currency):
return {
"from_date": doc.from_date,
"to_date": doc.to_date,
"party_type": "Customer",
"party": [entry.customer],
"party_name": [entry.customer_name] if entry.customer_name else None,
"presentation_currency": presentation_currency,
"group_by": doc.group_by,
"currency": doc.currency,
"project": [p.project_name for p in doc.project],
"show_opening_entries": 0,
"include_default_book_entries": 0,
"tax_id": tax_id if tax_id else None,
"show_net_values_in_party_account": doc.show_net_values_in_party_account,
}


def get_ar_filters(doc, entry):
return {
"report_date": doc.posting_date if doc.posting_date else None,
"customer_name": entry.customer,
"payment_terms_template": doc.payment_terms_template if doc.payment_terms_template else None,
"sales_partner": doc.sales_partner if doc.sales_partner else None,
"sales_person": doc.sales_person if doc.sales_person else None,
"territory": doc.territory if doc.territory else None,
"based_on_payment_terms": doc.based_on_payment_terms,
"report_name": "Accounts Receivable",
"ageing_based_on": doc.ageing_based_on,
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
}


def get_html(doc, filters, entry, col, res, ageing):
base_template_path = "frappe/www/printview.html"
template_path = (
"erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html"
if doc.report == "General Ledger"
else "erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts_accounts_receivable.html"
)

if doc.letter_head:
from frappe.www.printview import get_letter_head

letter_head = get_letter_head(doc, 0)

html = frappe.render_template(
template_path,
{
"filters": filters,
"data": res,
"report": {"report_name": doc.report, "columns": col},
"ageing": ageing[0] if (doc.include_ageing and ageing) else None,
"letter_head": letter_head if doc.letter_head else None,
"terms_and_conditions": frappe.db.get_value(
"Terms and Conditions", doc.terms_and_conditions, "terms"
)
if doc.terms_and_conditions
else None,
},
)

html = frappe.render_template(
base_template_path,
{"body": html, "css": get_print_style(), "title": "Statement For " + entry.customer},
)
return html


def get_customers_based_on_territory_or_customer_group(customer_collection, collection_name):
fields_dict = {
"Customer Group": "customer_group",
Expand Down
Loading

0 comments on commit 21d560c

Please sign in to comment.