feat: get carry forwarded leaves via ledger entries

This commit is contained in:
Mangesh-Khairnar 2019-05-09 19:43:35 +05:30
parent 2b421c39b5
commit 679371e397
4 changed files with 293 additions and 871 deletions

View File

@ -34,31 +34,34 @@ frappe.ui.form.on("Leave Allocation", {
}, },
carry_forwarded_leaves: function(frm) { carry_forwarded_leaves: function(frm) {
frm.set_value("total_leaves_allocated", flt(frm.doc.carry_forwarded_leaves)); frm.set_value("total_leaves_allocated",
flt(frm.doc.carry_forwarded_leaves) + flt(frm.doc.new_leaves_allocated));
}, },
new_leaves_allocated: function(frm) { new_leaves_allocated: function(frm) {
frm.set_value("total_leaves_allocated", flt(frm.doc.new_leaves_allocated)); frm.set_value("total_leaves_allocated",
flt(frm.doc.carry_forwarded_leaves) + flt(frm.doc.new_leaves_allocated));
}, },
calculate_total_leaves_allocated: function(frm) { calculate_total_leaves_allocated: function(frm) {
if (cint(frm.doc.carry_forward) === 1 && frm.doc.leave_type && frm.doc.employee) { if (cint(frm.doc.carry_forward) == 1 && frm.doc.leave_type && frm.doc.employee) {
return frappe.call({ return frappe.call({
method: "erpnext.hr.doctype.leave_allocation.leave_allocation.get_carry_forwarded_leaves", method: "erpnext.hr.doctype.leave_allocation.leave_allocation.get_carry_forwarded_leaves",
args: { args: {
"employee": frm.doc.employee, "employee": frm.doc.employee,
"leave_type": frm.doc.leave_type,
"date": frm.doc.from_date, "date": frm.doc.from_date,
"leave_type": frm.doc.leave_type,
"carry_forward": frm.doc.carry_forward
}, },
callback: function(r) { callback: function(r) {
if (!r.exc && r.message) { if (!r.exc && r.message) {
frm.set_value("new_leaves_allocated", 0);
frm.set_value('carry_forwarded_leaves', r.message); frm.set_value('carry_forwarded_leaves', r.message);
frm.set_value("total_leaves_allocated", flt(r.message)); frm.set_value("total_leaves_allocated",
flt(r.message) + flt(frm.doc.new_leaves_allocated));
} }
} }
}) })
} else if (cint(frm.doc.carry_forward) === 0) { } else if (cint(frm.doc.carry_forward) == 0) {
frm.set_value("carry_forwarded_leaves", 0); frm.set_value("carry_forwarded_leaves", 0);
frm.set_value("total_leaves_allocated", flt(frm.doc.new_leaves_allocated)); frm.set_value("total_leaves_allocated", flt(frm.doc.new_leaves_allocated));
} }

View File

@ -1,683 +1,192 @@
{ {
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 1, "allow_import": 1,
"allow_rename": 0,
"autoname": "naming_series:", "autoname": "naming_series:",
"beta": 0,
"creation": "2013-02-20 19:10:38", "creation": "2013-02-20 19:10:38",
"custom": 0,
"docstatus": 0,
"doctype": "DocType", "doctype": "DocType",
"document_type": "Setup", "document_type": "Setup",
"editable_grid": 0,
"engine": "InnoDB", "engine": "InnoDB",
"field_order": [
"naming_series",
"employee",
"employee_name",
"department",
"column_break1",
"leave_type",
"from_date",
"to_date",
"section_break_6",
"new_leaves_allocated",
"carry_forward",
"carry_forwarded_leaves",
"total_leaves_allocated",
"total_leaves_encashed",
"column_break_10",
"compensatory_request",
"leave_period",
"amended_from",
"notes",
"description"
],
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "",
"fieldname": "naming_series", "fieldname": "naming_series",
"fieldtype": "Select", "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": 0,
"label": "Series", "label": "Series",
"length": 0,
"no_copy": 1, "no_copy": 1,
"options": "HR-LAL-.YYYY.-", "options": "HR-LAL-.YYYY.-",
"permlevel": 0,
"precision": "",
"print_hide": 1, "print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1, "reqd": 1,
"search_index": 0, "set_only_once": 1
"set_only_once": 1,
"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", "fieldname": "employee",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 1, "in_global_search": 1,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 1, "in_standard_filter": 1,
"label": "Employee", "label": "Employee",
"length": 0,
"no_copy": 0,
"oldfieldname": "employee", "oldfieldname": "employee",
"oldfieldtype": "Link", "oldfieldtype": "Link",
"options": "Employee", "options": "Employee",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1, "reqd": 1,
"search_index": 1, "search_index": 1
"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_from": "employee.employee_name", "fetch_from": "employee.employee_name",
"fieldname": "employee_name", "fieldname": "employee_name",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 1, "in_global_search": 1,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0,
"label": "Employee Name", "label": "Employee Name",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1, "read_only": 1,
"remember_last_selected_value": 0, "search_index": 1
"report_hide": 0,
"reqd": 0,
"search_index": 1,
"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_from": "employee.department", "fetch_from": "employee.department",
"fieldname": "department", "fieldname": "department",
"fieldtype": "Link", "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", "label": "Department",
"length": 0,
"no_copy": 0,
"options": "Department", "options": "Department",
"permlevel": 0, "read_only": 1
"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": 0,
"columns": 0,
"fieldname": "column_break1", "fieldname": "column_break1",
"fieldtype": "Column Break", "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,
"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,
"width": "50%" "width": "50%"
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "leave_type", "fieldname": "leave_type",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 1, "in_standard_filter": 1,
"label": "Leave Type", "label": "Leave Type",
"length": 0,
"no_copy": 0,
"oldfieldname": "leave_type", "oldfieldname": "leave_type",
"oldfieldtype": "Link", "oldfieldtype": "Link",
"options": "Leave Type", "options": "Leave Type",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1, "reqd": 1,
"search_index": 1, "search_index": 1
"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": "from_date", "fieldname": "from_date",
"fieldtype": "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": "From Date", "label": "From Date",
"length": 0, "reqd": 1
"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", "fieldname": "to_date",
"fieldtype": "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": "To Date", "label": "To Date",
"length": 0, "reqd": 1
"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": "section_break_6", "fieldname": "section_break_6",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "label": "Allocation"
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Allocation",
"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": 1, "allow_on_submit": 1,
"bold": 1, "bold": 1,
"collapsible": 0,
"columns": 0,
"fieldname": "new_leaves_allocated", "fieldname": "new_leaves_allocated",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "label": "New Leaves Allocated"
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "New Leaves Allocated",
"length": 0,
"no_copy": 0,
"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,
"description": "",
"fieldname": "carry_forward", "fieldname": "carry_forward",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": 0, "label": "Add unused leaves from previous allocations"
"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 unused leaves from previous allocations",
"length": 0,
"no_copy": 0,
"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,
"depends_on": "carry_forward", "depends_on": "carry_forward",
"fieldname": "carry_forwarded_leaves", "fieldname": "carry_forwarded_leaves",
"fieldtype": "Float", "fieldtype": "Float",
"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": "Unused leaves", "label": "Unused leaves",
"length": 0, "read_only": 1
"no_copy": 0,
"permlevel": 0,
"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": 1, "allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "total_leaves_allocated", "fieldname": "total_leaves_allocated",
"fieldtype": "Float", "fieldtype": "Float",
"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": "Total Leaves Allocated", "label": "Total Leaves Allocated",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1, "read_only": 1,
"remember_last_selected_value": 0, "reqd": 1
"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,
"depends_on": "eval:doc.total_leaves_encashed>0", "depends_on": "eval:doc.total_leaves_encashed>0",
"fieldname": "total_leaves_encashed", "fieldname": "total_leaves_encashed",
"fieldtype": "Float", "fieldtype": "Float",
"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": "Total Leaves Encashed", "label": "Total Leaves Encashed",
"length": 0, "read_only": 1
"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": 0,
"columns": 0,
"fieldname": "column_break_10", "fieldname": "column_break_10",
"fieldtype": "Column Break", "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": "compensatory_request", "fieldname": "compensatory_request",
"fieldtype": "Link", "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": "Compensatory Leave Request", "label": "Compensatory Leave Request",
"length": 0,
"no_copy": 0,
"options": "Compensatory Leave Request", "options": "Compensatory Leave Request",
"permlevel": 0, "read_only": 1
"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": 0,
"columns": 0,
"fieldname": "leave_period", "fieldname": "leave_period",
"fieldtype": "Link", "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": 1, "in_standard_filter": 1,
"label": "Leave Period", "label": "Leave Period",
"length": 0,
"no_copy": 0,
"options": "Leave Period", "options": "Leave Period",
"permlevel": 0, "read_only": 1
"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": 0,
"columns": 0,
"fieldname": "amended_from", "fieldname": "amended_from",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 1, "ignore_user_permissions": 1,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Amended From", "label": "Amended From",
"length": 0,
"no_copy": 1, "no_copy": 1,
"oldfieldname": "amended_from", "oldfieldname": "amended_from",
"oldfieldtype": "Data", "oldfieldtype": "Data",
"options": "Leave Allocation", "options": "Leave Allocation",
"permlevel": 0,
"print_hide": 1, "print_hide": 1,
"print_hide_if_no_value": 0, "read_only": 1
"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, "collapsible": 1,
"columns": 0,
"fieldname": "notes", "fieldname": "notes",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "label": "Notes"
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Notes",
"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": "description", "fieldname": "description",
"fieldtype": "Small Text", "fieldtype": "Small 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", "label": "Description",
"length": 0,
"no_copy": 0,
"oldfieldname": "reason", "oldfieldname": "reason",
"oldfieldtype": "Small Text", "oldfieldtype": "Small Text",
"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,
"width": "300px" "width": "300px"
} }
], ],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "fa fa-ok", "icon": "fa fa-ok",
"idx": 1, "idx": 1,
"image_view": 0,
"in_create": 0,
"is_submittable": 1, "is_submittable": 1,
"issingle": 0, "modified": "2019-05-09 19:06:33.659196",
"istable": 0,
"max_attachments": 0,
"modified": "2019-01-30 11:28:09.360525",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "HR", "module": "HR",
"name": "Leave Allocation", "name": "Leave Allocation",
@ -689,15 +198,10 @@
"create": 1, "create": 1,
"delete": 1, "delete": 1,
"email": 1, "email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1, "print": 1,
"read": 1, "read": 1,
"report": 1, "report": 1,
"role": "HR User", "role": "HR User",
"set_user_permissions": 0,
"share": 1, "share": 1,
"submit": 1, "submit": 1,
"write": 1 "write": 1
@ -709,28 +213,19 @@
"delete": 1, "delete": 1,
"email": 1, "email": 1,
"export": 1, "export": 1,
"if_owner": 0,
"import": 1, "import": 1,
"permlevel": 0,
"print": 1, "print": 1,
"read": 1, "read": 1,
"report": 1, "report": 1,
"role": "HR Manager", "role": "HR Manager",
"set_user_permissions": 0,
"share": 1, "share": 1,
"submit": 1, "submit": 1,
"write": 1 "write": 1
} }
], ],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"search_fields": "employee,employee_name,leave_type,total_leaves_allocated", "search_fields": "employee,employee_name,leave_type,total_leaves_allocated",
"show_name_in_global_search": 1, "show_name_in_global_search": 1,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC",
"timeline_field": "employee", "timeline_field": "employee"
"track_changes": 0,
"track_seen": 0,
"track_views": 0
} }

