fix(accounts receivable): made territory field multi select (backport #57322) (#57346)

fix(accounts receivable): made territory field multi select (#57322)

(cherry picked from commit 1029cd988a)

Co-authored-by: Jatin3128 <140256508+Jatin3128@users.noreply.github.com>
This commit is contained in:
mergify[bot]
2026-07-31 14:41:15 +05:30
committed by GitHub
parent c0ac8aaf86
commit 9b452f12b7
7 changed files with 104 additions and 31 deletions

View File

@@ -117,8 +117,11 @@ frappe.query_reports["Accounts Payable"] = {
{
fieldname: "supplier_group",
label: __("Supplier Group"),
fieldtype: "Link",
fieldtype: "MultiSelectList",
options: "Supplier Group",
get_data: function (txt) {
return frappe.db.get_link_options("Supplier Group", txt);
},
hidden: 1,
},
{

View File

@@ -117,6 +117,36 @@ class TestAccountsPayable(ERPNextTestSuite, AccountsTestMixin):
self.assertEqual(len(report[1]), 2)
self.assertEqual([pi.name, payment_term1.payment_term_name], [row.voucher_no, row.payment_term])
def test_supplier_group_filter(self):
pi = self.create_purchase_invoice()
supplier_group = frappe.db.get_value("Supplier", self.supplier, "supplier_group")
other_group = frappe.get_doc(
doctype="Supplier Group",
supplier_group_name="_Test Supplier Group AP",
parent_supplier_group="All Supplier Groups",
).insert()
filters = {
"company": self.company,
"party_type": "Supplier",
"report_date": today(),
"range": "30, 60, 90, 120",
"supplier_group": supplier_group,
}
self.assertIn(pi.name, [row.voucher_no for row in execute(filters)[1]])
filters.update({"supplier_group": [other_group.name]})
self.assertEqual(len(execute(filters)[1]), 0)
filters.update({"supplier_group": [supplier_group, other_group.name]})
self.assertIn(pi.name, [row.voucher_no for row in execute(filters)[1]])
filters.update({"supplier_group": ["All Supplier Groups"]})
self.assertIn(pi.name, [row.voucher_no for row in execute(filters)[1]])
filters.update({"supplier_group": ["_Test Supplier Group Mars"]})
self.assertRaises(frappe.ValidationError, execute, filters)
def test_project_filter(self):
project = frappe.get_doc(
{"doctype": "Project", "project_name": "_Test AP Project", "company": self.company}

View File

@@ -100,8 +100,11 @@ frappe.query_reports["Accounts Payable Summary"] = {
{
fieldname: "supplier_group",
label: __("Supplier Group"),
fieldtype: "Link",
fieldtype: "MultiSelectList",
options: "Supplier Group",
get_data: function (txt) {
return frappe.db.get_link_options("Supplier Group", txt);
},
},
{
fieldname: "based_on_payment_terms",

View File

@@ -140,8 +140,11 @@ frappe.query_reports["Accounts Receivable"] = {
{
fieldname: "territory",
label: __("Territory"),
fieldtype: "Link",
fieldtype: "MultiSelectList",
options: "Territory",
get_data: function (txt) {
return frappe.db.get_link_options("Territory", txt);
},
},
{
fieldname: "group_by_party",

View File

@@ -1019,7 +1019,13 @@ class ReceivablePayableReport:
self.qb_selection_filter.append(self.ple.party.isin(customers))
if self.filters.get("territory"):
self.get_hierarchical_filters("Territory", "territory")
territories = get_nested_set_children("Territory", self.filters.territory)
customers = (
qb.from_(self.customer)
.select(self.customer.name)
.where(self.customer["territory"].isin(territories))
)
self.qb_selection_filter.append(self.ple.party.isin(customers))
if self.filters.get("payment_terms_template"):
customer_ptt = self.ple.party.isin(
@@ -1040,11 +1046,10 @@ class ReceivablePayableReport:
def add_supplier_filters(self):
supplier = qb.DocType("Supplier")
if self.filters.get("supplier_group"):
groups = get_party_group_with_children("Supplier", self.filters.supplier_group)
self.qb_selection_filter.append(
self.ple.party.isin(
qb.from_(supplier)
.select(supplier.name)
.where(supplier.supplier_group == self.filters.get("supplier_group"))
qb.from_(supplier).select(supplier.name).where(supplier.supplier_group.isin(groups))
)
)
@@ -1096,16 +1101,6 @@ class ReceivablePayableReport:
return ptt
def get_hierarchical_filters(self, doctype, key):
lft, rgt = frappe.db.get_value(doctype, self.filters.get(key), ["lft", "rgt"])
doc = qb.DocType(doctype)
ple = self.ple
customer = self.customer
groups = qb.from_(doc).select(doc.name).where((doc.lft >= lft) & (doc.rgt <= rgt))
customers = qb.from_(customer).select(customer.name).where(customer[key].isin(groups))
self.qb_selection_filter.append(ple.party.isin(customers))
def add_accounting_dimensions_filters(self):
accounting_dimensions = get_accounting_dimensions(as_list=False)
@@ -1349,19 +1344,23 @@ def get_party_group_with_children(party, party_groups):
if party not in ("Customer", "Supplier"):
return []
group_dtype = f"{party} Group"
if not isinstance(party_groups, list):
party_groups = [d.strip() for d in party_groups.strip().split(",") if d]
return get_nested_set_children(f"{party} Group", party_groups)
all_party_groups = []
for d in party_groups:
if frappe.db.exists(group_dtype, d):
lft, rgt = frappe.db.get_value(group_dtype, d, ["lft", "rgt"])
children = frappe.get_all(
group_dtype, filters={"lft": [">=", lft], "rgt": ["<=", rgt]}, pluck="name"
)
all_party_groups += children
def get_nested_set_children(doctype, values):
if not isinstance(values, list):
values = [d.strip() for d in values.split(",") if d.strip()]
if not values:
frappe.throw(_("Please select a valid {0}").format(_(doctype)))
all_values = []
for d in values:
if frappe.db.exists(doctype, d):
lft, rgt = frappe.db.get_value(doctype, d, ["lft", "rgt"])
children = frappe.get_all(doctype, filters={"lft": [">=", lft], "rgt": ["<=", rgt]}, pluck="name")
all_values += children
else:
frappe.throw(_("{0}: {1} does not exist").format(group_dtype, d))
frappe.throw(_("{0}: {1} does not exist").format(doctype, d))
return list(set(all_party_groups))
return list(set(all_values))

View File

@@ -779,6 +779,38 @@ class TestAccountsReceivable(ERPNextTestSuite, AccountsTestMixin):
# Assert that the customer group of each row is in the list of customer groups
self.assertIn(row.customer_group, cus_groups_list)
def test_territory_filter(self):
self.create_sales_invoice()
territory = frappe.db.get_value("Customer", self.customer, "territory")
filters = {
"company": self.company,
"report_date": today(),
"range": "30, 60, 90, 120",
"territory": territory,
}
report = execute(filters)[1]
self.assertEqual(len(report), 1)
self.assertEqual(
[100.0, 100.0, territory], [report[0].invoiced, report[0].outstanding, report[0].territory]
)
filters.update({"territory": ["_Test Territory United States"]})
self.assertEqual(len(execute(filters)[1]), 0)
filters.update({"territory": [territory, "_Test Territory United States"]})
self.assertEqual(len(execute(filters)[1]), 1)
frappe.db.set_value("Customer", self.customer, "territory", "_Test Territory Maharashtra")
filters.update({"territory": ["_Test Territory India"]})
self.assertEqual(len(execute(filters)[1]), 1)
filters.update({"territory": ["_Test Territory Mars"]})
self.assertRaises(frappe.ValidationError, execute, filters)
filters.update({"territory": " "})
self.assertRaises(frappe.ValidationError, execute, filters)
def test_party_account_filter(self):
si1 = self.create_sales_invoice()
jane = frappe.get_doc(

View File

@@ -106,8 +106,11 @@ frappe.query_reports["Accounts Receivable Summary"] = {
{
fieldname: "territory",
label: __("Territory"),
fieldtype: "Link",
fieldtype: "MultiSelectList",
options: "Territory",
get_data: function (txt) {
return frappe.db.get_link_options("Territory", txt);
},
},
{
fieldname: "sales_partner",