From 9fc1bd5141c61871b0ca6ad77ccdb8481bb5dc87 Mon Sep 17 00:00:00 2001 From: ljain112 Date: Fri, 17 Apr 2026 14:00:01 +0530 Subject: [PATCH] fix: add project filter to accounts payable and receivable reports (cherry picked from commit d51dbf5254561a2bc734c399205e556a10889b2a) # Conflicts: # erpnext/accounts/report/accounts_receivable/accounts_receivable.py --- .../accounts_payable/accounts_payable.js | 11 ++++++++++ .../accounts_payable/test_accounts_payable.py | 22 +++++++++++++++++++ .../accounts_payable_summary.js | 11 ++++++++++ .../accounts_receivable.js | 11 ++++++++++ .../accounts_receivable.py | 18 +++++++++++++++ .../test_accounts_receivable.py | 22 +++++++++++++++++++ .../accounts_receivable_summary.js | 11 ++++++++++ 7 files changed, 106 insertions(+) diff --git a/erpnext/accounts/report/accounts_payable/accounts_payable.js b/erpnext/accounts/report/accounts_payable/accounts_payable.js index c061b0c3902..5b8a9195d26 100644 --- a/erpnext/accounts/report/accounts_payable/accounts_payable.js +++ b/erpnext/accounts/report/accounts_payable/accounts_payable.js @@ -34,6 +34,17 @@ frappe.query_reports["Accounts Payable"] = { }, options: "Cost Center", }, + { + fieldname: "project", + label: __("Project"), + fieldtype: "MultiSelectList", + options: "Project", + get_data: function (txt) { + return frappe.db.get_link_options("Project", txt, { + company: frappe.query_report.get_filter_value("company"), + }); + }, + }, { fieldname: "party_account", label: __("Payable Account"), diff --git a/erpnext/accounts/report/accounts_payable/test_accounts_payable.py b/erpnext/accounts/report/accounts_payable/test_accounts_payable.py index 0c104f6f96e..545284d5edd 100644 --- a/erpnext/accounts/report/accounts_payable/test_accounts_payable.py +++ b/erpnext/accounts/report/accounts_payable/test_accounts_payable.py @@ -120,3 +120,25 @@ class TestAccountsPayable(AccountsTestMixin, FrappeTestCase): self.assertEqual(len(report[1]), 2) self.assertEqual([pi.name, payment_term1.payment_term_name], [row.voucher_no, row.payment_term]) + + def test_project_filter(self): + project = frappe.get_doc( + {"doctype": "Project", "project_name": "_Test AP Project", "company": self.company} + ).insert() + + pi = self.create_purchase_invoice(do_not_submit=True) + pi.project = project.name + pi.save().submit() + + filters = { + "company": self.company, + "report_date": today(), + "range": "30, 60, 90, 120", + "project": [project.name], + } + + report = execute(filters)[1] + self.assertEqual(len(report), 1) + row = report[0] + self.assertEqual(row.project, project.name) + self.assertEqual(row.invoiced, 300.0) diff --git a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js index a4cb0584bf1..3f603b62833 100644 --- a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js +++ b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js @@ -53,6 +53,17 @@ frappe.query_reports["Accounts Payable Summary"] = { }, options: "Cost Center", }, + { + fieldname: "project", + label: __("Project"), + fieldtype: "MultiSelectList", + options: "Project", + get_data: function (txt) { + return frappe.db.get_link_options("Project", txt, { + company: frappe.query_report.get_filter_value("company"), + }); + }, + }, { fieldname: "party_type", label: __("Party Type"), diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js index 4255568d1f9..02bb54abc79 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js @@ -36,6 +36,17 @@ frappe.query_reports["Accounts Receivable"] = { }, options: "Cost Center", }, + { + fieldname: "project", + label: __("Project"), + fieldtype: "MultiSelectList", + options: "Project", + get_data: function (txt) { + return frappe.db.get_link_options("Project", txt, { + company: frappe.query_report.get_filter_value("company"), + }); + }, + }, { fieldname: "party_type", label: __("Party Type"), diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index 831873055f1..053ca671806 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -194,6 +194,7 @@ class ReceivablePayableReport: and ple.against_voucher_type in self.advance_payment_doctypes ): self.voucher_balance[key].cost_center = ple.cost_center + self.voucher_balance[key].project = ple.project self.get_invoices(ple) @@ -360,6 +361,7 @@ class ReceivablePayableReport: posting_date, account_currency, cost_center, + project, sum(invoiced) `invoiced`, sum(paid) `paid`, sum(credit_note) `credit_note`, @@ -388,6 +390,7 @@ class ReceivablePayableReport: "credit_note_in_account_currency", "outstanding_in_account_currency", "cost_center", + "project", ]: _d[field] = x.get(field) @@ -925,6 +928,7 @@ class ReceivablePayableReport: ple.against_voucher_no, ple.party_type, ple.cost_center, + ple.project, ple.party, ple.posting_date, ple.due_date, @@ -992,6 +996,9 @@ class ReceivablePayableReport: if self.filters.cost_center: self.get_cost_center_conditions() + if self.filters.project: + self.qb_selection_filter.append(self.ple.project.isin(self.filters.project)) + self.add_accounting_dimensions_filters() def get_cost_center_conditions(self): @@ -1231,6 +1238,7 @@ class ReceivablePayableReport: ) self.add_column(label=_("Cost Center"), fieldname="cost_center", fieldtype="Data") + self.add_column(label=_("Project"), fieldname="project", fieldtype="Link", options="Project") self.add_column(label=_("Voucher Type"), fieldname="voucher_type", fieldtype="Data") self.add_column( label=_("Voucher No"), @@ -1403,6 +1411,7 @@ class InitSQLProceduresForAR: posting_date date, account_currency {_varchar_type}, cost_center {_varchar_type}, + project {_varchar_type}, invoiced {_currency_type}, paid {_currency_type}, credit_note {_currency_type}, @@ -1422,6 +1431,7 @@ class InitSQLProceduresForAR: against_voucher_no {_varchar_type}, party_type {_varchar_type}, cost_center {_varchar_type}, + project {_varchar_type}, party {_varchar_type}, posting_date date, due_date date, @@ -1450,7 +1460,11 @@ class InitSQLProceduresForAR: begin if not exists (select name from `{_voucher_balance_name}` where name = `{genkey_function_name}`(ple, false)) then +<<<<<<< HEAD insert into `{_voucher_balance_name}` values (`{genkey_function_name}`(ple, false), ple.voucher_type, ple.voucher_no, ple.party, ple.account, ple.posting_date, ple.account_currency, ple.cost_center, 0, 0, 0, 0, 0, 0); +======= + insert into `{_voucher_balance_name}` values (sha1(concat_ws(',', ple.account, ple.against_voucher_type, ple.against_voucher_no, ple.party)), ple.voucher_type, ple.voucher_no, ple.party, ple.account, ple.posting_date, ple.account_currency, ple.cost_center, ple.project, 0, 0, 0, 0, 0, 0); +>>>>>>> d51dbf5254 (fix: add project filter to accounts payable and receivable reports) end if; end; """ @@ -1492,7 +1506,11 @@ class InitSQLProceduresForAR: end if; +<<<<<<< HEAD insert into `{_voucher_balance_name}` values (`{genkey_function_name}`(ple, true), ple.against_voucher_type, ple.against_voucher_no, ple.party, ple.account, ple.posting_date, ple.account_currency,'', invoiced, paid, 0, invoiced_in_account_currency, paid_in_account_currency, 0); +======= + insert into `{_voucher_balance_name}` values (sha1(concat_ws(',', ple.account, ple.voucher_type, ple.voucher_no, ple.party)), ple.against_voucher_type, ple.against_voucher_no, ple.party, ple.account, ple.posting_date, ple.account_currency,'', '', invoiced, paid, 0, invoiced_in_account_currency, paid_in_account_currency, 0); +>>>>>>> d51dbf5254 (fix: add project filter to accounts payable and receivable reports) end; """ diff --git a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py index 88a3b818196..3959343ffbe 100644 --- a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py @@ -1204,3 +1204,25 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase): self.assertEqual(len(report[1]), 2) self.assertEqual([si.name, payment_term1.payment_term_name], [row.voucher_no, row.payment_term]) + + def test_project_filter(self): + project = frappe.get_doc( + {"doctype": "Project", "project_name": "_Test AR Project", "company": self.company} + ).insert() + + si = self.create_sales_invoice(no_payment_schedule=True, do_not_submit=True) + si.project = project.name + si.save().submit() + + filters = { + "company": self.company, + "report_date": today(), + "range": "30, 60, 90, 120", + "project": [project.name], + } + + report = execute(filters)[1] + self.assertEqual(len(report), 1) + row = report[0] + self.assertEqual(row.project, project.name) + self.assertEqual(row.invoiced, 100.0) diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js index c8e59d6e054..46585071174 100644 --- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js +++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js @@ -53,6 +53,17 @@ frappe.query_reports["Accounts Receivable Summary"] = { }, options: "Cost Center", }, + { + fieldname: "project", + label: __("Project"), + fieldtype: "MultiSelectList", + options: "Project", + get_data: function (txt) { + return frappe.db.get_link_options("Project", txt, { + company: frappe.query_report.get_filter_value("company"), + }); + }, + }, { fieldname: "party_type", label: __("Party Type"),