mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-14 15:11:52 +00:00
fix: apply Sales Person user permissions in Accounts Receivable
The report only narrowed by sales person when the filter was set, so a user
restricted to a Sales Person saw every row once the filter was cleared.
Resolve the permitted Sales Persons from user permissions and apply them on
top of the filter. Each Sales Team parent type is matched against its own
applicable_for scope, so a permission scoped to one doctype cannot authorise
rows through the other. Descendants are already expanded by
get_user_permissions, so Hide Descendants is respected. Gated to Receivable,
since the class is shared with Accounts Payable.
(cherry picked from commit 8b09ba429e)
# Conflicts:
# erpnext/accounts/report/accounts_receivable/accounts_receivable.py
This commit is contained in:
@@ -6,7 +6,11 @@ from collections import OrderedDict
|
||||
|
||||
import frappe
|
||||
from frappe import _, qb, query_builder, scrub
|
||||
<<<<<<< HEAD
|
||||
from frappe.database.schema import get_definition
|
||||
=======
|
||||
from frappe.permissions import get_allowed_docs_for_doctype
|
||||
>>>>>>> 8b09ba429e (fix: apply Sales Person user permissions in Accounts Receivable)
|
||||
from frappe.query_builder import Criterion
|
||||
from frappe.query_builder.functions import Date, Substring, Sum
|
||||
from frappe.utils import cint, cstr, flt, getdate, nowdate
|
||||
@@ -52,6 +56,7 @@ class ReceivablePayableReport:
|
||||
self.filters = frappe._dict(filters or {})
|
||||
self.qb_selection_filter = []
|
||||
self.ple = qb.DocType("Payment Ledger Entry")
|
||||
self.sales_person_records = None
|
||||
self.filters.report_date = getdate(self.filters.report_date or nowdate())
|
||||
self.age_as_on = (
|
||||
getdate(nowdate())
|
||||
@@ -92,6 +97,7 @@ class ReceivablePayableReport:
|
||||
self.party_type = get_party_types_from_account_type(self.account_type)
|
||||
self.party_details = {}
|
||||
self.invoices = set()
|
||||
self.sales_person_records = None
|
||||
self.skip_total_row = 0
|
||||
self.advance_payment_doctypes = get_advance_payment_doctypes()
|
||||
|
||||
@@ -206,7 +212,7 @@ class ReceivablePayableReport:
|
||||
|
||||
def get_invoices(self, ple):
|
||||
if ple.voucher_type in ("Sales Invoice", "Purchase Invoice"):
|
||||
if self.filters.get("sales_person"):
|
||||
if self.sales_person_records is not None:
|
||||
if ple.voucher_no in self.sales_person_records.get(
|
||||
"Sales Invoice", []
|
||||
) or ple.party in self.sales_person_records.get("Customer", []):
|
||||
@@ -237,7 +243,7 @@ class ReceivablePayableReport:
|
||||
]
|
||||
|
||||
def get_voucher_balance(self, ple):
|
||||
if self.filters.get("sales_person"):
|
||||
if self.sales_person_records is not None:
|
||||
if not (
|
||||
ple.party in self.sales_person_records.get("Customer", [])
|
||||
or ple.against_voucher_no in self.sales_person_records.get("Sales Invoice", [])
|
||||
@@ -896,9 +902,37 @@ class ReceivablePayableReport:
|
||||
|
||||
self.ple_query = query
|
||||
|
||||
def get_permitted_sales_persons(self, parenttype):
|
||||
if self.account_type != "Receivable":
|
||||
return None
|
||||
|
||||
permissions = frappe.permissions.get_user_permissions(frappe.session.user).get("Sales Person", [])
|
||||
if not permissions:
|
||||
return None
|
||||
|
||||
return get_allowed_docs_for_doctype(permissions, parenttype)
|
||||
|
||||
def get_sales_invoices_or_customers_based_on_sales_person(self):
|
||||
parenttypes = ["Customer", "Sales Invoice"]
|
||||
permitted = {p: self.get_permitted_sales_persons(p) for p in parenttypes}
|
||||
|
||||
if not (self.filters.get("sales_person") or any(p is not None for p in permitted.values())):
|
||||
return
|
||||
|
||||
steam = frappe.qb.DocType("Sales Team")
|
||||
|
||||
scope = []
|
||||
for parenttype in parenttypes:
|
||||
criterion = steam.parenttype == parenttype
|
||||
if (allowed := permitted[parenttype]) is not None:
|
||||
criterion &= steam.sales_person.isin(allowed or [""])
|
||||
scope.append(criterion)
|
||||
|
||||
conditions = [Criterion.any(scope)]
|
||||
|
||||
if self.filters.get("sales_person"):
|
||||
lft, rgt = frappe.db.get_value("Sales Person", self.filters.get("sales_person"), ["lft", "rgt"])
|
||||
<<<<<<< HEAD
|
||||
|
||||
# nosemgrep
|
||||
records = frappe.db.sql(
|
||||
@@ -910,11 +944,26 @@ class ReceivablePayableReport:
|
||||
""",
|
||||
(lft, rgt),
|
||||
as_dict=1,
|
||||
=======
|
||||
sp = frappe.qb.DocType("Sales Person")
|
||||
conditions.append(
|
||||
steam.sales_person.isin(
|
||||
frappe.qb.from_(sp).select(sp.name).where((sp.lft >= lft) & (sp.rgt <= rgt))
|
||||
)
|
||||
>>>>>>> 8b09ba429e (fix: apply Sales Person user permissions in Accounts Receivable)
|
||||
)
|
||||
|
||||
self.sales_person_records = frappe._dict()
|
||||
for d in records:
|
||||
self.sales_person_records.setdefault(d.parenttype, set()).add(d.parent)
|
||||
records = (
|
||||
frappe.qb.from_(steam)
|
||||
.select(steam.parent, steam.parenttype)
|
||||
.distinct()
|
||||
.where(Criterion.all(conditions))
|
||||
.run(as_dict=1)
|
||||
)
|
||||
|
||||
self.sales_person_records = frappe._dict()
|
||||
for d in records:
|
||||
self.sales_person_records.setdefault(d.parenttype, set()).add(d.parent)
|
||||
|
||||
def get_invoices_based_on_sales_partner(self):
|
||||
if not self.filters.get("sales_partner"):
|
||||
|
||||
Reference in New Issue
Block a user