From 679371e397a840267d1e29b7d19bdcccf5598f5a Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Thu, 9 May 2019 19:43:35 +0530 Subject: [PATCH] feat: get carry forwarded leaves via ledger entries --- .../leave_allocation/leave_allocation.js | 19 +- .../leave_allocation/leave_allocation.json | 965 +++++------------- .../leave_allocation/leave_allocation.py | 159 +-- .../hr/doctype/leave_period/leave_period.py | 21 +- 4 files changed, 293 insertions(+), 871 deletions(-) diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.js b/erpnext/hr/doctype/leave_allocation/leave_allocation.js index 0014c07a3c..228b5528de 100755 --- a/erpnext/hr/doctype/leave_allocation/leave_allocation.js +++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.js @@ -34,33 +34,36 @@ frappe.ui.form.on("Leave Allocation", { }, 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) { - 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) { - 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({ method: "erpnext.hr.doctype.leave_allocation.leave_allocation.get_carry_forwarded_leaves", args: { "employee": frm.doc.employee, - "leave_type": frm.doc.leave_type, "date": frm.doc.from_date, + "leave_type": frm.doc.leave_type, + "carry_forward": frm.doc.carry_forward }, callback: function(r) { if (!r.exc && r.message) { - frm.set_value("new_leaves_allocated", 0); 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("total_leaves_allocated", flt(frm.doc.new_leaves_allocated)); } } -}) +}) \ No newline at end of file diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.json b/erpnext/hr/doctype/leave_allocation/leave_allocation.json index 12c74de9d0..bb851c6850 100644 --- a/erpnext/hr/doctype/leave_allocation/leave_allocation.json +++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.json @@ -1,736 +1,231 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 1, - "allow_rename": 0, - "autoname": "naming_series:", - "beta": 0, - "creation": "2013-02-20 19:10:38", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "Setup", - "editable_grid": 0, - "engine": "InnoDB", - "fields": [ - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", - "fieldname": "naming_series", - "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", - "length": 0, - "no_copy": 1, - "options": "HR-LAL-.YYYY.-", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "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": 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", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Employee", - "length": 0, - "no_copy": 0, - "oldfieldname": "employee", - "oldfieldtype": "Link", - "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, - "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", - "fieldname": "employee_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Employee Name", - "length": 0, - "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": 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", - "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_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break1", - "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%" - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "leave_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": 1, - "label": "Leave Type", - "length": 0, - "no_copy": 0, - "oldfieldname": "leave_type", - "oldfieldtype": "Link", - "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, - "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", - "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", - "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": 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", - "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", - "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": 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", - "fieldtype": "Section 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, - "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, - "bold": 1, - "collapsible": 0, - "columns": 0, - "fieldname": "new_leaves_allocated", - "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": "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", - "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": "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", - "fieldname": "carry_forwarded_leaves", - "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", - "length": 0, - "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, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "total_leaves_allocated", - "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", - "length": 0, - "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": 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", - "fieldname": "total_leaves_encashed", - "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", - "length": 0, - "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", - "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", - "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", - "length": 0, - "no_copy": 0, - "options": "Compensatory Leave 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_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "leave_period", - "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, - "label": "Leave Period", - "length": 0, - "no_copy": 0, - "options": "Leave Period", - "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": "amended_from", - "fieldtype": "Link", - "hidden": 0, - "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", - "length": 0, - "no_copy": 1, - "oldfieldname": "amended_from", - "oldfieldtype": "Data", - "options": "Leave Allocation", - "permlevel": 0, - "print_hide": 1, - "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": 1, - "columns": 0, - "fieldname": "notes", - "fieldtype": "Section 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, - "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", - "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", - "length": 0, - "no_copy": 0, - "oldfieldname": "reason", - "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" - } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "icon": "fa fa-ok", - "idx": 1, - "image_view": 0, - "in_create": 0, - "is_submittable": 1, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2019-01-30 11:28:09.360525", - "modified_by": "Administrator", - "module": "HR", - "name": "Leave Allocation", - "owner": "Administrator", - "permissions": [ - { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "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, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 1, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "HR Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 1, - "write": 1 - } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "search_fields": "employee,employee_name,leave_type,total_leaves_allocated", - "show_name_in_global_search": 1, - "sort_field": "modified", - "sort_order": "DESC", - "timeline_field": "employee", - "track_changes": 0, - "track_seen": 0, - "track_views": 0 - } \ No newline at end of file + "allow_import": 1, + "autoname": "naming_series:", + "creation": "2013-02-20 19:10:38", + "doctype": "DocType", + "document_type": "Setup", + "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": [ + { + "fieldname": "naming_series", + "fieldtype": "Select", + "label": "Series", + "no_copy": 1, + "options": "HR-LAL-.YYYY.-", + "print_hide": 1, + "reqd": 1, + "set_only_once": 1 + }, + { + "fieldname": "employee", + "fieldtype": "Link", + "in_global_search": 1, + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Employee", + "oldfieldname": "employee", + "oldfieldtype": "Link", + "options": "Employee", + "reqd": 1, + "search_index": 1 + }, + { + "fetch_from": "employee.employee_name", + "fieldname": "employee_name", + "fieldtype": "Data", + "in_global_search": 1, + "in_list_view": 1, + "label": "Employee Name", + "read_only": 1, + "search_index": 1 + }, + { + "fetch_from": "employee.department", + "fieldname": "department", + "fieldtype": "Link", + "label": "Department", + "options": "Department", + "read_only": 1 + }, + { + "fieldname": "column_break1", + "fieldtype": "Column Break", + "width": "50%" + }, + { + "fieldname": "leave_type", + "fieldtype": "Link", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Leave Type", + "oldfieldname": "leave_type", + "oldfieldtype": "Link", + "options": "Leave Type", + "reqd": 1, + "search_index": 1 + }, + { + "fieldname": "from_date", + "fieldtype": "Date", + "label": "From Date", + "reqd": 1 + }, + { + "fieldname": "to_date", + "fieldtype": "Date", + "label": "To Date", + "reqd": 1 + }, + { + "fieldname": "section_break_6", + "fieldtype": "Section Break", + "label": "Allocation" + }, + { + "allow_on_submit": 1, + "bold": 1, + "fieldname": "new_leaves_allocated", + "fieldtype": "Float", + "label": "New Leaves Allocated" + }, + { + "fieldname": "carry_forward", + "fieldtype": "Check", + "label": "Add unused leaves from previous allocations" + }, + { + "depends_on": "carry_forward", + "fieldname": "carry_forwarded_leaves", + "fieldtype": "Float", + "label": "Unused leaves", + "read_only": 1 + }, + { + "allow_on_submit": 1, + "fieldname": "total_leaves_allocated", + "fieldtype": "Float", + "label": "Total Leaves Allocated", + "read_only": 1, + "reqd": 1 + }, + { + "depends_on": "eval:doc.total_leaves_encashed>0", + "fieldname": "total_leaves_encashed", + "fieldtype": "Float", + "label": "Total Leaves Encashed", + "read_only": 1 + }, + { + "fieldname": "column_break_10", + "fieldtype": "Column Break" + }, + { + "fieldname": "compensatory_request", + "fieldtype": "Link", + "label": "Compensatory Leave Request", + "options": "Compensatory Leave Request", + "read_only": 1 + }, + { + "fieldname": "leave_period", + "fieldtype": "Link", + "in_standard_filter": 1, + "label": "Leave Period", + "options": "Leave Period", + "read_only": 1 + }, + { + "fieldname": "amended_from", + "fieldtype": "Link", + "ignore_user_permissions": 1, + "label": "Amended From", + "no_copy": 1, + "oldfieldname": "amended_from", + "oldfieldtype": "Data", + "options": "Leave Allocation", + "print_hide": 1, + "read_only": 1 + }, + { + "collapsible": 1, + "fieldname": "notes", + "fieldtype": "Section Break", + "label": "Notes" + }, + { + "fieldname": "description", + "fieldtype": "Small Text", + "label": "Description", + "oldfieldname": "reason", + "oldfieldtype": "Small Text", + "width": "300px" + } + ], + "icon": "fa fa-ok", + "idx": 1, + "is_submittable": 1, + "modified": "2019-05-09 19:06:33.659196", + "modified_by": "Administrator", + "module": "HR", + "name": "Leave Allocation", + "owner": "Administrator", + "permissions": [ + { + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "HR User", + "share": 1, + "submit": 1, + "write": 1 + }, + { + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "import": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "HR Manager", + "share": 1, + "submit": 1, + "write": 1 + } + ], + "search_fields": "employee,employee_name,leave_type,total_leaves_allocated", + "show_name_in_global_search": 1, + "sort_field": "modified", + "sort_order": "DESC", + "timeline_field": "employee" +} \ No newline at end of file diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.py b/erpnext/hr/doctype/leave_allocation/leave_allocation.py index f7db7dee86..aa1cc9ecad 100755 --- a/erpnext/hr/doctype/leave_allocation/leave_allocation.py +++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.py @@ -8,6 +8,7 @@ from frappe import _ from frappe.model.document import Document 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_ledger_entry.leave_ledger_entry import create_leave_ledger_entry class OverlapError(frappe.ValidationError): pass class BackDatedAllocationError(frappe.ValidationError): pass @@ -18,66 +19,62 @@ class ValueMultiplierError(frappe.ValidationError): pass class LeaveAllocation(Document): def validate(self): self.validate_period() - self.validate_lwp() - set_employee_name(self) - self.set_total_leaves_allocated() + self.validate_new_leaves_allocated_value() self.validate_allocation_overlap() self.validate_back_dated_allocation() + self.set_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() def validate_leave_allocation_days(self): - new_leaves = self.new_leaves_allocated if not self.carry_forward else self.carry_forwarded_leaves - max_leaves, leaves_allocated = self.get_max_leaves_with_leaves_allocated_for_leave_type(flt(new_leaves)) + company = frappe.db.get_value("Employee", self.employee, "company") + 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: + 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")\ + .format(self.leave_type, self.employee)) - if leaves_allocated > max_leaves: - 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)) + def on_submit(self): + create_leave_ledger_entry(self) + + def on_cancel(self): + create_leave_ledger_entry(self) def on_update_after_submit(self): self.validate_new_leaves_allocated_value() self.set_total_leaves_allocated() - frappe.db.set(self,'total_leaves_allocated', flt(self.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)) self.validate_against_leave_applications() def validate_period(self): - allocation_period = date_diff(self.to_date, self.from_date) - - if allocation_period <= 0: + if date_diff(self.to_date, self.from_date) <= 0: 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): 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)) - def validate_leaves_allocated_value(self): + def validate_new_leaves_allocated_value(self): """validate that leave allocation is in multiples of 0.5""" if flt(self.new_leaves_allocated) % 0.5: frappe.throw(_("Leaves must be allocated in multiples of 0.5"), ValueMultiplierError) def validate_allocation_overlap(self): leave_allocation = frappe.db.sql(""" - SELECT - name - FROM `tabLeave Allocation` - WHERE - 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)) + select name from `tabLeave Allocation` + where employee=%s and leave_type=%s and docstatus=1 + and to_date >= %s and from_date <= %s""", + (self.employee, self.leave_type, self.from_date, self.to_date)) if leave_allocation: frappe.msgprint(_("{0} already allocated for Employee {1} for period {2} to {3}") @@ -97,20 +94,18 @@ class LeaveAllocation(Document): BackDatedAllocationError) def set_total_leaves_allocated(self): - if self.carry_forward: - self.set_carry_forwarded_leaves() - self.total_leaves_allocated = flt(self.carry_forwarded_leaves) - else: - self.total_leaves_allocated = flt(self.new_leaves_allocated) + self.carry_forwarded_leaves = get_carry_forwarded_leaves(self.employee, + self.leave_type, self.from_date, self.carry_forward) - 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"): + 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") 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): # Adding a day to include To Date in the difference 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) def validate_against_leave_applications(self): @@ -123,43 +118,16 @@ class LeaveAllocation(Document): 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) - 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): leave_allocated = 0 leave_allocations = frappe.db.sql(""" - SELECT - employee, - leave_type, - from_date, - to_date, - total_leaves_allocated - FROM `tabLeave Allocation` - 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)) + select employee, leave_type, from_date, to_date, total_leaves_allocated + from `tabLeave Allocation` + 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, "to_date": to_date, @@ -174,43 +142,14 @@ def get_leave_allocation_for_period(employee, leave_type, from_date, to_date): return leave_allocated @frappe.whitelist() -def get_carry_forwarded_leaves(employee, leave_type, date): - ''' Calculates carry forwarded days based on previous unused leave allocations ''' - carry_forwarded_leaves = 0 - expiry_days = get_days_to_expiry_for_leave_type(leave_type) - validate_carry_forward(leave_type) - filters = { - "employee": employee, - "leave_type": leave_type, - "docstatus": 1, - "to_date": ("<", date) - } - limit = 2 +def get_carry_forwarded_leaves(employee, leave_type, date, carry_forward=None): + leave_records = frappe.get_all("Leave Ledger Entry", + filters={'Employee':employee, + 'leave_type':leave_type, + 'to_date':("<=", date)}, + fields=['leaves']) - # check number of days to expire, ignore expiry for default value 0 - 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") + return sum(record.get("leaves") for record in leave_records) def validate_carry_forward(leave_type): if not frappe.db.get_value("Leave Type", leave_type, "is_carry_forward"): diff --git a/erpnext/hr/doctype/leave_period/leave_period.py b/erpnext/hr/doctype/leave_period/leave_period.py index a6198a8918..91cc9b8340 100644 --- a/erpnext/hr/doctype/leave_period/leave_period.py +++ b/erpnext/hr/doctype/leave_period/leave_period.py @@ -114,22 +114,7 @@ def create_leave_allocation(employee, leave_type, new_leaves_allocated, leave_ty allocation.leave_period = leave_period.name if carry_forward_leaves: 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.save(ignore_permissions=True) + allocation.carry_forward = carry_forward_leaves + allocation.save(ignore_permissions = True) allocation.submit() - 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() \ No newline at end of file + return allocation.name \ No newline at end of file