mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-27 13:55:19 +00:00
chore: move widely used doctypes from HR to Setup module
- Employee: used in Telephony, Stock, Quality, Projects, Manufacturing, Loans, Buying, Assets, Accounts, Dependent Apps: Healthcare - Holiday List: CRM (Appointment Booking), Projects, Healthcare, Support (SLA), Education (Student's Holiday List) - Branch: Selling (SMS Center), used widely as an accounting dimension - Department: Assets, Projects, SMS Center, used widely as an accounting dimension - Designation: Lead, Healthcare Practitioner, used in Employee master which will now be in core - Employee Group: Telephony, Communication - Child Tables for above dts: Employee Group Table (Employee Group), Employee Education (Employee), Employee External Work History (Employee), Employee Internal Work History (Employee), Designation Skill (Designation), Holiday (Holiday List)
This commit is contained in:
1
erpnext/setup/doctype/branch/README.md
Normal file
1
erpnext/setup/doctype/branch/README.md
Normal file
@@ -0,0 +1 @@
|
||||
Location belonging to the organization where Employees can belong.
|
||||
0
erpnext/setup/doctype/branch/__init__.py
Normal file
0
erpnext/setup/doctype/branch/__init__.py
Normal file
8
erpnext/setup/doctype/branch/branch.js
Normal file
8
erpnext/setup/doctype/branch/branch.js
Normal file
@@ -0,0 +1,8 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Branch', {
|
||||
refresh: function(frm) {
|
||||
|
||||
}
|
||||
});
|
||||
103
erpnext/setup/doctype/branch/branch.json
Normal file
103
erpnext/setup/doctype/branch/branch.json
Normal file
@@ -0,0 +1,103 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:branch",
|
||||
"beta": 0,
|
||||
"creation": "2013-01-10 16:34:13",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"editable_grid": 0,
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "branch",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Branch",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "branch",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "fa fa-code-fork",
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-07-25 05:24:26.534086",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Branch",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "HR User",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "HR Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"track_seen": 0
|
||||
}
|
||||
9
erpnext/setup/doctype/branch/branch.py
Normal file
9
erpnext/setup/doctype/branch/branch.py
Normal file
@@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class Branch(Document):
|
||||
pass
|
||||
6
erpnext/setup/doctype/branch/test_branch.py
Normal file
6
erpnext/setup/doctype/branch/test_branch.py
Normal file
@@ -0,0 +1,6 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
import frappe
|
||||
|
||||
test_records = frappe.get_test_records("Branch")
|
||||
1
erpnext/setup/doctype/branch/test_records.json
Normal file
1
erpnext/setup/doctype/branch/test_records.json
Normal file
@@ -0,0 +1 @@
|
||||
[]
|
||||
1
erpnext/setup/doctype/department/README.md
Normal file
1
erpnext/setup/doctype/department/README.md
Normal file
@@ -0,0 +1 @@
|
||||
Department where Employee belongs.
|
||||
0
erpnext/setup/doctype/department/__init__.py
Normal file
0
erpnext/setup/doctype/department/__init__.py
Normal file
31
erpnext/setup/doctype/department/department.js
Normal file
31
erpnext/setup/doctype/department/department.js
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Department', {
|
||||
onload: function(frm) {
|
||||
frm.set_query("parent_department", function(){
|
||||
return {"filters": [["Department", "is_group", "=", 1]]};
|
||||
});
|
||||
|
||||
frm.set_query("payroll_cost_center", function() {
|
||||
return {
|
||||
filters: {
|
||||
"company": frm.doc.company,
|
||||
"is_group": 0
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
refresh: function(frm) {
|
||||
// read-only for root department
|
||||
if(!frm.doc.parent_department && !frm.is_new()) {
|
||||
frm.set_read_only();
|
||||
frm.set_intro(__("This is a root department and cannot be edited."));
|
||||
}
|
||||
},
|
||||
validate: function(frm) {
|
||||
if(frm.doc.name=="All Departments") {
|
||||
frappe.throw(__("You cannot edit root node."));
|
||||
}
|
||||
}
|
||||
});
|
||||
228
erpnext/setup/doctype/department/department.json
Normal file
228
erpnext/setup/doctype/department/department.json
Normal file
@@ -0,0 +1,228 @@
|
||||
{
|
||||
"actions": [],
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"creation": "2013-02-05 11:48:26",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"department_name",
|
||||
"parent_department",
|
||||
"column_break_3",
|
||||
"company",
|
||||
"is_group",
|
||||
"disabled",
|
||||
"section_break_4",
|
||||
"payroll_cost_center",
|
||||
"column_break_9",
|
||||
"leave_block_list",
|
||||
"approvers",
|
||||
"leave_approvers",
|
||||
"expense_approvers",
|
||||
"shift_request_approver",
|
||||
"lft",
|
||||
"rgt",
|
||||
"old_parent"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "department_name",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Department",
|
||||
"oldfieldname": "department_name",
|
||||
"oldfieldtype": "Data",
|
||||
"reqd": 1,
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "parent_department",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Parent Department",
|
||||
"options": "Department",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"in_standard_filter": 1,
|
||||
"label": "Company",
|
||||
"options": "Company",
|
||||
"reqd": 1,
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"bold": 1,
|
||||
"default": "0",
|
||||
"fieldname": "is_group",
|
||||
"fieldtype": "Check",
|
||||
"in_list_view": 1,
|
||||
"label": "Is Group",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"label": "Disabled",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_4",
|
||||
"fieldtype": "Section Break",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"description": "Days for which Holidays are blocked for this department.",
|
||||
"fieldname": "leave_block_list",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Leave Block List",
|
||||
"options": "Leave Block List",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "leave_approvers",
|
||||
"fieldtype": "Table",
|
||||
"label": "Leave Approver",
|
||||
"options": "Department Approver",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "expense_approvers",
|
||||
"fieldtype": "Table",
|
||||
"label": "Expense Approver",
|
||||
"options": "Department Approver",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "lft",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 1,
|
||||
"label": "lft",
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "rgt",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 1,
|
||||
"label": "rgt",
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "old_parent",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 1,
|
||||
"label": "Old Parent",
|
||||
"print_hide": 1,
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "payroll_cost_center",
|
||||
"fieldtype": "Link",
|
||||
"label": "Payroll Cost Center",
|
||||
"options": "Cost Center",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_9",
|
||||
"fieldtype": "Column Break",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"description": "The first Approver in the list will be set as the default Approver.",
|
||||
"fieldname": "approvers",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Approvers",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "shift_request_approver",
|
||||
"fieldtype": "Table",
|
||||
"label": "Shift Request Approver",
|
||||
"options": "Department Approver",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-sitemap",
|
||||
"idx": 1,
|
||||
"is_tree": 1,
|
||||
"links": [],
|
||||
"modified": "2020-06-23 15:42:00.563272",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Department",
|
||||
"nsm_parent_field": "parent_department",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "HR User",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Academics User",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"import": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "HR Manager",
|
||||
"set_user_permissions": 1,
|
||||
"share": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"show_name_in_global_search": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "ASC"
|
||||
}
|
||||
94
erpnext/setup/doctype/department/department.py
Normal file
94
erpnext/setup/doctype/department/department.py
Normal file
@@ -0,0 +1,94 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
import frappe
|
||||
from frappe.utils.nestedset import NestedSet, get_root_of
|
||||
|
||||
from erpnext.utilities.transaction_base import delete_events
|
||||
|
||||
|
||||
class Department(NestedSet):
|
||||
nsm_parent_field = "parent_department"
|
||||
|
||||
def autoname(self):
|
||||
root = get_root_of("Department")
|
||||
if root and self.department_name != root:
|
||||
self.name = get_abbreviated_name(self.department_name, self.company)
|
||||
else:
|
||||
self.name = self.department_name
|
||||
|
||||
def validate(self):
|
||||
if not self.parent_department:
|
||||
root = get_root_of("Department")
|
||||
if root:
|
||||
self.parent_department = root
|
||||
|
||||
def before_rename(self, old, new, merge=False):
|
||||
# renaming consistency with abbreviation
|
||||
if not frappe.get_cached_value("Company", self.company, "abbr") in new:
|
||||
new = get_abbreviated_name(new, self.company)
|
||||
|
||||
return new
|
||||
|
||||
def on_update(self):
|
||||
if not (frappe.local.flags.ignore_update_nsm or frappe.flags.in_setup_wizard):
|
||||
super(Department, self).on_update()
|
||||
|
||||
def on_trash(self):
|
||||
super(Department, self).on_trash()
|
||||
delete_events(self.doctype, self.name)
|
||||
|
||||
|
||||
def on_doctype_update():
|
||||
frappe.db.add_index("Department", ["lft", "rgt"])
|
||||
|
||||
|
||||
def get_abbreviated_name(name, company):
|
||||
abbr = frappe.get_cached_value("Company", company, "abbr")
|
||||
new_name = "{0} - {1}".format(name, abbr)
|
||||
return new_name
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_children(doctype, parent=None, company=None, is_root=False):
|
||||
condition = ""
|
||||
var_dict = {
|
||||
"name": get_root_of("Department"),
|
||||
"parent": parent,
|
||||
"company": company,
|
||||
}
|
||||
if company == parent:
|
||||
condition = "name=%(name)s"
|
||||
elif company:
|
||||
condition = "parent_department=%(parent)s and company=%(company)s"
|
||||
else:
|
||||
condition = "parent_department = %(parent)s"
|
||||
|
||||
return frappe.db.sql(
|
||||
"""
|
||||
select
|
||||
name as value,
|
||||
is_group as expandable
|
||||
from `tab{doctype}`
|
||||
where
|
||||
{condition}
|
||||
order by name""".format(
|
||||
doctype=doctype, condition=condition
|
||||
),
|
||||
var_dict,
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def add_node():
|
||||
from frappe.desk.treeview import make_tree_args
|
||||
|
||||
args = frappe.form_dict
|
||||
args = make_tree_args(**args)
|
||||
|
||||
if args.parent_department == args.company:
|
||||
args.parent_department = None
|
||||
|
||||
frappe.get_doc(args).insert()
|
||||
28
erpnext/setup/doctype/department/department_tree.js
Normal file
28
erpnext/setup/doctype/department/department_tree.js
Normal file
@@ -0,0 +1,28 @@
|
||||
frappe.treeview_settings["Department"] = {
|
||||
ignore_fields:["parent_department"],
|
||||
get_tree_nodes: 'erpnext.hr.doctype.department.department.get_children',
|
||||
add_tree_node: 'erpnext.hr.doctype.department.department.add_node',
|
||||
filters: [
|
||||
{
|
||||
fieldname: "company",
|
||||
fieldtype:"Link",
|
||||
options: "Company",
|
||||
label: __("Company"),
|
||||
},
|
||||
],
|
||||
breadcrumb: "HR",
|
||||
root_label: "All Departments",
|
||||
get_tree_root: true,
|
||||
menu_items: [
|
||||
{
|
||||
label: __("New Department"),
|
||||
action: function() {
|
||||
frappe.new_doc("Department", true);
|
||||
},
|
||||
condition: 'frappe.boot.user.can_create.indexOf("Department") !== -1'
|
||||
}
|
||||
],
|
||||
onload: function(treeview) {
|
||||
treeview.make_tree();
|
||||
}
|
||||
};
|
||||
31
erpnext/setup/doctype/department/test_department.py
Normal file
31
erpnext/setup/doctype/department/test_department.py
Normal file
@@ -0,0 +1,31 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
import unittest
|
||||
|
||||
import frappe
|
||||
|
||||
test_ignore = ["Leave Block List"]
|
||||
|
||||
|
||||
class TestDepartment(unittest.TestCase):
|
||||
def test_remove_department_data(self):
|
||||
doc = create_department("Test Department")
|
||||
frappe.delete_doc("Department", doc.name)
|
||||
|
||||
|
||||
def create_department(department_name, parent_department=None):
|
||||
doc = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Department",
|
||||
"is_group": 0,
|
||||
"parent_department": parent_department,
|
||||
"department_name": department_name,
|
||||
"company": frappe.defaults.get_defaults().company,
|
||||
}
|
||||
).insert()
|
||||
|
||||
return doc
|
||||
|
||||
|
||||
test_records = frappe.get_test_records("Department")
|
||||
4
erpnext/setup/doctype/department/test_records.json
Normal file
4
erpnext/setup/doctype/department/test_records.json
Normal file
@@ -0,0 +1,4 @@
|
||||
[
|
||||
{"doctype":"Department", "department_name":"_Test Department", "company": "_Test Company", "parent_department": "All Departments"},
|
||||
{"doctype":"Department", "department_name":"_Test Department 1", "company": "_Test Company", "parent_department": "All Departments"}
|
||||
]
|
||||
1
erpnext/setup/doctype/designation/README.md
Normal file
1
erpnext/setup/doctype/designation/README.md
Normal file
@@ -0,0 +1 @@
|
||||
Employee Designation.
|
||||
0
erpnext/setup/doctype/designation/__init__.py
Normal file
0
erpnext/setup/doctype/designation/__init__.py
Normal file
8
erpnext/setup/doctype/designation/designation.js
Normal file
8
erpnext/setup/doctype/designation/designation.js
Normal file
@@ -0,0 +1,8 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Designation', {
|
||||
refresh: function(frm) {
|
||||
|
||||
}
|
||||
});
|
||||
198
erpnext/setup/doctype/designation/designation.json
Normal file
198
erpnext/setup/doctype/designation/designation.json
Normal file
@@ -0,0 +1,198 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:designation_name",
|
||||
"beta": 0,
|
||||
"creation": "2013-01-10 16:34:13",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"editable_grid": 0,
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "designation_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Designation",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "designation_name",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Description",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "required_skills_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Required Skills",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "skills",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Skills",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Designation Skill",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "fa fa-bookmark",
|
||||
"idx": 1,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2019-04-16 10:02:23.277734",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Designation",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "HR User",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"read": 1,
|
||||
"role": "Sales User"
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"show_name_in_global_search": 1,
|
||||
"sort_order": "ASC",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
||||
9
erpnext/setup/doctype/designation/designation.py
Normal file
9
erpnext/setup/doctype/designation/designation.py
Normal file
@@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class Designation(Document):
|
||||
pass
|
||||
22
erpnext/setup/doctype/designation/test_designation.py
Normal file
22
erpnext/setup/doctype/designation/test_designation.py
Normal file
@@ -0,0 +1,22 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
import frappe
|
||||
|
||||
# test_records = frappe.get_test_records('Designation')
|
||||
|
||||
|
||||
def create_designation(**args):
|
||||
args = frappe._dict(args)
|
||||
if frappe.db.exists("Designation", args.designation_name or "_Test designation"):
|
||||
return frappe.get_doc("Designation", args.designation_name or "_Test designation")
|
||||
|
||||
designation = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Designation",
|
||||
"designation_name": args.designation_name or "_Test designation",
|
||||
"description": args.description or "_Test description",
|
||||
}
|
||||
)
|
||||
designation.save()
|
||||
return designation
|
||||
1
erpnext/setup/doctype/designation/test_records.json
Normal file
1
erpnext/setup/doctype/designation/test_records.json
Normal file
@@ -0,0 +1 @@
|
||||
[]
|
||||
0
erpnext/setup/doctype/designation_skill/__init__.py
Normal file
0
erpnext/setup/doctype/designation_skill/__init__.py
Normal file
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2019-04-16 10:01:05.259881",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "skill",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Skill",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Skill",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-04-16 13:42:10.760449",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Designation Skill",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "ASC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
||||
10
erpnext/setup/doctype/designation_skill/designation_skill.py
Normal file
10
erpnext/setup/doctype/designation_skill/designation_skill.py
Normal file
@@ -0,0 +1,10 @@
|
||||
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class DesignationSkill(Document):
|
||||
pass
|
||||
1
erpnext/setup/doctype/employee/README.md
Normal file
1
erpnext/setup/doctype/employee/README.md
Normal file
@@ -0,0 +1 @@
|
||||
Employee master.
|
||||
0
erpnext/setup/doctype/employee/__init__.py
Normal file
0
erpnext/setup/doctype/employee/__init__.py
Normal file
159
erpnext/setup/doctype/employee/employee.js
Executable file
159
erpnext/setup/doctype/employee/employee.js
Executable file
@@ -0,0 +1,159 @@
|
||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.provide("erpnext.hr");
|
||||
erpnext.hr.EmployeeController = class EmployeeController extends frappe.ui.form.Controller {
|
||||
setup() {
|
||||
this.frm.fields_dict.user_id.get_query = function(doc, cdt, cdn) {
|
||||
return {
|
||||
query: "frappe.core.doctype.user.user.user_query",
|
||||
filters: {ignore_user_type: 1}
|
||||
}
|
||||
}
|
||||
this.frm.fields_dict.reports_to.get_query = function(doc, cdt, cdn) {
|
||||
return { query: "erpnext.controllers.queries.employee_query"} }
|
||||
}
|
||||
|
||||
refresh() {
|
||||
erpnext.toggle_naming_series();
|
||||
}
|
||||
|
||||
date_of_birth() {
|
||||
return cur_frm.call({
|
||||
method: "get_retirement_date",
|
||||
args: {
|
||||
date_of_birth: this.frm.doc.date_of_birth
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
salutation() {
|
||||
if (this.frm.doc.salutation) {
|
||||
this.frm.set_value("gender", {
|
||||
"Mr": "Male",
|
||||
"Ms": "Female"
|
||||
}[this.frm.doc.salutation]);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
frappe.ui.form.on('Employee', {
|
||||
setup: function (frm) {
|
||||
frm.set_query("leave_policy", function() {
|
||||
return {
|
||||
"filters": {
|
||||
"docstatus": 1
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query("payroll_cost_center", function() {
|
||||
return {
|
||||
filters: {
|
||||
"company": frm.doc.company,
|
||||
"is_group": 0
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
onload: function (frm) {
|
||||
frm.set_query("department", function() {
|
||||
return {
|
||||
"filters": {
|
||||
"company": frm.doc.company,
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
prefered_contact_email: function(frm) {
|
||||
frm.events.update_contact(frm);
|
||||
},
|
||||
|
||||
personal_email: function(frm) {
|
||||
frm.events.update_contact(frm);
|
||||
},
|
||||
|
||||
company_email: function(frm) {
|
||||
frm.events.update_contact(frm);
|
||||
},
|
||||
|
||||
user_id: function(frm) {
|
||||
frm.events.update_contact(frm);
|
||||
},
|
||||
|
||||
update_contact: function(frm) {
|
||||
var prefered_email_fieldname = frappe.model.scrub(frm.doc.prefered_contact_email) || 'user_id';
|
||||
frm.set_value("prefered_email",
|
||||
frm.fields_dict[prefered_email_fieldname].value);
|
||||
},
|
||||
|
||||
status: function(frm) {
|
||||
return frm.call({
|
||||
method: "deactivate_sales_person",
|
||||
args: {
|
||||
employee: frm.doc.employee,
|
||||
status: frm.doc.status
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
create_user: function(frm) {
|
||||
if (!frm.doc.prefered_email) {
|
||||
frappe.throw(__("Please enter Preferred Contact Email"));
|
||||
}
|
||||
frappe.call({
|
||||
method: "erpnext.hr.doctype.employee.employee.create_user",
|
||||
args: {
|
||||
employee: frm.doc.name,
|
||||
email: frm.doc.prefered_email
|
||||
},
|
||||
callback: function (r) {
|
||||
frm.set_value("user_id", r.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
cur_frm.cscript = new erpnext.hr.EmployeeController({
|
||||
frm: cur_frm
|
||||
});
|
||||
|
||||
|
||||
frappe.tour['Employee'] = [
|
||||
{
|
||||
fieldname: "first_name",
|
||||
title: "First Name",
|
||||
description: __("Enter First and Last name of Employee, based on Which Full Name will be updated. IN transactions, it will be Full Name which will be fetched.")
|
||||
},
|
||||
{
|
||||
fieldname: "company",
|
||||
title: "Company",
|
||||
description: __("Select a Company this Employee belongs to. Other HR features like Payroll. Expense Claims and Leaves for this Employee will be created for a given company only.")
|
||||
},
|
||||
{
|
||||
fieldname: "date_of_birth",
|
||||
title: "Date of Birth",
|
||||
description: __("Select Date of Birth. This will validate Employees age and prevent hiring of under-age staff.")
|
||||
},
|
||||
{
|
||||
fieldname: "date_of_joining",
|
||||
title: "Date of Joining",
|
||||
description: __("Select Date of joining. It will have impact on the first salary calculation, Leave allocation on pro-rata bases.")
|
||||
},
|
||||
{
|
||||
fieldname: "holiday_list",
|
||||
title: "Holiday List",
|
||||
description: __("Select a default Holiday List for this Employee. The days listed in Holiday List will not be counted in Leave Application.")
|
||||
},
|
||||
{
|
||||
fieldname: "reports_to",
|
||||
title: "Reports To",
|
||||
description: __("Here, you can select a senior of this Employee. Based on this, Organization Chart will be populated.")
|
||||
},
|
||||
{
|
||||
fieldname: "leave_approver",
|
||||
title: "Leave Approver",
|
||||
description: __("Select Leave Approver for an employee. The user one who will look after his/her Leave application")
|
||||
},
|
||||
];
|
||||
880
erpnext/setup/doctype/employee/employee.json
Normal file
880
erpnext/setup/doctype/employee/employee.json
Normal file
@@ -0,0 +1,880 @@
|
||||
{
|
||||
"actions": [],
|
||||
"allow_events_in_timeline": 1,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "naming_series:",
|
||||
"creation": "2022-02-21 11:54:09.632218",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"basic_information",
|
||||
"employee",
|
||||
"naming_series",
|
||||
"first_name",
|
||||
"middle_name",
|
||||
"last_name",
|
||||
"salutation",
|
||||
"employee_name",
|
||||
"employment_type",
|
||||
"image",
|
||||
"column_break1",
|
||||
"company",
|
||||
"status",
|
||||
"gender",
|
||||
"date_of_birth",
|
||||
"date_of_joining",
|
||||
"employee_number",
|
||||
"emergency_contact_details",
|
||||
"person_to_be_contacted",
|
||||
"relation",
|
||||
"column_break_19",
|
||||
"emergency_phone_number",
|
||||
"erpnext_user",
|
||||
"user_id",
|
||||
"create_user",
|
||||
"create_user_permission",
|
||||
"employment_details",
|
||||
"job_applicant",
|
||||
"scheduled_confirmation_date",
|
||||
"final_confirmation_date",
|
||||
"col_break_22",
|
||||
"contract_end_date",
|
||||
"notice_number_of_days",
|
||||
"date_of_retirement",
|
||||
"job_profile",
|
||||
"department",
|
||||
"designation",
|
||||
"reports_to",
|
||||
"column_break_31",
|
||||
"grade",
|
||||
"branch",
|
||||
"approvers_section",
|
||||
"expense_approver",
|
||||
"leave_approver",
|
||||
"column_break_45",
|
||||
"shift_request_approver",
|
||||
"attendance_and_leave_details",
|
||||
"attendance_device_id",
|
||||
"column_break_44",
|
||||
"holiday_list",
|
||||
"default_shift",
|
||||
"salary_information",
|
||||
"salary_currency",
|
||||
"ctc",
|
||||
"salary_mode",
|
||||
"payroll_cost_center",
|
||||
"column_break_52",
|
||||
"bank_name",
|
||||
"bank_ac_no",
|
||||
"health_insurance_section",
|
||||
"health_insurance_provider",
|
||||
"health_insurance_no",
|
||||
"contact_details",
|
||||
"cell_number",
|
||||
"prefered_email",
|
||||
"personal_email",
|
||||
"unsubscribed",
|
||||
"permanent_accommodation_type",
|
||||
"permanent_address",
|
||||
"column_break4",
|
||||
"prefered_contact_email",
|
||||
"company_email",
|
||||
"current_accommodation_type",
|
||||
"current_address",
|
||||
"sb53",
|
||||
"bio",
|
||||
"personal_details",
|
||||
"passport_number",
|
||||
"date_of_issue",
|
||||
"valid_upto",
|
||||
"place_of_issue",
|
||||
"marital_status",
|
||||
"blood_group",
|
||||
"column_break6",
|
||||
"family_background",
|
||||
"health_details",
|
||||
"educational_qualification",
|
||||
"education",
|
||||
"previous_work_experience",
|
||||
"external_work_history",
|
||||
"history_in_company",
|
||||
"internal_work_history",
|
||||
"exit",
|
||||
"resignation_letter_date",
|
||||
"relieving_date",
|
||||
"reason_for_leaving",
|
||||
"leave_encashed",
|
||||
"encashment_date",
|
||||
"exit_interview_details",
|
||||
"held_on",
|
||||
"new_workplace",
|
||||
"feedback",
|
||||
"lft",
|
||||
"rgt",
|
||||
"old_parent"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "basic_information",
|
||||
"fieldtype": "Section Break",
|
||||
"oldfieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "employee",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"label": "Employee",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1,
|
||||
"report_hide": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "naming_series",
|
||||
"fieldtype": "Select",
|
||||
"label": "Series",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "naming_series",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "HR-EMP-",
|
||||
"set_only_once": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "salutation",
|
||||
"fieldtype": "Link",
|
||||
"label": "Salutation",
|
||||
"oldfieldname": "salutation",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Salutation"
|
||||
},
|
||||
{
|
||||
"fieldname": "first_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "First Name",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_in_quick_entry": 1,
|
||||
"fieldname": "middle_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "Middle Name"
|
||||
},
|
||||
{
|
||||
"allow_in_quick_entry": 1,
|
||||
"fieldname": "last_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "Last Name"
|
||||
},
|
||||
{
|
||||
"fieldname": "employee_name",
|
||||
"fieldtype": "Data",
|
||||
"in_global_search": 1,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Full Name",
|
||||
"oldfieldname": "employee_name",
|
||||
"oldfieldtype": "Data",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fetch_from": "user_id.user_image",
|
||||
"fetch_if_empty": 1,
|
||||
"fieldname": "image",
|
||||
"fieldtype": "Attach Image",
|
||||
"hidden": 1,
|
||||
"label": "Image",
|
||||
"no_copy": 1
|
||||
},
|
||||
{
|
||||
"allow_in_quick_entry": 1,
|
||||
"fieldname": "column_break1",
|
||||
"fieldtype": "Column Break",
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"label": "Company",
|
||||
"options": "Company",
|
||||
"print_hide": 1,
|
||||
"remember_last_selected_value": 1,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"default": "Active",
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"label": "Status",
|
||||
"oldfieldname": "status",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Active\nInactive\nSuspended\nLeft",
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "employee_number",
|
||||
"fieldtype": "Data",
|
||||
"in_global_search": 1,
|
||||
"label": "Employee Number",
|
||||
"oldfieldname": "employee_number",
|
||||
"oldfieldtype": "Data"
|
||||
},
|
||||
{
|
||||
"fieldname": "employment_type",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
"label": "Employment Type",
|
||||
"oldfieldname": "employment_type",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Employment Type"
|
||||
},
|
||||
{
|
||||
"fieldname": "gender",
|
||||
"fieldtype": "Link",
|
||||
"label": "Gender",
|
||||
"oldfieldname": "gender",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Gender",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "date_of_birth",
|
||||
"fieldtype": "Date",
|
||||
"label": "Date of Birth",
|
||||
"oldfieldname": "date_of_birth",
|
||||
"oldfieldtype": "Date",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "date_of_joining",
|
||||
"fieldtype": "Date",
|
||||
"label": "Date of Joining",
|
||||
"oldfieldname": "date_of_joining",
|
||||
"oldfieldtype": "Date",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_in_quick_entry": 1,
|
||||
"fieldname": "emergency_contact_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Emergency Contact"
|
||||
},
|
||||
{
|
||||
"bold": 1,
|
||||
"fieldname": "emergency_phone_number",
|
||||
"fieldtype": "Data",
|
||||
"label": "Emergency Phone",
|
||||
"options": "Phone"
|
||||
},
|
||||
{
|
||||
"bold": 1,
|
||||
"fieldname": "person_to_be_contacted",
|
||||
"fieldtype": "Data",
|
||||
"label": "Emergency Contact Name"
|
||||
},
|
||||
{
|
||||
"fieldname": "relation",
|
||||
"fieldtype": "Data",
|
||||
"label": "Relation"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "erpnext_user",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "ERPNext User"
|
||||
},
|
||||
{
|
||||
"description": "System User (login) ID. If set, it will become default for all HR forms.",
|
||||
"fieldname": "user_id",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
"label": "User ID",
|
||||
"options": "User"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:(!doc.user_id)",
|
||||
"fieldname": "create_user",
|
||||
"fieldtype": "Button",
|
||||
"label": "Create User"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"depends_on": "user_id",
|
||||
"description": "This will restrict user access to other employee records",
|
||||
"fieldname": "create_user_permission",
|
||||
"fieldtype": "Check",
|
||||
"label": "Create User Permission"
|
||||
},
|
||||
{
|
||||
"allow_in_quick_entry": 1,
|
||||
"collapsible": 1,
|
||||
"fieldname": "employment_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Joining Details"
|
||||
},
|
||||
{
|
||||
"fieldname": "job_applicant",
|
||||
"fieldtype": "Link",
|
||||
"label": "Job Applicant",
|
||||
"options": "Job Applicant"
|
||||
},
|
||||
{
|
||||
"fieldname": "scheduled_confirmation_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Offer Date",
|
||||
"oldfieldname": "scheduled_confirmation_date",
|
||||
"oldfieldtype": "Date"
|
||||
},
|
||||
{
|
||||
"fieldname": "final_confirmation_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Confirmation Date",
|
||||
"oldfieldname": "final_confirmation_date",
|
||||
"oldfieldtype": "Date"
|
||||
},
|
||||
{
|
||||
"fieldname": "col_break_22",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "contract_end_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Contract End Date",
|
||||
"oldfieldname": "contract_end_date",
|
||||
"oldfieldtype": "Date"
|
||||
},
|
||||
{
|
||||
"fieldname": "notice_number_of_days",
|
||||
"fieldtype": "Int",
|
||||
"label": "Notice (days)",
|
||||
"oldfieldname": "notice_number_of_days",
|
||||
"oldfieldtype": "Int"
|
||||
},
|
||||
{
|
||||
"fieldname": "date_of_retirement",
|
||||
"fieldtype": "Date",
|
||||
"label": "Date Of Retirement",
|
||||
"oldfieldname": "date_of_retirement",
|
||||
"oldfieldtype": "Date"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "job_profile",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Department and Grade"
|
||||
},
|
||||
{
|
||||
"fieldname": "department",
|
||||
"fieldtype": "Link",
|
||||
"in_standard_filter": 1,
|
||||
"label": "Department",
|
||||
"oldfieldname": "department",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Department"
|
||||
},
|
||||
{
|
||||
"fieldname": "designation",
|
||||
"fieldtype": "Link",
|
||||
"in_global_search": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Designation",
|
||||
"oldfieldname": "designation",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Designation",
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "reports_to",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
"label": "Reports to",
|
||||
"oldfieldname": "reports_to",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Employee"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_31",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "grade",
|
||||
"fieldtype": "Link",
|
||||
"label": "Grade",
|
||||
"options": "Employee Grade"
|
||||
},
|
||||
{
|
||||
"fieldname": "branch",
|
||||
"fieldtype": "Link",
|
||||
"label": "Branch",
|
||||
"oldfieldname": "branch",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Branch"
|
||||
},
|
||||
{
|
||||
"description": "Applicable Holiday List",
|
||||
"fieldname": "holiday_list",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
"label": "Holiday List",
|
||||
"oldfieldname": "holiday_list",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Holiday List"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "salary_information",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Salary Details",
|
||||
"oldfieldtype": "Section Break",
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"fieldname": "salary_mode",
|
||||
"fieldtype": "Select",
|
||||
"label": "Salary Mode",
|
||||
"oldfieldname": "salary_mode",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nBank\nCash\nCheque"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.salary_mode == 'Bank'",
|
||||
"fieldname": "bank_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "Bank Name",
|
||||
"oldfieldname": "bank_name",
|
||||
"oldfieldtype": "Link"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.salary_mode == 'Bank'",
|
||||
"fieldname": "bank_ac_no",
|
||||
"fieldtype": "Data",
|
||||
"label": "Bank A/C No.",
|
||||
"oldfieldname": "bank_ac_no",
|
||||
"oldfieldtype": "Data"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "health_insurance_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Health Insurance"
|
||||
},
|
||||
{
|
||||
"fieldname": "health_insurance_provider",
|
||||
"fieldtype": "Link",
|
||||
"label": "Health Insurance Provider",
|
||||
"options": "Employee Health Insurance"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.health_insurance_provider",
|
||||
"fieldname": "health_insurance_no",
|
||||
"fieldtype": "Data",
|
||||
"label": "Health Insurance No"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "contact_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Contact Details"
|
||||
},
|
||||
{
|
||||
"fieldname": "cell_number",
|
||||
"fieldtype": "Data",
|
||||
"label": "Mobile",
|
||||
"options": "Phone"
|
||||
},
|
||||
{
|
||||
"fieldname": "prefered_contact_email",
|
||||
"fieldtype": "Select",
|
||||
"label": "Prefered Contact Email",
|
||||
"options": "\nCompany Email\nPersonal Email\nUser ID"
|
||||
},
|
||||
{
|
||||
"fieldname": "prefered_email",
|
||||
"fieldtype": "Data",
|
||||
"label": "Prefered Email",
|
||||
"options": "Email",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"description": "Provide Email Address registered in company",
|
||||
"fieldname": "company_email",
|
||||
"fieldtype": "Data",
|
||||
"label": "Company Email",
|
||||
"oldfieldname": "company_email",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "Email"
|
||||
},
|
||||
{
|
||||
"fieldname": "personal_email",
|
||||
"fieldtype": "Data",
|
||||
"label": "Personal Email",
|
||||
"options": "Email"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "unsubscribed",
|
||||
"fieldtype": "Check",
|
||||
"label": "Unsubscribed"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break4",
|
||||
"fieldtype": "Column Break",
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"fieldname": "permanent_accommodation_type",
|
||||
"fieldtype": "Select",
|
||||
"label": "Permanent Address Is",
|
||||
"options": "\nRented\nOwned"
|
||||
},
|
||||
{
|
||||
"fieldname": "permanent_address",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Permanent Address"
|
||||
},
|
||||
{
|
||||
"fieldname": "current_accommodation_type",
|
||||
"fieldtype": "Select",
|
||||
"label": "Current Address Is",
|
||||
"options": "\nRented\nOwned"
|
||||
},
|
||||
{
|
||||
"fieldname": "current_address",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Current Address"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "sb53",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Personal Bio"
|
||||
},
|
||||
{
|
||||
"description": "Short biography for website and other publications.",
|
||||
"fieldname": "bio",
|
||||
"fieldtype": "Text Editor",
|
||||
"label": "Bio / Cover Letter"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "personal_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Personal Details"
|
||||
},
|
||||
{
|
||||
"fieldname": "passport_number",
|
||||
"fieldtype": "Data",
|
||||
"label": "Passport Number"
|
||||
},
|
||||
{
|
||||
"fieldname": "date_of_issue",
|
||||
"fieldtype": "Date",
|
||||
"label": "Date of Issue"
|
||||
},
|
||||
{
|
||||
"fieldname": "valid_upto",
|
||||
"fieldtype": "Date",
|
||||
"label": "Valid Upto"
|
||||
},
|
||||
{
|
||||
"fieldname": "place_of_issue",
|
||||
"fieldtype": "Data",
|
||||
"label": "Place of Issue"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break6",
|
||||
"fieldtype": "Column Break",
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"fieldname": "marital_status",
|
||||
"fieldtype": "Select",
|
||||
"label": "Marital Status",
|
||||
"options": "\nSingle\nMarried\nDivorced\nWidowed"
|
||||
},
|
||||
{
|
||||
"fieldname": "blood_group",
|
||||
"fieldtype": "Select",
|
||||
"label": "Blood Group",
|
||||
"options": "\nA+\nA-\nB+\nB-\nAB+\nAB-\nO+\nO-"
|
||||
},
|
||||
{
|
||||
"description": "Here you can maintain family details like name and occupation of parent, spouse and children",
|
||||
"fieldname": "family_background",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Family Background"
|
||||
},
|
||||
{
|
||||
"description": "Here you can maintain height, weight, allergies, medical concerns etc",
|
||||
"fieldname": "health_details",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Health Details"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "educational_qualification",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Educational Qualification"
|
||||
},
|
||||
{
|
||||
"fieldname": "education",
|
||||
"fieldtype": "Table",
|
||||
"label": "Education",
|
||||
"options": "Employee Education"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "previous_work_experience",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Previous Work Experience",
|
||||
"options": "Simple"
|
||||
},
|
||||
{
|
||||
"fieldname": "external_work_history",
|
||||
"fieldtype": "Table",
|
||||
"label": "External Work History",
|
||||
"options": "Employee External Work History"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "history_in_company",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "History In Company",
|
||||
"options": "Simple"
|
||||
},
|
||||
{
|
||||
"fieldname": "internal_work_history",
|
||||
"fieldtype": "Table",
|
||||
"label": "Internal Work History",
|
||||
"options": "Employee Internal Work History"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "exit",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Exit",
|
||||
"oldfieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "resignation_letter_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Resignation Letter Date",
|
||||
"oldfieldname": "resignation_letter_date",
|
||||
"oldfieldtype": "Date"
|
||||
},
|
||||
{
|
||||
"fieldname": "relieving_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Relieving Date",
|
||||
"mandatory_depends_on": "eval:doc.status == \"Left\"",
|
||||
"oldfieldname": "relieving_date",
|
||||
"oldfieldtype": "Date"
|
||||
},
|
||||
{
|
||||
"fieldname": "reason_for_leaving",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Reason for Leaving",
|
||||
"oldfieldname": "reason_for_leaving",
|
||||
"oldfieldtype": "Data"
|
||||
},
|
||||
{
|
||||
"fieldname": "leave_encashed",
|
||||
"fieldtype": "Select",
|
||||
"label": "Leave Encashed?",
|
||||
"oldfieldname": "leave_encashed",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nYes\nNo"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.leave_encashed ==\"Yes\"",
|
||||
"fieldname": "encashment_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Encashment Date",
|
||||
"oldfieldname": "encashment_date",
|
||||
"oldfieldtype": "Date"
|
||||
},
|
||||
{
|
||||
"fieldname": "exit_interview_details",
|
||||
"fieldtype": "Column Break",
|
||||
"oldfieldname": "col_brk6",
|
||||
"oldfieldtype": "Column Break",
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"fieldname": "held_on",
|
||||
"fieldtype": "Date",
|
||||
"label": "Exit Interview Held On",
|
||||
"oldfieldname": "held_on",
|
||||
"oldfieldtype": "Date"
|
||||
},
|
||||
{
|
||||
"fieldname": "new_workplace",
|
||||
"fieldtype": "Data",
|
||||
"label": "New Workplace",
|
||||
"oldfieldname": "new_workplace",
|
||||
"oldfieldtype": "Data"
|
||||
},
|
||||
{
|
||||
"fieldname": "feedback",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Feedback",
|
||||
"oldfieldname": "feedback",
|
||||
"oldfieldtype": "Text"
|
||||
},
|
||||
{
|
||||
"fieldname": "lft",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 1,
|
||||
"label": "lft",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "rgt",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 1,
|
||||
"label": "rgt",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "old_parent",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 1,
|
||||
"label": "Old Parent"
|
||||
},
|
||||
{
|
||||
"fieldname": "attendance_device_id",
|
||||
"fieldtype": "Data",
|
||||
"label": "Attendance Device ID (Biometric/RF tag ID)",
|
||||
"no_copy": 1,
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "attendance_and_leave_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Attendance and Leave Details"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_44",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "default_shift",
|
||||
"fieldtype": "Link",
|
||||
"label": "Default Shift",
|
||||
"options": "Shift Type"
|
||||
},
|
||||
{
|
||||
"fieldname": "leave_approver",
|
||||
"fieldtype": "Link",
|
||||
"label": "Leave Approver",
|
||||
"options": "User"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_19",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fetch_from": "department.payroll_cost_center",
|
||||
"fetch_if_empty": 1,
|
||||
"fieldname": "payroll_cost_center",
|
||||
"fieldtype": "Link",
|
||||
"label": "Payroll Cost Center",
|
||||
"options": "Cost Center"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_52",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "expense_approver",
|
||||
"fieldtype": "Link",
|
||||
"label": "Expense Approver",
|
||||
"options": "User"
|
||||
},
|
||||
{
|
||||
"fieldname": "approvers_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Approvers"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_45",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "shift_request_approver",
|
||||
"fieldtype": "Link",
|
||||
"label": "Shift Request Approver",
|
||||
"options": "User"
|
||||
},
|
||||
{
|
||||
"fieldname": "salary_currency",
|
||||
"fieldtype": "Link",
|
||||
"label": "Salary Currency",
|
||||
"options": "Currency"
|
||||
},
|
||||
{
|
||||
"fieldname": "ctc",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Cost to Company (CTC)",
|
||||
"options": "salary_currency"
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-user",
|
||||
"idx": 24,
|
||||
"image_field": "image",
|
||||
"links": [],
|
||||
"modified": "2022-04-22 16:21:55.811983",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee",
|
||||
"name_case": "Title Case",
|
||||
"naming_rule": "By \"Naming Series\" field",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"email": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Employee"
|
||||
},
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"import": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "HR User",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"import": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "HR Manager",
|
||||
"set_user_permissions": 1,
|
||||
"share": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"search_fields": "employee_name",
|
||||
"show_name_in_global_search": 1,
|
||||
"show_title_field_in_link": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"title_field": "employee_name"
|
||||
}
|
||||
521
erpnext/setup/doctype/employee/employee.py
Executable file
521
erpnext/setup/doctype/employee/employee.py
Executable file
@@ -0,0 +1,521 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
import frappe
|
||||
from frappe import _, scrub, throw
|
||||
from frappe.model.naming import set_name_by_naming_series
|
||||
from frappe.permissions import (
|
||||
add_user_permission,
|
||||
get_doc_permissions,
|
||||
has_permission,
|
||||
remove_user_permission,
|
||||
set_user_permission_if_allowed,
|
||||
)
|
||||
from frappe.utils import add_years, cstr, getdate, today, validate_email_address
|
||||
from frappe.utils.nestedset import NestedSet
|
||||
|
||||
from erpnext.utilities.transaction_base import delete_events
|
||||
|
||||
|
||||
class EmployeeUserDisabledError(frappe.ValidationError):
|
||||
pass
|
||||
|
||||
|
||||
class InactiveEmployeeStatusError(frappe.ValidationError):
|
||||
pass
|
||||
|
||||
|
||||
class Employee(NestedSet):
|
||||
nsm_parent_field = "reports_to"
|
||||
|
||||
def autoname(self):
|
||||
naming_method = frappe.db.get_value("HR Settings", None, "emp_created_by")
|
||||
if not naming_method:
|
||||
throw(_("Please setup Employee Naming System in Human Resource > HR Settings"))
|
||||
else:
|
||||
if naming_method == "Naming Series":
|
||||
set_name_by_naming_series(self)
|
||||
elif naming_method == "Employee Number":
|
||||
self.name = self.employee_number
|
||||
elif naming_method == "Full Name":
|
||||
self.set_employee_name()
|
||||
self.name = self.employee_name
|
||||
|
||||
self.employee = self.name
|
||||
|
||||
def validate(self):
|
||||
from erpnext.controllers.status_updater import validate_status
|
||||
|
||||
validate_status(self.status, ["Active", "Inactive", "Suspended", "Left"])
|
||||
|
||||
self.employee = self.name
|
||||
self.set_employee_name()
|
||||
self.validate_date()
|
||||
self.validate_email()
|
||||
self.validate_status()
|
||||
self.validate_reports_to()
|
||||
self.validate_preferred_email()
|
||||
if self.job_applicant:
|
||||
self.validate_onboarding_process()
|
||||
|
||||
if self.user_id:
|
||||
self.validate_user_details()
|
||||
else:
|
||||
existing_user_id = frappe.db.get_value("Employee", self.name, "user_id")
|
||||
if existing_user_id:
|
||||
remove_user_permission("Employee", self.name, existing_user_id)
|
||||
|
||||
def after_rename(self, old, new, merge):
|
||||
self.db_set("employee", new)
|
||||
|
||||
def set_employee_name(self):
|
||||
self.employee_name = " ".join(
|
||||
filter(lambda x: x, [self.first_name, self.middle_name, self.last_name])
|
||||
)
|
||||
|
||||
def validate_user_details(self):
|
||||
if self.user_id:
|
||||
data = frappe.db.get_value("User", self.user_id, ["enabled", "user_image"], as_dict=1)
|
||||
|
||||
if not data:
|
||||
self.user_id = None
|
||||
return
|
||||
|
||||
if data.get("user_image") and self.image == "":
|
||||
self.image = data.get("user_image")
|
||||
self.validate_for_enabled_user_id(data.get("enabled", 0))
|
||||
self.validate_duplicate_user_id()
|
||||
|
||||
def update_nsm_model(self):
|
||||
frappe.utils.nestedset.update_nsm(self)
|
||||
|
||||
def on_update(self):
|
||||
self.update_nsm_model()
|
||||
if self.user_id:
|
||||
self.update_user()
|
||||
self.update_user_permissions()
|
||||
self.reset_employee_emails_cache()
|
||||
self.update_approver_role()
|
||||
|
||||
def update_user_permissions(self):
|
||||
if not self.create_user_permission:
|
||||
return
|
||||
if not has_permission("User Permission", ptype="write", raise_exception=False):
|
||||
return
|
||||
|
||||
employee_user_permission_exists = frappe.db.exists(
|
||||
"User Permission", {"allow": "Employee", "for_value": self.name, "user": self.user_id}
|
||||
)
|
||||
|
||||
if employee_user_permission_exists:
|
||||
return
|
||||
|
||||
add_user_permission("Employee", self.name, self.user_id)
|
||||
set_user_permission_if_allowed("Company", self.company, self.user_id)
|
||||
|
||||
def update_user(self):
|
||||
# add employee role if missing
|
||||
user = frappe.get_doc("User", self.user_id)
|
||||
user.flags.ignore_permissions = True
|
||||
|
||||
if "Employee" not in user.get("roles"):
|
||||
user.append_roles("Employee")
|
||||
|
||||
# copy details like Fullname, DOB and Image to User
|
||||
if self.employee_name and not (user.first_name and user.last_name):
|
||||
employee_name = self.employee_name.split(" ")
|
||||
if len(employee_name) >= 3:
|
||||
user.last_name = " ".join(employee_name[2:])
|
||||
user.middle_name = employee_name[1]
|
||||
elif len(employee_name) == 2:
|
||||
user.last_name = employee_name[1]
|
||||
|
||||
user.first_name = employee_name[0]
|
||||
|
||||
if self.date_of_birth:
|
||||
user.birth_date = self.date_of_birth
|
||||
|
||||
if self.gender:
|
||||
user.gender = self.gender
|
||||
|
||||
if self.image:
|
||||
if not user.user_image:
|
||||
user.user_image = self.image
|
||||
try:
|
||||
frappe.get_doc(
|
||||
{
|
||||
"doctype": "File",
|
||||
"file_url": self.image,
|
||||
"attached_to_doctype": "User",
|
||||
"attached_to_name": self.user_id,
|
||||
}
|
||||
).insert(ignore_if_duplicate=True)
|
||||
except frappe.DuplicateEntryError:
|
||||
# already exists
|
||||
pass
|
||||
|
||||
user.save()
|
||||
|
||||
def update_approver_role(self):
|
||||
if self.leave_approver:
|
||||
user = frappe.get_doc("User", self.leave_approver)
|
||||
user.flags.ignore_permissions = True
|
||||
user.add_roles("Leave Approver")
|
||||
|
||||
if self.expense_approver:
|
||||
user = frappe.get_doc("User", self.expense_approver)
|
||||
user.flags.ignore_permissions = True
|
||||
user.add_roles("Expense Approver")
|
||||
|
||||
def validate_date(self):
|
||||
if self.date_of_birth and getdate(self.date_of_birth) > getdate(today()):
|
||||
throw(_("Date of Birth cannot be greater than today."))
|
||||
|
||||
if (
|
||||
self.date_of_birth
|
||||
and self.date_of_joining
|
||||
and getdate(self.date_of_birth) >= getdate(self.date_of_joining)
|
||||
):
|
||||
throw(_("Date of Joining must be greater than Date of Birth"))
|
||||
|
||||
elif (
|
||||
self.date_of_retirement
|
||||
and self.date_of_joining
|
||||
and (getdate(self.date_of_retirement) <= getdate(self.date_of_joining))
|
||||
):
|
||||
throw(_("Date Of Retirement must be greater than Date of Joining"))
|
||||
|
||||
elif (
|
||||
self.relieving_date
|
||||
and self.date_of_joining
|
||||
and (getdate(self.relieving_date) < getdate(self.date_of_joining))
|
||||
):
|
||||
throw(_("Relieving Date must be greater than or equal to Date of Joining"))
|
||||
|
||||
elif (
|
||||
self.contract_end_date
|
||||
and self.date_of_joining
|
||||
and (getdate(self.contract_end_date) <= getdate(self.date_of_joining))
|
||||
):
|
||||
throw(_("Contract End Date must be greater than Date of Joining"))
|
||||
|
||||
def validate_email(self):
|
||||
if self.company_email:
|
||||
validate_email_address(self.company_email, True)
|
||||
if self.personal_email:
|
||||
validate_email_address(self.personal_email, True)
|
||||
|
||||
def set_preferred_email(self):
|
||||
preferred_email_field = frappe.scrub(self.prefered_contact_email)
|
||||
if preferred_email_field:
|
||||
preferred_email = self.get(preferred_email_field)
|
||||
self.prefered_email = preferred_email
|
||||
|
||||
def validate_status(self):
|
||||
if self.status == "Left":
|
||||
reports_to = frappe.db.get_all(
|
||||
"Employee",
|
||||
filters={"reports_to": self.name, "status": "Active"},
|
||||
fields=["name", "employee_name"],
|
||||
)
|
||||
if reports_to:
|
||||
link_to_employees = [
|
||||
frappe.utils.get_link_to_form("Employee", employee.name, label=employee.employee_name)
|
||||
for employee in reports_to
|
||||
]
|
||||
message = _("The following employees are currently still reporting to {0}:").format(
|
||||
frappe.bold(self.employee_name)
|
||||
)
|
||||
message += "<br><br><ul><li>" + "</li><li>".join(link_to_employees)
|
||||
message += "</li></ul><br>"
|
||||
message += _("Please make sure the employees above report to another Active employee.")
|
||||
throw(message, InactiveEmployeeStatusError, _("Cannot Relieve Employee"))
|
||||
if not self.relieving_date:
|
||||
throw(_("Please enter relieving date."))
|
||||
|
||||
def validate_for_enabled_user_id(self, enabled):
|
||||
if not self.status == "Active":
|
||||
return
|
||||
|
||||
if enabled is None:
|
||||
frappe.throw(_("User {0} does not exist").format(self.user_id))
|
||||
if enabled == 0:
|
||||
frappe.throw(_("User {0} is disabled").format(self.user_id), EmployeeUserDisabledError)
|
||||
|
||||
def validate_duplicate_user_id(self):
|
||||
employee = frappe.db.sql_list(
|
||||
"""select name from `tabEmployee` where
|
||||
user_id=%s and status='Active' and name!=%s""",
|
||||
(self.user_id, self.name),
|
||||
)
|
||||
if employee:
|
||||
throw(
|
||||
_("User {0} is already assigned to Employee {1}").format(self.user_id, employee[0]),
|
||||
frappe.DuplicateEntryError,
|
||||
)
|
||||
|
||||
def validate_reports_to(self):
|
||||
if self.reports_to == self.name:
|
||||
throw(_("Employee cannot report to himself."))
|
||||
|
||||
def on_trash(self):
|
||||
self.update_nsm_model()
|
||||
delete_events(self.doctype, self.name)
|
||||
if frappe.db.exists("Employee Transfer", {"new_employee_id": self.name, "docstatus": 1}):
|
||||
emp_transfer = frappe.get_doc(
|
||||
"Employee Transfer", {"new_employee_id": self.name, "docstatus": 1}
|
||||
)
|
||||
emp_transfer.db_set("new_employee_id", "")
|
||||
|
||||
def validate_preferred_email(self):
|
||||
if self.prefered_contact_email and not self.get(scrub(self.prefered_contact_email)):
|
||||
frappe.msgprint(_("Please enter {0}").format(self.prefered_contact_email))
|
||||
|
||||
def validate_onboarding_process(self):
|
||||
employee_onboarding = frappe.get_all(
|
||||
"Employee Onboarding",
|
||||
filters={
|
||||
"job_applicant": self.job_applicant,
|
||||
"docstatus": 1,
|
||||
"boarding_status": ("!=", "Completed"),
|
||||
},
|
||||
)
|
||||
if employee_onboarding:
|
||||
doc = frappe.get_doc("Employee Onboarding", employee_onboarding[0].name)
|
||||
doc.validate_employee_creation()
|
||||
doc.db_set("employee", self.name)
|
||||
|
||||
def reset_employee_emails_cache(self):
|
||||
prev_doc = self.get_doc_before_save() or {}
|
||||
cell_number = cstr(self.get("cell_number"))
|
||||
prev_number = cstr(prev_doc.get("cell_number"))
|
||||
if cell_number != prev_number or self.get("user_id") != prev_doc.get("user_id"):
|
||||
frappe.cache().hdel("employees_with_number", cell_number)
|
||||
frappe.cache().hdel("employees_with_number", prev_number)
|
||||
|
||||
|
||||
def get_timeline_data(doctype, name):
|
||||
"""Return timeline for attendance"""
|
||||
return dict(
|
||||
frappe.db.sql(
|
||||
"""select unix_timestamp(attendance_date), count(*)
|
||||
from `tabAttendance` where employee=%s
|
||||
and attendance_date > date_sub(curdate(), interval 1 year)
|
||||
and status in ('Present', 'Half Day')
|
||||
group by attendance_date""",
|
||||
name,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_retirement_date(date_of_birth=None):
|
||||
ret = {}
|
||||
if date_of_birth:
|
||||
try:
|
||||
retirement_age = int(frappe.db.get_single_value("HR Settings", "retirement_age") or 60)
|
||||
dt = add_years(getdate(date_of_birth), retirement_age)
|
||||
ret = {"date_of_retirement": dt.strftime("%Y-%m-%d")}
|
||||
except ValueError:
|
||||
# invalid date
|
||||
ret = {}
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def validate_employee_role(doc, method):
|
||||
# called via User hook
|
||||
if "Employee" in [d.role for d in doc.get("roles")]:
|
||||
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("roles").remove(doc.get("roles", {"role": "Employee"})[0])
|
||||
|
||||
|
||||
def update_user_permissions(doc, method):
|
||||
# called via User hook
|
||||
if "Employee" in [d.role for d in doc.get("roles")]:
|
||||
if not has_permission("User Permission", ptype="write", raise_exception=False):
|
||||
return
|
||||
employee = frappe.get_doc("Employee", {"user_id": doc.name})
|
||||
employee.update_user_permissions()
|
||||
|
||||
|
||||
def get_employee_email(employee_doc):
|
||||
return (
|
||||
employee_doc.get("user_id")
|
||||
or employee_doc.get("personal_email")
|
||||
or employee_doc.get("company_email")
|
||||
)
|
||||
|
||||
|
||||
def get_holiday_list_for_employee(employee, raise_exception=True):
|
||||
if employee:
|
||||
holiday_list, company = frappe.db.get_value("Employee", employee, ["holiday_list", "company"])
|
||||
else:
|
||||
holiday_list = ""
|
||||
company = frappe.db.get_value("Global Defaults", None, "default_company")
|
||||
|
||||
if not holiday_list:
|
||||
holiday_list = frappe.get_cached_value("Company", company, "default_holiday_list")
|
||||
|
||||
if not holiday_list and raise_exception:
|
||||
frappe.throw(
|
||||
_("Please set a default Holiday List for Employee {0} or Company {1}").format(employee, company)
|
||||
)
|
||||
|
||||
return holiday_list
|
||||
|
||||
|
||||
def is_holiday(
|
||||
employee, date=None, raise_exception=True, only_non_weekly=False, with_description=False
|
||||
):
|
||||
"""
|
||||
Returns True if given Employee has an holiday on the given date
|
||||
:param employee: Employee `name`
|
||||
:param date: Date to check. Will check for today if None
|
||||
:param raise_exception: Raise an exception if no holiday list found, default is True
|
||||
:param only_non_weekly: Check only non-weekly holidays, default is False
|
||||
"""
|
||||
|
||||
holiday_list = get_holiday_list_for_employee(employee, raise_exception)
|
||||
if not date:
|
||||
date = today()
|
||||
|
||||
if not holiday_list:
|
||||
return False
|
||||
|
||||
filters = {"parent": holiday_list, "holiday_date": date}
|
||||
if only_non_weekly:
|
||||
filters["weekly_off"] = False
|
||||
|
||||
holidays = frappe.get_all("Holiday", fields=["description"], filters=filters, pluck="description")
|
||||
|
||||
if with_description:
|
||||
return len(holidays) > 0, holidays
|
||||
|
||||
return len(holidays) > 0
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def deactivate_sales_person(status=None, employee=None):
|
||||
if status == "Left":
|
||||
sales_person = frappe.db.get_value("Sales Person", {"Employee": employee})
|
||||
if sales_person:
|
||||
frappe.db.set_value("Sales Person", sales_person, "enabled", 0)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_user(employee, user=None, email=None):
|
||||
emp = frappe.get_doc("Employee", employee)
|
||||
|
||||
employee_name = emp.employee_name.split(" ")
|
||||
middle_name = last_name = ""
|
||||
|
||||
if len(employee_name) >= 3:
|
||||
last_name = " ".join(employee_name[2:])
|
||||
middle_name = employee_name[1]
|
||||
elif len(employee_name) == 2:
|
||||
last_name = employee_name[1]
|
||||
|
||||
first_name = employee_name[0]
|
||||
|
||||
if email:
|
||||
emp.prefered_email = email
|
||||
|
||||
user = frappe.new_doc("User")
|
||||
user.update(
|
||||
{
|
||||
"name": emp.employee_name,
|
||||
"email": emp.prefered_email,
|
||||
"enabled": 1,
|
||||
"first_name": first_name,
|
||||
"middle_name": middle_name,
|
||||
"last_name": last_name,
|
||||
"gender": emp.gender,
|
||||
"birth_date": emp.date_of_birth,
|
||||
"phone": emp.cell_number,
|
||||
"bio": emp.bio,
|
||||
}
|
||||
)
|
||||
user.insert()
|
||||
return user.name
|
||||
|
||||
|
||||
def get_all_employee_emails(company):
|
||||
"""Returns list of employee emails either based on user_id or company_email"""
|
||||
employee_list = frappe.get_all(
|
||||
"Employee", fields=["name", "employee_name"], filters={"status": "Active", "company": company}
|
||||
)
|
||||
employee_emails = []
|
||||
for employee in employee_list:
|
||||
if not employee:
|
||||
continue
|
||||
user, company_email, personal_email = frappe.db.get_value(
|
||||
"Employee", employee, ["user_id", "company_email", "personal_email"]
|
||||
)
|
||||
email = user or company_email or personal_email
|
||||
if email:
|
||||
employee_emails.append(email)
|
||||
return employee_emails
|
||||
|
||||
|
||||
def get_employee_emails(employee_list):
|
||||
"""Returns list of employee emails either based on user_id or company_email"""
|
||||
employee_emails = []
|
||||
for employee in employee_list:
|
||||
if not employee:
|
||||
continue
|
||||
user, company_email, personal_email = frappe.db.get_value(
|
||||
"Employee", employee, ["user_id", "company_email", "personal_email"]
|
||||
)
|
||||
email = user or company_email or personal_email
|
||||
if email:
|
||||
employee_emails.append(email)
|
||||
return employee_emails
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_children(doctype, parent=None, company=None, is_root=False, is_tree=False):
|
||||
|
||||
filters = [["status", "=", "Active"]]
|
||||
if company and company != "All Companies":
|
||||
filters.append(["company", "=", company])
|
||||
|
||||
fields = ["name as value", "employee_name as title"]
|
||||
|
||||
if is_root:
|
||||
parent = ""
|
||||
if parent and company and parent != company:
|
||||
filters.append(["reports_to", "=", parent])
|
||||
else:
|
||||
filters.append(["reports_to", "=", ""])
|
||||
|
||||
employees = frappe.get_list(doctype, fields=fields, filters=filters, order_by="name")
|
||||
|
||||
for employee in employees:
|
||||
is_expandable = frappe.get_all(doctype, filters=[["reports_to", "=", employee.get("value")]])
|
||||
employee.expandable = 1 if is_expandable else 0
|
||||
|
||||
return employees
|
||||
|
||||
|
||||
def on_doctype_update():
|
||||
frappe.db.add_index("Employee", ["lft", "rgt"])
|
||||
|
||||
|
||||
def has_user_permission_for_employee(user_name, employee_name):
|
||||
return frappe.db.exists(
|
||||
{
|
||||
"doctype": "User Permission",
|
||||
"user": user_name,
|
||||
"allow": "Employee",
|
||||
"for_value": employee_name,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def has_upload_permission(doc, ptype="read", user=None):
|
||||
if not user:
|
||||
user = frappe.session.user
|
||||
if get_doc_permissions(doc, user=user, ptype=ptype).get(ptype):
|
||||
return True
|
||||
return doc.user_id == user
|
||||
50
erpnext/setup/doctype/employee/employee_dashboard.py
Normal file
50
erpnext/setup/doctype/employee/employee_dashboard.py
Normal file
@@ -0,0 +1,50 @@
|
||||
from frappe import _
|
||||
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
"heatmap": True,
|
||||
"heatmap_message": _("This is based on the attendance of this Employee"),
|
||||
"fieldname": "employee",
|
||||
"non_standard_fieldnames": {"Bank Account": "party", "Employee Grievance": "raised_by"},
|
||||
"transactions": [
|
||||
{"label": _("Attendance"), "items": ["Attendance", "Attendance Request", "Employee Checkin"]},
|
||||
{
|
||||
"label": _("Leave"),
|
||||
"items": ["Leave Application", "Leave Allocation", "Leave Policy Assignment"],
|
||||
},
|
||||
{
|
||||
"label": _("Lifecycle"),
|
||||
"items": [
|
||||
"Employee Onboarding",
|
||||
"Employee Transfer",
|
||||
"Employee Promotion",
|
||||
"Employee Grievance",
|
||||
],
|
||||
},
|
||||
{
|
||||
"label": _("Exit"),
|
||||
"items": ["Employee Separation", "Exit Interview", "Full and Final Statement"],
|
||||
},
|
||||
{"label": _("Shift"), "items": ["Shift Request", "Shift Assignment"]},
|
||||
{"label": _("Expense"), "items": ["Expense Claim", "Travel Request", "Employee Advance"]},
|
||||
{"label": _("Benefit"), "items": ["Employee Benefit Application", "Employee Benefit Claim"]},
|
||||
{
|
||||
"label": _("Payroll"),
|
||||
"items": [
|
||||
"Salary Structure Assignment",
|
||||
"Salary Slip",
|
||||
"Additional Salary",
|
||||
"Timesheet",
|
||||
"Employee Incentive",
|
||||
"Retention Bonus",
|
||||
"Bank Account",
|
||||
],
|
||||
},
|
||||
{
|
||||
"label": _("Training"),
|
||||
"items": ["Training Event", "Training Result", "Training Feedback", "Employee Skill Map"],
|
||||
},
|
||||
{"label": _("Evaluation"), "items": ["Appraisal"]},
|
||||
],
|
||||
}
|
||||
9
erpnext/setup/doctype/employee/employee_list.js
Normal file
9
erpnext/setup/doctype/employee/employee_list.js
Normal file
@@ -0,0 +1,9 @@
|
||||
frappe.listview_settings['Employee'] = {
|
||||
add_fields: ["status", "branch", "department", "designation","image"],
|
||||
filters: [["status","=", "Active"]],
|
||||
get_indicator: function(doc) {
|
||||
var indicator = [__(doc.status), frappe.utils.guess_colour(doc.status), "status,=," + doc.status];
|
||||
indicator[1] = {"Active": "green", "Inactive": "red", "Left": "gray", "Suspended": "orange"}[doc.status];
|
||||
return indicator;
|
||||
}
|
||||
};
|
||||
274
erpnext/setup/doctype/employee/employee_reminders.py
Normal file
274
erpnext/setup/doctype/employee/employee_reminders.py
Normal file
@@ -0,0 +1,274 @@
|
||||
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import add_days, add_months, comma_sep, getdate, today
|
||||
|
||||
from erpnext.hr.doctype.employee.employee import get_all_employee_emails, get_employee_email
|
||||
from erpnext.hr.utils import get_holidays_for_employee
|
||||
|
||||
|
||||
# -----------------
|
||||
# HOLIDAY REMINDERS
|
||||
# -----------------
|
||||
def send_reminders_in_advance_weekly():
|
||||
to_send_in_advance = int(frappe.db.get_single_value("HR Settings", "send_holiday_reminders"))
|
||||
frequency = frappe.db.get_single_value("HR Settings", "frequency")
|
||||
if not (to_send_in_advance and frequency == "Weekly"):
|
||||
return
|
||||
|
||||
send_advance_holiday_reminders("Weekly")
|
||||
|
||||
|
||||
def send_reminders_in_advance_monthly():
|
||||
to_send_in_advance = int(frappe.db.get_single_value("HR Settings", "send_holiday_reminders"))
|
||||
frequency = frappe.db.get_single_value("HR Settings", "frequency")
|
||||
if not (to_send_in_advance and frequency == "Monthly"):
|
||||
return
|
||||
|
||||
send_advance_holiday_reminders("Monthly")
|
||||
|
||||
|
||||
def send_advance_holiday_reminders(frequency):
|
||||
"""Send Holiday Reminders in Advance to Employees
|
||||
`frequency` (str): 'Weekly' or 'Monthly'
|
||||
"""
|
||||
if frequency == "Weekly":
|
||||
start_date = getdate()
|
||||
end_date = add_days(getdate(), 7)
|
||||
elif frequency == "Monthly":
|
||||
# Sent on 1st of every month
|
||||
start_date = getdate()
|
||||
end_date = add_months(getdate(), 1)
|
||||
else:
|
||||
return
|
||||
|
||||
employees = frappe.db.get_all("Employee", filters={"status": "Active"}, pluck="name")
|
||||
for employee in employees:
|
||||
holidays = get_holidays_for_employee(
|
||||
employee, start_date, end_date, only_non_weekly=True, raise_exception=False
|
||||
)
|
||||
|
||||
send_holidays_reminder_in_advance(employee, holidays)
|
||||
|
||||
|
||||
def send_holidays_reminder_in_advance(employee, holidays):
|
||||
if not holidays:
|
||||
return
|
||||
|
||||
employee_doc = frappe.get_doc("Employee", employee)
|
||||
employee_email = get_employee_email(employee_doc)
|
||||
frequency = frappe.db.get_single_value("HR Settings", "frequency")
|
||||
|
||||
email_header = _("Holidays this Month.") if frequency == "Monthly" else _("Holidays this Week.")
|
||||
frappe.sendmail(
|
||||
recipients=[employee_email],
|
||||
subject=_("Upcoming Holidays Reminder"),
|
||||
template="holiday_reminder",
|
||||
args=dict(
|
||||
reminder_text=_("Hey {}! This email is to remind you about the upcoming holidays.").format(
|
||||
employee_doc.get("first_name")
|
||||
),
|
||||
message=_("Below is the list of upcoming holidays for you:"),
|
||||
advance_holiday_reminder=True,
|
||||
holidays=holidays,
|
||||
frequency=frequency[:-2],
|
||||
),
|
||||
header=email_header,
|
||||
)
|
||||
|
||||
|
||||
# ------------------
|
||||
# BIRTHDAY REMINDERS
|
||||
# ------------------
|
||||
def send_birthday_reminders():
|
||||
"""Send Employee birthday reminders if no 'Stop Birthday Reminders' is not set."""
|
||||
to_send = int(frappe.db.get_single_value("HR Settings", "send_birthday_reminders"))
|
||||
if not to_send:
|
||||
return
|
||||
|
||||
employees_born_today = get_employees_who_are_born_today()
|
||||
|
||||
for company, birthday_persons in employees_born_today.items():
|
||||
employee_emails = get_all_employee_emails(company)
|
||||
birthday_person_emails = [get_employee_email(doc) for doc in birthday_persons]
|
||||
recipients = list(set(employee_emails) - set(birthday_person_emails))
|
||||
|
||||
reminder_text, message = get_birthday_reminder_text_and_message(birthday_persons)
|
||||
send_birthday_reminder(recipients, reminder_text, birthday_persons, message)
|
||||
|
||||
if len(birthday_persons) > 1:
|
||||
# special email for people sharing birthdays
|
||||
for person in birthday_persons:
|
||||
person_email = person["user_id"] or person["personal_email"] or person["company_email"]
|
||||
others = [d for d in birthday_persons if d != person]
|
||||
reminder_text, message = get_birthday_reminder_text_and_message(others)
|
||||
send_birthday_reminder(person_email, reminder_text, others, message)
|
||||
|
||||
|
||||
def get_birthday_reminder_text_and_message(birthday_persons):
|
||||
if len(birthday_persons) == 1:
|
||||
birthday_person_text = birthday_persons[0]["name"]
|
||||
else:
|
||||
# converts ["Jim", "Rim", "Dim"] to Jim, Rim & Dim
|
||||
person_names = [d["name"] for d in birthday_persons]
|
||||
birthday_person_text = comma_sep(person_names, frappe._("{0} & {1}"), False)
|
||||
|
||||
reminder_text = _("Today is {0}'s birthday 🎉").format(birthday_person_text)
|
||||
message = _("A friendly reminder of an important date for our team.")
|
||||
message += "<br>"
|
||||
message += _("Everyone, let’s congratulate {0} on their birthday.").format(birthday_person_text)
|
||||
|
||||
return reminder_text, message
|
||||
|
||||
|
||||
def send_birthday_reminder(recipients, reminder_text, birthday_persons, message):
|
||||
frappe.sendmail(
|
||||
recipients=recipients,
|
||||
subject=_("Birthday Reminder"),
|
||||
template="birthday_reminder",
|
||||
args=dict(
|
||||
reminder_text=reminder_text,
|
||||
birthday_persons=birthday_persons,
|
||||
message=message,
|
||||
),
|
||||
header=_("Birthday Reminder 🎂"),
|
||||
)
|
||||
|
||||
|
||||
def get_employees_who_are_born_today():
|
||||
"""Get all employee born today & group them based on their company"""
|
||||
return get_employees_having_an_event_today("birthday")
|
||||
|
||||
|
||||
def get_employees_having_an_event_today(event_type):
|
||||
"""Get all employee who have `event_type` today
|
||||
& group them based on their company. `event_type`
|
||||
can be `birthday` or `work_anniversary`"""
|
||||
|
||||
from collections import defaultdict
|
||||
|
||||
# Set column based on event type
|
||||
if event_type == "birthday":
|
||||
condition_column = "date_of_birth"
|
||||
elif event_type == "work_anniversary":
|
||||
condition_column = "date_of_joining"
|
||||
else:
|
||||
return
|
||||
|
||||
employees_born_today = frappe.db.multisql(
|
||||
{
|
||||
"mariadb": f"""
|
||||
SELECT `personal_email`, `company`, `company_email`, `user_id`, `employee_name` AS 'name', `image`, `date_of_joining`
|
||||
FROM `tabEmployee`
|
||||
WHERE
|
||||
DAY({condition_column}) = DAY(%(today)s)
|
||||
AND
|
||||
MONTH({condition_column}) = MONTH(%(today)s)
|
||||
AND
|
||||
YEAR({condition_column}) < YEAR(%(today)s)
|
||||
AND
|
||||
`status` = 'Active'
|
||||
""",
|
||||
"postgres": f"""
|
||||
SELECT "personal_email", "company", "company_email", "user_id", "employee_name" AS 'name', "image"
|
||||
FROM "tabEmployee"
|
||||
WHERE
|
||||
DATE_PART('day', {condition_column}) = date_part('day', %(today)s)
|
||||
AND
|
||||
DATE_PART('month', {condition_column}) = date_part('month', %(today)s)
|
||||
AND
|
||||
DATE_PART('year', {condition_column}) < date_part('year', %(today)s)
|
||||
AND
|
||||
"status" = 'Active'
|
||||
""",
|
||||
},
|
||||
dict(today=today(), condition_column=condition_column),
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
grouped_employees = defaultdict(lambda: [])
|
||||
|
||||
for employee_doc in employees_born_today:
|
||||
grouped_employees[employee_doc.get("company")].append(employee_doc)
|
||||
|
||||
return grouped_employees
|
||||
|
||||
|
||||
# --------------------------
|
||||
# WORK ANNIVERSARY REMINDERS
|
||||
# --------------------------
|
||||
def send_work_anniversary_reminders():
|
||||
"""Send Employee Work Anniversary Reminders if 'Send Work Anniversary Reminders' is checked"""
|
||||
to_send = int(frappe.db.get_single_value("HR Settings", "send_work_anniversary_reminders"))
|
||||
if not to_send:
|
||||
return
|
||||
|
||||
employees_joined_today = get_employees_having_an_event_today("work_anniversary")
|
||||
|
||||
for company, anniversary_persons in employees_joined_today.items():
|
||||
employee_emails = get_all_employee_emails(company)
|
||||
anniversary_person_emails = [get_employee_email(doc) for doc in anniversary_persons]
|
||||
recipients = list(set(employee_emails) - set(anniversary_person_emails))
|
||||
|
||||
reminder_text, message = get_work_anniversary_reminder_text_and_message(anniversary_persons)
|
||||
send_work_anniversary_reminder(recipients, reminder_text, anniversary_persons, message)
|
||||
|
||||
if len(anniversary_persons) > 1:
|
||||
# email for people sharing work anniversaries
|
||||
for person in anniversary_persons:
|
||||
person_email = person["user_id"] or person["personal_email"] or person["company_email"]
|
||||
others = [d for d in anniversary_persons if d != person]
|
||||
reminder_text, message = get_work_anniversary_reminder_text_and_message(others)
|
||||
send_work_anniversary_reminder(person_email, reminder_text, others, message)
|
||||
|
||||
|
||||
def get_work_anniversary_reminder_text_and_message(anniversary_persons):
|
||||
if len(anniversary_persons) == 1:
|
||||
anniversary_person = anniversary_persons[0]["name"]
|
||||
persons_name = anniversary_person
|
||||
# Number of years completed at the company
|
||||
completed_years = getdate().year - anniversary_persons[0]["date_of_joining"].year
|
||||
anniversary_person += f" completed {get_pluralized_years(completed_years)}"
|
||||
else:
|
||||
person_names_with_years = []
|
||||
names = []
|
||||
for person in anniversary_persons:
|
||||
person_text = person["name"]
|
||||
names.append(person_text)
|
||||
# Number of years completed at the company
|
||||
completed_years = getdate().year - person["date_of_joining"].year
|
||||
person_text += f" completed {get_pluralized_years(completed_years)}"
|
||||
person_names_with_years.append(person_text)
|
||||
|
||||
# converts ["Jim", "Rim", "Dim"] to Jim, Rim & Dim
|
||||
anniversary_person = comma_sep(person_names_with_years, frappe._("{0} & {1}"), False)
|
||||
persons_name = comma_sep(names, frappe._("{0} & {1}"), False)
|
||||
|
||||
reminder_text = _("Today {0} at our Company! 🎉").format(anniversary_person)
|
||||
message = _("A friendly reminder of an important date for our team.")
|
||||
message += "<br>"
|
||||
message += _("Everyone, let’s congratulate {0} on their work anniversary!").format(persons_name)
|
||||
|
||||
return reminder_text, message
|
||||
|
||||
|
||||
def get_pluralized_years(years):
|
||||
if years == 1:
|
||||
return "1 year"
|
||||
return f"{years} years"
|
||||
|
||||
|
||||
def send_work_anniversary_reminder(recipients, reminder_text, anniversary_persons, message):
|
||||
frappe.sendmail(
|
||||
recipients=recipients,
|
||||
subject=_("Work Anniversary Reminder"),
|
||||
template="anniversary_reminder",
|
||||
args=dict(
|
||||
reminder_text=reminder_text,
|
||||
anniversary_persons=anniversary_persons,
|
||||
message=message,
|
||||
),
|
||||
header=_("Work Anniversary Reminder"),
|
||||
)
|
||||
36
erpnext/setup/doctype/employee/employee_tree.js
Normal file
36
erpnext/setup/doctype/employee/employee_tree.js
Normal file
@@ -0,0 +1,36 @@
|
||||
frappe.treeview_settings['Employee'] = {
|
||||
get_tree_nodes: "erpnext.hr.doctype.employee.employee.get_children",
|
||||
filters: [
|
||||
{
|
||||
fieldname: "company",
|
||||
fieldtype:"Select",
|
||||
options: ['All Companies'].concat(erpnext.utils.get_tree_options("company")),
|
||||
label: __("Company"),
|
||||
default: erpnext.utils.get_tree_default("company")
|
||||
}
|
||||
],
|
||||
breadcrumb: "Hr",
|
||||
disable_add_node: true,
|
||||
get_tree_root: false,
|
||||
toolbar: [
|
||||
{ toggle_btn: true },
|
||||
{
|
||||
label:__("Edit"),
|
||||
condition: function(node) {
|
||||
return !node.is_root;
|
||||
},
|
||||
click: function(node) {
|
||||
frappe.set_route("Form", "Employee", node.data.value);
|
||||
}
|
||||
}
|
||||
],
|
||||
menu_items: [
|
||||
{
|
||||
label: __("New Employee"),
|
||||
action: function() {
|
||||
frappe.new_doc("Employee", true);
|
||||
},
|
||||
condition: 'frappe.boot.user.can_create.indexOf("Employee") !== -1'
|
||||
}
|
||||
],
|
||||
};
|
||||
99
erpnext/setup/doctype/employee/test_employee.py
Normal file
99
erpnext/setup/doctype/employee/test_employee.py
Normal file
@@ -0,0 +1,99 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
import unittest
|
||||
|
||||
import frappe
|
||||
import frappe.utils
|
||||
|
||||
import erpnext
|
||||
from erpnext.hr.doctype.employee.employee import InactiveEmployeeStatusError
|
||||
|
||||
test_records = frappe.get_test_records("Employee")
|
||||
|
||||
|
||||
class TestEmployee(unittest.TestCase):
|
||||
def test_employee_status_left(self):
|
||||
employee1 = make_employee("test_employee_1@company.com")
|
||||
employee2 = make_employee("test_employee_2@company.com")
|
||||
employee1_doc = frappe.get_doc("Employee", employee1)
|
||||
employee2_doc = frappe.get_doc("Employee", employee2)
|
||||
employee2_doc.reload()
|
||||
employee2_doc.reports_to = employee1_doc.name
|
||||
employee2_doc.save()
|
||||
employee1_doc.reload()
|
||||
employee1_doc.status = "Left"
|
||||
self.assertRaises(InactiveEmployeeStatusError, employee1_doc.save)
|
||||
|
||||
def test_employee_status_inactive(self):
|
||||
from erpnext.payroll.doctype.salary_slip.test_salary_slip import make_holiday_list
|
||||
from erpnext.payroll.doctype.salary_structure.salary_structure import make_salary_slip
|
||||
from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure
|
||||
|
||||
employee = make_employee("test_employee_status@company.com")
|
||||
employee_doc = frappe.get_doc("Employee", employee)
|
||||
employee_doc.status = "Inactive"
|
||||
employee_doc.save()
|
||||
employee_doc.reload()
|
||||
|
||||
make_holiday_list()
|
||||
frappe.db.set_value(
|
||||
"Company", employee_doc.company, "default_holiday_list", "Salary Slip Test Holiday List"
|
||||
)
|
||||
|
||||
frappe.db.sql(
|
||||
"""delete from `tabSalary Structure` where name='Test Inactive Employee Salary Slip'"""
|
||||
)
|
||||
salary_structure = make_salary_structure(
|
||||
"Test Inactive Employee Salary Slip",
|
||||
"Monthly",
|
||||
employee=employee_doc.name,
|
||||
company=employee_doc.company,
|
||||
)
|
||||
salary_slip = make_salary_slip(salary_structure.name, employee=employee_doc.name)
|
||||
|
||||
self.assertRaises(InactiveEmployeeStatusError, salary_slip.save)
|
||||
|
||||
def tearDown(self):
|
||||
frappe.db.rollback()
|
||||
|
||||
|
||||
def make_employee(user, company=None, **kwargs):
|
||||
if not frappe.db.get_value("User", user):
|
||||
frappe.get_doc(
|
||||
{
|
||||
"doctype": "User",
|
||||
"email": user,
|
||||
"first_name": user,
|
||||
"new_password": "password",
|
||||
"send_welcome_email": 0,
|
||||
"roles": [{"doctype": "Has Role", "role": "Employee"}],
|
||||
}
|
||||
).insert()
|
||||
|
||||
if not frappe.db.get_value("Employee", {"user_id": user}):
|
||||
employee = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Employee",
|
||||
"naming_series": "EMP-",
|
||||
"first_name": user,
|
||||
"company": company or erpnext.get_default_company(),
|
||||
"user_id": user,
|
||||
"date_of_birth": "1990-05-08",
|
||||
"date_of_joining": "2013-01-01",
|
||||
"department": frappe.get_all("Department", fields="name")[0].name,
|
||||
"gender": "Female",
|
||||
"company_email": user,
|
||||
"prefered_contact_email": "Company Email",
|
||||
"prefered_email": user,
|
||||
"status": "Active",
|
||||
"employment_type": "Intern",
|
||||
}
|
||||
)
|
||||
if kwargs:
|
||||
employee.update(kwargs)
|
||||
employee.insert()
|
||||
return employee.name
|
||||
else:
|
||||
frappe.db.set_value("Employee", {"employee_name": user}, "status", "Active")
|
||||
return frappe.get_value("Employee", {"employee_name": user}, "name")
|
||||
268
erpnext/setup/doctype/employee/test_employee_reminders.py
Normal file
268
erpnext/setup/doctype/employee/test_employee_reminders.py
Normal file
@@ -0,0 +1,268 @@
|
||||
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
import unittest
|
||||
from datetime import timedelta
|
||||
|
||||
import frappe
|
||||
from frappe.utils import add_months, getdate
|
||||
|
||||
from erpnext.hr.doctype.employee.employee_reminders import send_holidays_reminder_in_advance
|
||||
from erpnext.hr.doctype.employee.test_employee import make_employee
|
||||
from erpnext.hr.doctype.hr_settings.hr_settings import set_proceed_with_frequency_change
|
||||
from erpnext.hr.utils import get_holidays_for_employee
|
||||
|
||||
|
||||
class TestEmployeeReminders(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
from erpnext.hr.doctype.holiday_list.test_holiday_list import make_holiday_list
|
||||
|
||||
# Create a test holiday list
|
||||
test_holiday_dates = cls.get_test_holiday_dates()
|
||||
test_holiday_list = make_holiday_list(
|
||||
"TestHolidayRemindersList",
|
||||
holiday_dates=[
|
||||
{"holiday_date": test_holiday_dates[0], "description": "test holiday1"},
|
||||
{"holiday_date": test_holiday_dates[1], "description": "test holiday2"},
|
||||
{"holiday_date": test_holiday_dates[2], "description": "test holiday3", "weekly_off": 1},
|
||||
{"holiday_date": test_holiday_dates[3], "description": "test holiday4"},
|
||||
{"holiday_date": test_holiday_dates[4], "description": "test holiday5"},
|
||||
{"holiday_date": test_holiday_dates[5], "description": "test holiday6"},
|
||||
],
|
||||
from_date=getdate() - timedelta(days=10),
|
||||
to_date=getdate() + timedelta(weeks=5),
|
||||
)
|
||||
|
||||
# Create a test employee
|
||||
test_employee = frappe.get_doc(
|
||||
"Employee", make_employee("test@gopher.io", company="_Test Company")
|
||||
)
|
||||
|
||||
# Attach the holiday list to employee
|
||||
test_employee.holiday_list = test_holiday_list.name
|
||||
test_employee.save()
|
||||
|
||||
# Attach to class
|
||||
cls.test_employee = test_employee
|
||||
cls.test_holiday_dates = test_holiday_dates
|
||||
|
||||
# Employee without holidays in this month/week
|
||||
test_employee_2 = make_employee("test@empwithoutholiday.io", company="_Test Company")
|
||||
test_employee_2 = frappe.get_doc("Employee", test_employee_2)
|
||||
|
||||
test_holiday_list = make_holiday_list(
|
||||
"TestHolidayRemindersList2",
|
||||
holiday_dates=[
|
||||
{"holiday_date": add_months(getdate(), 1), "description": "test holiday1"},
|
||||
],
|
||||
from_date=add_months(getdate(), -2),
|
||||
to_date=add_months(getdate(), 2),
|
||||
)
|
||||
test_employee_2.holiday_list = test_holiday_list.name
|
||||
test_employee_2.save()
|
||||
|
||||
cls.test_employee_2 = test_employee_2
|
||||
cls.holiday_list_2 = test_holiday_list
|
||||
|
||||
@classmethod
|
||||
def get_test_holiday_dates(cls):
|
||||
today_date = getdate()
|
||||
return [
|
||||
today_date,
|
||||
today_date - timedelta(days=4),
|
||||
today_date - timedelta(days=3),
|
||||
today_date + timedelta(days=1),
|
||||
today_date + timedelta(days=3),
|
||||
today_date + timedelta(weeks=3),
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
# Clear Email Queue
|
||||
frappe.db.sql("delete from `tabEmail Queue`")
|
||||
frappe.db.sql("delete from `tabEmail Queue Recipient`")
|
||||
|
||||
def test_is_holiday(self):
|
||||
from erpnext.hr.doctype.employee.employee import is_holiday
|
||||
|
||||
self.assertTrue(is_holiday(self.test_employee.name))
|
||||
self.assertTrue(is_holiday(self.test_employee.name, date=self.test_holiday_dates[1]))
|
||||
self.assertFalse(is_holiday(self.test_employee.name, date=getdate() - timedelta(days=1)))
|
||||
|
||||
# Test weekly_off holidays
|
||||
self.assertTrue(is_holiday(self.test_employee.name, date=self.test_holiday_dates[2]))
|
||||
self.assertFalse(
|
||||
is_holiday(self.test_employee.name, date=self.test_holiday_dates[2], only_non_weekly=True)
|
||||
)
|
||||
|
||||
# Test with descriptions
|
||||
has_holiday, descriptions = is_holiday(self.test_employee.name, with_description=True)
|
||||
self.assertTrue(has_holiday)
|
||||
self.assertTrue("test holiday1" in descriptions)
|
||||
|
||||
def test_birthday_reminders(self):
|
||||
employee = frappe.get_doc(
|
||||
"Employee", frappe.db.sql_list("select name from tabEmployee limit 1")[0]
|
||||
)
|
||||
employee.date_of_birth = "1992" + frappe.utils.nowdate()[4:]
|
||||
employee.company_email = "test@example.com"
|
||||
employee.company = "_Test Company"
|
||||
employee.save()
|
||||
|
||||
from erpnext.hr.doctype.employee.employee_reminders import (
|
||||
get_employees_who_are_born_today,
|
||||
send_birthday_reminders,
|
||||
)
|
||||
|
||||
employees_born_today = get_employees_who_are_born_today()
|
||||
self.assertTrue(employees_born_today.get("_Test Company"))
|
||||
|
||||
hr_settings = frappe.get_doc("HR Settings", "HR Settings")
|
||||
hr_settings.send_birthday_reminders = 1
|
||||
hr_settings.save()
|
||||
|
||||
send_birthday_reminders()
|
||||
|
||||
email_queue = frappe.db.sql("""select * from `tabEmail Queue`""", as_dict=True)
|
||||
self.assertTrue("Subject: Birthday Reminder" in email_queue[0].message)
|
||||
|
||||
def test_work_anniversary_reminders(self):
|
||||
make_employee(
|
||||
"test_work_anniversary@gmail.com",
|
||||
date_of_joining="1998" + frappe.utils.nowdate()[4:],
|
||||
company="_Test Company",
|
||||
)
|
||||
|
||||
from erpnext.hr.doctype.employee.employee_reminders import (
|
||||
get_employees_having_an_event_today,
|
||||
send_work_anniversary_reminders,
|
||||
)
|
||||
|
||||
employees_having_work_anniversary = get_employees_having_an_event_today("work_anniversary")
|
||||
employees = employees_having_work_anniversary.get("_Test Company") or []
|
||||
user_ids = []
|
||||
for entry in employees:
|
||||
user_ids.append(entry.user_id)
|
||||
|
||||
self.assertTrue("test_work_anniversary@gmail.com" in user_ids)
|
||||
|
||||
hr_settings = frappe.get_doc("HR Settings", "HR Settings")
|
||||
hr_settings.send_work_anniversary_reminders = 1
|
||||
hr_settings.save()
|
||||
|
||||
send_work_anniversary_reminders()
|
||||
|
||||
email_queue = frappe.db.sql("""select * from `tabEmail Queue`""", as_dict=True)
|
||||
self.assertTrue("Subject: Work Anniversary Reminder" in email_queue[0].message)
|
||||
|
||||
def test_work_anniversary_reminder_not_sent_for_0_years(self):
|
||||
make_employee(
|
||||
"test_work_anniversary_2@gmail.com",
|
||||
date_of_joining=getdate(),
|
||||
company="_Test Company",
|
||||
)
|
||||
|
||||
from erpnext.hr.doctype.employee.employee_reminders import get_employees_having_an_event_today
|
||||
|
||||
employees_having_work_anniversary = get_employees_having_an_event_today("work_anniversary")
|
||||
employees = employees_having_work_anniversary.get("_Test Company") or []
|
||||
user_ids = []
|
||||
for entry in employees:
|
||||
user_ids.append(entry.user_id)
|
||||
|
||||
self.assertTrue("test_work_anniversary_2@gmail.com" not in user_ids)
|
||||
|
||||
def test_send_holidays_reminder_in_advance(self):
|
||||
setup_hr_settings("Weekly")
|
||||
|
||||
holidays = get_holidays_for_employee(
|
||||
self.test_employee.get("name"),
|
||||
getdate(),
|
||||
getdate() + timedelta(days=3),
|
||||
only_non_weekly=True,
|
||||
raise_exception=False,
|
||||
)
|
||||
|
||||
send_holidays_reminder_in_advance(self.test_employee.get("name"), holidays)
|
||||
|
||||
email_queue = frappe.db.sql("""select * from `tabEmail Queue`""", as_dict=True)
|
||||
self.assertEqual(len(email_queue), 1)
|
||||
self.assertTrue("Holidays this Week." in email_queue[0].message)
|
||||
|
||||
def test_advance_holiday_reminders_monthly(self):
|
||||
from erpnext.hr.doctype.employee.employee_reminders import send_reminders_in_advance_monthly
|
||||
|
||||
setup_hr_settings("Monthly")
|
||||
|
||||
# disable emp 2, set same holiday list
|
||||
frappe.db.set_value(
|
||||
"Employee",
|
||||
self.test_employee_2.name,
|
||||
{"status": "Left", "holiday_list": self.test_employee.holiday_list},
|
||||
)
|
||||
|
||||
send_reminders_in_advance_monthly()
|
||||
email_queue = frappe.db.sql("""select * from `tabEmail Queue`""", as_dict=True)
|
||||
self.assertTrue(len(email_queue) > 0)
|
||||
|
||||
# even though emp 2 has holiday, non-active employees should not be recipients
|
||||
recipients = frappe.db.get_all("Email Queue Recipient", pluck="recipient")
|
||||
self.assertTrue(self.test_employee_2.user_id not in recipients)
|
||||
|
||||
# teardown: enable emp 2
|
||||
frappe.db.set_value(
|
||||
"Employee",
|
||||
self.test_employee_2.name,
|
||||
{"status": "Active", "holiday_list": self.holiday_list_2.name},
|
||||
)
|
||||
|
||||
def test_advance_holiday_reminders_weekly(self):
|
||||
from erpnext.hr.doctype.employee.employee_reminders import send_reminders_in_advance_weekly
|
||||
|
||||
setup_hr_settings("Weekly")
|
||||
|
||||
# disable emp 2, set same holiday list
|
||||
frappe.db.set_value(
|
||||
"Employee",
|
||||
self.test_employee_2.name,
|
||||
{"status": "Left", "holiday_list": self.test_employee.holiday_list},
|
||||
)
|
||||
|
||||
send_reminders_in_advance_weekly()
|
||||
email_queue = frappe.db.sql("""select * from `tabEmail Queue`""", as_dict=True)
|
||||
self.assertTrue(len(email_queue) > 0)
|
||||
|
||||
# even though emp 2 has holiday, non-active employees should not be recipients
|
||||
recipients = frappe.db.get_all("Email Queue Recipient", pluck="recipient")
|
||||
self.assertTrue(self.test_employee_2.user_id not in recipients)
|
||||
|
||||
# teardown: enable emp 2
|
||||
frappe.db.set_value(
|
||||
"Employee",
|
||||
self.test_employee_2.name,
|
||||
{"status": "Active", "holiday_list": self.holiday_list_2.name},
|
||||
)
|
||||
|
||||
def test_reminder_not_sent_if_no_holdays(self):
|
||||
setup_hr_settings("Monthly")
|
||||
|
||||
# reminder not sent if there are no holidays
|
||||
holidays = get_holidays_for_employee(
|
||||
self.test_employee_2.get("name"),
|
||||
getdate(),
|
||||
getdate() + timedelta(days=3),
|
||||
only_non_weekly=True,
|
||||
raise_exception=False,
|
||||
)
|
||||
send_holidays_reminder_in_advance(self.test_employee_2.get("name"), holidays)
|
||||
email_queue = frappe.db.sql("""select * from `tabEmail Queue`""", as_dict=True)
|
||||
self.assertEqual(len(email_queue), 0)
|
||||
|
||||
|
||||
def setup_hr_settings(frequency=None):
|
||||
# Get HR settings and enable advance holiday reminders
|
||||
hr_settings = frappe.get_doc("HR Settings", "HR Settings")
|
||||
hr_settings.send_holiday_reminders = 1
|
||||
set_proceed_with_frequency_change()
|
||||
hr_settings.frequency = frequency or "Weekly"
|
||||
hr_settings.save()
|
||||
38
erpnext/setup/doctype/employee/test_records.json
Normal file
38
erpnext/setup/doctype/employee/test_records.json
Normal file
@@ -0,0 +1,38 @@
|
||||
[
|
||||
{
|
||||
"company": "_Test Company",
|
||||
"date_of_birth": "1980-01-01",
|
||||
"date_of_joining": "2010-01-01",
|
||||
"department": "_Test Department - _TC",
|
||||
"doctype": "Employee",
|
||||
"first_name": "_Test Employee",
|
||||
"gender": "Female",
|
||||
"naming_series": "_T-Employee-",
|
||||
"status": "Active",
|
||||
"user_id": "test@example.com"
|
||||
},
|
||||
{
|
||||
"company": "_Test Company",
|
||||
"date_of_birth": "1980-01-01",
|
||||
"date_of_joining": "2010-01-01",
|
||||
"department": "_Test Department 1 - _TC",
|
||||
"doctype": "Employee",
|
||||
"first_name": "_Test Employee 1",
|
||||
"gender": "Male",
|
||||
"naming_series": "_T-Employee-",
|
||||
"status": "Active",
|
||||
"user_id": "test1@example.com"
|
||||
},
|
||||
{
|
||||
"company": "_Test Company",
|
||||
"date_of_birth": "1980-01-01",
|
||||
"date_of_joining": "2010-01-01",
|
||||
"department": "_Test Department 1 - _TC",
|
||||
"doctype": "Employee",
|
||||
"first_name": "_Test Employee 2",
|
||||
"gender": "Male",
|
||||
"naming_series": "_T-Employee-",
|
||||
"status": "Active",
|
||||
"user_id": "test2@example.com"
|
||||
}
|
||||
]
|
||||
1
erpnext/setup/doctype/employee_education/README.md
Normal file
1
erpnext/setup/doctype/employee_education/README.md
Normal file
@@ -0,0 +1 @@
|
||||
Education detail for parent Employee.
|
||||
192
erpnext/setup/doctype/employee_education/employee_education.json
Normal file
192
erpnext/setup/doctype/employee_education/employee_education.json
Normal file
@@ -0,0 +1,192 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2013-02-22 01:27:45",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "school_univ",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "School/University",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "school_univ",
|
||||
"oldfieldtype": "Small Text",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "qualification",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Qualification",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "qualification",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "100px",
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0,
|
||||
"width": "100px"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "level",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Level",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "level",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Graduate\nPost Graduate\nUnder Graduate",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "year_of_passing",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Year of Passing",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "year_of_passing",
|
||||
"oldfieldtype": "Int",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "class_per",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Class / Percentage",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "class_per",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "maj_opt_subj",
|
||||
"fieldtype": "Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Major/Optional Subjects",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "maj_opt_subj",
|
||||
"oldfieldtype": "Text",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-07-11 03:27:59.995464",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee Education",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"track_seen": 0
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class EmployeeEducation(Document):
|
||||
pass
|
||||
@@ -0,0 +1 @@
|
||||
External work history details of parent Employee.
|
||||
@@ -0,0 +1,190 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2013-02-22 01:27:45",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "company_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Company",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "company_name",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "designation",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Designation",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "designation",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "salary",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Salary",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "salary",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "address",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Address",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "address",
|
||||
"oldfieldtype": "Small Text",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "contact",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Contact",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "contact",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "total_experience",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Total Experience",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "total_experience",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-07-11 03:28:00.088980",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee External Work History",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"track_seen": 0
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class EmployeeExternalWorkHistory(Document):
|
||||
pass
|
||||
0
erpnext/setup/doctype/employee_group/__init__.py
Normal file
0
erpnext/setup/doctype/employee_group/__init__.py
Normal file
6
erpnext/setup/doctype/employee_group/employee_group.js
Normal file
6
erpnext/setup/doctype/employee_group/employee_group.js
Normal file
@@ -0,0 +1,6 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Employee Group', {
|
||||
|
||||
});
|
||||
162
erpnext/setup/doctype/employee_group/employee_group.json
Normal file
162
erpnext/setup/doctype/employee_group/employee_group.json
Normal file
@@ -0,0 +1,162 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"autoname": "field:employee_group_name",
|
||||
"beta": 0,
|
||||
"creation": "2018-11-19 12:33:31.351364",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "employee_group_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_00",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Employee",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "employee_list",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Employee",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Employee Group Table",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-12-27 19:52:34.791538",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee Group",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
||||
9
erpnext/setup/doctype/employee_group/employee_group.py
Normal file
9
erpnext/setup/doctype/employee_group/employee_group.py
Normal file
@@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class EmployeeGroup(Document):
|
||||
pass
|
||||
34
erpnext/setup/doctype/employee_group/test_employee_group.py
Normal file
34
erpnext/setup/doctype/employee_group/test_employee_group.py
Normal file
@@ -0,0 +1,34 @@
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
|
||||
import unittest
|
||||
|
||||
import frappe
|
||||
|
||||
from erpnext.hr.doctype.employee.test_employee import make_employee
|
||||
|
||||
|
||||
class TestEmployeeGroup(unittest.TestCase):
|
||||
pass
|
||||
|
||||
|
||||
def make_employee_group():
|
||||
employee = make_employee("testemployee@example.com")
|
||||
employee_group = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Employee Group",
|
||||
"employee_group_name": "_Test Employee Group",
|
||||
"employee_list": [{"employee": employee}],
|
||||
}
|
||||
)
|
||||
employee_group_exist = frappe.db.exists("Employee Group", "_Test Employee Group")
|
||||
if not employee_group_exist:
|
||||
employee_group.insert()
|
||||
return employee_group.employee_group_name
|
||||
else:
|
||||
return employee_group_exist
|
||||
|
||||
|
||||
def get_employee_group():
|
||||
employee_group = frappe.db.exists("Employee Group", "_Test Employee Group")
|
||||
return employee_group
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"creation": "2018-11-19 12:39:46.153061",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"employee",
|
||||
"employee_name",
|
||||
"user_id"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "employee",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Employee",
|
||||
"options": "Employee"
|
||||
},
|
||||
{
|
||||
"fetch_from": "employee.first_name",
|
||||
"fieldname": "employee_name",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Employee Name"
|
||||
},
|
||||
{
|
||||
"fetch_from": "employee.user_id",
|
||||
"fieldname": "user_id",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "ERPNext User ID",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"istable": 1,
|
||||
"modified": "2022-02-13 19:44:21.302938",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee Group Table",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class EmployeeGroupTable(Document):
|
||||
pass
|
||||
@@ -0,0 +1 @@
|
||||
Work history details of parent Employee within the organization.
|
||||
@@ -0,0 +1,168 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2013-02-22 01:27:45",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "branch",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Branch",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "branch",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Branch",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "department",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Department",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "department",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Department",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "designation",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Designation",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "designation",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Designation",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "from_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "From Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "from_date",
|
||||
"oldfieldtype": "Date",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "to_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "To Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "to_date",
|
||||
"oldfieldtype": "Date",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-07-11 03:28:00.195130",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee Internal Work History",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_seen": 0
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class EmployeeInternalWorkHistory(Document):
|
||||
pass
|
||||
1
erpnext/setup/doctype/holiday/README.md
Normal file
1
erpnext/setup/doctype/holiday/README.md
Normal file
@@ -0,0 +1 @@
|
||||
Holiday date in Holiday List.
|
||||
0
erpnext/setup/doctype/holiday/__init__.py
Normal file
0
erpnext/setup/doctype/holiday/__init__.py
Normal file
60
erpnext/setup/doctype/holiday/holiday.json
Normal file
60
erpnext/setup/doctype/holiday/holiday.json
Normal file
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2013-02-22 01:27:46",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"holiday_date",
|
||||
"column_break_2",
|
||||
"weekly_off",
|
||||
"section_break_4",
|
||||
"description"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "holiday_date",
|
||||
"fieldtype": "Date",
|
||||
"in_list_view": 1,
|
||||
"label": "Date",
|
||||
"oldfieldname": "holiday_date",
|
||||
"oldfieldtype": "Date",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text Editor",
|
||||
"in_list_view": 1,
|
||||
"label": "Description",
|
||||
"print_width": "300px",
|
||||
"reqd": 1,
|
||||
"width": "300px"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "weekly_off",
|
||||
"fieldtype": "Check",
|
||||
"label": "Weekly Off"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_4",
|
||||
"fieldtype": "Section Break"
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-04-18 19:03:23.507845",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Holiday",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "ASC"
|
||||
}
|
||||
9
erpnext/setup/doctype/holiday/holiday.py
Normal file
9
erpnext/setup/doctype/holiday/holiday.py
Normal file
@@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class Holiday(Document):
|
||||
pass
|
||||
1
erpnext/setup/doctype/holiday_list/README.md
Normal file
1
erpnext/setup/doctype/holiday_list/README.md
Normal file
@@ -0,0 +1 @@
|
||||
List of Holidays.
|
||||
0
erpnext/setup/doctype/holiday_list/__init__.py
Normal file
0
erpnext/setup/doctype/holiday_list/__init__.py
Normal file
49
erpnext/setup/doctype/holiday_list/holiday_list.js
Normal file
49
erpnext/setup/doctype/holiday_list/holiday_list.js
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on("Holiday List", {
|
||||
refresh: function(frm) {
|
||||
if (frm.doc.holidays) {
|
||||
frm.set_value("total_holidays", frm.doc.holidays.length);
|
||||
}
|
||||
},
|
||||
from_date: function(frm) {
|
||||
if (frm.doc.from_date && !frm.doc.to_date) {
|
||||
var a_year_from_start = frappe.datetime.add_months(frm.doc.from_date, 12);
|
||||
frm.set_value("to_date", frappe.datetime.add_days(a_year_from_start, -1));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
frappe.tour["Holiday List"] = [
|
||||
{
|
||||
fieldname: "holiday_list_name",
|
||||
title: "Holiday List Name",
|
||||
description: __("Enter a name for this Holiday List."),
|
||||
},
|
||||
{
|
||||
fieldname: "from_date",
|
||||
title: "From Date",
|
||||
description: __("Based on your HR Policy, select your leave allocation period's start date"),
|
||||
},
|
||||
{
|
||||
fieldname: "to_date",
|
||||
title: "To Date",
|
||||
description: __("Based on your HR Policy, select your leave allocation period's end date"),
|
||||
},
|
||||
{
|
||||
fieldname: "weekly_off",
|
||||
title: "Weekly Off",
|
||||
description: __("Select your weekly off day"),
|
||||
},
|
||||
{
|
||||
fieldname: "get_weekly_off_dates",
|
||||
title: "Add Holidays",
|
||||
description: __("Click on Add to Holidays. This will populate the holidays table with all the dates that fall on the selected weekly off. Repeat the process for populating the dates for all your weekly holidays"),
|
||||
},
|
||||
{
|
||||
fieldname: "holidays",
|
||||
title: "Holidays",
|
||||
description: __("Here, your weekly offs are pre-populated based on the previous selections. You can add more rows to also add public and national holidays individually.")
|
||||
},
|
||||
];
|
||||
480
erpnext/setup/doctype/holiday_list/holiday_list.json
Normal file
480
erpnext/setup/doctype/holiday_list/holiday_list.json
Normal file
@@ -0,0 +1,480 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:holiday_list_name",
|
||||
"beta": 0,
|
||||
"creation": "2013-01-10 16:34:14",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"editable_grid": 0,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "holiday_list_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Holiday List Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "holiday_list_name",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "from_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "From Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "to_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "To Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "total_holidays",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Total Holidays",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"fieldname": "add_weekly_holidays",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Add Weekly Holidays",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "weekly_off",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Weekly Off",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "\nSunday\nMonday\nTuesday\nWednesday\nThursday\nFriday\nSaturday",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "get_weekly_off_dates",
|
||||
"fieldtype": "Button",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Add to Holidays",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "get_weekly_off_dates",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "holidays_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Holidays",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "holidays",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Holidays",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "holiday_list_details",
|
||||
"oldfieldtype": "Table",
|
||||
"options": "Holiday",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "clear_table",
|
||||
"fieldtype": "Button",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Clear Table",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "clear_table",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_9",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "color",
|
||||
"fieldtype": "Color",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Color",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "fa fa-calendar",
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-07-03 07:22:46.474096",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Holiday List",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "HR Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
||||
120
erpnext/setup/doctype/holiday_list/holiday_list.py
Normal file
120
erpnext/setup/doctype/holiday_list/holiday_list.py
Normal file
@@ -0,0 +1,120 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
import json
|
||||
|
||||
import frappe
|
||||
from frappe import _, throw
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import cint, formatdate, getdate, today
|
||||
|
||||
|
||||
class OverlapError(frappe.ValidationError):
|
||||
pass
|
||||
|
||||
|
||||
class HolidayList(Document):
|
||||
def validate(self):
|
||||
self.validate_days()
|
||||
self.total_holidays = len(self.holidays)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_weekly_off_dates(self):
|
||||
self.validate_values()
|
||||
date_list = self.get_weekly_off_date_list(self.from_date, self.to_date)
|
||||
last_idx = max(
|
||||
[cint(d.idx) for d in self.get("holidays")]
|
||||
or [
|
||||
0,
|
||||
]
|
||||
)
|
||||
for i, d in enumerate(date_list):
|
||||
ch = self.append("holidays", {})
|
||||
ch.description = _(self.weekly_off)
|
||||
ch.holiday_date = d
|
||||
ch.weekly_off = 1
|
||||
ch.idx = last_idx + i + 1
|
||||
|
||||
def validate_values(self):
|
||||
if not self.weekly_off:
|
||||
throw(_("Please select weekly off day"))
|
||||
|
||||
def validate_days(self):
|
||||
if getdate(self.from_date) > getdate(self.to_date):
|
||||
throw(_("To Date cannot be before From Date"))
|
||||
|
||||
for day in self.get("holidays"):
|
||||
if not (getdate(self.from_date) <= getdate(day.holiday_date) <= getdate(self.to_date)):
|
||||
frappe.throw(
|
||||
_("The holiday on {0} is not between From Date and To Date").format(
|
||||
formatdate(day.holiday_date)
|
||||
)
|
||||
)
|
||||
|
||||
def get_weekly_off_date_list(self, start_date, end_date):
|
||||
start_date, end_date = getdate(start_date), getdate(end_date)
|
||||
|
||||
import calendar
|
||||
from datetime import timedelta
|
||||
|
||||
from dateutil import relativedelta
|
||||
|
||||
date_list = []
|
||||
existing_date_list = []
|
||||
weekday = getattr(calendar, (self.weekly_off).upper())
|
||||
reference_date = start_date + relativedelta.relativedelta(weekday=weekday)
|
||||
|
||||
existing_date_list = [getdate(holiday.holiday_date) for holiday in self.get("holidays")]
|
||||
|
||||
while reference_date <= end_date:
|
||||
if reference_date not in existing_date_list:
|
||||
date_list.append(reference_date)
|
||||
reference_date += timedelta(days=7)
|
||||
|
||||
return date_list
|
||||
|
||||
@frappe.whitelist()
|
||||
def clear_table(self):
|
||||
self.set("holidays", [])
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_events(start, end, filters=None):
|
||||
"""Returns events for Gantt / Calendar view rendering.
|
||||
|
||||
:param start: Start date-time.
|
||||
:param end: End date-time.
|
||||
:param filters: Filters (JSON).
|
||||
"""
|
||||
if filters:
|
||||
filters = json.loads(filters)
|
||||
else:
|
||||
filters = []
|
||||
|
||||
if start:
|
||||
filters.append(["Holiday", "holiday_date", ">", getdate(start)])
|
||||
if end:
|
||||
filters.append(["Holiday", "holiday_date", "<", getdate(end)])
|
||||
|
||||
return frappe.get_list(
|
||||
"Holiday List",
|
||||
fields=[
|
||||
"name",
|
||||
"`tabHoliday`.holiday_date",
|
||||
"`tabHoliday`.description",
|
||||
"`tabHoliday List`.color",
|
||||
],
|
||||
filters=filters,
|
||||
update={"allDay": 1},
|
||||
)
|
||||
|
||||
|
||||
def is_holiday(holiday_list, date=None):
|
||||
"""Returns true if the given date is a holiday in the given holiday list"""
|
||||
if date is None:
|
||||
date = today()
|
||||
if holiday_list:
|
||||
return bool(frappe.get_all("Holiday List", dict(name=holiday_list, holiday_date=date)))
|
||||
else:
|
||||
return False
|
||||
22
erpnext/setup/doctype/holiday_list/holiday_list_calendar.js
Normal file
22
erpnext/setup/doctype/holiday_list/holiday_list_calendar.js
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.views.calendar["Holiday List"] = {
|
||||
field_map: {
|
||||
"start": "holiday_date",
|
||||
"end": "holiday_date",
|
||||
"id": "name",
|
||||
"title": "description",
|
||||
"allDay": "allDay"
|
||||
},
|
||||
order_by: `from_date`,
|
||||
get_events_method: "erpnext.hr.doctype.holiday_list.holiday_list.get_events",
|
||||
filters: [
|
||||
{
|
||||
'fieldtype': 'Link',
|
||||
'fieldname': 'holiday_list',
|
||||
'options': 'Holiday List',
|
||||
'label': __('Holiday List')
|
||||
}
|
||||
]
|
||||
}
|
||||
15
erpnext/setup/doctype/holiday_list/holiday_list_dashboard.py
Normal file
15
erpnext/setup/doctype/holiday_list/holiday_list_dashboard.py
Normal file
@@ -0,0 +1,15 @@
|
||||
def get_data():
|
||||
return {
|
||||
"fieldname": "holiday_list",
|
||||
"non_standard_fieldnames": {
|
||||
"Company": "default_holiday_list",
|
||||
"Leave Period": "optional_holiday_list",
|
||||
},
|
||||
"transactions": [
|
||||
{
|
||||
"items": ["Company", "Employee", "Workstation"],
|
||||
},
|
||||
{"items": ["Leave Period", "Shift Type"]},
|
||||
{"items": ["Service Level", "Service Level Agreement"]},
|
||||
],
|
||||
}
|
||||
61
erpnext/setup/doctype/holiday_list/test_holiday_list.py
Normal file
61
erpnext/setup/doctype/holiday_list/test_holiday_list.py
Normal file
@@ -0,0 +1,61 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
import unittest
|
||||
from contextlib import contextmanager
|
||||
from datetime import timedelta
|
||||
|
||||
import frappe
|
||||
from frappe.utils import getdate
|
||||
|
||||
|
||||
class TestHolidayList(unittest.TestCase):
|
||||
def test_holiday_list(self):
|
||||
today_date = getdate()
|
||||
test_holiday_dates = [today_date - timedelta(days=5), today_date - timedelta(days=4)]
|
||||
holiday_list = make_holiday_list(
|
||||
"test_holiday_list",
|
||||
holiday_dates=[
|
||||
{"holiday_date": test_holiday_dates[0], "description": "test holiday"},
|
||||
{"holiday_date": test_holiday_dates[1], "description": "test holiday2"},
|
||||
],
|
||||
)
|
||||
fetched_holiday_list = frappe.get_value("Holiday List", holiday_list.name)
|
||||
self.assertEqual(holiday_list.name, fetched_holiday_list)
|
||||
|
||||
|
||||
def make_holiday_list(
|
||||
name, from_date=getdate() - timedelta(days=10), to_date=getdate(), holiday_dates=None
|
||||
):
|
||||
frappe.delete_doc_if_exists("Holiday List", name, force=1)
|
||||
doc = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Holiday List",
|
||||
"holiday_list_name": name,
|
||||
"from_date": from_date,
|
||||
"to_date": to_date,
|
||||
"holidays": holiday_dates,
|
||||
}
|
||||
).insert()
|
||||
return doc
|
||||
|
||||
|
||||
@contextmanager
|
||||
def set_holiday_list(holiday_list, company_name):
|
||||
"""
|
||||
Context manager for setting holiday list in tests
|
||||
"""
|
||||
try:
|
||||
company = frappe.get_doc("Company", company_name)
|
||||
previous_holiday_list = company.default_holiday_list
|
||||
|
||||
company.default_holiday_list = holiday_list
|
||||
company.save()
|
||||
|
||||
yield
|
||||
|
||||
finally:
|
||||
# restore holiday list setup
|
||||
company = frappe.get_doc("Company", company_name)
|
||||
company.default_holiday_list = previous_holiday_list
|
||||
company.save()
|
||||
22
erpnext/setup/doctype/holiday_list/test_records.json
Normal file
22
erpnext/setup/doctype/holiday_list/test_records.json
Normal file
@@ -0,0 +1,22 @@
|
||||
[
|
||||
{
|
||||
"doctype": "Holiday List",
|
||||
"from_date": "2013-01-01",
|
||||
"to_date":"2013-12-31",
|
||||
"holidays": [
|
||||
{
|
||||
"description": "New Year",
|
||||
"holiday_date": "2013-01-01"
|
||||
},
|
||||
{
|
||||
"description": "Republic Day",
|
||||
"holiday_date": "2013-01-26"
|
||||
},
|
||||
{
|
||||
"description": "Test Holiday",
|
||||
"holiday_date": "2013-02-01"
|
||||
}
|
||||
],
|
||||
"holiday_list_name": "_Test Holiday List"
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user