View File

@ -8,6 +8,7 @@ from frappe import _
from frappe.model.document import Document from frappe.model.document import Document
from erpnext.hr.utils import set_employee_name, get_leave_period from erpnext.hr.utils import set_employee_name, get_leave_period
from erpnext.hr.doctype.leave_application.leave_application import get_approved_leaves_for_period from erpnext.hr.doctype.leave_application.leave_application import get_approved_leaves_for_period
from erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry import create_leave_ledger_entry
class OverlapError(frappe.ValidationError): pass class OverlapError(frappe.ValidationError): pass
class BackDatedAllocationError(frappe.ValidationError): pass class BackDatedAllocationError(frappe.ValidationError): pass
@ -18,66 +19,62 @@ class ValueMultiplierError(frappe.ValidationError): pass
class LeaveAllocation(Document): class LeaveAllocation(Document):
def validate(self): def validate(self):
self.validate_period() self.validate_period()
self.validate_lwp() self.validate_new_leaves_allocated_value()
set_employee_name(self)
self.set_total_leaves_allocated()
self.validate_allocation_overlap() self.validate_allocation_overlap()
self.validate_back_dated_allocation() self.validate_back_dated_allocation()
self.set_total_leaves_allocated()
self.validate_total_leaves_allocated() self.validate_total_leaves_allocated()
self.validate_leaves_allocated_value() self.validate_lwp()
set_employee_name(self)
self.validate_leave_allocation_days() self.validate_leave_allocation_days()
def validate_leave_allocation_days(self): def validate_leave_allocation_days(self):
new_leaves = self.new_leaves_allocated if not self.carry_forward else self.carry_forwarded_leaves company = frappe.db.get_value("Employee", self.employee, "company")
max_leaves, leaves_allocated = self.get_max_leaves_with_leaves_allocated_for_leave_type(flt(new_leaves)) leave_period = get_leave_period(self.from_date, self.to_date, company)
max_leaves_allowed = frappe.db.get_value("Leave Type", self.leave_type, "max_leaves_allowed")
if leaves_allocated > max_leaves: if max_leaves_allowed > 0:
leave_allocated = 0
if leave_period:
leave_allocated = get_leave_allocation_for_period(self.employee, self.leave_type, leave_period[0].from_date, leave_period[0].to_date)
leave_allocated += self.new_leaves_allocated
if leave_allocated > max_leaves_allowed:
frappe.throw(_("Total allocated leaves are more days than maximum allocation of {0} leave type for employee {1} in the period")\ frappe.throw(_("Total allocated leaves are more days than maximum allocation of {0} leave type for employee {1} in the period")\
.format(self.leave_type, self.employee)) .format(self.leave_type, self.employee))
def on_submit(self):
create_leave_ledger_entry(self)
def on_cancel(self):
create_leave_ledger_entry(self)
def on_update_after_submit(self): def on_update_after_submit(self):
self.validate_new_leaves_allocated_value() self.validate_new_leaves_allocated_value()
self.set_total_leaves_allocated() self.set_total_leaves_allocated()
frappe.db.set(self,'carry_forwarded_leaves', flt(self.carry_forwarded_leaves))
frappe.db.set(self,'total_leaves_allocated',flt(self.total_leaves_allocated)) frappe.db.set(self,'total_leaves_allocated',flt(self.total_leaves_allocated))
self.validate_against_leave_applications() self.validate_against_leave_applications()
def validate_period(self): def validate_period(self):
allocation_period = date_diff(self.to_date, self.from_date) if date_diff(self.to_date, self.from_date) <= 0:
if allocation_period <= 0:
frappe.throw(_("To date cannot be before from date")) frappe.throw(_("To date cannot be before from date"))
# check if the allocation period is more than the expiry allows for carry forwarded allocation
if self.carry_forward:
expiry_days = get_days_to_expiry_for_leave_type(self.leave_type)
if allocation_period > flt(expiry_days) and expiry_days:
frappe.throw(_("Leave allocation period cannot exceed carry forward expiry limit"))
def validate_lwp(self): def validate_lwp(self):
if frappe.db.get_value("Leave Type", self.leave_type, "is_lwp"): if frappe.db.get_value("Leave Type", self.leave_type, "is_lwp"):
frappe.throw(_("Leave Type {0} cannot be allocated since it is leave without pay").format(self.leave_type)) frappe.throw(_("Leave Type {0} cannot be allocated since it is leave without pay").format(self.leave_type))
def validate_leaves_allocated_value(self): def validate_new_leaves_allocated_value(self):
"""validate that leave allocation is in multiples of 0.5""" """validate that leave allocation is in multiples of 0.5"""
if flt(self.new_leaves_allocated) % 0.5: if flt(self.new_leaves_allocated) % 0.5:
frappe.throw(_("Leaves must be allocated in multiples of 0.5"), ValueMultiplierError) frappe.throw(_("Leaves must be allocated in multiples of 0.5"), ValueMultiplierError)
def validate_allocation_overlap(self): def validate_allocation_overlap(self):
leave_allocation = frappe.db.sql(""" leave_allocation = frappe.db.sql("""
SELECT select name from `tabLeave Allocation`
name where employee=%s and leave_type=%s and docstatus=1
FROM `tabLeave Allocation` and to_date >= %s and from_date <= %s""",
WHERE (self.employee, self.leave_type, self.from_date, self.to_date))
employee=%s
AND leave_type=%s
AND docstatus=1
AND carry_forward={0}
AND to_date >= %s
AND from_date <= %s""" #nosec
.format(self.carry_forward), (self.employee, self.leave_type, self.from_date, self.to_date))
if leave_allocation: if leave_allocation:
frappe.msgprint(_("{0} already allocated for Employee {1} for period {2} to {3}") frappe.msgprint(_("{0} already allocated for Employee {1} for period {2} to {3}")
@ -97,20 +94,18 @@ class LeaveAllocation(Document):
BackDatedAllocationError) BackDatedAllocationError)
def set_total_leaves_allocated(self): def set_total_leaves_allocated(self):
if self.carry_forward: self.carry_forwarded_leaves = get_carry_forwarded_leaves(self.employee,
self.set_carry_forwarded_leaves() self.leave_type, self.from_date, self.carry_forward)
self.total_leaves_allocated = flt(self.carry_forwarded_leaves)
else:
self.total_leaves_allocated = 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")\ self.total_leaves_allocated = flt(self.carry_forwarded_leaves) + flt(self.new_leaves_allocated)
and not frappe.db.get_value("Leave Type", self.leave_type, "is_compensatory"):
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))) frappe.throw(_("Total leaves allocated is mandatory for Leave Type {0}".format(self.leave_type)))
def validate_total_leaves_allocated(self): def validate_total_leaves_allocated(self):
# Adding a day to include To Date in the difference # Adding a day to include To Date in the difference
date_difference = date_diff(self.to_date, self.from_date) + 1 date_difference = date_diff(self.to_date, self.from_date) + 1
if date_difference < flt(self.total_leaves_allocated): if date_difference < self.total_leaves_allocated:
frappe.throw(_("Total allocated leaves are more than days in the period"), OverAllocationError) frappe.throw(_("Total allocated leaves are more than days in the period"), OverAllocationError)
def validate_against_leave_applications(self): def validate_against_leave_applications(self):
@ -123,43 +118,16 @@ class LeaveAllocation(Document):
else: else:
frappe.throw(_("Total allocated leaves {0} cannot be less than already approved leaves {1} for the period").format(self.total_leaves_allocated, leaves_taken), LessAllocationError) frappe.throw(_("Total allocated leaves {0} cannot be less than already approved leaves {1} for the period").format(self.total_leaves_allocated, leaves_taken), LessAllocationError)
def set_carry_forwarded_leaves(self):
self.carry_forwarded_leaves = get_carry_forwarded_leaves(self.employee, self.leave_type, self.from_date)
max_leaves, leaves_allocated = self.get_max_leaves_with_leaves_allocated_for_leave_type(self.carry_forwarded_leaves)
if leaves_allocated > max_leaves:
self.carry_forwarded_leaves = max_leaves - (leaves_allocated - self.carry_forwarded_leaves)
def get_max_leaves_with_leaves_allocated_for_leave_type(self, new_leaves):
''' compare new leaves allocated with max leaves '''
company = frappe.db.get_value("Employee", self.employee, "company")
leaves_allocated = 0
leave_period = get_leave_period(self.from_date, self.to_date, company)
max_leaves_allowed = frappe.db.get_value("Leave Type", self.leave_type, "max_leaves_allowed")
if max_leaves_allowed > 0:
if leave_period:
leaves_allocated = get_leave_allocation_for_period(self.employee, self.leave_type, leave_period[0].from_date, leave_period[0].to_date)
leaves_allocated += new_leaves
return max_leaves_allowed, leaves_allocated
def get_leave_allocation_for_period(employee, leave_type, from_date, to_date): def get_leave_allocation_for_period(employee, leave_type, from_date, to_date):
leave_allocated = 0 leave_allocated = 0
leave_allocations = frappe.db.sql(""" leave_allocations = frappe.db.sql("""
SELECT select employee, leave_type, from_date, to_date, total_leaves_allocated
employee, from `tabLeave Allocation`
leave_type, where employee=%(employee)s and leave_type=%(leave_type)s
from_date, and docstatus=1
to_date, and (from_date between %(from_date)s and %(to_date)s
total_leaves_allocated or to_date between %(from_date)s and %(to_date)s
FROM `tabLeave Allocation` or (from_date < %(from_date)s and to_date > %(to_date)s))
WHERE
employee=%(employee)s
AND leave_type=%(leave_type)s
AND docstatus=1
AND (from_date BETWEEN %(from_date)s AND %(to_date)s
OR to_date BETWEEN %(from_date)s AND %(to_date)s
OR (from_date < %(from_date)s AND to_date > %(to_date)s))
""", { """, {
"from_date": from_date, "from_date": from_date,
"to_date": to_date, "to_date": to_date,
@ -174,43 +142,14 @@ def get_leave_allocation_for_period(employee, leave_type, from_date, to_date):
return leave_allocated return leave_allocated
@frappe.whitelist() @frappe.whitelist()
def get_carry_forwarded_leaves(employee, leave_type, date): def get_carry_forwarded_leaves(employee, leave_type, date, carry_forward=None):
''' Calculates carry forwarded days based on previous unused leave allocations ''' leave_records = frappe.get_all("Leave Ledger Entry",
carry_forwarded_leaves = 0 filters={'Employee':employee,
expiry_days = get_days_to_expiry_for_leave_type(leave_type) 'leave_type':leave_type,
validate_carry_forward(leave_type) 'to_date':("<=", date)},
filters = { fields=['leaves'])
"employee": employee,
"leave_type": leave_type,
"docstatus": 1,
"to_date": ("<", date)
}
limit = 2
# check number of days to expire, ignore expiry for default value 0 return sum(record.get("leaves") for record in leave_records)
if expiry_days:
filters.update(carry_forward=0)
limit = 1
previous_allocation = frappe.get_all("Leave Allocation",
filters=filters,
fields=["name","from_date","to_date","total_leaves_allocated"],
order_by="to_date desc",
limit=limit)
if previous_allocation:
leaves_taken = get_approved_leaves_for_period(employee, leave_type,
previous_allocation[0].from_date, previous_allocation[0].to_date)
carry_forwarded_leaves = flt(previous_allocation[0].total_leaves_allocated) - flt(leaves_taken)
return carry_forwarded_leaves
def get_days_to_expiry_for_leave_type(leave_type):
''' returns days to expiry for a provided leave type '''
return frappe.db.get_value("Leave Type",
filters={"leave_type_name": leave_type, "is_carry_forward": 1},
fieldname="carry_forward_leave_expiry")
def validate_carry_forward(leave_type): def validate_carry_forward(leave_type):
if not frappe.db.get_value("Leave Type", leave_type, "is_carry_forward"): if not frappe.db.get_value("Leave Type", leave_type, "is_carry_forward"):

View File

@ -114,22 +114,7 @@ def create_leave_allocation(employee, leave_type, new_leaves_allocated, leave_ty
allocation.leave_period = leave_period.name allocation.leave_period = leave_period.name
if carry_forward_leaves: if carry_forward_leaves:
if leave_type_details.get(leave_type).is_carry_forward: if leave_type_details.get(leave_type).is_carry_forward:
create_carry_forward_leaves_allocation(employee, leave_type, leave_type_details, leave_period, carry_forward_leaves) allocation.carry_forward = carry_forward_leaves
allocation.save(ignore_permissions = True) allocation.save(ignore_permissions = True)
allocation.submit() allocation.submit()
return allocation.name return allocation.name
def create_carry_forward_leaves_allocation(employee, leave_type, leave_type_details, leave_period, carry_forward_leaves):
carry_forwarded_leaves = get_carry_forwarded_leaves(employee, leave_type, leave_period.from_date)
if not carry_forwarded_leaves:
return
allocation = frappe.new_doc("Leave Allocation")
allocation.employee = employee
allocation.leave_type = leave_type
allocation.from_date = leave_period.from_date
allocation.to_date = add_days(leave_period.from_date, leave_type_details.carry_forward_leave_expiry) if not leave_type_details.carry_forward_leave_expiry else leave_period.to_date
allocation.leave_period = leave_period.name
allocation.carry_forward = carry_forward_leaves
allocation.carry_forwarded_leaves = carry_forwarded_leaves
allocation.save(ignore_permissions=True)
allocation.submit()