fix: HR dashboard and onboarding
diff --git a/erpnext/hr/dashboard_fixtures.py b/erpnext/hr/dashboard_fixtures.py
new file mode 100644
index 0000000..004477c
--- /dev/null
+++ b/erpnext/hr/dashboard_fixtures.py
@@ -0,0 +1,228 @@
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+import frappe
+import erpnext
+import json
+from frappe import _
+
+def get_data():
+ return frappe._dict({
+ "dashboards": get_dashboards(),
+ "charts": get_charts(),
+ "number_cards": get_number_cards(),
+ })
+
+def get_dashboards():
+ dashboards = []
+ dashboards.append(get_human_resource_dashboard())
+ return dashboards
+
+def get_human_resource_dashboard():
+ return {
+ "name": "Human Resource",
+ "dashboard_name": "Human Resource",
+ "is_default": 1,
+ "charts": [
+ { "chart": "Outgoing Salary", "width": "Full"},
+ { "chart": "Gender Diversity Ratio", "width": "Half"},
+ { "chart": "Job Application Status", "width": "Half"},
+ { "chart": 'Designation Wise Employee Count', "width": "Half"},
+ { "chart": 'Department Wise Employee Count', "width": "Half"},
+ { "chart": 'Designation Wise Openings', "width": "Half"},
+ { "chart": 'Department Wise Openings', "width": "Half"},
+ { "chart": "Attendance Count", "width": "Full"}
+ ],
+ "cards": [
+ {"card": "Total Employees"},
+ {"card": "New Joinees (Last year)"},
+ {'card': "Employees Left (Last year)"},
+ {'card': "Total Job Openings (Last month)"},
+ {'card': "Total Applicants (Last month)"},
+ {'card': "Shortlisted Candidates (Last month)"},
+ {'card': "Rejected Candidates (Last month)"},
+ {'card': "Total Job Offered (Last month)"},
+ ]
+ }
+
+def get_recruitment_dashboard():
+ pass
+
+
+def get_charts():
+ company = erpnext.get_default_company()
+ date = frappe.utils.get_datetime()
+
+ month_map = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov","Dec"]
+
+
+ if not company:
+ company = frappe.db.get_value("Company", {"is_group": 0}, "name")
+
+ dashboard_charts = [
+ get_dashboards_chart_doc('Gender Diversity Ratio', "Group By", "Pie",
+ document_type = "Employee", group_by_type="Count", group_by_based_on="gender",
+ filters_json = json.dumps([["Employee", "status", "=", "Active"]]))
+ ]
+
+ dashboard_charts.append(
+ get_dashboards_chart_doc('Job Application Status', "Group By", "Pie",
+ document_type = "Job Applicant", group_by_type="Count", group_by_based_on="status",
+ filters_json = json.dumps([["Job Applicant", "creation", "Previous", "1 month"]]))
+ )
+
+ dashboard_charts.append(
+ get_dashboards_chart_doc('Outgoing Salary', "Sum", "Line",
+ document_type = "Salary Slip", based_on="end_date",
+ value_based_on = "rounded_total", time_interval = "Monthly", timeseries = 1,
+ filters_json = json.dumps([["Salary Slip", "docstatus", "=", 1]]))
+ )
+
+ custom_options = '''{
+ "type": "line",
+ "axisOptions": {
+ "shortenYAxisNumbers": 1
+ },
+ "tooltipOptions": {}
+ }'''
+
+ filters_json = json.dumps({
+ "month": month_map[date.month - 1],
+ "year": str(date.year),
+ "company":company
+ })
+
+ dashboard_charts.append(
+ get_dashboards_chart_doc('Attendance Count', "Report", "Line",
+ report_name = "Monthly Attendance Sheet", is_custom =1, group_by_type="Count",
+ filters_json = filters_json, custom_options=custom_options)
+ )
+
+ dashboard_charts.append(
+ get_dashboards_chart_doc('Department Wise Employee Count', "Group By", "Donut",
+ document_type = "Employee", group_by_type="Count", group_by_based_on="department",
+ filters_json = json.dumps([["Employee", "status", "=", "Active"]]))
+ )
+
+ dashboard_charts.append(
+ get_dashboards_chart_doc('Designation Wise Employee Count', "Group By", "Donut",
+ document_type = "Employee", group_by_type="Count", group_by_based_on="designation",
+ filters_json = json.dumps([["Employee", "status", "=", "Active"]]))
+ )
+
+ dashboard_charts.append(
+ get_dashboards_chart_doc('Designation Wise Openings', "Group By", "Bar",
+ document_type = "Job Opening", group_by_type="Sum", group_by_based_on="designation",
+ time_interval = "Monthly", aggregate_function_based_on = "planned_vacancies")
+ )
+ dashboard_charts.append(
+ get_dashboards_chart_doc('Department Wise Openings', "Group By", "Bar",
+ document_type = "Job Opening", group_by_type="Sum", group_by_based_on="department",
+ time_interval = "Monthly", aggregate_function_based_on = "planned_vacancies")
+ )
+ return dashboard_charts
+
+
+def get_number_cards():
+ number_cards = []
+
+ number_cards = [
+ get_number_cards_doc("Employee", "Total Employees", filters_json = json.dumps([
+ ["Employee","status","=","Active"]
+ ])
+ )
+ ]
+
+ number_cards.append(
+ get_number_cards_doc("Employee", "New Joinees (Last year)", filters_json = json.dumps([
+ ["Employee","date_of_joining","Previous","1 year"],
+ ["Employee","status","=","Active"]
+ ])
+ )
+ )
+
+ number_cards.append(
+ get_number_cards_doc("Employee", "Employees Left (Last year)", filters_json = json.dumps([
+ ["Employee", "modified", "Previous", "1 year"],
+ ["Employee", "status", "=", "Left"]
+ ])
+ )
+ )
+
+ number_cards.append(
+ get_number_cards_doc("Job Applicant", "Total Applicants (Last month)", filters_json = json.dumps([
+ ["Job Applicant", "creation", "Previous", "1 month"]
+ ])
+ )
+ )
+
+ number_cards.append(
+ get_number_cards_doc("Job Opening", "Total Job Openings (Last month)", func = "Sum",
+ aggregate_function_based_on = "planned_vacancies",
+ filters_json = json.dumps([["Job Opening", "creation", "Previous", "1 month"]])
+ )
+ )
+ number_cards.append(
+ get_number_cards_doc("Job Applicant", "Shortlisted Candidates (Last month)", filters_json = json.dumps([
+ ["Job Applicant", "status", "=", "Accepted"],
+ ["Job Applicant", "creation", "Previous", "1 month"]
+ ])
+ )
+ )
+ number_cards.append(
+ get_number_cards_doc("Job Applicant", "Rejected Candidates (Last month)", filters_json = json.dumps([
+ ["Job Applicant", "status", "=", "Rejected"],
+ ["Job Applicant", "creation", "Previous", "1 month"]
+ ])
+ )
+ )
+ number_cards.append(
+ get_number_cards_doc("Job Offer", "Total Job Offered (Last month)",
+ filters_json = json.dumps([["Job Offer", "creation", "Previous", "1 month"]])
+ )
+ )
+
+ return number_cards
+
+
+def get_number_cards_doc(document_type, label, **args):
+ args = frappe._dict(args)
+
+ return {
+ "doctype": "Number Card",
+ "document_type": document_type,
+ "function": args.func or "Count",
+ "is_public": args.is_public or 1,
+ "label": _(label),
+ "name": args.name or label,
+ "show_percentage_stats": args.show_percentage_stats or 1,
+ "stats_time_interval": args.stats_time_interval or 'Monthly',
+ "filters_json": args.filters_json or '[]',
+ "aggregate_function_based_on": args.aggregate_function_based_on or None
+ }
+
+def get_dashboards_chart_doc(name, chart_type, graph_type, **args):
+ args = frappe._dict(args)
+
+ return {
+ "name": name,
+ "chart_name": _(args.chart_name or name),
+ "chart_type": chart_type,
+ "document_type": args.document_type or None,
+ "report_name": args.report_name or None,
+ "is_custom": args.is_custom or 0,
+ "group_by_type": args.group_by_type or None,
+ "group_by_based_on": args.group_by_based_on or None,
+ "based_on": args.based_on or None,
+ "value_based_on": args.value_based_on or None,
+ "number_of_groups": args.number_of_groups or 0,
+ "is_public": args.is_public or 1,
+ "timespan": args.timespan or "Last Year",
+ "time_interval": args.time_interval or "Yearly",
+ "timeseries": args.timeseries or 0,
+ "filters_json": args.filters_json or '[]',
+ "type": graph_type,
+ "custom_options": args.custom_options or '',
+ "doctype": "Dashboard Chart",
+ "aggregate_function_based_on": args.aggregate_function_based_on or None
+ }
\ No newline at end of file
diff --git a/erpnext/hr/desk_page/hr/hr.json b/erpnext/hr/desk_page/hr/hr.json
index 22aa170..2d0e885 100644
--- a/erpnext/hr/desk_page/hr/hr.json
+++ b/erpnext/hr/desk_page/hr/hr.json
@@ -77,21 +77,27 @@
}
],
"category": "Modules",
- "charts": [],
+ "charts": [
+ {
+ "chart_name": "Outgoing Salary",
+ "label": "Outgoing Salary"
+ }
+ ],
"creation": "2020-03-02 15:48:58.322521",
"developer_mode_only": 0,
"disable_user_customization": 0,
"docstatus": 0,
"doctype": "Desk Page",
"extends_another_page": 0,
- "icon": "",
+ "hide_custom": 0,
"idx": 0,
"is_standard": 1,
"label": "HR",
- "modified": "2020-04-29 20:29:22.114309",
+ "modified": "2020-05-20 11:20:54.255557",
"modified_by": "Administrator",
"module": "HR",
"name": "HR",
+ "onboarding": "Human Resource",
"owner": "Administrator",
"pin_to_bottom": 0,
"pin_to_top": 0,
@@ -104,33 +110,33 @@
"type": "DocType"
},
{
- "format": "{} Unpaid",
- "label": "Expense Claim",
- "link_to": "Expense Claim",
- "stats_filter": "{\"approval_status\":\"Draft\"}",
- "type": "DocType"
- },
- {
- "format": "{} Open",
- "label": "Job Applicant",
- "link_to": "Job Applicant",
- "stats_filter": "{\n \"status\": \"Open\"\n}",
- "type": "DocType"
- },
- {
- "label": "Salary Structure",
- "link_to": "Salary Structure",
+ "label": "Attendance",
+ "link_to": "Attendance",
+ "stats_filter": "",
"type": "DocType"
},
{
"label": "Leave Application",
"link_to": "Leave Application",
+ "stats_filter": "{\"status\":\"Open\"}",
+ "type": "DocType"
+ },
+ {
+ "label": "Salary Structure",
+ "link_to": "Payroll Entry",
"type": "DocType"
},
{
"label": "Salary Register",
- "link_to": "Salary Register",
+ "link_to": "Monthly Attendance Sheet",
"type": "Report"
+ },
+ {
+ "format": "{} Open",
+ "label": "HR Dashboard",
+ "link_to": "Human Resource",
+ "stats_filter": "{\n \"status\": \"Open\"\n}",
+ "type": "Dashboard"
}
]
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/attendance/attendance.py b/erpnext/hr/doctype/attendance/attendance.py
index 6c7ee00..45b7060 100644
--- a/erpnext/hr/doctype/attendance/attendance.py
+++ b/erpnext/hr/doctype/attendance/attendance.py
@@ -172,8 +172,8 @@
records = frappe.get_all("Attendance", fields = ['attendance_date', 'employee'] , filters = [
- ["attendance_date", ">", month_start],
- ["attendance_date", "<", month_end],
+ ["attendance_date", ">=", month_start],
+ ["attendance_date", "<=", month_end],
["employee", "=", employee],
["docstatus", "!=", 2]
])
diff --git a/erpnext/hr/doctype/leave_application/leave_application.json b/erpnext/hr/doctype/leave_application/leave_application.json
index 74707a2..7f50ace 100644
--- a/erpnext/hr/doctype/leave_application/leave_application.json
+++ b/erpnext/hr/doctype/leave_application/leave_application.json
@@ -174,7 +174,8 @@
"label": "Status",
"no_copy": 1,
"options": "Open\nApproved\nRejected\nCancelled",
- "permlevel": 1
+ "permlevel": 1,
+ "reqd": 1
},
{
"fieldname": "sb10",
@@ -189,14 +190,14 @@
"reqd": 1
},
{
+ "fetch_from": "employee.company",
"fieldname": "company",
"fieldtype": "Link",
"label": "Company",
"options": "Company",
"read_only": 1,
"remember_last_selected_value": 1,
- "reqd": 1,
- "fetch_from": "employee.company"
+ "reqd": 1
},
{
"allow_on_submit": 1,
@@ -249,7 +250,7 @@
"is_submittable": 1,
"links": [],
"max_attachments": 3,
- "modified": "2020-03-10 22:40:43.487721",
+ "modified": "2020-05-18 13:00:41.577327",
"modified_by": "Administrator",
"module": "HR",
"name": "Leave Application",
@@ -334,4 +335,4 @@
"sort_order": "DESC",
"timeline_field": "employee",
"title_field": "employee_name"
-}
+}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py
index d2620be..84f2c83 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.py
+++ b/erpnext/hr/doctype/leave_application/leave_application.py
@@ -131,6 +131,8 @@
for dt in daterange(getdate(self.from_date), getdate(self.to_date)):
date = dt.strftime("%Y-%m-%d")
status = "Half Day" if getdate(date) == getdate(self.half_day_date) else "On Leave"
+ print("-------->>>", status)
+ # frappe.throw("Hello")
attendance_name = frappe.db.exists('Attendance', dict(employee = self.employee,
attendance_date = date, docstatus = ('!=', 2)))
@@ -596,7 +598,7 @@
is_carry_forward, is_expired
FROM `tabLeave Ledger Entry`
WHERE employee=%(employee)s AND leave_type=%(leave_type)s
- AND docstatus=1
+ AND docstatus=1
AND (leaves<0
OR is_expired=1)
AND (from_date between %(from_date)s AND %(to_date)s
diff --git a/erpnext/hr/module_onboarding/human_resource/human_resource.json b/erpnext/hr/module_onboarding/human_resource/human_resource.json
new file mode 100644
index 0000000..e64582b
--- /dev/null
+++ b/erpnext/hr/module_onboarding/human_resource/human_resource.json
@@ -0,0 +1,51 @@
+{
+ "allow_roles": [
+ {
+ "role": "HR Manager"
+ },
+ {
+ "role": "HR User"
+ }
+ ],
+ "creation": "2020-05-14 11:51:45.050242",
+ "docstatus": 0,
+ "doctype": "Module Onboarding",
+ "documentation_url": "https://docs.erpnext.com/docs/user/manual/en/human-resources",
+ "idx": 0,
+ "is_complete": 0,
+ "modified": "2020-05-20 11:20:07.992597",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Human Resource",
+ "owner": "Administrator",
+ "steps": [
+ {
+ "step": "Create Department"
+ },
+ {
+ "step": "Create Designation"
+ },
+ {
+ "step": "Create Holiday list"
+ },
+ {
+ "step": "Create Employee"
+ },
+ {
+ "step": "Create Leave Type"
+ },
+ {
+ "step": "Create Leave Allocation"
+ },
+ {
+ "step": "Create Leave Application"
+ },
+ {
+ "step": "HR Settings"
+ }
+ ],
+ "subtitle": "Employee, Leaves and more.",
+ "success_message": "The HR Module is all set up!",
+ "title": "Let's Setup the Human Resource Module. ",
+ "user_can_dismiss": 0
+}
\ No newline at end of file
diff --git a/erpnext/hr/onboarding_step/create_department/create_department.json b/erpnext/hr/onboarding_step/create_department/create_department.json
new file mode 100644
index 0000000..66a54cf
--- /dev/null
+++ b/erpnext/hr/onboarding_step/create_department/create_department.json
@@ -0,0 +1,19 @@
+{
+ "action": "Create Entry",
+ "creation": "2020-05-14 11:44:34.682115",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_mandatory": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2020-05-14 12:22:26.448420",
+ "modified_by": "Administrator",
+ "name": "Create Department",
+ "owner": "Administrator",
+ "reference_document": "Department",
+ "show_full_form": 0,
+ "title": "Create Department",
+ "validate_action": 0
+}
\ No newline at end of file
diff --git a/erpnext/hr/onboarding_step/create_designation/create_designation.json b/erpnext/hr/onboarding_step/create_designation/create_designation.json
new file mode 100644
index 0000000..c4e9cc7
--- /dev/null
+++ b/erpnext/hr/onboarding_step/create_designation/create_designation.json
@@ -0,0 +1,19 @@
+{
+ "action": "Create Entry",
+ "creation": "2020-05-14 11:45:07.514193",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_mandatory": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2020-05-14 12:22:41.500795",
+ "modified_by": "Administrator",
+ "name": "Create Designation",
+ "owner": "Administrator",
+ "reference_document": "Designation",
+ "show_full_form": 0,
+ "title": "Create Designation",
+ "validate_action": 0
+}
\ No newline at end of file
diff --git a/erpnext/hr/onboarding_step/create_employee/create_employee.json b/erpnext/hr/onboarding_step/create_employee/create_employee.json
new file mode 100644
index 0000000..3aa33c6
--- /dev/null
+++ b/erpnext/hr/onboarding_step/create_employee/create_employee.json
@@ -0,0 +1,19 @@
+{
+ "action": "Create Entry",
+ "creation": "2020-05-14 11:43:25.561152",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_mandatory": 1,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2020-05-14 12:26:28.629074",
+ "modified_by": "Administrator",
+ "name": "Create Employee",
+ "owner": "Administrator",
+ "reference_document": "Employee",
+ "show_full_form": 0,
+ "title": "Create Employee",
+ "validate_action": 0
+}
\ No newline at end of file
diff --git a/erpnext/hr/onboarding_step/create_holiday_list/create_holiday_list.json b/erpnext/hr/onboarding_step/create_holiday_list/create_holiday_list.json
new file mode 100644
index 0000000..25cb9fe
--- /dev/null
+++ b/erpnext/hr/onboarding_step/create_holiday_list/create_holiday_list.json
@@ -0,0 +1,19 @@
+{
+ "action": "Create Entry",
+ "creation": "2020-05-14 11:47:34.700174",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_mandatory": 1,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2020-05-14 12:25:38.068582",
+ "modified_by": "Administrator",
+ "name": "Create Holiday list",
+ "owner": "Administrator",
+ "reference_document": "Holiday List",
+ "show_full_form": 0,
+ "title": "Create Holiday list",
+ "validate_action": 0
+}
\ No newline at end of file
diff --git a/erpnext/hr/onboarding_step/create_leave_allocation/create_leave_allocation.json b/erpnext/hr/onboarding_step/create_leave_allocation/create_leave_allocation.json
new file mode 100644
index 0000000..fa9941e
--- /dev/null
+++ b/erpnext/hr/onboarding_step/create_leave_allocation/create_leave_allocation.json
@@ -0,0 +1,19 @@
+{
+ "action": "Create Entry",
+ "creation": "2020-05-14 11:48:56.123718",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_mandatory": 1,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2020-05-14 11:48:56.123718",
+ "modified_by": "Administrator",
+ "name": "Create Leave Allocation",
+ "owner": "Administrator",
+ "reference_document": "Leave Allocation",
+ "show_full_form": 0,
+ "title": "Create Leave Allocation",
+ "validate_action": 0
+}
\ No newline at end of file
diff --git a/erpnext/hr/onboarding_step/create_leave_application/create_leave_application.json b/erpnext/hr/onboarding_step/create_leave_application/create_leave_application.json
new file mode 100644
index 0000000..1ed074e
--- /dev/null
+++ b/erpnext/hr/onboarding_step/create_leave_application/create_leave_application.json
@@ -0,0 +1,19 @@
+{
+ "action": "Create Entry",
+ "creation": "2020-05-14 11:49:45.400764",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_mandatory": 1,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2020-05-14 11:49:45.400764",
+ "modified_by": "Administrator",
+ "name": "Create Leave Application",
+ "owner": "Administrator",
+ "reference_document": "Leave Application",
+ "show_full_form": 0,
+ "title": "Create Leave Application",
+ "validate_action": 0
+}
\ No newline at end of file
diff --git a/erpnext/hr/onboarding_step/create_leave_type/create_leave_type.json b/erpnext/hr/onboarding_step/create_leave_type/create_leave_type.json
new file mode 100644
index 0000000..e8b97c2
--- /dev/null
+++ b/erpnext/hr/onboarding_step/create_leave_type/create_leave_type.json
@@ -0,0 +1,19 @@
+{
+ "action": "Create Entry",
+ "creation": "2020-05-20 11:17:31.119312",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_mandatory": 1,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2020-05-20 11:17:31.119312",
+ "modified_by": "Administrator",
+ "name": "Create Leave Type",
+ "owner": "Administrator",
+ "reference_document": "Leave Type",
+ "show_full_form": 0,
+ "title": "Create Leave Type",
+ "validate_action": 0
+}
\ No newline at end of file
diff --git a/erpnext/hr/onboarding_step/hr_settings/hr_settings.json b/erpnext/hr/onboarding_step/hr_settings/hr_settings.json
new file mode 100644
index 0000000..a8c96fb
--- /dev/null
+++ b/erpnext/hr/onboarding_step/hr_settings/hr_settings.json
@@ -0,0 +1,19 @@
+{
+ "action": "Update Settings",
+ "creation": "2020-05-14 13:13:52.427711",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_mandatory": 0,
+ "is_single": 1,
+ "is_skipped": 0,
+ "modified": "2020-05-20 11:16:42.430974",
+ "modified_by": "Administrator",
+ "name": "HR Settings",
+ "owner": "Administrator",
+ "reference_document": "HR Settings",
+ "show_full_form": 0,
+ "title": "HR settings",
+ "validate_action": 0
+}
\ No newline at end of file
diff --git a/erpnext/hr/report/department_analytics/department_analytics.js b/erpnext/hr/report/department_analytics/department_analytics.js
deleted file mode 100644
index 29fedcd..0000000
--- a/erpnext/hr/report/department_analytics/department_analytics.js
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.query_reports["Department Analytics"] = {
- "filters": [
- {
- "fieldname":"company",
- "label": __("Company"),
- "fieldtype": "Link",
- "options": "Company",
- "default": frappe.defaults.get_user_default("Company"),
- "reqd": 1
- },
- ]
-};
\ No newline at end of file
diff --git a/erpnext/hr/report/department_analytics/department_analytics.json b/erpnext/hr/report/department_analytics/department_analytics.json
deleted file mode 100644
index 1e26b33..0000000
--- a/erpnext/hr/report/department_analytics/department_analytics.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "add_total_row": 0,
- "creation": "2018-05-15 15:37:20.883263",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Report",
- "idx": 0,
- "is_standard": "Yes",
- "modified": "2018-05-15 17:19:32.934321",
- "modified_by": "Administrator",
- "module": "HR",
- "name": "Department Analytics",
- "owner": "Administrator",
- "ref_doctype": "Employee",
- "report_name": "Department Analytics",
- "report_type": "Script Report",
- "roles": [
- {
- "role": "Employee"
- },
- {
- "role": "HR User"
- },
- {
- "role": "HR Manager"
- }
- ]
-}
\ No newline at end of file
diff --git a/erpnext/hr/report/department_analytics/department_analytics.py b/erpnext/hr/report/department_analytics/department_analytics.py
deleted file mode 100644
index b28eac4..0000000
--- a/erpnext/hr/report/department_analytics/department_analytics.py
+++ /dev/null
@@ -1,67 +0,0 @@
-# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe import _
-
-def execute(filters=None):
- if not filters: filters = {}
-
- if not filters["company"]:
- frappe.throw(_('{0} is mandatory').format(_('Company')))
-
- columns = get_columns()
- employees = get_employees(filters)
- departments_result = get_department(filters)
- departments = []
- if departments_result:
- for department in departments_result:
- departments.append(department)
- chart = get_chart_data(departments,employees)
- return columns, employees, None, chart
-
-def get_columns():
- return [
- _("Employee") + ":Link/Employee:120", _("Name") + ":Data:200", _("Date of Birth")+ ":Date:100",
- _("Branch") + ":Link/Branch:120", _("Department") + ":Link/Department:120",
- _("Designation") + ":Link/Designation:120", _("Gender") + "::60", _("Company") + ":Link/Company:120"
- ]
-
-def get_conditions(filters):
- conditions = ""
- if filters.get("department"): conditions += " and department = '%s'" % \
- filters["department"].replace("'", "\\'")
-
- if filters.get("company"): conditions += " and company = '%s'" % \
- filters["company"].replace("'", "\\'")
- return conditions
-
-def get_employees(filters):
- conditions = get_conditions(filters)
- return frappe.db.sql("""select name, employee_name, date_of_birth,
- branch, department, designation,
- gender, company from `tabEmployee` where status = 'Active' %s""" % conditions, as_list=1)
-
-def get_department(filters):
- return frappe.db.sql("""select name from `tabDepartment` where company = %s""", (filters["company"]), as_list=1)
-
-def get_chart_data(departments,employees):
- if not departments:
- departments = []
- datasets = []
- for department in departments:
- if department:
- total_employee = frappe.db.sql("""select count(*) from \
- `tabEmployee` where \
- department = %s""" ,(department[0]), as_list=1)
- datasets.append(total_employee[0][0])
- chart = {
- "data": {
- 'labels': departments,
- 'datasets': [{'name': 'Employees','values': datasets}]
- }
- }
- chart["type"] = "bar"
- return chart
-
diff --git a/erpnext/hr/report/department_analytics/__init__.py b/erpnext/hr/report/employee_analytics/__init__.py
similarity index 100%
rename from erpnext/hr/report/department_analytics/__init__.py
rename to erpnext/hr/report/employee_analytics/__init__.py
diff --git a/erpnext/hr/report/employee_analytics/employee_analytics.js b/erpnext/hr/report/employee_analytics/employee_analytics.js
new file mode 100644
index 0000000..8620a65
--- /dev/null
+++ b/erpnext/hr/report/employee_analytics/employee_analytics.js
@@ -0,0 +1,23 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Employee Analytics"] = {
+ "filters": [
+ {
+ "fieldname":"company",
+ "label": __("Company"),
+ "fieldtype": "Link",
+ "options": "Company",
+ "default": frappe.defaults.get_user_default("Company"),
+ "reqd": 1
+ },
+ {
+ "fieldname":"parameter",
+ "label": __("Parameter"),
+ "fieldtype": "Select",
+ "options": ["Branch","Grade","Department","Designation", "Employment Type"],
+ "reqd": 1
+ }
+ ]
+};
diff --git a/erpnext/hr/report/employee_analytics/employee_analytics.json b/erpnext/hr/report/employee_analytics/employee_analytics.json
new file mode 100644
index 0000000..5a7ab9a
--- /dev/null
+++ b/erpnext/hr/report/employee_analytics/employee_analytics.json
@@ -0,0 +1,30 @@
+{
+ "add_total_row": 0,
+ "creation": "2020-05-12 13:52:50.631086",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "idx": 0,
+ "is_standard": "Yes",
+ "modified": "2020-05-12 13:52:50.631086",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Employee Analytics",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Employee",
+ "report_name": "Employee Analytics",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "Employee"
+ },
+ {
+ "role": "HR User"
+ },
+ {
+ "role": "HR Manager"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/hr/report/employee_analytics/employee_analytics.py b/erpnext/hr/report/employee_analytics/employee_analytics.py
new file mode 100644
index 0000000..df64006
--- /dev/null
+++ b/erpnext/hr/report/employee_analytics/employee_analytics.py
@@ -0,0 +1,79 @@
+# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+
+def execute(filters=None):
+ if not filters: filters = {}
+
+ if not filters["company"]:
+ frappe.throw(_('{0} is mandatory').format(_('Company')))
+
+ columns = get_columns()
+ employees = get_employees(filters)
+ parameters_result = get_parameters(filters)
+ parameters = []
+ if parameters_result:
+ for department in parameters_result:
+ parameters.append(department)
+
+ chart = get_chart_data(parameters,employees, filters)
+ return columns, employees, None, chart
+
+def get_columns():
+ return [
+ _("Employee") + ":Link/Employee:120", _("Name") + ":Data:200", _("Date of Birth")+ ":Date:100",
+ _("Branch") + ":Link/Branch:120", _("Department") + ":Link/Department:120",
+ _("Designation") + ":Link/Designation:120", _("Gender") + "::60", _("Company") + ":Link/Company:120"
+ ]
+
+def get_conditions(filters):
+ conditions = " and "+filters.get("parameter").lower().replace(" ","_")+" IS NOT NULL "
+
+ if filters.get("company"): conditions += " and company = '%s'" % \
+ filters["company"].replace("'", "\\'")
+ return conditions
+
+def get_employees(filters):
+ conditions = get_conditions(filters)
+ return frappe.db.sql("""select name, employee_name, date_of_birth,
+ branch, department, designation,
+ gender, company from `tabEmployee` where status = 'Active' %s""" % conditions, as_list=1)
+
+def get_parameters(filters):
+ return frappe.db.sql("""select name from `tab"""+filters.get("parameter")+"""` """, as_list=1)
+
+def get_chart_data(parameters,employees, filters):
+ if not parameters:
+ parameters = []
+ datasets = []
+ parameter_field_name = filters.get("parameter").lower().replace(" ","_")
+ label = []
+ for parameter in parameters:
+ if parameter:
+ total_employee = frappe.db.sql("""select count(*) from
+ `tabEmployee` where """+
+ parameter_field_name + """ = %s and company = %s""" ,( parameter[0], filters.get("company")), as_list=1)
+ if total_employee[0][0]:
+ label.append(parameter)
+ datasets.append(total_employee[0][0])
+
+ values = [ value for value in datasets if value !=0]
+
+ total_employee = frappe.db.count('Employee', {'status':'Active'})
+ others = total_employee - sum(values)
+
+ label.append(["Not Set"])
+ values.append(others)
+
+ chart = {
+ "data": {
+ 'labels': label,
+ 'datasets': [{'name': 'Employees','values': values}]
+ }
+ }
+ chart["type"] = "donut"
+ return chart
+
diff --git a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py
index 82ed277..efc43bf 100644
--- a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py
+++ b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py
@@ -30,8 +30,11 @@
def execute(filters=None):
if not filters: filters = {}
+ if filters.hide_year_field == 1:
+ filters.year = 2020
+
conditions, filters = get_conditions(filters)
- columns = get_columns(filters)
+ columns, days = get_columns(filters)
att_map = get_attendance_list(conditions, filters)
if filters.group_by:
@@ -60,20 +63,67 @@
columns.extend([_("Total Late Entries") + ":Float:120", _("Total Early Exits") + ":Float:120"])
if filters.group_by:
+ emp_att_map = {}
for parameter in group_by_parameters:
data.append([ "<b>"+ parameter + "</b>"])
- record = add_data(emp_map[parameter], att_map, filters, holiday_map, conditions, leave_list=leave_list)
+ record, aaa = add_data(emp_map[parameter], att_map, filters, holiday_map, conditions, leave_list=leave_list)
+ emp_att_map.update(aaa)
data += record
else:
- record = add_data(emp_map, att_map, filters, holiday_map, conditions, leave_list=leave_list)
+ record, emp_att_map = add_data(emp_map, att_map, filters, holiday_map, conditions, leave_list=leave_list)
data += record
- return columns, data
+ chart_data = get_chart_data(emp_att_map, days)
+
+ return columns, data, None, chart_data
+
+def get_chart_data(emp_att_map, days):
+ labels = []
+ datasets = [
+ {"name": "Absent", "values": []},
+ {"name": "Present", "values": []},
+ {"name": "Leave", "values": []},
+ ]
+ for idx, day in enumerate(days, start=0):
+ p = day.replace("::65", "")
+ labels.append(day.replace("::65", ""))
+ total_absent_on_day = 0
+ total_leave_on_day = 0
+ total_present_on_day = 0
+ total_holiday = 0
+ for emp in emp_att_map.keys():
+ if emp_att_map[emp][idx]:
+ if emp_att_map[emp][idx] == "A":
+ total_absent_on_day += 1
+ if emp_att_map[emp][idx] in ["P", "WFH"]:
+ total_present_on_day += 1
+ if emp_att_map[emp][idx] == "HD":
+ total_present_on_day += 0.5
+ total_leave_on_day += 0.5
+ if emp_att_map[emp][idx] == "L":
+ total_leave_on_day += 1
-def add_data(employee_map, att_map, filters, holiday_map, conditions, leave_list=None):
+ datasets[0]["values"].append(total_absent_on_day)
+ datasets[1]["values"].append(total_present_on_day)
+ datasets[2]["values"].append(total_leave_on_day)
+
+
+ chart = {
+ "data": {
+ 'labels': labels,
+ 'datasets': datasets
+ }
+ }
+
+ chart["type"] = "line"
+
+ return chart
+
+def add_data(employee_map, att_map, filters, holiday_map, conditions,leave_list=None):
record = []
+ emp_att_map = {}
for emp in employee_map:
emp_det = employee_map.get(emp)
if not emp_det or emp not in att_map:
@@ -85,6 +135,7 @@
row += [emp, emp_det.employee_name]
total_p = total_a = total_l = total_h = total_um= 0.0
+ ggg = []
for day in range(filters["total_days_in_month"]):
status = None
status = att_map.get(emp).get(day + 1)
@@ -101,19 +152,12 @@
status = "Holiday"
total_h += 1
-
- # if emp_holiday_list in holiday_map and (day+1) in holiday_map[emp_holiday_list][0]:
- # if holiday_map[emp_holiday_list][1]:
- # status= "Weekly Off"
- # else:
- # status = "Holiday"
-
- # += 1
+ ggg.append(status_map.get(status, ""))
if not filters.summarized_view:
- row.append(status_map.get(status, ""))
+ row += ggg
else:
- if status == "Present":
+ if status == "Present" or status == "Work From Home":
total_p += 1
elif status == "Absent":
total_a += 1
@@ -159,10 +203,10 @@
row.append("0.0")
row.extend([time_default_counts[0][0],time_default_counts[0][1]])
+ emp_att_map[emp] = ggg
record.append(row)
-
- return record
+ return record, emp_att_map
def get_columns(filters):
@@ -174,15 +218,17 @@
columns += [
_("Employee") + ":Link/Employee:120", _("Employee Name") + ":Link/Employee:120"
]
-
+ days = []
+ for day in range(filters["total_days_in_month"]):
+ date = str(filters.year) + "-" + str(filters.month)+ "-" + str(day+1)
+ day_name = day_abbr[getdate(date).weekday()]
+ days.append(cstr(day+1)+ " " +day_name +"::65")
if not filters.summarized_view:
- for day in range(filters["total_days_in_month"]):
- date = str(filters.year) + "-" + str(filters.month)+ "-" + str(day+1)
- day_name = day_abbr[getdate(date).weekday()]
- columns.append(cstr(day+1)+ " " +day_name +"::65")
- else:
+ columns += days
+
+ if filters.summarized_view:
columns += [_("Total Present") + ":Float:120", _("Total Leaves") + ":Float:120", _("Total Absent") + ":Float:120", _("Total Holidays") + ":Float:120", _("Unmarked Days")+ ":Float:120"]
- return columns
+ return columns, days
def get_attendance_list(conditions, filters):
attendance_list = frappe.db.sql("""select employee, day(attendance_date) as day_of_month,
diff --git a/erpnext/manufacturing/report/production_analytics/production_analytics.py b/erpnext/manufacturing/report/production_analytics/production_analytics.py
index f62cd25..79af8a1 100644
--- a/erpnext/manufacturing/report/production_analytics/production_analytics.py
+++ b/erpnext/manufacturing/report/production_analytics/production_analytics.py
@@ -55,32 +55,27 @@
if d.status == 'Completed':
if getdate(d.actual_end_date) < getdate(from_date) or getdate(d.modified) < getdate(from_date):
periodic_data = update_periodic_data(periodic_data, "Completed", period)
-
elif getdate(d.actual_start_date) < getdate(from_date) :
periodic_data = update_periodic_data(periodic_data, "Pending", period)
-
elif getdate(d.planned_start_date) < getdate(from_date) :
periodic_data = update_periodic_data(periodic_data, "Overdue", period)
-
else:
periodic_data = update_periodic_data(periodic_data, "Not Started", period)
elif d.status == 'In Process':
if getdate(d.actual_start_date) < getdate(from_date) :
periodic_data = update_periodic_data(periodic_data, "Pending", period)
-
elif getdate(d.planned_start_date) < getdate(from_date) :
periodic_data = update_periodic_data(periodic_data, "Overdue", period)
-
else:
periodic_data = update_periodic_data(periodic_data, "Not Started", period)
elif d.status == 'Not Started':
if getdate(d.planned_start_date) < getdate(from_date) :
periodic_data = update_periodic_data(periodic_data, "Overdue", period)
-
else:
periodic_data = update_periodic_data(periodic_data, "Not Started", period)
+
return periodic_data
def update_periodic_data(periodic_data, status, period):
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index bb9bb97..af7cb8e 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -690,3 +690,4 @@
erpnext.patches.v13_0.update_actual_start_and_end_date_in_wo
erpnext.patches.v13_0.set_company_field_in_healthcare_doctypes
erpnext.patches.v12_0.update_bom_in_so_mr
+execute:frappe.delete_doc("Report", "Department Analytics")