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

Examples

\n\n\n" + "options": "
\n

Note

\n\n

Examples

\n\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..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 @@ -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) @@ -58,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]: @@ -70,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) @@ -141,6 +145,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, @@ -366,18 +371,20 @@ 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) 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) @@ -396,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: @@ -405,8 +412,11 @@ def send_emails(document_name, from_scheduler=False): 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) + 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 @@ -416,7 +426,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/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() }}

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