Compensatory Leave Request (#14611)
* Compensatory Leave Request - Validate Holidays and Attendance
* Compensatory Leave Request - Cancel
* Half Day in Compensatory Leave Request
* Leave allocation on Compensatory Leave Request - Fix
* Unused import
diff --git a/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.js b/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.js
index bb57562..1baa1e0 100644
--- a/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.js
+++ b/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.js
@@ -10,5 +10,13 @@
}
};
});
+ },
+ half_day: function(frm) {
+ if(frm.doc.half_day == 1){
+ frm.set_df_property('half_day_date', 'reqd', true);
+ }
+ else{
+ frm.set_df_property('half_day_date', 'reqd', false);
+ }
}
});
diff --git a/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.json b/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.json
index 9d2a966..be309cd 100644
--- a/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.json
+++ b/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.json
@@ -43,7 +43,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
- "translatable": 0,
+ "translatable": 0,
"unique": 0
},
{
@@ -77,7 +77,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
- "translatable": 0,
+ "translatable": 0,
"unique": 0
},
{
@@ -87,39 +87,40 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fetch_from": "employee.department",
- "fieldname": "department",
- "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": "Department",
- "length": 0,
- "no_copy": 0,
- "options": "Department",
- "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,
+ "fetch_from": "employee.department",
+ "fieldname": "department",
+ "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": "Department",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Department",
+ "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,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
"fieldname": "work_from_date",
"fieldtype": "Date",
"hidden": 0,
@@ -142,7 +143,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
- "translatable": 0,
+ "translatable": 0,
"unique": 0
},
{
@@ -174,7 +175,72 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
- "translatable": 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": "half_day",
+ "fieldtype": "Check",
+ "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": "Half Day",
+ "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,
+ "depends_on": "half_day",
+ "fieldname": "half_day_date",
+ "fieldtype": "Date",
+ "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": "Half Day 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": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
},
{
@@ -205,7 +271,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
- "translatable": 0,
+ "translatable": 0,
"unique": 0
},
{
@@ -238,7 +304,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
- "translatable": 0,
+ "translatable": 0,
"unique": 0
},
{
@@ -270,7 +336,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
- "translatable": 0,
+ "translatable": 0,
"unique": 0
},
{
@@ -303,7 +369,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
- "translatable": 0,
+ "translatable": 0,
"unique": 0
},
{
@@ -335,7 +401,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
- "translatable": 0,
+ "translatable": 0,
"unique": 0
}
],
@@ -349,7 +415,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2018-05-25 12:02:05.585184",
+ "modified": "2018-06-20 17:32:40.735664",
"modified_by": "Administrator",
"module": "HR",
"name": "Compensatory Leave Request",
@@ -442,4 +508,4 @@
"title_field": "employee_name",
"track_changes": 1,
"track_seen": 0
-}
+}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.py b/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.py
index 6a67d47..bc4a1b4 100644
--- a/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.py
+++ b/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.py
@@ -5,33 +5,72 @@
from __future__ import unicode_literals
import frappe
from frappe import _
-from frappe.utils import date_diff, add_days
+from frappe.utils import date_diff, add_days, getdate
from frappe.model.document import Document
-from erpnext.hr.utils import validate_dates, validate_overlap, get_leave_period
+from erpnext.hr.utils import validate_dates, validate_overlap, get_leave_period, get_holidays_for_employee
class CompensatoryLeaveRequest(Document):
def validate(self):
validate_dates(self, self.work_from_date, self.work_end_date)
+ if self.half_day:
+ if not self.half_day_date:
+ frappe.throw(_("Half Day Date is mandatory"))
+ if not getdate(self.work_from_date)<=getdate(self.half_day_date)<=getdate(self.work_end_date):
+ frappe.throw(_("Half Day Date should be in between Work From Date and Work End Date"))
validate_overlap(self, self.work_from_date, self.work_end_date)
+ self.validate_holidays()
+ self.validate_attendance()
+ if not self.leave_type:
+ frappe.throw(_("Leave Type is madatory"))
+
+ def validate_attendance(self):
+ query = """select attendance_date, status
+ from `tabAttendance` where
+ attendance_date between %(work_from_date)s and %(work_end_date)s
+ and docstatus=1 and status = 'Present' and employee=%(employee)s"""
+
+ attendance = frappe.db.sql(query, {
+ "work_from_date": self.work_from_date,
+ "work_end_date": self.work_end_date,
+ "employee": self.employee
+ }, as_dict=True)
+ if len(attendance) < date_diff(self.work_end_date, self.work_from_date) + 1:
+ frappe.throw(_("You are not present all day(s) between compensatory leave request days"))
+
+ def validate_holidays(self):
+ holidays = get_holidays_for_employee(self.employee, self.work_from_date, self.work_end_date)
+ if len(holidays) < date_diff(self.work_end_date, self.work_from_date) + 1:
+ frappe.throw(_("Compensatory leave request days not in valid holidays"))
def on_submit(self):
- if not self.leave_type:
- frappe.throw(_("Please select a leave type to submit the request"))
- else:
- company = frappe.db.get_value("Employee", self.employee, "company")
- date_difference = date_diff(self.work_end_date, self.work_from_date) + 1
- leave_period = get_leave_period(self.work_from_date, self.work_end_date, company)
- if leave_period:
- leave_allocation = self.exists_allocation_for_period(leave_period)
- if leave_allocation:
- leave_allocation.new_leaves_allocated += date_difference
- leave_allocation.submit()
- else:
- leave_allocation = self.create_leave_allocation(leave_period, date_difference)
- self.db_set("leave_allocation", leave_allocation.name)
+ company = frappe.db.get_value("Employee", self.employee, "company")
+ date_difference = date_diff(self.work_end_date, self.work_from_date) + 1
+ if self.half_day:
+ date_difference -= 0.5
+ leave_period = get_leave_period(self.work_from_date, self.work_end_date, company)
+ if leave_period:
+ leave_allocation = self.exists_allocation_for_period(leave_period)
+ if leave_allocation:
+ leave_allocation.new_leaves_allocated += date_difference
+ leave_allocation.submit()
else:
- frappe.throw(_("There is no leave period in between {0} and {1}").format(self.work_from_date, self.work_end_date))
+ leave_allocation = self.create_leave_allocation(leave_period, date_difference)
+ self.db_set("leave_allocation", leave_allocation.name)
+ else:
+ frappe.throw(_("There is no leave period in between {0} and {1}").format(self.work_from_date, self.work_end_date))
+
+ def on_cancel(self):
+ if self.leave_allocation:
+ date_difference = date_diff(self.work_end_date, self.work_from_date) + 1
+ if self.half_day:
+ date_difference -= 0.5
+ leave_allocation = frappe.get_doc("Leave Allocation", self.leave_allocation)
+ if leave_allocation:
+ leave_allocation.new_leaves_allocated -= date_difference
+ if leave_allocation.total_leaves_allocated - date_difference <= 0:
+ leave_allocation.total_leaves_allocated = 0
+ leave_allocation.submit()
def exists_allocation_for_period(self, leave_period):
leave_allocation = frappe.db.sql("""
diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.py b/erpnext/hr/doctype/leave_allocation/leave_allocation.py
index 7cffa4c..dc270db 100755
--- a/erpnext/hr/doctype/leave_allocation/leave_allocation.py
+++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.py
@@ -92,7 +92,7 @@
self.total_leaves_allocated = flt(self.carry_forwarded_leaves) + flt(self.new_leaves_allocated)
- if not self.total_leaves_allocated and not frappe.db.get_value("Leave Type", self.leave_type, "is_earned_leave"):
+ if not self.total_leaves_allocated and not frappe.db.get_value("Leave Type", self.leave_type, "is_earned_leave") and not frappe.db.get_value("Leave Type", self.leave_type, "is_compensatory"):
frappe.throw(_("Total leaves allocated is mandatory for Leave Type {0}".format(self.leave_type)))
def validate_total_leaves_allocated(self):