diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 5bf383baf5..1a5b81d847 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -48,6 +48,7 @@ doc_events = {
"on_cancel": "erpnext.stock.doctype.material_request.material_request.update_completed_qty"
},
"User": {
+ "validate": "erpnext.hr.doctype.employee.employee.validate_employee_role",
"on_update": "erpnext.hr.doctype.employee.employee.update_user_permissions"
}
}
diff --git a/erpnext/hr/doctype/employee/employee.py b/erpnext/hr/doctype/employee/employee.py
index 0a4ae03182..b58a300fc0 100644
--- a/erpnext/hr/doctype/employee/employee.py
+++ b/erpnext/hr/doctype/employee/employee.py
@@ -55,7 +55,7 @@ class Employee(Document):
frappe.permissions.set_user_permission_if_allowed("Company", self.company, self.user_id)
def update_leave_approver_user_permissions(self):
- """restrict to this employee for leave approver"""
+ """add employee user permission for leave approver"""
employee_leave_approvers = [d.leave_approver for d in self.get("employee_leave_approvers")]
if self.reports_to and self.reports_to not in employee_leave_approvers:
employee_leave_approvers.append(frappe.db.get_value("Employee", self.reports_to, "user_id"))
@@ -204,13 +204,15 @@ def make_salary_structure(source_name, target=None):
target.make_earn_ded_table()
return target
-def update_user_permissions(doc, method):
+def validate_employee_role(doc, method):
# called via User hook
-
if "Employee" in [d.role for d in doc.get("user_roles")]:
- try:
- employee = frappe.get_doc("Employee", {"user_id": doc.name})
- employee.update_user_permissions()
- except frappe.DoesNotExistError:
+ if not frappe.db.get_value("Employee", {"user_id": doc.name}):
frappe.msgprint("Please set User ID field in an Employee record to set Employee Role")
doc.get("user_roles").remove(doc.get("user_roles", {"role": "Employee"})[0])
+
+def update_user_permissions(doc, method):
+ # called via User hook
+ if "Employee" in [d.role for d in doc.get("user_roles")]:
+ employee = frappe.get_doc("Employee", {"user_id": doc.name})
+ employee.update_user_permissions()
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 7694d549f2..e5e9e0ad15 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -2,10 +2,10 @@ execute:import unidecode # new requirement
erpnext.patches.v4_0.validate_v3_patch
erpnext.patches.v4_0.fix_employee_user_id
+erpnext.patches.v4_0.remove_employee_role_if_no_employee
erpnext.patches.v4_0.update_user_properties
+erpnext.patches.v4_0.apply_user_permissions
erpnext.patches.v4_0.move_warehouse_user_to_restrictions
-execute:frappe.delete_doc_if_exists("DocType", "Warehouse User")
-erpnext.patches.v4_0.new_permissions
erpnext.patches.v4_0.global_defaults_to_system_settings
erpnext.patches.v4_0.update_incharge_name_to_sales_person_in_maintenance_schedule
execute:frappe.reload_doc('accounts', 'doctype', 'sales_invoice') # 2014-01-29
diff --git a/erpnext/patches/v4_0/apply_user_permissions.py b/erpnext/patches/v4_0/apply_user_permissions.py
new file mode 100644
index 0000000000..7f5b951696
--- /dev/null
+++ b/erpnext/patches/v4_0/apply_user_permissions.py
@@ -0,0 +1,45 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+ update_hr_permissions()
+ update_permissions()
+ remove_duplicate_user_permissions()
+ frappe.clear_cache()
+
+def update_hr_permissions():
+ from frappe.core.page.user_permissions import user_permissions
+
+ # add set user permissions rights to HR Manager
+ frappe.db.sql("""update `tabDocPerm` set `set_user_permissions`=1 where parent in ('Employee', 'Leave Application')
+ and role='HR Manager' and permlevel=0 and `read`=1""")
+
+ # apply user permissions on Employee and Leave Application
+ frappe.db.sql("""update `tabDocPerm` set `apply_user_permissions`=1 where parent in ('Employee', 'Leave Application')
+ and role in ('Employee', 'Leave Approver') and permlevel=0 and `read`=1""")
+
+ frappe.clear_cache()
+
+ # save employees to run on_update events
+ for employee in frappe.db.sql_list("""select name from `tabEmployee`"""):
+ frappe.get_doc("Employee", employee).save()
+
+def update_permissions():
+ # clear match conditions other than owner
+ frappe.db.sql("""update tabDocPerm set `match`=''
+ where ifnull(`match`,'') not in ('', 'owner')""")
+
+def remove_duplicate_user_permissions():
+ # remove duplicate user_permissions (if they exist)
+ for d in frappe.db.sql("""select parent, defkey, defvalue,
+ count(*) as cnt from tabDefaultValue
+ where parent not in ('__global', '__default')
+ group by parent, defkey, defvalue""", as_dict=1):
+ if d.cnt > 1:
+ # order by parenttype so that user permission does not get removed!
+ frappe.db.sql("""delete from tabDefaultValue where `parent`=%s and `defkey`=%s and
+ `defvalue`=%s order by parenttype limit %s""", (d.parent, d.defkey, d.defvalue, d.cnt-1))
+
diff --git a/erpnext/patches/v4_0/move_warehouse_user_to_restrictions.py b/erpnext/patches/v4_0/move_warehouse_user_to_restrictions.py
index 64d53477a7..35b3c8661d 100644
--- a/erpnext/patches/v4_0/move_warehouse_user_to_restrictions.py
+++ b/erpnext/patches/v4_0/move_warehouse_user_to_restrictions.py
@@ -3,11 +3,11 @@
from __future__ import unicode_literals
import frappe
+import frappe.permissions
def execute():
- from frappe.core.page.user_permissions import user_permissions
for warehouse, user in frappe.db.sql("""select parent, user from `tabWarehouse User`"""):
- user_permissions.add(user, "Warehouse", warehouse)
-
- frappe.delete_doc("DocType", "Warehouse User")
- frappe.reload_doc("stock", "doctype", "warehouse")
\ No newline at end of file
+ frappe.permissions.add_user_permission("Warehouse", warehouse, user)
+
+ frappe.delete_doc_if_exists("DocType", "Warehouse User")
+ frappe.reload_doc("stock", "doctype", "warehouse")
diff --git a/erpnext/patches/v4_0/new_permissions.py b/erpnext/patches/v4_0/new_permissions.py
deleted file mode 100644
index 2b87437dd8..0000000000
--- a/erpnext/patches/v4_0/new_permissions.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # reset Page perms
- from frappe.core.page.permission_manager.permission_manager import reset
- reset("Page")
- reset("Report")
-
- # patch to move print, email into DocPerm
- for doctype, hide_print, hide_email in frappe.db.sql("""select name, ifnull(allow_print, 0), ifnull(allow_email, 0)
- from `tabDocType` where ifnull(issingle, 0)=0 and ifnull(istable, 0)=0 and
- (ifnull(allow_print, 0)=0 or ifnull(allow_email, 0)=0)"""):
-
- if not hide_print:
- frappe.db.sql("""update `tabDocPerm` set `print`=1
- where permlevel=0 and `read`=1 and parent=%s""", doctype)
-
- if not hide_email:
- frappe.db.sql("""update `tabDocPerm` set `email`=1
- where permlevel=0 and `read`=1 and parent=%s""", doctype)
diff --git a/erpnext/patches/v4_0/remove_employee_role_if_no_employee.py b/erpnext/patches/v4_0/remove_employee_role_if_no_employee.py
new file mode 100644
index 0000000000..76ec1a7c38
--- /dev/null
+++ b/erpnext/patches/v4_0/remove_employee_role_if_no_employee.py
@@ -0,0 +1,15 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+import frappe.permissions
+
+def execute():
+ for user in frappe.db.sql_list("select distinct parent from `tabUserRole` where role='Employee'"):
+ # if employee record does not exists, remove employee role!
+ if not frappe.db.get_value("Employee", {"user_id": user}):
+ user = frappe.get_doc("User", user)
+ for role in user.get("user_roles", {"role": "Employee"}):
+ user.get("user_roles").remove(role)
+ user.save()
diff --git a/erpnext/patches/v4_0/update_user_properties.py b/erpnext/patches/v4_0/update_user_properties.py
index 54a907afda..a5b7bfd185 100644
--- a/erpnext/patches/v4_0/update_user_properties.py
+++ b/erpnext/patches/v4_0/update_user_properties.py
@@ -7,100 +7,45 @@ import frappe.permissions
import frappe.defaults
def execute():
- frappe.reload_doc("core", "doctype", "docperm")
+ frappe.reload_doc("core", "doctype", "docfield")
frappe.reload_doc("hr", "doctype", "employee")
- update_user_permissions()
- update_user_match()
- add_employee_user_permissions_to_leave_approver()
- update_permissions()
- remove_duplicate_user_permissions()
- frappe.defaults.clear_cache()
+
+ set_print_email_permissions()
+ migrate_user_properties_to_user_permissions()
+
frappe.clear_cache()
-def update_user_permissions():
- frappe.reload_doc("core", "doctype", "docfield")
-
+def migrate_user_properties_to_user_permissions():
for d in frappe.db.sql("""select parent, defkey, defvalue from tabDefaultValue
where parent not in ('__global', '__default')""", as_dict=True):
df = frappe.db.sql("""select options from tabDocField
where fieldname=%s and fieldtype='Link'""", d.defkey, as_dict=True)
-
+
if df:
frappe.db.sql("""update tabDefaultValue
set defkey=%s, parenttype='User Permission'
where defkey=%s and
parent not in ('__global', '__default')""", (df[0].options, d.defkey))
-def update_user_match():
- import frappe.defaults
- doctype_matches = {}
- for doctype, match in frappe.db.sql("""select parent, `match` from `tabDocPerm`
- where `match` like %s and ifnull(`match`, '')!="leave_approver:user" """, "%:user"):
- doctype_matches.setdefault(doctype, []).append(match)
-
- for doctype, user_matches in doctype_matches.items():
- meta = frappe.get_meta(doctype)
-
- # for each user with roles of this doctype, check if match condition applies
- for user in frappe.db.sql_list("""select name from `tabUser`
- where enabled=1 and user_type='System User'"""):
-
- user_roles = frappe.get_roles(user)
-
- perms = meta.get({"doctype": "DocPerm", "permlevel": 0,
- "role": ["in", [["All"] + user_roles]], "read": 1})
+def set_print_email_permissions():
+ # reset Page perms
+ from frappe.core.page.permission_manager.permission_manager import reset
+ reset("Page")
+ reset("Report")
- # user does not have required roles
- if not perms:
- continue
-
- # assume match
- user_match = True
- for perm in perms:
- if not perm.match:
- # aha! non match found
- user_match = False
- break
-
- if not user_match:
- continue
-
- # if match condition applies, restrict that user
- # add that doc's restriction to that user
- for match in user_matches:
- for name in frappe.db.sql_list("""select name from `tab{doctype}`
- where `{field}`=%s""".format(doctype=doctype, field=match.split(":")[0]), user):
-
- frappe.defaults.add_default(doctype, name, user, "User Permission")
-
-def add_employee_user_permissions_to_leave_approver():
- from frappe.core.page.user_permissions import user_permissions
-
- # add restrict rights to HR User and HR Manager
- frappe.db.sql("""update `tabDocPerm` set `restrict`=1 where parent in ('Employee', 'Leave Application')
- and role in ('HR User', 'HR Manager') and permlevel=0 and `read`=1""")
- frappe.clear_cache()
-
- # add Employee user_permissions (in on_update method)
- for employee in frappe.db.sql_list("""select name from `tabEmployee`
- where (exists(select leave_approver from `tabEmployee Leave Approver`
- where `tabEmployee Leave Approver`.parent=`tabEmployee`.name)
- or ifnull(`reports_to`, '')!='') and docstatus<2 and status='Active'"""):
-
- frappe.get_doc("Employee", employee).save()
+ if "allow_print" not in frappe.db.get_table_columns("DocType"):
+ return
-def update_permissions():
- # clear match conditions other than owner
- frappe.db.sql("""update tabDocPerm set `match`=''
- where ifnull(`match`,'') not in ('', 'owner')""")
+ # patch to move print, email into DocPerm
+ # NOTE: allow_print and allow_email are misnamed. They were used to hide print / hide email
+ for doctype, hide_print, hide_email in frappe.db.sql("""select name, ifnull(allow_print, 0), ifnull(allow_email, 0)
+ from `tabDocType` where ifnull(issingle, 0)=0 and ifnull(istable, 0)=0 and
+ (ifnull(allow_print, 0)=0 or ifnull(allow_email, 0)=0)"""):
-def remove_duplicate_user_permissions():
- # remove duplicate user_permissions (if they exist)
- for d in frappe.db.sql("""select parent, defkey, defvalue,
- count(*) as cnt from tabDefaultValue
- where parent not in ('__global', '__default')
- group by parent, defkey, defvalue""", as_dict=1):
- if d.cnt > 1:
- # order by parenttype so that restriction does not get removed!
- frappe.db.sql("""delete from tabDefaultValue where `parent`=%s and `defkey`=%s and
- `defvalue`=%s order by parenttype limit %s""", (d.parent, d.defkey, d.defvalue, d.cnt-1))
+ if not hide_print:
+ frappe.db.sql("""update `tabDocPerm` set `print`=1
+ where permlevel=0 and `read`=1 and parent=%s""", doctype)
+
+ if not hide_email:
+ frappe.db.sql("""update `tabDocPerm` set `email`=1
+ where permlevel=0 and `read`=1 and parent=%s""", doctype)
diff --git a/erpnext/selling/doctype/selling_settings/selling_settings.json b/erpnext/selling/doctype/selling_settings/selling_settings.json
index 25b0819d5d..03d35b739e 100644
--- a/erpnext/selling/doctype/selling_settings/selling_settings.json
+++ b/erpnext/selling/doctype/selling_settings/selling_settings.json
@@ -1,355 +1,102 @@
{
- "_last_update": null,
- "_user_tags": null,
- "allow_attach": null,
- "allow_copy": null,
- "allow_email": null,
- "allow_import": null,
- "allow_print": null,
- "allow_rename": null,
- "allow_trash": null,
- "autoname": null,
- "change_log": null,
- "client_script": null,
- "client_script_core": null,
- "client_string": null,
- "colour": null,
"creation": "2013-06-25 10:25:16",
- "custom": null,
- "default_print_format": null,
"description": "Settings for Selling Module",
"docstatus": 0,
"doctype": "DocType",
"document_type": "Other",
- "dt_template": null,
"fields": [
{
- "allow_on_submit": null,
"default": "Customer Name",
- "depends_on": null,
- "description": null,
"fieldname": "cust_master_name",
"fieldtype": "Select",
- "hidden": null,
- "in_filter": null,
"in_list_view": 1,
"label": "Customer Naming By",
- "no_column": null,
- "no_copy": null,
- "oldfieldname": null,
- "oldfieldtype": null,
"options": "Customer Name\nNaming Series",
- "permlevel": 0,
- "print_hide": null,
- "print_width": null,
- "read_only": null,
- "report_hide": null,
- "reqd": null,
- "search_index": null,
- "set_only_once": null,
- "trigger": null,
- "width": null
+ "permlevel": 0
},
{
- "allow_on_submit": null,
- "default": null,
- "depends_on": null,
- "description": null,
"fieldname": "campaign_naming_by",
"fieldtype": "Select",
- "hidden": null,
- "in_filter": null,
"in_list_view": 1,
"label": "Campaign Naming By",
- "no_column": null,
- "no_copy": null,
- "oldfieldname": null,
- "oldfieldtype": null,
"options": "Campaign Name\nNaming Series",
- "permlevel": 0,
- "print_hide": null,
- "print_width": null,
- "read_only": null,
- "report_hide": null,
- "reqd": null,
- "search_index": null,
- "set_only_once": null,
- "trigger": null,
- "width": null
+ "permlevel": 0
},
{
- "allow_on_submit": null,
- "default": null,
- "depends_on": null,
"description": "Add / Edit",
"fieldname": "customer_group",
"fieldtype": "Link",
- "hidden": null,
- "in_filter": null,
"in_list_view": 1,
"label": "Default Customer Group",
- "no_column": null,
- "no_copy": null,
- "oldfieldname": null,
- "oldfieldtype": null,
"options": "Customer Group",
- "permlevel": 0,
- "print_hide": null,
- "print_width": null,
- "read_only": null,
- "report_hide": null,
- "reqd": null,
- "search_index": null,
- "set_only_once": null,
- "trigger": null,
- "width": null
+ "permlevel": 0
},
{
- "allow_on_submit": null,
- "default": null,
- "depends_on": null,
"description": "Add / Edit",
"fieldname": "territory",
"fieldtype": "Link",
- "hidden": null,
- "in_filter": null,
"in_list_view": 1,
"label": "Default Territory",
- "no_column": null,
- "no_copy": null,
- "oldfieldname": null,
- "oldfieldtype": null,
"options": "Territory",
- "permlevel": 0,
- "print_hide": null,
- "print_width": null,
- "read_only": null,
- "report_hide": null,
- "reqd": null,
- "search_index": null,
- "set_only_once": null,
- "trigger": null,
- "width": null
+ "permlevel": 0
},
{
- "allow_on_submit": null,
- "default": null,
- "depends_on": null,
- "description": null,
"fieldname": "selling_price_list",
"fieldtype": "Link",
- "hidden": null,
- "in_filter": null,
"in_list_view": 1,
"label": "Default Price List",
- "no_column": null,
- "no_copy": null,
- "oldfieldname": null,
- "oldfieldtype": null,
"options": "Price List",
- "permlevel": 0,
- "print_hide": null,
- "print_width": null,
- "read_only": null,
- "report_hide": null,
- "reqd": null,
- "search_index": null,
- "set_only_once": null,
- "trigger": null,
- "width": null
+ "permlevel": 0
},
{
- "allow_on_submit": null,
- "default": null,
- "depends_on": null,
- "description": null,
"fieldname": "column_break_5",
"fieldtype": "Column Break",
- "hidden": null,
- "in_filter": null,
- "in_list_view": null,
- "label": null,
- "no_column": null,
- "no_copy": null,
- "oldfieldname": null,
- "oldfieldtype": null,
- "options": null,
- "permlevel": 0,
- "print_hide": null,
- "print_width": null,
- "read_only": null,
- "report_hide": null,
- "reqd": null,
- "search_index": null,
- "set_only_once": null,
- "trigger": null,
- "width": null
+ "permlevel": 0
},
{
- "allow_on_submit": null,
- "default": null,
- "depends_on": null,
- "description": null,
"fieldname": "so_required",
"fieldtype": "Select",
- "hidden": null,
- "in_filter": null,
- "in_list_view": null,
"label": "Sales Order Required",
- "no_column": null,
- "no_copy": null,
- "oldfieldname": null,
- "oldfieldtype": null,
"options": "No\nYes",
- "permlevel": 0,
- "print_hide": null,
- "print_width": null,
- "read_only": null,
- "report_hide": null,
- "reqd": null,
- "search_index": null,
- "set_only_once": null,
- "trigger": null,
- "width": null
+ "permlevel": 0
},
{
- "allow_on_submit": null,
- "default": null,
- "depends_on": null,
- "description": null,
"fieldname": "dn_required",
"fieldtype": "Select",
- "hidden": null,
- "in_filter": null,
- "in_list_view": null,
"label": "Delivery Note Required",
- "no_column": null,
- "no_copy": null,
- "oldfieldname": null,
- "oldfieldtype": null,
"options": "No\nYes",
- "permlevel": 0,
- "print_hide": null,
- "print_width": null,
- "read_only": null,
- "report_hide": null,
- "reqd": null,
- "search_index": null,
- "set_only_once": null,
- "trigger": null,
- "width": null
+ "permlevel": 0
},
{
- "allow_on_submit": null,
- "default": null,
- "depends_on": null,
- "description": null,
"fieldname": "maintain_same_sales_rate",
"fieldtype": "Check",
- "hidden": null,
- "in_filter": null,
- "in_list_view": null,
"label": "Maintain Same Rate Throughout Sales Cycle",
- "no_column": null,
- "no_copy": null,
- "oldfieldname": null,
- "oldfieldtype": null,
- "options": null,
- "permlevel": 0,
- "print_hide": null,
- "print_width": null,
- "read_only": null,
- "report_hide": null,
- "reqd": null,
- "search_index": null,
- "set_only_once": null,
- "trigger": null,
- "width": null
+ "permlevel": 0
},
{
- "allow_on_submit": null,
- "default": null,
- "depends_on": null,
- "description": null,
"fieldname": "editable_price_list_rate",
"fieldtype": "Check",
- "hidden": null,
- "in_filter": null,
- "in_list_view": null,
"label": "Allow user to edit Price List Rate in transactions",
- "no_column": null,
- "no_copy": null,
- "oldfieldname": null,
- "oldfieldtype": null,
- "options": null,
- "permlevel": 0,
- "print_hide": null,
- "print_width": null,
- "read_only": null,
- "report_hide": null,
- "reqd": null,
- "search_index": null,
- "set_only_once": null,
- "trigger": null,
- "width": null
+ "permlevel": 0
}
],
- "hide_heading": null,
- "hide_toolbar": null,
"icon": "icon-cog",
"idx": 1,
- "in_create": null,
- "in_dialog": null,
- "is_submittable": null,
- "is_transaction_doc": null,
"issingle": 1,
- "istable": null,
- "max_attachments": null,
- "menu_index": null,
- "modified": "2014-04-16 12:21:36.117261",
+ "modified": "2014-05-28 18:12:55.898953",
"modified_by": "Administrator",
"module": "Selling",
"name": "Selling Settings",
- "name_case": null,
"owner": "Administrator",
- "parent": null,
- "parent_node": null,
- "parentfield": null,
- "parenttype": null,
"permissions": [
{
- "amend": null,
- "cancel": null,
"create": 1,
- "delete": null,
"email": 1,
- "export": null,
- "import": null,
- "match": null,
"permlevel": 0,
"print": 1,
"read": 1,
- "report": null,
- "restrict": null,
"role": "System Manager",
- "submit": null,
"write": 1
}
- ],
- "plugin": null,
- "print_outline": null,
- "read_only": null,
- "read_only_onload": null,
- "search_fields": null,
- "server_code": null,
- "server_code_compiled": null,
- "server_code_core": null,
- "server_code_error": null,
- "show_in_menu": null,
- "smallicon": null,
- "subject": null,
- "tag_fields": null,
- "title_field": null,
- "use_template": null,
- "version": null
+ ]
}
diff --git a/erpnext/setup/page/setup_wizard/setup_wizard.py b/erpnext/setup/page/setup_wizard/setup_wizard.py
index fe4dec0c42..176470376e 100644
--- a/erpnext/setup/page/setup_wizard/setup_wizard.py
+++ b/erpnext/setup/page/setup_wizard/setup_wizard.py
@@ -392,7 +392,7 @@ def create_logo(args):
def add_all_roles_to(name):
user = frappe.get_doc("User", name)
for role in frappe.db.sql("""select name from tabRole"""):
- if role[0] not in ["Administrator", "Guest", "All", "Customer", "Supplier", "Partner"]:
+ if role[0] not in ["Administrator", "Guest", "All", "Customer", "Supplier", "Partner", "Employee"]:
d = user.append("user_roles")
d.role = role[0]
user.save()