From 3bc6a958c70ac64733507fb704ffb332f6a2eb21 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 13 Jul 2016 16:04:38 +0530 Subject: [PATCH] [Fix] Timesheet overlap issue --- .../salary_structure/salary_structure.js | 4 +- .../salary_structure/salary_structure.json | 57 +++++++-------- erpnext/patches.txt | 3 +- .../doctype/timesheet/test_timesheet.py | 12 ++-- .../projects/doctype/timesheet/timesheet.js | 1 + .../projects/doctype/timesheet/timesheet.json | 69 +++++++++++++++++-- .../projects/doctype/timesheet/timesheet.py | 27 ++++---- 7 files changed, 121 insertions(+), 52 deletions(-) diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.js b/erpnext/hr/doctype/salary_structure/salary_structure.js index 10b7544c42..fab7ac4c50 100755 --- a/erpnext/hr/doctype/salary_structure/salary_structure.js +++ b/erpnext/hr/doctype/salary_structure/salary_structure.js @@ -32,8 +32,8 @@ frappe.ui.form.on('Salary Structure', { }, toggle_fields: function(frm) { - frm.toggle_display('time_sheet_earning_detail', frm.doc.salary_slip_based_on_timesheet); - frm.toggle_reqd('salary_component', frm.doc.salary_slip_based_on_timesheet); + frm.toggle_display(['salary_component', 'hour_rate'], frm.doc.salary_slip_based_on_timesheet); + frm.toggle_reqd(['salary_component', 'hour_rate'], frm.doc.salary_slip_based_on_timesheet); } }) diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.json b/erpnext/hr/doctype/salary_structure/salary_structure.json index 08b035517b..4cdc67b7f0 100644 --- a/erpnext/hr/doctype/salary_structure/salary_structure.json +++ b/erpnext/hr/doctype/salary_structure/salary_structure.json @@ -8,6 +8,7 @@ "docstatus": 0, "doctype": "DocType", "document_type": "Document", + "editable_grid": 0, "fields": [ { "allow_on_submit": 0, @@ -349,6 +350,31 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "time_sheet_earning_detail", + "fieldtype": "Section Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "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, @@ -379,14 +405,13 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, - "fieldname": "time_sheet_earning_detail", - "fieldtype": "Section Break", + "fieldname": "column_break_17", + "fieldtype": "Column Break", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "label": "", "length": 0, "no_copy": 0, "permlevel": 0, @@ -428,30 +453,6 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "column_break_17", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "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, @@ -779,7 +780,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2016-07-02 18:04:06.529332", + "modified": "2016-07-13 23:56:01.550518", "modified_by": "Administrator", "module": "HR", "name": "Salary Structure", diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 83519e61a8..979c1a55b5 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -291,4 +291,5 @@ erpnext.patches.v7_0.rename_salary_components erpnext.patches.v7_0.rename_prevdoc_fields erpnext.patches.v7_0.rename_time_sheet_doctype execute:frappe.delete_doc_if_exists("Report", "Customers Not Buying Since Long Time") -erpnext.patches.v7_0.make_is_group_fieldtype_as_check \ No newline at end of file +erpnext.patches.v7_0.make_is_group_fieldtype_as_check +execute:frappe.reload_doc('projects', 'doctype', 'timesheet', force=True) diff --git a/erpnext/projects/doctype/timesheet/test_timesheet.py b/erpnext/projects/doctype/timesheet/test_timesheet.py index 281414b0ed..300933aac6 100644 --- a/erpnext/projects/doctype/timesheet/test_timesheet.py +++ b/erpnext/projects/doctype/timesheet/test_timesheet.py @@ -86,28 +86,30 @@ def make_salary_structure(employee): return salary_structure -def make_timesheet(employee, simulate=False, billable = 0): - update_activity_type("_Test Activity Type") +def make_timesheet(employee, simulate=False, billable = 0, activity_type="_Test Activity Type", project=None, task=None): + update_activity_type(activity_type) timesheet = frappe.new_doc("Timesheet") timesheet.employee = employee timesheet_detail = timesheet.append('time_logs', {}) timesheet_detail.billable = billable - timesheet_detail.activity_type = "_Test Activity Type" + timesheet_detail.activity_type = activity_type timesheet_detail.from_time = now_datetime() timesheet_detail.hours = 2 timesheet_detail.to_time = timesheet_detail.from_time + datetime.timedelta(hours= timesheet_detail.hours) + timesheet_detail.project = project + timesheet_detail.task = task for data in timesheet.get('time_logs'): if simulate: while True: try: - timesheet.save() + timesheet.save(ignore_permissions=True) break except OverlapError: data.from_time = data.from_time + datetime.timedelta(minutes=10) data.to_time = data.from_time + datetime.timedelta(hours= data.hours) else: - timesheet.save() + timesheet.save(ignore_permissions=True) timesheet.submit() diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js index dfd7abef29..4d16295979 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.js +++ b/erpnext/projects/doctype/timesheet/timesheet.js @@ -1,5 +1,6 @@ // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors // License: GNU General Public License v3. See license.txt +cur_frm.add_fetch('employee', 'employee_name', 'employee_name'); frappe.ui.form.on("Timesheet", { setup: function(frm) { diff --git a/erpnext/projects/doctype/timesheet/timesheet.json b/erpnext/projects/doctype/timesheet/timesheet.json index ac6093ee08..a15522b880 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.json +++ b/erpnext/projects/doctype/timesheet/timesheet.json @@ -225,8 +225,9 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "depends_on": "employee", "fieldname": "employee_name", - "fieldtype": "Read Only", + "fieldtype": "Data", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -235,12 +236,12 @@ "label": "Employee Name", "length": 0, "no_copy": 0, - "options": "employee.employee_name", + "options": "", "permlevel": 0, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, - "read_only": 0, + "read_only": 1, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -636,7 +637,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2016-07-13 01:18:57.918882", + "modified": "2016-07-13 23:44:05.086570", "modified_by": "Administrator", "module": "Projects", "name": "Timesheet", @@ -661,6 +662,66 @@ "share": 1, "submit": 1, "write": 1 + }, + { + "amend": 1, + "apply_user_permissions": 0, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "HR User", + "set_user_permissions": 0, + "share": 1, + "submit": 1, + "write": 1 + }, + { + "amend": 1, + "apply_user_permissions": 0, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Manufacturing User", + "set_user_permissions": 0, + "share": 1, + "submit": 1, + "write": 1 + }, + { + "amend": 0, + "apply_user_permissions": 0, + "cancel": 0, + "create": 1, + "delete": 0, + "email": 0, + "export": 0, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 0, + "read": 1, + "report": 0, + "role": "Employee", + "set_user_permissions": 0, + "share": 0, + "submit": 0, + "write": 1 } ], "quick_entry": 0, diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py index 24a379671b..686f7c2f78 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.py +++ b/erpnext/projects/doctype/timesheet/timesheet.py @@ -141,31 +141,34 @@ class Timesheet(Document): def validate_overlap(self, data): if self.production_order: - self.validate_overlap_for("workstation", data) + self.validate_overlap_for("workstation", data, data.workstation) else: - self.validate_overlap_for("user", data) - self.validate_overlap_for("employee", data) + self.validate_overlap_for("user", data, self.user) + self.validate_overlap_for("employee", data, self.employee) - def validate_overlap_for(self, fieldname, args): - existing = self.get_overlap_for(fieldname, args) + def validate_overlap_for(self, fieldname, args, value): + if not value: return + + existing = self.get_overlap_for(fieldname, args, value) if existing: frappe.throw(_("Row {0}: From Time and To Time overlap with existing from and to time").format(args.idx), OverlapError) - def get_overlap_for(self, fieldname, args): - if not args.get(fieldname): - return + def get_overlap_for(self, fieldname, args, value): + cond = "ts.`{0}`".format(fieldname) + if fieldname == 'workstation': + cond = "tsd.`{0}`".format(fieldname) existing = frappe.db.sql("""select ts.name as name, tsd.from_time as from_time, tsd.to_time as to_time from - `tabTimesheet Detail` tsd, `tabTimesheet` ts where tsd.`{0}`=%(val)s and tsd.parent = ts.name and + `tabTimesheet Detail` tsd, `tabTimesheet` ts where {0}=%(val)s and tsd.parent = ts.name and ( (%(from_time)s > tsd.from_time and %(from_time)s < tsd.to_time) or (%(to_time)s > tsd.from_time and %(to_time)s < tsd.to_time) or (%(from_time)s <= tsd.from_time and %(to_time)s >= tsd.to_time)) and tsd.name!=%(name)s - and ts.docstatus < 2""".format(fieldname), + and ts.docstatus < 2""".format(cond), { - "val": args.get(fieldname), + "val": value, "from_time": args.from_time, "to_time": args.to_time, "name": args.name or "No Name" @@ -184,7 +187,7 @@ class Timesheet(Document): if self.time_logs: for data in self.time_logs: if data.idx == index: - overlapping = self.get_overlap_for("workstation", data) + overlapping = self.get_overlap_for("workstation", data, data.workstation) if not overlapping: frappe.throw(_("Logical error: Must find overlapping"))