mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-21 14:09:19 +00:00
Leave workflow patch fixes (#12823)
* modified patch for leave application workflow * removed leave approval field from leave application doctype * fetch lwp and attendance only if workflow field exists * modified test cases * modified files with leave application * docstatus draft for rejected applications * modified leave application calendar * test fixed * run patch only if any record exists
This commit is contained in:
@@ -172,7 +172,6 @@ def make_leave_application():
|
|||||||
"from_date": frappe.flags.current_date,
|
"from_date": frappe.flags.current_date,
|
||||||
"to_date": to_date,
|
"to_date": to_date,
|
||||||
"leave_type": allocated_leave.leave_type,
|
"leave_type": allocated_leave.leave_type,
|
||||||
"status": "Approved"
|
|
||||||
})
|
})
|
||||||
try:
|
try:
|
||||||
leave_application.insert()
|
leave_application.insert()
|
||||||
@@ -191,8 +190,9 @@ def mark_attendance():
|
|||||||
"employee": employee.name,
|
"employee": employee.name,
|
||||||
"attendance_date": attendance_date
|
"attendance_date": attendance_date
|
||||||
})
|
})
|
||||||
|
|
||||||
leave = frappe.db.sql("""select name from `tabLeave Application`
|
leave = frappe.db.sql("""select name from `tabLeave Application`
|
||||||
where employee = %s and %s between from_date and to_date and workflow_state = 'Approved'
|
where employee = %s and %s between from_date and to_date
|
||||||
and docstatus = 1""", (employee.name, attendance_date))
|
and docstatus = 1""", (employee.name, attendance_date))
|
||||||
|
|
||||||
if leave:
|
if leave:
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ def get_availability_data(date, physician):
|
|||||||
|
|
||||||
# Check if He/She on Leave
|
# Check if He/She on Leave
|
||||||
leave_record = frappe.db.sql("""select half_day from `tabLeave Application`
|
leave_record = frappe.db.sql("""select half_day from `tabLeave Application`
|
||||||
where employee = %s and %s between from_date and to_date and status = 'Approved'
|
where employee = %s and %s between from_date and to_date
|
||||||
and docstatus = 1""", (employee, date), as_dict=True)
|
and docstatus = 1""", (employee, date), as_dict=True)
|
||||||
if leave_record:
|
if leave_record:
|
||||||
if leave_record[0].half_day:
|
if leave_record[0].half_day:
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class Attendance(Document):
|
|||||||
|
|
||||||
def check_leave_record(self):
|
def check_leave_record(self):
|
||||||
leave_record = frappe.db.sql("""select leave_type, half_day from `tabLeave Application`
|
leave_record = frappe.db.sql("""select leave_type, half_day from `tabLeave Application`
|
||||||
where employee = %s and %s between from_date and to_date and workflow_state = 'Approved'
|
where employee = %s and %s between from_date and to_date
|
||||||
and docstatus = 1""", (self.employee, self.attendance_date), as_dict=True)
|
and docstatus = 1""", (self.employee, self.attendance_date), as_dict=True)
|
||||||
if leave_record:
|
if leave_record:
|
||||||
if leave_record[0].half_day:
|
if leave_record[0].half_day:
|
||||||
|
|||||||
@@ -10,15 +10,6 @@ frappe.ui.form.on("Leave Application", {
|
|||||||
frm.set_value("posting_date", frappe.datetime.get_today());
|
frm.set_value("posting_date", frappe.datetime.get_today());
|
||||||
}
|
}
|
||||||
|
|
||||||
frm.set_query("leave_approver", function() {
|
|
||||||
return {
|
|
||||||
query: "erpnext.hr.doctype.leave_application.leave_application.get_approvers",
|
|
||||||
filters: {
|
|
||||||
employee: frm.doc.employee
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
frm.set_query("employee", erpnext.queries.employee);
|
frm.set_query("employee", erpnext.queries.employee);
|
||||||
|
|
||||||
},
|
},
|
||||||
@@ -29,14 +20,11 @@ frappe.ui.form.on("Leave Application", {
|
|||||||
|
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
if (frm.is_new()) {
|
if (frm.is_new()) {
|
||||||
frm.set_value("workflow_state", "Open");
|
|
||||||
frm.trigger("calculate_total_days");
|
frm.trigger("calculate_total_days");
|
||||||
}
|
}
|
||||||
},
|
cur_frm.set_intro("");
|
||||||
|
if(frm.doc.__islocal && !in_list(frappe.user_roles, "Employee")) {
|
||||||
leave_approver: function(frm) {
|
frm.set_intro(__("Fill the form and save it"));
|
||||||
if(frm.doc.leave_approver){
|
|
||||||
frm.set_value("leave_approver_name", frappe.user.full_name(frm.doc.leave_approver));
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -427,96 +427,6 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "column_break_15",
|
|
||||||
"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,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"description": "",
|
|
||||||
"fieldname": "leave_approver",
|
|
||||||
"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": 1,
|
|
||||||
"label": "Leave Approver",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "User",
|
|
||||||
"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,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "leave_approver_name",
|
|
||||||
"fieldtype": "Read Only",
|
|
||||||
"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": "Leave Approver Name",
|
|
||||||
"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,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@@ -736,7 +646,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 3,
|
"max_attachments": 3,
|
||||||
"modified": "2018-01-22 12:10:40.757274",
|
"modified": "2018-02-12 13:10:05.766762",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Leave Application",
|
"name": "Leave Application",
|
||||||
@@ -885,7 +795,7 @@
|
|||||||
"submit": 0,
|
"submit": 0,
|
||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 0,
|
"quick_entry": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"read_only_onload": 0,
|
"read_only_onload": 0,
|
||||||
|
|||||||
@@ -21,17 +21,10 @@ class AttendanceAlreadyMarkedError(frappe.ValidationError): pass
|
|||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
class LeaveApplication(Document):
|
class LeaveApplication(Document):
|
||||||
def get_feed(self):
|
def get_feed(self):
|
||||||
return _("{0}: From {0} of type {1}").format(self.workflow_state, self.employee_name, self.leave_type)
|
return _("{0}: From {0} of type {1}").format(self.employee_name, self.leave_type)
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
if self.get("__islocal"): self.workflow_state = 'Open'
|
|
||||||
if not getattr(self, "__islocal", None) and frappe.db.exists(self.doctype, self.name):
|
|
||||||
self.previous_doc = frappe.get_value(self.doctype, self.name, "leave_approver", as_dict=True)
|
|
||||||
else:
|
|
||||||
self.previous_doc = None
|
|
||||||
|
|
||||||
set_employee_name(self)
|
set_employee_name(self)
|
||||||
|
|
||||||
self.validate_dates()
|
self.validate_dates()
|
||||||
self.validate_balance_leaves()
|
self.validate_balance_leaves()
|
||||||
self.validate_leave_overlap()
|
self.validate_leave_overlap()
|
||||||
@@ -39,22 +32,12 @@ class LeaveApplication(Document):
|
|||||||
self.show_block_day_warning()
|
self.show_block_day_warning()
|
||||||
self.validate_block_days()
|
self.validate_block_days()
|
||||||
self.validate_salary_processed_days()
|
self.validate_salary_processed_days()
|
||||||
self.validate_leave_approver()
|
|
||||||
self.validate_attendance()
|
self.validate_attendance()
|
||||||
|
|
||||||
def on_update(self):
|
|
||||||
if (not self.previous_doc and self.leave_approver) or (self.previous_doc and \
|
|
||||||
self.workflow_state == "Open" and self.previous_doc.leave_approver != self.leave_approver):
|
|
||||||
# notify leave approver about creation
|
|
||||||
self.notify_leave_approver()
|
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
|
|
||||||
self.validate_back_dated_application()
|
self.validate_back_dated_application()
|
||||||
|
|
||||||
# notify leave applier about approval
|
|
||||||
self.notify_employee(self.workflow_state)
|
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
# notify leave applier about cancellation
|
# notify leave applier about cancellation
|
||||||
self.notify_employee("cancelled")
|
self.notify_employee("cancelled")
|
||||||
@@ -128,7 +111,7 @@ class LeaveApplication(Document):
|
|||||||
block_dates = get_applicable_block_dates(self.from_date, self.to_date,
|
block_dates = get_applicable_block_dates(self.from_date, self.to_date,
|
||||||
self.employee, self.company)
|
self.employee, self.company)
|
||||||
|
|
||||||
if block_dates and self.workflow_state == "Approved":
|
if block_dates and self.docstatus == 1:
|
||||||
frappe.throw(_("You are not authorized to approve leaves on Block Dates"), LeaveDayBlockedError)
|
frappe.throw(_("You are not authorized to approve leaves on Block Dates"), LeaveDayBlockedError)
|
||||||
|
|
||||||
def validate_balance_leaves(self):
|
def validate_balance_leaves(self):
|
||||||
@@ -143,7 +126,7 @@ class LeaveApplication(Document):
|
|||||||
self.leave_balance = get_leave_balance_on(self.employee, self.leave_type, self.from_date,
|
self.leave_balance = get_leave_balance_on(self.employee, self.leave_type, self.from_date,
|
||||||
consider_all_leaves_in_the_allocation_period=True)
|
consider_all_leaves_in_the_allocation_period=True)
|
||||||
|
|
||||||
if self.workflow_state != "Rejected" and self.leave_balance < self.total_leave_days:
|
if self.leave_balance < self.total_leave_days:
|
||||||
if frappe.db.get_value("Leave Type", self.leave_type, "allow_negative"):
|
if frappe.db.get_value("Leave Type", self.leave_type, "allow_negative"):
|
||||||
frappe.msgprint(_("Note: There is not enough leave balance for Leave Type {0}")
|
frappe.msgprint(_("Note: There is not enough leave balance for Leave Type {0}")
|
||||||
.format(self.leave_type))
|
.format(self.leave_type))
|
||||||
@@ -160,7 +143,7 @@ class LeaveApplication(Document):
|
|||||||
select
|
select
|
||||||
name, leave_type, posting_date, from_date, to_date, total_leave_days, half_day_date
|
name, leave_type, posting_date, from_date, to_date, total_leave_days, half_day_date
|
||||||
from `tabLeave Application`
|
from `tabLeave Application`
|
||||||
where employee = %(employee)s and docstatus < 2 and workflow_state in ("Open", "Approved")
|
where employee = %(employee)s and docstatus < 2
|
||||||
and to_date >= %(from_date)s and from_date <= %(to_date)s
|
and to_date >= %(from_date)s and from_date <= %(to_date)s
|
||||||
and name != %(name)s""", {
|
and name != %(name)s""", {
|
||||||
"employee": self.employee,
|
"employee": self.employee,
|
||||||
@@ -190,7 +173,6 @@ class LeaveApplication(Document):
|
|||||||
leave_count_on_half_day_date = frappe.db.sql("""select count(name) from `tabLeave Application`
|
leave_count_on_half_day_date = frappe.db.sql("""select count(name) from `tabLeave Application`
|
||||||
where employee = %(employee)s
|
where employee = %(employee)s
|
||||||
and docstatus < 2
|
and docstatus < 2
|
||||||
and workflow_state in ("Open", "Approved")
|
|
||||||
and half_day = 1
|
and half_day = 1
|
||||||
and half_day_date = %(half_day_date)s
|
and half_day_date = %(half_day_date)s
|
||||||
and name != %(name)s""", {
|
and name != %(name)s""", {
|
||||||
@@ -206,23 +188,6 @@ class LeaveApplication(Document):
|
|||||||
if max_days and self.total_leave_days > cint(max_days):
|
if max_days and self.total_leave_days > cint(max_days):
|
||||||
frappe.throw(_("Leave of type {0} cannot be longer than {1}").format(self.leave_type, max_days))
|
frappe.throw(_("Leave of type {0} cannot be longer than {1}").format(self.leave_type, max_days))
|
||||||
|
|
||||||
def validate_leave_approver(self):
|
|
||||||
employee = frappe.get_doc("Employee", self.employee)
|
|
||||||
leave_approvers = [l.leave_approver for l in employee.get("leave_approvers")]
|
|
||||||
|
|
||||||
if len(leave_approvers) and self.leave_approver not in leave_approvers:
|
|
||||||
frappe.throw(_("Leave approver must be one of {0}")
|
|
||||||
.format(comma_or(leave_approvers)), InvalidLeaveApproverError)
|
|
||||||
|
|
||||||
elif self.leave_approver and not frappe.db.sql("""select name from `tabHas Role`
|
|
||||||
where parent=%s and role='Leave Approver'""", self.leave_approver):
|
|
||||||
frappe.throw(_("{0} ({1}) must have role 'Leave Approver'")\
|
|
||||||
.format(get_fullname(self.leave_approver), self.leave_approver), InvalidLeaveApproverError)
|
|
||||||
|
|
||||||
elif self.docstatus==1 and len(leave_approvers) and self.leave_approver != frappe.session.user:
|
|
||||||
frappe.throw(_("Only the selected Leave Approver can submit this Leave Application"),
|
|
||||||
LeaveApproverIdentityError)
|
|
||||||
|
|
||||||
def validate_attendance(self):
|
def validate_attendance(self):
|
||||||
attendance = frappe.db.sql("""select name from `tabAttendance` where employee = %s and (attendance_date between %s and %s)
|
attendance = frappe.db.sql("""select name from `tabAttendance` where employee = %s and (attendance_date between %s and %s)
|
||||||
and status = "Present" and docstatus = 1""",
|
and status = "Present" and docstatus = 1""",
|
||||||
@@ -231,7 +196,7 @@ class LeaveApplication(Document):
|
|||||||
frappe.throw(_("Attendance for employee {0} is already marked for this day").format(self.employee),
|
frappe.throw(_("Attendance for employee {0} is already marked for this day").format(self.employee),
|
||||||
AttendanceAlreadyMarkedError)
|
AttendanceAlreadyMarkedError)
|
||||||
|
|
||||||
def notify_employee(self, workflow_state):
|
def notify_employee(self):
|
||||||
employee = frappe.get_doc("Employee", self.employee)
|
employee = frappe.get_doc("Employee", self.employee)
|
||||||
if not employee.user_id:
|
if not employee.user_id:
|
||||||
return
|
return
|
||||||
@@ -246,19 +211,15 @@ class LeaveApplication(Document):
|
|||||||
message += "Leave Type: {leave_type}".format(leave_type=self.leave_type)+"<br>"
|
message += "Leave Type: {leave_type}".format(leave_type=self.leave_type)+"<br>"
|
||||||
message += "From Date: {from_date}".format(from_date=self.from_date)+"<br>"
|
message += "From Date: {from_date}".format(from_date=self.from_date)+"<br>"
|
||||||
message += "To Date: {to_date}".format(to_date=self.to_date)+"<br>"
|
message += "To Date: {to_date}".format(to_date=self.to_date)+"<br>"
|
||||||
message += "Status: {workflow_state}".format(workflow_state=_(workflow_state))
|
|
||||||
return message
|
return message
|
||||||
|
|
||||||
self.notify({
|
self.notify({
|
||||||
# for post in messages
|
# for post in messages
|
||||||
"message": _get_message(url=True),
|
"message": _get_message(url=True),
|
||||||
"message_to": employee.user_id,
|
"message_to": employee.user_id,
|
||||||
"subject": (_("Leave Application") + ": %s - %s") % (self.name, _(workflow_state))
|
"subject": (_("Leave Application") + ": %s - %s") % (self.name)
|
||||||
})
|
})
|
||||||
|
|
||||||
def notify_leave_approver(self):
|
|
||||||
employee = frappe.get_doc("Employee", self.employee)
|
|
||||||
|
|
||||||
def _get_message(url=False):
|
def _get_message(url=False):
|
||||||
name = self.name
|
name = self.name
|
||||||
employee_name = cstr(employee.employee_name)
|
employee_name = cstr(employee.employee_name)
|
||||||
@@ -275,7 +236,6 @@ class LeaveApplication(Document):
|
|||||||
self.notify({
|
self.notify({
|
||||||
# for post in messages
|
# for post in messages
|
||||||
"message": _get_message(url=True),
|
"message": _get_message(url=True),
|
||||||
"message_to": self.leave_approver,
|
|
||||||
|
|
||||||
# for email
|
# for email
|
||||||
"subject": (_("New Leave Application") + ": %s - " + _("Employee") + ": %s") % (self.name, cstr(employee.employee_name))
|
"subject": (_("New Leave Application") + ": %s - " + _("Employee") + ": %s") % (self.name, cstr(employee.employee_name))
|
||||||
@@ -320,23 +280,6 @@ class LeaveApplication(Document):
|
|||||||
# Arrey!
|
# Arrey!
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def get_approvers(doctype, txt, searchfield, start, page_len, filters):
|
|
||||||
if not filters.get("employee"):
|
|
||||||
frappe.throw(_("Please select Employee Record first."))
|
|
||||||
|
|
||||||
employee_user = frappe.get_value("Employee", filters.get("employee"), "user_id")
|
|
||||||
|
|
||||||
approvers_list = frappe.db.sql("""select user.name, user.first_name, user.last_name from
|
|
||||||
tabUser user, `tabEmployee Leave Approver` approver where
|
|
||||||
approver.parent = %s
|
|
||||||
and user.name like %s
|
|
||||||
and approver.leave_approver=user.name""", (filters.get("employee"), "%" + txt + "%"))
|
|
||||||
|
|
||||||
if not approvers_list:
|
|
||||||
approvers_list = get_approver_list(employee_user)
|
|
||||||
return approvers_list
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_number_of_leave_days(employee, leave_type, from_date, to_date, half_day = None, half_day_date = None):
|
def get_number_of_leave_days(employee, leave_type, from_date, to_date, half_day = None, half_day_date = None):
|
||||||
number_of_days = 0
|
number_of_days = 0
|
||||||
@@ -371,7 +314,7 @@ def get_approved_leaves_for_period(employee, leave_type, from_date, to_date):
|
|||||||
select employee, leave_type, from_date, to_date, total_leave_days
|
select employee, leave_type, from_date, to_date, total_leave_days
|
||||||
from `tabLeave Application`
|
from `tabLeave Application`
|
||||||
where employee=%(employee)s and leave_type=%(leave_type)s
|
where employee=%(employee)s and leave_type=%(leave_type)s
|
||||||
and workflow_state="Approved" and docstatus=1
|
and docstatus=1
|
||||||
and (from_date between %(from_date)s and %(to_date)s
|
and (from_date between %(from_date)s and %(to_date)s
|
||||||
or to_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))
|
or (from_date < %(from_date)s and to_date > %(to_date)s))
|
||||||
@@ -471,11 +414,10 @@ def add_department_leaves(events, start, end, employee, company):
|
|||||||
|
|
||||||
def add_leaves(events, start, end, match_conditions=None):
|
def add_leaves(events, start, end, match_conditions=None):
|
||||||
query = """select name, from_date, to_date, employee_name, half_day,
|
query = """select name, from_date, to_date, employee_name, half_day,
|
||||||
workflow_state, employee, docstatus
|
employee, docstatus
|
||||||
from `tabLeave Application` where
|
from `tabLeave Application` where
|
||||||
from_date <= %(end)s and to_date >= %(start)s <= to_date
|
from_date <= %(end)s and to_date >= %(start)s <= to_date
|
||||||
and docstatus < 2
|
and docstatus < 2"""
|
||||||
and workflow_state!="Rejected" """
|
|
||||||
if match_conditions:
|
if match_conditions:
|
||||||
query += match_conditions
|
query += match_conditions
|
||||||
|
|
||||||
@@ -485,7 +427,6 @@ def add_leaves(events, start, end, match_conditions=None):
|
|||||||
"doctype": "Leave Application",
|
"doctype": "Leave Application",
|
||||||
"from_date": d.from_date,
|
"from_date": d.from_date,
|
||||||
"to_date": d.to_date,
|
"to_date": d.to_date,
|
||||||
"workflow_state": d.workflow_state,
|
|
||||||
"title": cstr(d.employee_name) + \
|
"title": cstr(d.employee_name) + \
|
||||||
(d.half_day and _(" (Half Day)") or ""),
|
(d.half_day and _(" (Half Day)") or ""),
|
||||||
"docstatus": d.docstatus
|
"docstatus": d.docstatus
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ frappe.views.calendar["Leave Application"] = {
|
|||||||
"end": "to_date",
|
"end": "to_date",
|
||||||
"id": "name",
|
"id": "name",
|
||||||
"title": "title",
|
"title": "title",
|
||||||
"workflow_state": "workflow_state",
|
"docstatus": 1
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
header: {
|
header: {
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
frappe.listview_settings['Leave Application'] = {
|
frappe.listview_settings['Leave Application'] = {
|
||||||
add_fields: ["workflow_state", "leave_type", "employee", "employee_name", "total_leave_days", "from_date", "to_date"],
|
add_fields: ["leave_type", "employee", "employee_name", "total_leave_days", "from_date", "to_date"]
|
||||||
get_indicator: function(doc) {
|
|
||||||
return [__(doc.workflow_state), frappe.utils.guess_colour(doc.workflow_state),
|
|
||||||
"workflow_state,=," + doc.workflow_state];
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ QUnit.test("Test: Leave application [HR]", function (assert) {
|
|||||||
{to_date: leave_date},
|
{to_date: leave_date},
|
||||||
{half_day: 1},
|
{half_day: 1},
|
||||||
{employee: employee.message.name},
|
{employee: employee.message.name},
|
||||||
{leave_approver: "Administrator"},
|
|
||||||
{follow_via_email: 0}
|
{follow_via_email: 0}
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
@@ -36,8 +35,8 @@ QUnit.test("Test: Leave application [HR]", function (assert) {
|
|||||||
() => frappe.set_route("List", "Leave Application", "List"),
|
() => frappe.set_route("List", "Leave Application", "List"),
|
||||||
() => frappe.timeout(1),
|
() => frappe.timeout(1),
|
||||||
// // check approved application in list
|
// // check approved application in list
|
||||||
() => assert.deepEqual(["Test Employee 1", "Approved"], [cur_list.data[0].employee_name, cur_list.data[0].workflow_state]),
|
() => assert.deepEqual(["Test Employee 1", 1], [cur_list.data[0].employee_name, cur_list.data[0].docstatus]),
|
||||||
// "leave for correct employee is approved"),
|
// "leave for correct employee is submitted"),
|
||||||
() => done()
|
() => done()
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
@@ -103,7 +103,6 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
|
|
||||||
application = self.get_application(_test_records[0])
|
application = self.get_application(_test_records[0])
|
||||||
application.insert()
|
application.insert()
|
||||||
application.workflow_state = "Approved"
|
|
||||||
self.assertRaises(LeaveDayBlockedError, application.submit)
|
self.assertRaises(LeaveDayBlockedError, application.submit)
|
||||||
|
|
||||||
frappe.set_user("test1@example.com")
|
frappe.set_user("test1@example.com")
|
||||||
@@ -127,11 +126,9 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
make_allocation_record()
|
make_allocation_record()
|
||||||
|
|
||||||
application = self.get_application(_test_records[0])
|
application = self.get_application(_test_records[0])
|
||||||
application.leave_approver = "test2@example.com"
|
|
||||||
application.insert()
|
application.insert()
|
||||||
|
|
||||||
application = self.get_application(_test_records[0])
|
application = self.get_application(_test_records[0])
|
||||||
application.leave_approver = "test2@example.com"
|
|
||||||
self.assertRaises(OverlapError, application.insert)
|
self.assertRaises(OverlapError, application.insert)
|
||||||
|
|
||||||
def test_overlap_with_half_day_1(self):
|
def test_overlap_with_half_day_1(self):
|
||||||
@@ -148,14 +145,12 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
|
|
||||||
# leave from 1-5, half day on 3rd
|
# leave from 1-5, half day on 3rd
|
||||||
application = self.get_application(_test_records[0])
|
application = self.get_application(_test_records[0])
|
||||||
application.leave_approver = "test2@example.com"
|
|
||||||
application.half_day = 1
|
application.half_day = 1
|
||||||
application.half_day_date = "2013-01-03"
|
application.half_day_date = "2013-01-03"
|
||||||
application.insert()
|
application.insert()
|
||||||
|
|
||||||
# Apply again for a half day leave on 3rd
|
# Apply again for a half day leave on 3rd
|
||||||
application = self.get_application(_test_records[0])
|
application = self.get_application(_test_records[0])
|
||||||
application.leave_approver = "test2@example.com"
|
|
||||||
application.from_date = "2013-01-03"
|
application.from_date = "2013-01-03"
|
||||||
application.to_date = "2013-01-03"
|
application.to_date = "2013-01-03"
|
||||||
application.half_day = 1
|
application.half_day = 1
|
||||||
@@ -164,7 +159,6 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
|
|
||||||
# Apply again for a half day leave on 3rd
|
# Apply again for a half day leave on 3rd
|
||||||
application = self.get_application(_test_records[0])
|
application = self.get_application(_test_records[0])
|
||||||
application.leave_approver = "test2@example.com"
|
|
||||||
application.from_date = "2013-01-03"
|
application.from_date = "2013-01-03"
|
||||||
application.to_date = "2013-01-03"
|
application.to_date = "2013-01-03"
|
||||||
application.half_day = 1
|
application.half_day = 1
|
||||||
@@ -186,12 +180,10 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
|
|
||||||
# leave from 1-5, no half day
|
# leave from 1-5, no half day
|
||||||
application = self.get_application(_test_records[0])
|
application = self.get_application(_test_records[0])
|
||||||
application.leave_approver = "test2@example.com"
|
|
||||||
application.insert()
|
application.insert()
|
||||||
|
|
||||||
# Apply again for a half day leave on 1st
|
# Apply again for a half day leave on 1st
|
||||||
application = self.get_application(_test_records[0])
|
application = self.get_application(_test_records[0])
|
||||||
application.leave_approver = "test2@example.com"
|
|
||||||
application.half_day = 1
|
application.half_day = 1
|
||||||
application.half_day_date = application.from_date
|
application.half_day_date = application.from_date
|
||||||
|
|
||||||
@@ -211,14 +203,12 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
|
|
||||||
# leave from 1-5, half day on 5th
|
# leave from 1-5, half day on 5th
|
||||||
application = self.get_application(_test_records[0])
|
application = self.get_application(_test_records[0])
|
||||||
application.leave_approver = "test2@example.com"
|
|
||||||
application.half_day = 1
|
application.half_day = 1
|
||||||
application.half_day_date = "2013-01-05"
|
application.half_day_date = "2013-01-05"
|
||||||
application.insert()
|
application.insert()
|
||||||
|
|
||||||
# Apply leave from 4-7, half day on 5th
|
# Apply leave from 4-7, half day on 5th
|
||||||
application = self.get_application(_test_records[0])
|
application = self.get_application(_test_records[0])
|
||||||
application.leave_approver = "test2@example.com"
|
|
||||||
application.from_date = "2013-01-04"
|
application.from_date = "2013-01-04"
|
||||||
application.to_date = "2013-01-07"
|
application.to_date = "2013-01-07"
|
||||||
application.half_day = 1
|
application.half_day = 1
|
||||||
@@ -228,7 +218,6 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
|
|
||||||
# Apply leave from 5-7, half day on 5th
|
# Apply leave from 5-7, half day on 5th
|
||||||
application = self.get_application(_test_records[0])
|
application = self.get_application(_test_records[0])
|
||||||
application.leave_approver = "test2@example.com"
|
|
||||||
application.from_date = "2013-01-05"
|
application.from_date = "2013-01-05"
|
||||||
application.to_date = "2013-01-07"
|
application.to_date = "2013-01-07"
|
||||||
application.half_day = 1
|
application.half_day = 1
|
||||||
@@ -246,7 +235,6 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
make_allocation_record(employee="_T-Employee-0002")
|
make_allocation_record(employee="_T-Employee-0002")
|
||||||
|
|
||||||
application = self.get_application(_test_records[1])
|
application = self.get_application(_test_records[1])
|
||||||
application.leave_approver = "test@example.com"
|
|
||||||
|
|
||||||
frappe.db.set_value("Leave Block List", "_Test Leave Block List",
|
frappe.db.set_value("Leave Block List", "_Test Leave Block List",
|
||||||
"applies_to_all_departments", 1)
|
"applies_to_all_departments", 1)
|
||||||
@@ -257,7 +245,6 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
application.insert()
|
application.insert()
|
||||||
|
|
||||||
frappe.set_user("test@example.com")
|
frappe.set_user("test@example.com")
|
||||||
application.workflow_state = "Approved"
|
|
||||||
|
|
||||||
# clear permlevel access cache on change user
|
# clear permlevel access cache on change user
|
||||||
del application._has_access_to
|
del application._has_access_to
|
||||||
@@ -267,114 +254,6 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
frappe.db.set_value("Leave Block List", "_Test Leave Block List",
|
frappe.db.set_value("Leave Block List", "_Test Leave Block List",
|
||||||
"applies_to_all_departments", 0)
|
"applies_to_all_departments", 0)
|
||||||
|
|
||||||
def test_leave_approval(self):
|
|
||||||
self._clear_roles()
|
|
||||||
|
|
||||||
from frappe.utils.user import add_role
|
|
||||||
add_role("test@example.com", "Employee")
|
|
||||||
add_role("test1@example.com", "HR User")
|
|
||||||
add_role("test1@example.com", "Leave Approver")
|
|
||||||
add_role("test2@example.com", "Leave Approver")
|
|
||||||
|
|
||||||
self._test_leave_approval_basic_case()
|
|
||||||
self._test_leave_approval_invalid_leave_approver_insert()
|
|
||||||
self._test_leave_approval_invalid_leave_approver_submit()
|
|
||||||
self._test_leave_approval_valid_leave_approver_insert()
|
|
||||||
|
|
||||||
def _test_leave_approval_basic_case(self):
|
|
||||||
self._clear_applications()
|
|
||||||
|
|
||||||
self._add_employee_leave_approver("_T-Employee-0001", "test1@example.com")
|
|
||||||
|
|
||||||
# create leave application as Employee
|
|
||||||
frappe.set_user("test@example.com")
|
|
||||||
|
|
||||||
make_allocation_record()
|
|
||||||
|
|
||||||
application = self.get_application(_test_records[0])
|
|
||||||
application.leave_approver = "test1@example.com"
|
|
||||||
application.insert()
|
|
||||||
|
|
||||||
# submit leave application by Leave Approver
|
|
||||||
frappe.set_user("test1@example.com")
|
|
||||||
application.workflow_state = "Approved"
|
|
||||||
del application._has_access_to
|
|
||||||
application.submit()
|
|
||||||
self.assertEqual(frappe.db.get_value("Leave Application", application.name,
|
|
||||||
"docstatus"), 1)
|
|
||||||
|
|
||||||
def _test_leave_approval_invalid_leave_approver_insert(self):
|
|
||||||
from erpnext.hr.doctype.leave_application.leave_application import InvalidLeaveApproverError
|
|
||||||
|
|
||||||
self._clear_applications()
|
|
||||||
|
|
||||||
# add a different leave approver in the employee's list
|
|
||||||
# should raise exception if not a valid leave approver
|
|
||||||
self._add_employee_leave_approver("_T-Employee-0001", "test2@example.com")
|
|
||||||
self._remove_employee_leave_approver("_T-Employee-0001", "test1@example.com")
|
|
||||||
|
|
||||||
make_allocation_record()
|
|
||||||
|
|
||||||
application = self.get_application(_test_records[0])
|
|
||||||
frappe.set_user("test@example.com")
|
|
||||||
|
|
||||||
application.leave_approver = "test1@example.com"
|
|
||||||
self.assertRaises(InvalidLeaveApproverError, application.insert)
|
|
||||||
|
|
||||||
frappe.db.sql("""delete from `tabEmployee Leave Approver` where parent=%s""",
|
|
||||||
"_T-Employee-0001")
|
|
||||||
|
|
||||||
def _test_leave_approval_invalid_leave_approver_submit(self):
|
|
||||||
self._clear_applications()
|
|
||||||
self._add_employee_leave_approver("_T-Employee-0001", "test2@example.com")
|
|
||||||
|
|
||||||
# create leave application as employee
|
|
||||||
# but submit as invalid leave approver - should raise exception
|
|
||||||
frappe.set_user("test@example.com")
|
|
||||||
|
|
||||||
make_allocation_record()
|
|
||||||
|
|
||||||
application = self.get_application(_test_records[0])
|
|
||||||
application.leave_approver = "test2@example.com"
|
|
||||||
application.insert()
|
|
||||||
frappe.set_user("test1@example.com")
|
|
||||||
del application._has_access_to
|
|
||||||
application.workflow_state = "Approved"
|
|
||||||
|
|
||||||
from erpnext.hr.doctype.leave_application.leave_application import LeaveApproverIdentityError
|
|
||||||
self.assertRaises(LeaveApproverIdentityError, application.submit)
|
|
||||||
|
|
||||||
frappe.db.sql("""delete from `tabEmployee Leave Approver` where parent=%s""",
|
|
||||||
"_T-Employee-0001")
|
|
||||||
|
|
||||||
def _test_leave_approval_valid_leave_approver_insert(self):
|
|
||||||
self._clear_applications()
|
|
||||||
self._add_employee_leave_approver("_T-Employee-0001", "test2@example.com")
|
|
||||||
|
|
||||||
original_department = frappe.db.get_value("Employee", "_T-Employee-0001", "department")
|
|
||||||
frappe.db.set_value("Employee", "_T-Employee-0001", "department", None)
|
|
||||||
|
|
||||||
frappe.set_user("test@example.com")
|
|
||||||
|
|
||||||
make_allocation_record()
|
|
||||||
|
|
||||||
application = self.get_application(_test_records[0])
|
|
||||||
application.leave_approver = "test2@example.com"
|
|
||||||
application.insert()
|
|
||||||
|
|
||||||
# change to valid leave approver and try to submit leave application
|
|
||||||
frappe.set_user("test2@example.com")
|
|
||||||
application.workflow_state = "Approved"
|
|
||||||
del application._has_access_to
|
|
||||||
application.submit()
|
|
||||||
self.assertEqual(frappe.db.get_value("Leave Application", application.name,
|
|
||||||
"docstatus"), 1)
|
|
||||||
|
|
||||||
frappe.db.sql("""delete from `tabEmployee Leave Approver` where parent=%s""",
|
|
||||||
"_T-Employee-0001")
|
|
||||||
|
|
||||||
frappe.db.set_value("Employee", "_T-Employee-0001", "department", original_department)
|
|
||||||
|
|
||||||
def make_allocation_record(employee=None, leave_type=None):
|
def make_allocation_record(employee=None, leave_type=None):
|
||||||
frappe.db.sql("delete from `tabLeave Allocation`")
|
frappe.db.sql("delete from `tabLeave Allocation`")
|
||||||
|
|
||||||
@@ -388,4 +267,4 @@ def make_allocation_record(employee=None, leave_type=None):
|
|||||||
})
|
})
|
||||||
|
|
||||||
allocation.insert(ignore_permissions=True)
|
allocation.insert(ignore_permissions=True)
|
||||||
allocation.submit()
|
allocation.submit()
|
||||||
@@ -300,7 +300,6 @@ class SalarySlip(TransactionBase):
|
|||||||
where t2.name = t1.leave_type
|
where t2.name = t1.leave_type
|
||||||
and t2.is_lwp = 1
|
and t2.is_lwp = 1
|
||||||
and t1.docstatus = 1
|
and t1.docstatus = 1
|
||||||
and t1.workflow_state = 'Approved'
|
|
||||||
and t1.employee = %(employee)s
|
and t1.employee = %(employee)s
|
||||||
and CASE WHEN t2.include_holiday != 1 THEN %(dt)s not in ('{0}') and %(dt)s between from_date and to_date
|
and CASE WHEN t2.include_holiday != 1 THEN %(dt)s not in ('{0}') and %(dt)s between from_date and to_date
|
||||||
WHEN t2.include_holiday THEN %(dt)s between from_date and to_date
|
WHEN t2.include_holiday THEN %(dt)s between from_date and to_date
|
||||||
|
|||||||
@@ -489,7 +489,7 @@ erpnext.patches.v10_0.fichier_des_ecritures_comptables_for_france
|
|||||||
erpnext.patches.v10_0.update_assessment_plan
|
erpnext.patches.v10_0.update_assessment_plan
|
||||||
erpnext.patches.v10_0.update_assessment_result
|
erpnext.patches.v10_0.update_assessment_result
|
||||||
erpnext.patches.v10_0.added_extra_gst_custom_field
|
erpnext.patches.v10_0.added_extra_gst_custom_field
|
||||||
erpnext.patches.v10_0.workflow_leave_application #2018-01-24
|
erpnext.patches.v10_0.workflow_leave_application #2018-01-24 #2018-02-02 #2018-02-08
|
||||||
erpnext.patches.v10_0.set_default_payment_terms_based_on_company
|
erpnext.patches.v10_0.set_default_payment_terms_based_on_company
|
||||||
erpnext.patches.v10_0.update_sales_order_link_to_purchase_order
|
erpnext.patches.v10_0.update_sales_order_link_to_purchase_order
|
||||||
erpnext.patches.v10_0.added_extra_gst_custom_field_in_gstr2
|
erpnext.patches.v10_0.added_extra_gst_custom_field_in_gstr2
|
||||||
|
|||||||
@@ -3,11 +3,66 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
from erpnext.setup.install import leave_application_workflow
|
|
||||||
|
|
||||||
def execute():
|
def execute():
|
||||||
frappe.reload_doc("hr", "doctype", "leave_application")
|
if frappe.db.a_row_exists("Leave Application"):
|
||||||
frappe.reload_doc("workflow", "doctype", "workflow")
|
frappe.reload_doc("hr", "doctype", "leave_application")
|
||||||
leave_application_workflow()
|
frappe.reload_doc("workflow", "doctype", "workflow")
|
||||||
if frappe.db.has_column("Leave Application", "status"):
|
states = {'Approved': 'Success', 'Rejected': 'Danger', 'Open': 'Warning'}
|
||||||
frappe.db.sql("""update `tabLeave Application` set workflow_state = status""")
|
|
||||||
|
for state, style in states.items():
|
||||||
|
if not frappe.db.exists("Workflow State", state):
|
||||||
|
frappe.get_doc({
|
||||||
|
'doctype': 'Workflow State',
|
||||||
|
'workflow_state_name': state,
|
||||||
|
'style': style
|
||||||
|
}).insert(ignore_permissions=True)
|
||||||
|
|
||||||
|
for action in ['Approve', 'Reject']:
|
||||||
|
if not frappe.db.exists("Workflow Action", action):
|
||||||
|
frappe.get_doc({
|
||||||
|
'doctype': 'Workflow Action',
|
||||||
|
'workflow_action_name': action
|
||||||
|
}).insert(ignore_permissions=True)
|
||||||
|
|
||||||
|
if not frappe.db.exists("Workflow", "Leave Approval"):
|
||||||
|
frappe.get_doc({
|
||||||
|
'doctype': 'Workflow',
|
||||||
|
'workflow_name': 'Leave Approval',
|
||||||
|
'document_type': 'Leave Application',
|
||||||
|
'is_active': 1,
|
||||||
|
'workflow_state_field': 'workflow_state',
|
||||||
|
'states': [{
|
||||||
|
"state": 'Open',
|
||||||
|
"doc_status": 0,
|
||||||
|
"allow_edit": 'Employee'
|
||||||
|
}, {
|
||||||
|
"state": 'Approved',
|
||||||
|
"doc_status": 1,
|
||||||
|
"allow_edit": 'Leave Approver'
|
||||||
|
}, {
|
||||||
|
"state": 'Rejected',
|
||||||
|
"doc_status": 0,
|
||||||
|
"allow_edit": 'Leave Approver'
|
||||||
|
}],
|
||||||
|
'transitions': [{
|
||||||
|
"state": 'Open',
|
||||||
|
"action": 'Approve',
|
||||||
|
"next_state": 'Approved',
|
||||||
|
"allowed": 'Leave Approver'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": 'Open',
|
||||||
|
"action": 'Reject',
|
||||||
|
"next_state": 'Rejected',
|
||||||
|
"allowed": 'Leave Approver'
|
||||||
|
}]
|
||||||
|
}).insert(ignore_permissions=True)
|
||||||
|
|
||||||
|
if frappe.db.has_column("Leave Application", "status"):
|
||||||
|
frappe.db.sql("""update `tabLeave Application` set workflow_state = status""")
|
||||||
|
|
||||||
|
if frappe.db.has_column("Leave Application", "workflow_state"):
|
||||||
|
frappe.db.sql("""update `tabWorkflow Document State` set doc_status = 0 where parent = "Leave Approval" \
|
||||||
|
and state = "Rejected" and doc_status = 1""")
|
||||||
|
frappe.db.sql("""update `tabLeave Application` set docstatus = 0 where workflow_state = "Rejected" and docstatus = 1""")
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ default_mail_footer = """<div style="padding: 7px; text-align: right; color: #88
|
|||||||
<a style="color: #888" href="http://erpnext.org">ERPNext</a></div>"""
|
<a style="color: #888" href="http://erpnext.org">ERPNext</a></div>"""
|
||||||
|
|
||||||
def after_install():
|
def after_install():
|
||||||
leave_application_workflow()
|
|
||||||
frappe.get_doc({'doctype': "Role", "role_name": "Analytics"}).insert()
|
frappe.get_doc({'doctype': "Role", "role_name": "Analytics"}).insert()
|
||||||
set_single_defaults()
|
set_single_defaults()
|
||||||
create_compact_item_print_custom_field()
|
create_compact_item_print_custom_field()
|
||||||
@@ -20,58 +19,6 @@ def after_install():
|
|||||||
add_all_roles_to("Administrator")
|
add_all_roles_to("Administrator")
|
||||||
frappe.db.commit()
|
frappe.db.commit()
|
||||||
|
|
||||||
def leave_application_workflow():
|
|
||||||
states = {'Approved': 'Success', 'Rejected': 'Danger', 'Open': 'Warning'}
|
|
||||||
|
|
||||||
for state, style in states.items():
|
|
||||||
if not frappe.db.exists("Workflow State", state):
|
|
||||||
frappe.get_doc({
|
|
||||||
'doctype': 'Workflow State',
|
|
||||||
'workflow_state_name': state,
|
|
||||||
'style': style
|
|
||||||
}).insert(ignore_permissions=True)
|
|
||||||
|
|
||||||
for action in ['Approve', 'Reject']:
|
|
||||||
if not frappe.db.exists("Workflow Action", action):
|
|
||||||
frappe.get_doc({
|
|
||||||
'doctype': 'Workflow Action',
|
|
||||||
'workflow_action_name': action
|
|
||||||
}).insert(ignore_permissions=True)
|
|
||||||
|
|
||||||
if not frappe.db.exists("Workflow", "Leave Approval"):
|
|
||||||
frappe.get_doc({
|
|
||||||
'doctype': 'Workflow',
|
|
||||||
'workflow_name': 'Leave Approval',
|
|
||||||
'document_type': 'Leave Application',
|
|
||||||
'is_active': 1,
|
|
||||||
'workflow_state_field': 'workflow_state',
|
|
||||||
'states': [{
|
|
||||||
"state": 'Open',
|
|
||||||
"doc_status": 0,
|
|
||||||
"allow_edit": 'Employee'
|
|
||||||
}, {
|
|
||||||
"state": 'Approved',
|
|
||||||
"doc_status": 1,
|
|
||||||
"allow_edit": 'Leave Approver'
|
|
||||||
}, {
|
|
||||||
"state": 'Rejected',
|
|
||||||
"doc_status": 1,
|
|
||||||
"allow_edit": 'Leave Approver'
|
|
||||||
}],
|
|
||||||
'transitions': [{
|
|
||||||
"state": 'Open',
|
|
||||||
"action": 'Approve',
|
|
||||||
"next_state": 'Approved',
|
|
||||||
"allowed": 'Leave Approver'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"state": 'Open',
|
|
||||||
"action": 'Reject',
|
|
||||||
"next_state": 'Rejected',
|
|
||||||
"allowed": 'Leave Approver'
|
|
||||||
}]
|
|
||||||
}).insert(ignore_permissions=True)
|
|
||||||
|
|
||||||
def check_setup_wizard_not_completed():
|
def check_setup_wizard_not_completed():
|
||||||
if frappe.db.get_default('desktop:home_page') == 'desktop':
|
if frappe.db.get_default('desktop:home_page') == 'desktop':
|
||||||
print()
|
print()
|
||||||
|
|||||||
Reference in New Issue
Block a user