Apply User Permissions optional in script and query report, option to pass user in has_permission
This commit is contained in:
parent
1dc4968c3a
commit
2b2a608bab
16 changed files with 190 additions and 76 deletions
|
|
@ -291,9 +291,9 @@ def get_roles(username=None):
|
|||
else:
|
||||
return User(username).get_roles()
|
||||
|
||||
def has_permission(doctype, ptype="read", doc=None):
|
||||
def has_permission(doctype, ptype="read", doc=None, user=None):
|
||||
import frappe.permissions
|
||||
return frappe.permissions.has_permission(doctype, ptype, doc)
|
||||
return frappe.permissions.has_permission(doctype, ptype, doc, user=user)
|
||||
|
||||
def is_table(doctype):
|
||||
tables = cache().get_value("is_table")
|
||||
|
|
@ -573,13 +573,13 @@ def build_match_conditions(doctype, as_condition=True):
|
|||
|
||||
def get_list(doctype, filters=None, fields=None, or_filters=None, docstatus=None,
|
||||
group_by=None, order_by=None, limit_start=0, limit_page_length=None,
|
||||
as_list=False, debug=False, ignore_permissions=False):
|
||||
as_list=False, debug=False, ignore_permissions=False, user=None):
|
||||
import frappe.model.db_query
|
||||
return frappe.model.db_query.DatabaseQuery(doctype).execute(filters=filters,
|
||||
fields=fields, docstatus=docstatus, or_filters=or_filters,
|
||||
group_by=group_by, order_by=order_by, limit_start=limit_start,
|
||||
limit_page_length=limit_page_length, as_list=as_list, debug=debug,
|
||||
ignore_permissions=ignore_permissions)
|
||||
ignore_permissions=ignore_permissions, user=user)
|
||||
|
||||
run_query = get_list
|
||||
|
||||
|
|
|
|||
|
|
@ -27,14 +27,14 @@ def get_permission_query_conditions():
|
|||
"roles": "', '".join(frappe.get_roles(frappe.session.user))
|
||||
}
|
||||
|
||||
def has_permission(doc):
|
||||
if doc.event_type=="Public" or doc.owner==frappe.session.user:
|
||||
def has_permission(doc, user):
|
||||
if doc.event_type=="Public" or doc.owner==user:
|
||||
return True
|
||||
|
||||
if doc.get("event_individuals", {"person":frappe.session.user}):
|
||||
if doc.get("event_individuals", {"person": user}):
|
||||
return True
|
||||
|
||||
if doc.get("event_roles", {"role":("in", frappe.get_roles())}):
|
||||
if doc.get("event_roles", {"role":("in", frappe.get_roles(user))}):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
|
|
|||
|
|
@ -61,6 +61,15 @@
|
|||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"depends_on": "eval:[\"Query Report\", \"Script Report\"].indexOf(doc.report_type)!==-1",
|
||||
"fieldname": "apply_user_permissions",
|
||||
"fieldtype": "Check",
|
||||
"in_list_view": 0,
|
||||
"label": "Apply User Permissions",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_6",
|
||||
"fieldtype": "Section Break",
|
||||
|
|
@ -101,7 +110,7 @@
|
|||
],
|
||||
"icon": "icon-table",
|
||||
"idx": 1,
|
||||
"modified": "2014-05-27 03:49:17.001234",
|
||||
"modified": "2014-06-03 07:25:41.509885",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "Report",
|
||||
|
|
|
|||
|
|
@ -12,26 +12,26 @@ class Report(Document):
|
|||
"""only administrator can save standard report"""
|
||||
if not self.module:
|
||||
self.module = frappe.db.get_value("DocType", self.ref_doctype, "module")
|
||||
|
||||
|
||||
if not self.is_standard:
|
||||
self.is_standard = "No"
|
||||
if frappe.session.user=="Administrator" and getattr(conf, 'developer_mode',0)==1:
|
||||
self.is_standard = "Yes"
|
||||
|
||||
if self.is_standard == "Yes" and frappe.session.user!="Administrator":
|
||||
frappe.msgprint(_("Only Administrator can save a standard report. Please rename and save."),
|
||||
frappe.msgprint(_("Only Administrator can save a standard report. Please rename and save."),
|
||||
raise_exception=True)
|
||||
|
||||
if self.report_type in ("Query Report", "Script Report") \
|
||||
and frappe.session.user!="Administrator":
|
||||
frappe.msgprint(_("Only Administrator allowed to create Query / Script Reports"),
|
||||
raise_exception=True)
|
||||
|
||||
|
||||
def on_update(self):
|
||||
self.export_doc()
|
||||
|
||||
|
||||
def export_doc(self):
|
||||
from frappe.modules.export_file import export_to_files
|
||||
if self.is_standard == 'Yes' and (conf.get('developer_mode') or 0) == 1:
|
||||
export_to_files(record_list=[['Report', self.name]],
|
||||
export_to_files(record_list=[['Report', self.name]],
|
||||
record_module=self.module)
|
||||
|
|
|
|||
|
|
@ -14,24 +14,24 @@ class ToDo(Document):
|
|||
cur_status = frappe.db.get_value("ToDo", self.name, "status")
|
||||
if cur_status != self.status:
|
||||
self.add_comment(frappe._("Assignment Status Changed"))
|
||||
|
||||
|
||||
def add_comment(self, text):
|
||||
if not self.reference_type and self.reference_name:
|
||||
return
|
||||
|
||||
|
||||
comment = frappe.get_doc({
|
||||
"doctype":"Comment",
|
||||
"comment_by": frappe.session.user,
|
||||
"comment_doctype": self.reference_type,
|
||||
"comment_docname": self.reference_name,
|
||||
"comment": """<div>{text}:
|
||||
"comment": """<div>{text}:
|
||||
<a href='#Form/ToDo/{name}'>{status}: {description}</a></div>""".format(text=text,
|
||||
status = frappe._(self.status),
|
||||
name = self.name,
|
||||
description = self.description)
|
||||
}).insert(ignore_permissions=True)
|
||||
|
||||
|
||||
|
||||
|
||||
# todo is viewable if either owner or assigned_to or System Manager in roles
|
||||
|
||||
def get_permission_query_conditions():
|
||||
|
|
@ -39,10 +39,9 @@ def get_permission_query_conditions():
|
|||
return None
|
||||
else:
|
||||
return """(tabToDo.owner = '{user}' or tabToDo.assigned_by = '{user}')""".format(user=frappe.session.user)
|
||||
|
||||
def has_permission(doc):
|
||||
if "System Manager" in frappe.get_roles():
|
||||
|
||||
def has_permission(doc, user):
|
||||
if "System Manager" in frappe.get_roles(user):
|
||||
return True
|
||||
else:
|
||||
return doc.owner==frappe.session.user or doc.assigned_by==frappe.session.user
|
||||
|
||||
return doc.owner==user or doc.assigned_by==user
|
||||
|
|
|
|||
|
|
@ -475,14 +475,13 @@
|
|||
},
|
||||
{
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
"email": 1,
|
||||
"email": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"print": 0,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"report": 0,
|
||||
"role": "All",
|
||||
"submit": 0,
|
||||
"write": 0
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// MIT License. See license.txt
|
||||
|
||||
frappe.query_reports["Permitted Documents For User"] = {
|
||||
"filters": [
|
||||
{
|
||||
"fieldname": "user",
|
||||
"label": __("User"),
|
||||
"fieldtype": "Link",
|
||||
"options": "User",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "doctype",
|
||||
"label": __("DocType"),
|
||||
"fieldtype": "Link",
|
||||
"options": "DocType",
|
||||
"reqd": 1,
|
||||
"get_query": function() {
|
||||
return {
|
||||
"query": "frappe.core.report.permitted_documents_for_user.permitted_documents_for_user.query_doctypes",
|
||||
"filters": {
|
||||
"user": frappe.query_report.filters_by_name.user.get_value()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"apply_user_permissions": 1,
|
||||
"creation": "2014-06-03 05:20:35.218263",
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"is_standard": "Yes",
|
||||
"modified": "2014-06-03 07:18:17.218526",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "Permitted Documents For User",
|
||||
"owner": "Administrator",
|
||||
"ref_doctype": "User",
|
||||
"report_name": "Permitted Documents For User",
|
||||
"report_type": "Script Report"
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _, throw
|
||||
import frappe.utils.user
|
||||
from frappe.permissions import check_admin_or_system_manager
|
||||
|
||||
def execute(filters=None):
|
||||
user, doctype = filters.get("user"), filters.get("doctype")
|
||||
validate(user, doctype)
|
||||
|
||||
columns, fields = get_columns_and_fields(doctype)
|
||||
data = frappe.get_list(doctype, fields=fields, as_list=True, user=user)
|
||||
|
||||
return columns, data
|
||||
|
||||
def validate(user, doctype):
|
||||
# check if current user is System Manager
|
||||
check_admin_or_system_manager()
|
||||
|
||||
if not user:
|
||||
throw(_("Please specify user"))
|
||||
|
||||
if not doctype:
|
||||
throw(_("Please specify doctype"))
|
||||
|
||||
def get_columns_and_fields(doctype):
|
||||
columns = ["Name:Link/{}:200".format(doctype)]
|
||||
fields = ["name"]
|
||||
for df in frappe.get_meta(doctype).fields:
|
||||
if df.in_list_view:
|
||||
fields.append(df.fieldname)
|
||||
fieldtype = "Link/{}".format(df.options) if df.fieldtype=="Link" else df.fieldtype
|
||||
columns.append("{label}:{fieldtype}:{width}".format(label=df.label, fieldtype=fieldtype, width=df.width or 100))
|
||||
|
||||
return columns, fields
|
||||
|
||||
def query_doctypes(doctype, txt, searchfield, start, page_len, filters):
|
||||
user = filters.get("user")
|
||||
user_obj = frappe.utils.user.User(user)
|
||||
user_obj.build_permissions()
|
||||
can_read = user_obj.can_read
|
||||
|
||||
out = []
|
||||
for dt in can_read:
|
||||
if txt.lower().replace("%", "") in dt.lower():
|
||||
out.append([dt])
|
||||
|
||||
return out
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
{
|
||||
"creation": "2013-02-25 14:26:30.000000",
|
||||
"apply_user_permissions": 1,
|
||||
"creation": "2013-02-25 14:26:30",
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 1,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2014-03-07 15:30:27.000000",
|
||||
"modified": "2014-06-03 07:18:17.374222",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "ToDo",
|
||||
|
|
|
|||
|
|
@ -17,12 +17,13 @@ class DatabaseQuery(object):
|
|||
self.conditions = []
|
||||
self.ignore_permissions = False
|
||||
self.fields = ["name"]
|
||||
self.user = None
|
||||
|
||||
def execute(self, query=None, filters=None, fields=None, or_filters=None,
|
||||
docstatus=None, group_by=None, order_by=None, limit_start=0,
|
||||
limit_page_length=20, as_list=False, with_childnames=False, debug=False,
|
||||
ignore_permissions=False):
|
||||
if not frappe.has_permission(self.doctype, "read"):
|
||||
ignore_permissions=False, user=None):
|
||||
if not frappe.has_permission(self.doctype, "read", user=user):
|
||||
raise frappe.PermissionError
|
||||
|
||||
if fields:
|
||||
|
|
@ -38,7 +39,7 @@ class DatabaseQuery(object):
|
|||
self.debug = debug
|
||||
self.as_list = as_list
|
||||
self.ignore_permissions = ignore_permissions
|
||||
|
||||
self.user = user or frappe.session.user
|
||||
|
||||
if query:
|
||||
return self.run_custom_query(query)
|
||||
|
|
@ -216,10 +217,10 @@ class DatabaseQuery(object):
|
|||
if not self.tables: self.extract_tables()
|
||||
|
||||
# apply user permissions?
|
||||
role_permissions = frappe.permissions.get_role_permissions(frappe.get_meta(self.doctype))
|
||||
role_permissions = frappe.permissions.get_role_permissions(frappe.get_meta(self.doctype), user=self.user)
|
||||
if role_permissions.get("apply_user_permissions", {}).get("read"):
|
||||
# get user permissions
|
||||
user_permissions = frappe.defaults.get_user_permissions()
|
||||
user_permissions = frappe.defaults.get_user_permissions(self.user)
|
||||
self.add_user_permissions(user_permissions)
|
||||
|
||||
if as_condition:
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ execute:frappe.reload_doc('core', 'doctype', 'doctype', force=True) #2014-01-24
|
|||
execute:frappe.reload_doc('core', 'doctype', 'docfield', force=True) #2014-03-01
|
||||
execute:frappe.reload_doc('core', 'doctype', 'docperm') #2013-13-26
|
||||
execute:frappe.reload_doc('core', 'doctype', 'page') #2013-13-26
|
||||
execute:frappe.reload_doc('core', 'doctype', 'report') #2013-13-26
|
||||
execute:frappe.reload_doc('core', 'doctype', 'report') #2014-06-03
|
||||
execute:frappe.reload_doc('core', 'doctype', 'version') #2014-02-21
|
||||
execute:frappe.db.sql("alter table `tabSessions` modify `user` varchar(255), engine=InnoDB")
|
||||
execute:frappe.db.sql("delete from `tabDocField` where parent='0'")
|
||||
|
|
@ -33,3 +33,4 @@ frappe.patches.v4_0.update_custom_field_insert_after
|
|||
frappe.patches.v4_0.set_user_permissions
|
||||
frappe.patches.v4_0.create_custom_field_for_owner_match
|
||||
frappe.patches.v4_0.enable_scheduler_in_system_settings
|
||||
execute:frappe.db.sql("update tabReport set apply_user_permissions=1") #2014-06-03
|
||||
|
|
|
|||
|
|
@ -9,13 +9,16 @@ from frappe.utils import cint
|
|||
rights = ("read", "write", "create", "delete", "submit", "cancel", "amend",
|
||||
"print", "email", "report", "import", "export", "set_user_permissions")
|
||||
|
||||
def check_admin_or_system_manager():
|
||||
if ("System Manager" not in frappe.get_roles()) and \
|
||||
(frappe.session.user!="Administrator"):
|
||||
def check_admin_or_system_manager(user=None):
|
||||
if not user: user = frappe.session.user
|
||||
|
||||
if ("System Manager" not in frappe.get_roles(user)) and (user!="Administrator"):
|
||||
frappe.throw(_("Not permitted"), frappe.PermissionError)
|
||||
|
||||
def has_permission(doctype, ptype="read", doc=None, verbose=True):
|
||||
def has_permission(doctype, ptype="read", doc=None, verbose=True, user=None):
|
||||
"""check if user has permission"""
|
||||
if not user: user = frappe.session.user
|
||||
|
||||
if frappe.is_table(doctype):
|
||||
return True
|
||||
|
||||
|
|
@ -27,10 +30,10 @@ def has_permission(doctype, ptype="read", doc=None, verbose=True):
|
|||
if ptype=="import" and not cint(meta.allow_import):
|
||||
return False
|
||||
|
||||
if frappe.session.user=="Administrator":
|
||||
if user=="Administrator":
|
||||
return True
|
||||
|
||||
role_permissions = get_role_permissions(meta)
|
||||
role_permissions = get_role_permissions(meta, user=user)
|
||||
if not role_permissions.get(ptype):
|
||||
return False
|
||||
|
||||
|
|
@ -38,17 +41,16 @@ def has_permission(doctype, ptype="read", doc=None, verbose=True):
|
|||
if isinstance(doc, basestring):
|
||||
doc = frappe.get_doc(meta.name, doc)
|
||||
|
||||
if not user_has_permission(doc, verbose=verbose):
|
||||
if not user_has_permission(doc, verbose=verbose, user=user):
|
||||
return False
|
||||
|
||||
if not has_controller_permissions(doc):
|
||||
if not has_controller_permissions(doc, user=user):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def get_role_permissions(meta, user=None):
|
||||
if not user:
|
||||
user = frappe.session.user
|
||||
if not user: user = frappe.session.user
|
||||
cache_key = (meta.name, user)
|
||||
|
||||
if not frappe.local.role_permissions.get(cache_key):
|
||||
|
|
@ -71,9 +73,9 @@ def get_role_permissions(meta, user=None):
|
|||
|
||||
return frappe.local.role_permissions[cache_key]
|
||||
|
||||
def user_has_permission(doc, verbose=True):
|
||||
def user_has_permission(doc, verbose=True, user=None):
|
||||
from frappe.defaults import get_user_permissions
|
||||
user_permissions = get_user_permissions()
|
||||
user_permissions = get_user_permissions(user)
|
||||
user_permissions_keys = user_permissions.keys()
|
||||
|
||||
def check_user_permission(d):
|
||||
|
|
@ -99,9 +101,11 @@ def user_has_permission(doc, verbose=True):
|
|||
|
||||
return _user_has_permission
|
||||
|
||||
def has_controller_permissions(doc):
|
||||
def has_controller_permissions(doc, user=None):
|
||||
if not user: user = frappe.session.user
|
||||
|
||||
for method in frappe.get_hooks("has_permission").get(doc.doctype, []):
|
||||
if not frappe.call(frappe.get_attr(method), doc=doc):
|
||||
if not frappe.call(frappe.get_attr(method), doc=doc, user=user):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -894,7 +894,11 @@ frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({
|
|||
select: function(event, ui) {
|
||||
me.autocomplete_open = false;
|
||||
if(ui.item.make_new) {
|
||||
me.frm.new_doc(me.df.options, me);
|
||||
if (me.frm) {
|
||||
me.frm.new_doc(me.df.options, me);
|
||||
} else {
|
||||
new_doc(me.df.options);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,58 +16,58 @@ def get_report_doc(report_name):
|
|||
doc = frappe.get_doc("Report", report_name)
|
||||
if not doc.has_permission("read"):
|
||||
raise frappe.PermissionError("You don't have access to: {report}".format(report=report_name))
|
||||
|
||||
|
||||
if not frappe.has_permission(doc.ref_doctype, "report"):
|
||||
raise frappe.PermissionError("You don't have access to get a report on: {doctype}".format(
|
||||
doctype=doc.ref_doctype))
|
||||
|
||||
|
||||
return doc
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_script(report_name):
|
||||
report = get_report_doc(report_name)
|
||||
|
||||
|
||||
module = frappe.db.get_value("DocType", report.ref_doctype, "module")
|
||||
module_path = get_module_path(module)
|
||||
report_folder = os.path.join(module_path, "report", scrub(report.name))
|
||||
script_path = os.path.join(report_folder, scrub(report.name) + ".js")
|
||||
|
||||
|
||||
script = None
|
||||
if os.path.exists(script_path):
|
||||
with open(script_path, "r") as script:
|
||||
script = script.read()
|
||||
|
||||
|
||||
if not script and report.javascript:
|
||||
script = report.javascript
|
||||
|
||||
|
||||
if not script:
|
||||
script = "frappe.query_reports['%s']={}" % report_name
|
||||
|
||||
|
||||
# load translations
|
||||
if frappe.lang != "en":
|
||||
frappe.response["__messages"] = frappe.get_lang_dict("report", report_name)
|
||||
|
||||
|
||||
return script
|
||||
|
||||
@frappe.whitelist()
|
||||
def run(report_name, filters=()):
|
||||
report = get_report_doc(report_name)
|
||||
|
||||
|
||||
if filters and isinstance(filters, basestring):
|
||||
filters = json.loads(filters)
|
||||
|
||||
if not frappe.has_permission(report.ref_doctype, "report"):
|
||||
frappe.msgprint(_("Must have report permission to access this report."),
|
||||
frappe.msgprint(_("Must have report permission to access this report."),
|
||||
raise_exception=True)
|
||||
|
||||
|
||||
if report.report_type=="Query Report":
|
||||
if not report.query:
|
||||
frappe.msgprint(_("Must specify a Query to run"), raise_exception=True)
|
||||
|
||||
|
||||
|
||||
|
||||
if not report.query.lower().startswith("select"):
|
||||
frappe.msgprint(_("Query must be a SELECT"), raise_exception=True)
|
||||
|
||||
|
||||
result = [list(t) for t in frappe.db.sql(report.query, filters)]
|
||||
columns = [c[0] for c in frappe.db.get_description()]
|
||||
else:
|
||||
|
|
@ -76,17 +76,18 @@ def run(report_name, filters=()):
|
|||
method_name = frappe.local.module_app[scrub(module)] + "." + scrub(module) \
|
||||
+ ".report." + scrub(report.name) + "." + scrub(report.name) + ".execute"
|
||||
columns, result = frappe.get_attr(method_name)(frappe._dict(filters))
|
||||
|
||||
result = get_filtered_data(report.ref_doctype, columns, result)
|
||||
|
||||
|
||||
if report.apply_user_permissions:
|
||||
result = get_filtered_data(report.ref_doctype, columns, result)
|
||||
|
||||
if cint(report.add_total_row) and result:
|
||||
result = add_total_row(result, columns)
|
||||
|
||||
|
||||
return {
|
||||
"result": result,
|
||||
"columns": columns
|
||||
}
|
||||
|
||||
|
||||
def add_total_row(result, columns):
|
||||
total_row = [""]*len(columns)
|
||||
has_percent = []
|
||||
|
|
@ -98,14 +99,14 @@ def add_total_row(result, columns):
|
|||
total_row[i] = flt(total_row[i]) + flt(row[i])
|
||||
if col[1] == "Percent" and i not in has_percent:
|
||||
has_percent.append(i)
|
||||
|
||||
|
||||
for i in has_percent:
|
||||
total_row[i] = total_row[i] / len(result)
|
||||
|
||||
|
||||
first_col = columns[0].split(":")
|
||||
if len(first_col) > 1 and first_col[1] not in ["Currency", "Int", "Float", "Percent"]:
|
||||
total_row[0] = "Total"
|
||||
|
||||
|
||||
result.append(total_row)
|
||||
return result
|
||||
|
||||
|
|
@ -114,12 +115,12 @@ def get_filtered_data(ref_doctype, columns, data):
|
|||
|
||||
linked_doctypes = get_linked_doctypes(columns)
|
||||
match_filters = get_user_match_filters(linked_doctypes, ref_doctype)
|
||||
|
||||
|
||||
if match_filters:
|
||||
matched_columns = get_matched_columns(linked_doctypes, match_filters)
|
||||
for row in data:
|
||||
match = True
|
||||
|
||||
|
||||
if not ("owner" in match_filters and matched_columns.get("user", None)==match_filters["owner"]):
|
||||
for col, idx in matched_columns.items():
|
||||
if row[idx] not in match_filters[col]:
|
||||
|
|
@ -165,4 +166,4 @@ def get_matched_columns(linked_doctypes, match_filters):
|
|||
if link_field in match_filters:
|
||||
col_idx_map[link_field] = idx
|
||||
|
||||
return col_idx_map
|
||||
return col_idx_map
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue