Shift Management (#13667)
* [fix] #13634 * review_changes * rename function * rename function
This commit is contained in:
parent
efff6e53de
commit
2215d4c593
@ -263,10 +263,6 @@ def get_data():
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Shift Assignment",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Shift Assignment Tool",
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
"autoname": "SH.#####",
|
||||
"beta": 0,
|
||||
@ -26,7 +26,7 @@
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Employee",
|
||||
"length": 0,
|
||||
@ -183,7 +183,7 @@
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Company",
|
||||
"length": 0,
|
||||
@ -215,7 +215,7 @@
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Date",
|
||||
"length": 0,
|
||||
@ -233,6 +233,38 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "shift_request",
|
||||
"fieldtype": "Link",
|
||||
"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": "Shift Request",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Shift Request",
|
||||
"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_on_submit": 0,
|
||||
@ -275,7 +307,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-04-14 15:42:12.617715",
|
||||
"modified": "2018-04-17 14:50:09.125737",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Shift Assignment",
|
||||
|
@ -4,7 +4,77 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import cint, cstr, date_diff, flt, formatdate, getdate
|
||||
|
||||
class OverlapError(frappe.ValidationError): pass
|
||||
|
||||
class ShiftAssignment(Document):
|
||||
pass
|
||||
def validate(self):
|
||||
self.validate_overlapping_dates();
|
||||
|
||||
def validate_overlapping_dates(self):
|
||||
if not self.name:
|
||||
self.name = "New Shift Assignment"
|
||||
|
||||
d = frappe.db.sql("""
|
||||
select
|
||||
name, shift_type, date
|
||||
from `tabShift Assignment`
|
||||
where employee = %(employee)s and docstatus < 2
|
||||
and date = %(date)s
|
||||
and name != %(name)s""", {
|
||||
"employee": self.employee,
|
||||
"shift_type": self.shift_type,
|
||||
"date": self.date,
|
||||
"name": self.name
|
||||
}, as_dict = 1)
|
||||
|
||||
for date_overlap in d:
|
||||
if date_overlap['name']:
|
||||
self.throw_overlap_error(date_overlap)
|
||||
|
||||
def throw_overlap_error(self, d):
|
||||
msg = _("Employee {0} has already applied for {1} on {2} : ").format(self.employee,
|
||||
d['shift_type'], formatdate(d['date'])) \
|
||||
+ """ <b><a href="#Form/Shift Request/{0}">{0}</a></b>""".format(d["name"])
|
||||
frappe.throw(msg, OverlapError)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_events(start, end, filters=None):
|
||||
events = []
|
||||
|
||||
employee = frappe.db.get_value("Employee", {"user_id": frappe.session.user}, ["name", "company"],
|
||||
as_dict=True)
|
||||
if employee:
|
||||
employee, company = employee.name, employee.company
|
||||
else:
|
||||
employee=''
|
||||
company=frappe.db.get_value("Global Defaults", None, "default_company")
|
||||
|
||||
from frappe.desk.reportview import get_filters_cond
|
||||
conditions = get_filters_cond("Shift Assignment", filters, [])
|
||||
add_assignments(events, start, end, conditions=conditions)
|
||||
return events
|
||||
|
||||
def add_assignments(events, start, end, conditions=None):
|
||||
query = """select name, date, employee_name,
|
||||
employee, docstatus
|
||||
from `tabShift Assignment` where
|
||||
date <= %(date)s
|
||||
and docstatus < 2"""
|
||||
if conditions:
|
||||
query += conditions
|
||||
|
||||
for d in frappe.db.sql(query, {"date":start, "date":end}, as_dict=True):
|
||||
e = {
|
||||
"name": d.name,
|
||||
"doctype": "Shift Assignment",
|
||||
"date": d.date,
|
||||
"title": cstr(d.employee_name) + \
|
||||
cstr(d.shift_type),
|
||||
"docstatus": d.docstatus
|
||||
}
|
||||
if e not in events:
|
||||
events.append(e)
|
@ -0,0 +1,19 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.views.calendar["Shift Assignment"] = {
|
||||
field_map: {
|
||||
"start": "date",
|
||||
"end": "date",
|
||||
"id": "name",
|
||||
"docstatus": 1
|
||||
},
|
||||
options: {
|
||||
header: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
right: 'month'
|
||||
}
|
||||
},
|
||||
get_events_method: "erpnext.hr.doctype.shift_assignment.shift_assignment.get_events"
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
"autoname": "SREQ.#####",
|
||||
"beta": 0,
|
||||
@ -13,6 +13,38 @@
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "shift_type",
|
||||
"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": "Shift Type",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Shift Type",
|
||||
"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_on_submit": 0,
|
||||
@ -77,6 +109,36 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 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_on_submit": 0,
|
||||
@ -109,38 +171,6 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "shift_type",
|
||||
"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": "Shift Type",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Shift Type",
|
||||
"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_on_submit": 0,
|
||||
@ -245,7 +275,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-04-14 15:40:39.590051",
|
||||
"modified": "2018-04-16 11:01:25.902995",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Shift Request",
|
||||
|
@ -4,7 +4,84 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import formatdate, getdate
|
||||
|
||||
class OverlapError(frappe.ValidationError): pass
|
||||
|
||||
class ShiftRequest(Document):
|
||||
pass
|
||||
def validate(self):
|
||||
self.validate_dates();
|
||||
self.validate_shift_request_overlap_dates();
|
||||
|
||||
def on_submit(self):
|
||||
date_list = self.get_working_days(self.from_date, self.to_date)
|
||||
for date in date_list:
|
||||
assignment_doc = frappe.new_doc("Shift Assignment")
|
||||
assignment_doc.company = self.company
|
||||
assignment_doc.shift_type = self.shift_type
|
||||
assignment_doc.employee = self.employee
|
||||
assignment_doc.date = date
|
||||
assignment_doc.shift_request = self.name
|
||||
assignment_doc.insert()
|
||||
assignment_doc.submit()
|
||||
|
||||
def validate_dates(self):
|
||||
if self.from_date and self.to_date and (getdate(self.to_date) < getdate(self.from_date)):
|
||||
frappe.throw(_("To date cannot be before from date"))
|
||||
|
||||
def validate_shift_request_overlap_dates(self):
|
||||
if not self.name:
|
||||
self.name = "New Shift Request"
|
||||
|
||||
d = frappe.db.sql("""
|
||||
select
|
||||
name, shift_type, from_date, to_date
|
||||
from `tabShift Request`
|
||||
where employee = %(employee)s and docstatus < 2
|
||||
and ((%(from_date)s >= from_date
|
||||
and %(from_date)s <= to_date) or
|
||||
( %(to_date)s >= from_date
|
||||
and %(to_date)s <= to_date ))
|
||||
and name != %(name)s""", {
|
||||
"employee": self.employee,
|
||||
"shift_type": self.shift_type,
|
||||
"from_date": self.from_date,
|
||||
"to_date": self.to_date,
|
||||
"name": self.name
|
||||
}, as_dict=1)
|
||||
|
||||
for date_overlap in d:
|
||||
if date_overlap ['name']:
|
||||
self.throw_overlap_error(date_overlap)
|
||||
|
||||
def throw_overlap_error(self, d):
|
||||
msg = _("Employee {0} has already applied for {1} between {2} and {3} : ").format(self.employee,
|
||||
d['shift_type'], formatdate(d['from_date']), formatdate(d['to_date'])) \
|
||||
+ """ <b><a href="#Form/Shift Request/{0}">{0}</a></b>""".format(d["name"])
|
||||
frappe.throw(msg, OverlapError)
|
||||
|
||||
def get_working_days(self, start_date, end_date):
|
||||
start_date, end_date = getdate(start_date), getdate(end_date)
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
date_list = []
|
||||
employee_holiday_list = []
|
||||
|
||||
employee_holidays = frappe.db.sql("""select holiday_date from `tabHoliday`
|
||||
where parent in (select holiday_list from `tabEmployee`
|
||||
where name = %s)""",self.employee,as_dict=1)
|
||||
|
||||
for d in employee_holidays:
|
||||
employee_holiday_list.append(d.holiday_date)
|
||||
|
||||
reference_date = start_date
|
||||
|
||||
while reference_date <= end_date:
|
||||
if reference_date not in employee_holiday_list:
|
||||
date_list.append(reference_date)
|
||||
reference_date += timedelta(days=1)
|
||||
|
||||
return date_list
|
@ -7,4 +7,4 @@ import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class ShiftType(Document):
|
||||
pass
|
||||
pass
|
Loading…
x
Reference in New Issue
Block a user