From 0a9187ea422f2312ffd9508f1f3c6a120c228f71 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 28 Aug 2023 13:09:51 +0530 Subject: [PATCH 1/5] fix: show letterhead and terms for AR pdf --- ...ement_of_accounts_accounts_receivable.html | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts_accounts_receivable.html b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts_accounts_receivable.html index 259526f8c43a..647600a9fea0 100644 --- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts_accounts_receivable.html +++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts_accounts_receivable.html @@ -8,9 +8,24 @@ } +
+ {% if letter_head.content %} +
{{ letter_head.content }}
+
+ {% endif %} +
+ +

{{ _(report.report_name) }}

- {{ filters.customer }} + {{ filters.customer_name }}

{% if (filters.tax_id) %} @@ -341,4 +356,9 @@

{{ _("Ageing Report based on ") }} {{ ageing.ageing_base {% endif %} + {% if terms_and_conditions %} +
+ {{ terms_and_conditions }} +
+ {% endif %}

{{ _("Printed On ") }}{{ frappe.utils.now() }}

From 5c2a949593727ec6c9f84f8b801035e4da01558d Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 28 Aug 2023 13:11:28 +0530 Subject: [PATCH 2/5] feat: add field for specifying pdf name --- .../process_statement_of_accounts.json | 10 ++++++++-- .../process_statement_of_accounts.py | 15 ++++++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json index 8004659065ed..a3a953f910fa 100644 --- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json +++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json @@ -51,6 +51,7 @@ "column_break_21", "start_date", "section_break_33", + "pdf_name", "subject", "column_break_28", "cc_to", @@ -275,7 +276,7 @@ "fieldname": "help_text", "fieldtype": "HTML", "label": "Help Text", - "options": "
\n

Note

\n
    \n
  • \nYou can use Jinja tags in Subject and Body fields for dynamic values.\n
  • \n All fields in this doctype are available under the doc object and all fields for the customer to whom the mail will go to is available under the customer object.\n
\n

Examples

\n\n
    \n
  • Subject:

    Statement Of Accounts for {{ customer.name }}

  • \n
  • Body:

    \n
    Hello {{ customer.name }},
    PFA your Statement Of Accounts from {{ doc.from_date }} to {{ doc.to_date }}.
  • \n
\n" + "options": "
\n

Note

\n
    \n
  • \nYou can use Jinja tags in Subject and Body fields for dynamic values.\n
  • \n All fields in this doctype are available under the doc object and all fields for the customer to whom the mail will go to is available under the customer object.\n
\n

Examples

\n\n
    \n
  • Subject:

    Statement Of Accounts for {{ customer.customer_name }}

  • \n
  • Body:

    \n
    Hello {{ customer.customer_name }},
    PFA your Statement Of Accounts from {{ doc.from_date }} to {{ doc.to_date }}.
  • \n
\n" }, { "fieldname": "subject", @@ -370,10 +371,15 @@ "fieldname": "based_on_payment_terms", "fieldtype": "Check", "label": "Based On Payment Terms" + }, + { + "fieldname": "pdf_name", + "fieldtype": "Data", + "label": "PDF Name" } ], "links": [], - "modified": "2023-06-23 10:13:15.051950", + "modified": "2023-08-28 12:59:53.071334", "modified_by": "Administrator", "module": "Accounts", "name": "Process Statement Of Accounts", diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py index 6193c849b5ba..b35d237cfb3e 100644 --- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py +++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py @@ -27,7 +27,13 @@ def validate(self): if not self.subject: self.subject = "Statement Of Accounts for {{ customer.customer_name }}" if not self.body: - self.body = "Hello {{ customer.name }},
PFA your Statement Of Accounts from {{ doc.from_date }} to {{ doc.to_date }}." + if self.report == "General Ledger": + body_str = " from {{ doc.from_date }} to {{ doc.to_date }}." + else: + body_str = " until {{ doc.posting_date }}." + self.body = "Hello {{ customer.customer_name }},
PFA your Statement Of Accounts" + body_str + if not self.pdf_name: + self.pdf_name = "{{ customer.customer_name }}" validate_template(self.subject) validate_template(self.body) @@ -141,6 +147,7 @@ def get_ar_filters(doc, entry): return { "report_date": doc.posting_date if doc.posting_date else None, "customer": entry.customer, + "customer_name": entry.customer_name if entry.customer_name else None, "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, @@ -372,12 +379,14 @@ def send_emails(document_name, from_scheduler=False): if report: for customer, report_pdf in report.items(): - attachments = [{"fname": customer + ".pdf", "fcontent": report_pdf}] + context = get_context(customer, doc) + filename = frappe.render_template(doc.pdf_name, context) + attachments = [{"fname": filename + ".pdf", "fcontent": report_pdf}] recipients, cc = get_recipients_and_cc(customer, doc) if not recipients: continue - context = get_context(customer, doc) + subject = frappe.render_template(doc.subject, context) message = frappe.render_template(doc.body, context) From f07f4ce86f5963d03ea41ab699df2c4ce53ef2c5 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 28 Aug 2023 17:14:15 +0530 Subject: [PATCH 3/5] fix: generate pdf only when result exists --- .../process_statement_of_accounts.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py index b35d237cfb3e..cace9678336b 100644 --- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py +++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py @@ -64,11 +64,6 @@ def get_report_pdf(doc, consolidated=True): filters = get_common_filters(doc) - if doc.report == "General Ledger": - filters.update(get_gl_filters(doc, entry, tax_id, presentation_currency)) - else: - filters.update(get_ar_filters(doc, entry)) - if doc.report == "General Ledger": col, res = get_soa(filters) for x in [0, -2, -1]: @@ -76,8 +71,11 @@ def get_report_pdf(doc, consolidated=True): if len(res) == 3: continue else: + filters.update(get_ar_filters(doc, entry)) ar_res = get_ar_soa(filters) col, res = ar_res[0], ar_res[1] + if not res: + continue statement_dict[entry.customer] = get_html(doc, filters, entry, col, res, ageing) From a006b66e45c1b0c192674ad522b05f5565513e35 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Tue, 29 Aug 2023 14:51:35 +0530 Subject: [PATCH 4/5] test: auto email for ar report --- .../process_statement_of_accounts.py | 9 +++-- .../test_process_statement_of_accounts.py | 37 ++++++++++++++++++- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py index cace9678336b..e487dcb5cee6 100644 --- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py +++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py @@ -371,7 +371,7 @@ def download_statements(document_name): @frappe.whitelist() -def send_emails(document_name, from_scheduler=False): +def send_emails(document_name, from_scheduler=False, posting_date=None): doc = frappe.get_doc("Process Statement Of Accounts", document_name) report = get_report_pdf(doc, consolidated=False) @@ -403,7 +403,7 @@ def send_emails(document_name, from_scheduler=False): ) if doc.enable_auto_email and from_scheduler: - new_to_date = getdate(today()) + new_to_date = getdate(posting_date or today()) if doc.frequency == "Weekly": new_to_date = add_days(new_to_date, 7) else: @@ -414,6 +414,8 @@ def send_emails(document_name, from_scheduler=False): ) doc.db_set("to_date", new_to_date, commit=True) doc.db_set("from_date", new_from_date, commit=True) + doc.db_set("posting_date", new_to_date, commit=True) + doc.db_set("report", doc.report, commit=True) return True else: return False @@ -423,7 +425,8 @@ def send_emails(document_name, from_scheduler=False): def send_auto_email(): selected = frappe.get_list( "Process Statement Of Accounts", - filters={"to_date": format_date(today()), "enable_auto_email": 1}, + filters={"enable_auto_email": 1}, + or_filters={"to_date": format_date(today()), "posting_date": format_date(today())}, ) for entry in selected: send_emails(entry.name, from_scheduler=True) diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/test_process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/test_process_statement_of_accounts.py index c281040aaf2d..fb0d8d152f00 100644 --- a/erpnext/accounts/doctype/process_statement_of_accounts/test_process_statement_of_accounts.py +++ b/erpnext/accounts/doctype/process_statement_of_accounts/test_process_statement_of_accounts.py @@ -1,9 +1,42 @@ # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors # See license.txt -# import frappe import unittest +import frappe +from frappe.utils import add_days, getdate, today + +from erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts import ( + send_emails, +) +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice + class TestProcessStatementOfAccounts(unittest.TestCase): - pass + def setUp(self): + self.si = create_sales_invoice() + self.process_soa = create_process_soa() + + def test_auto_email_for_process_soa_ar(self): + send_emails(self.process_soa.name, from_scheduler=True) + self.process_soa.load_from_db() + self.assertEqual(self.process_soa.posting_date, getdate(add_days(today(), 7))) + + def tearDown(self): + frappe.delete_doc_if_exists("Process Statement Of Accounts", "Test Process SOA") + + +def create_process_soa(): + frappe.delete_doc_if_exists("Process Statement Of Accounts", "Test Process SOA") + process_soa = frappe.new_doc("Process Statement Of Accounts") + soa_dict = { + "name": "Test Process SOA", + "company": "_Test Company", + } + process_soa.update(soa_dict) + process_soa.set("customers", [{"customer": "_Test Customer"}]) + process_soa.enable_auto_email = 1 + process_soa.frequency = "Weekly" + process_soa.report = "Accounts Receivable" + process_soa.save() + return process_soa From 060da2c5bc47300d8e7103af63626d0b53ce2807 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Tue, 29 Aug 2023 16:16:50 +0530 Subject: [PATCH 5/5] fix: remove report field db set --- .../process_statement_of_accounts.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py index e487dcb5cee6..786310326982 100644 --- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py +++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py @@ -412,10 +412,11 @@ def send_emails(document_name, from_scheduler=False, posting_date=None): doc.add_comment( "Comment", "Emails sent on: " + frappe.utils.format_datetime(frappe.utils.now()) ) - doc.db_set("to_date", new_to_date, commit=True) - doc.db_set("from_date", new_from_date, commit=True) - doc.db_set("posting_date", new_to_date, commit=True) - doc.db_set("report", doc.report, commit=True) + if doc.report == "General Ledger": + doc.db_set("to_date", new_to_date, commit=True) + doc.db_set("from_date", new_from_date, commit=True) + else: + doc.db_set("posting_date", new_to_date, commit=True) return True else: return False