Skip to content

Commit

Permalink
Merge pull request #2454 from frappe/shift-schedule-refactor
Browse files Browse the repository at this point in the history
refactor: Shift Assignment Schedule
  • Loading branch information
krantheman authored Dec 19, 2024
2 parents 8fd2912 + cfb5c85 commit 6bc37fe
Show file tree
Hide file tree
Showing 40 changed files with 1,040 additions and 424 deletions.
67 changes: 51 additions & 16 deletions hrms/api/roster.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from hrms.hr.doctype.shift_assignment.shift_assignment import ShiftAssignment
from hrms.hr.doctype.shift_assignment_tool.shift_assignment_tool import create_shift_assignment
from hrms.hr.doctype.shift_schedule.shift_schedule import get_or_insert_shift_schedule


@frappe.whitelist()
Expand Down Expand Up @@ -37,7 +38,17 @@ def get_events(


@frappe.whitelist()
def create_shift_assignment_schedule(
def get_schedule_from_assignment(shift_schedule_assignment: str):
shift_schedule = frappe.db.get_value(
"Shift Schedule Assignment", shift_schedule_assignment, "shift_schedule"
)
frequency = frappe.db.get_value("Shift Schedule", shift_schedule, "frequency")
repeat_on_days = frappe.get_all("Assignment Rule Day", filters={"parent": shift_schedule}, pluck="day")
return {"frequency": frequency, "repeat_on_days": repeat_on_days}


@frappe.whitelist()
def create_shift_schedule_assignment(
employee: str,
company: str,
shift_type: str,
Expand All @@ -46,34 +57,39 @@ def create_shift_assignment_schedule(
end_date: str | None,
repeat_on_days: list[str],
frequency: str,
shift_location: str | None = None,
) -> None:
schedule = frappe.get_doc(
shift_schedule = get_or_insert_shift_schedule(shift_type, frequency, repeat_on_days)
shift_schedule_assignment = frappe.get_doc(
{
"doctype": "Shift Assignment Schedule",
"frequency": frequency,
"repeat_on_days": [{"day": day} for day in repeat_on_days],
"enabled": 0 if end_date else 1,
"doctype": "Shift Schedule Assignment",
"shift_schedule": shift_schedule,
"employee": employee,
"company": company,
"shift_type": shift_type,
"shift_status": status,
"shift_location": shift_location,
"enabled": 0 if end_date else 1,
}
).insert()

if not end_date or date_diff(end_date, start_date) <= 90:
return schedule.create_shifts(start_date, end_date)
return shift_schedule_assignment.create_shifts(start_date, end_date)

frappe.enqueue(schedule.create_shifts, timeout=4500, start_date=start_date, end_date=end_date)
frappe.enqueue(
shift_schedule_assignment.create_shifts, timeout=4500, start_date=start_date, end_date=end_date
)


@frappe.whitelist()
def delete_shift_assignment_schedule(schedule: str) -> None:
for shift_assignment in frappe.get_all("Shift Assignment", {"schedule": schedule}, pluck="name"):
def delete_shift_schedule_assignment(shift_schedule_assignment: str) -> None:
for shift_assignment in frappe.get_all(
"Shift Assignment", {"shift_schedule_assignment": shift_schedule_assignment}, pluck="name"
):
doc = frappe.get_doc("Shift Assignment", shift_assignment)
if doc.docstatus == 1:
doc.cancel()
frappe.delete_doc("Shift Assignment", shift_assignment)
frappe.delete_doc("Shift Assignment Schedule", schedule)
frappe.delete_doc("Shift Schedule Assignment", shift_schedule_assignment)


@frappe.whitelist()
Expand All @@ -93,7 +109,13 @@ def swap_shift(
src_shift_doc = frappe.get_doc("Shift Assignment", src_shift)
break_shift(src_shift_doc, src_date)
insert_shift(
tgt_employee, tgt_company, src_shift_doc.shift_type, tgt_date, tgt_date, src_shift_doc.status
tgt_employee,
tgt_company,
src_shift_doc.shift_type,
tgt_date,
tgt_date,
src_shift_doc.status,
src_shift_doc.shift_location,
)

if tgt_shift:
Expand All @@ -104,6 +126,7 @@ def swap_shift(
src_date,
src_date,
tgt_shift_doc.status,
tgt_shift_doc.shift_location,
)


Expand All @@ -122,6 +145,7 @@ def break_shift(assignment: str | ShiftAssignment, date: str) -> None:
shift_type = assignment.shift_type
status = assignment.status
end_date = assignment.end_date
shift_location = assignment.shift_location

if date_diff(date, assignment.start_date) == 0:
assignment.cancel()
Expand All @@ -131,19 +155,28 @@ def break_shift(assignment: str | ShiftAssignment, date: str) -> None:
assignment.save()

if not end_date or date_diff(end_date, date) > 0:
create_shift_assignment(employee, company, shift_type, add_days(date, 1), end_date, status)
create_shift_assignment(
employee, company, shift_type, add_days(date, 1), end_date, status, shift_location
)


@frappe.whitelist()
def insert_shift(
employee: str, company: str, shift_type: str, start_date: str, end_date: str | None, status: str
employee: str,
company: str,
shift_type: str,
start_date: str,
end_date: str | None,
status: str,
shift_location: str | None = None,
) -> None:
filters = {
"doctype": "Shift Assignment",
"employee": employee,
"company": company,
"shift_type": shift_type,
"status": status,
"shift_location": shift_location,
}
prev_shift = frappe.db.exists(dict({"end_date": add_days(start_date, -1)}, **filters))
next_shift = (
Expand All @@ -161,7 +194,7 @@ def insert_shift(
frappe.db.set_value("Shift Assignment", next_shift, "start_date", start_date)

else:
create_shift_assignment(employee, company, shift_type, start_date, end_date, status)
create_shift_assignment(employee, company, shift_type, start_date, end_date, status, shift_location)


def get_holidays(month_start: str, month_end: str, employee_filters: dict[str, str]) -> dict[str, list[dict]]:
Expand Down Expand Up @@ -223,9 +256,11 @@ def get_shifts(
ShiftAssignment.name,
ShiftAssignment.employee,
ShiftAssignment.shift_type,
ShiftAssignment.shift_location,
ShiftAssignment.start_date,
ShiftAssignment.end_date,
ShiftAssignment.status,
ShiftAssignment.shift_schedule_assignment,
ShiftType.start_time,
ShiftType.end_time,
ShiftType.color,
Expand Down
2 changes: 1 addition & 1 deletion hrms/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@
],
"hourly_long": [
"hrms.hr.doctype.shift_type.shift_type.process_auto_attendance_for_all_shifts",
"hrms.hr.doctype.shift_assignment_schedule.shift_assignment_schedule.process_auto_shift_creation",
"hrms.hr.doctype.shift_schedule_assignment.shift_schedule_assignment.process_auto_shift_creation",
],
"daily": [
"hrms.controllers.employee_reminders.send_birthday_reminders",
Expand Down
10 changes: 5 additions & 5 deletions hrms/hr/doctype/shift_assignment/shift_assignment.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"start_date",
"end_date",
"shift_request",
"schedule",
"shift_schedule_assignment",
"amended_from"
],
"fields": [
Expand Down Expand Up @@ -129,16 +129,16 @@
"fieldtype": "Column Break"
},
{
"fieldname": "schedule",
"fieldname": "shift_schedule_assignment",
"fieldtype": "Link",
"label": "Schedule",
"options": "Shift Assignment Schedule",
"label": "Shift Schedule Assignment",
"options": "Shift Schedule Assignment",
"read_only": 1
}
],
"is_submittable": 1,
"links": [],
"modified": "2024-09-16 15:29:41.502080",
"modified": "2024-11-13 12:59:50.928962",
"modified_by": "Administrator",
"module": "HR",
"name": "Shift Assignment",
Expand Down
18 changes: 1 addition & 17 deletions hrms/hr/doctype/shift_assignment/shift_assignment_list.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,3 @@
frappe.listview_settings["Shift Assignment"] = {
onload: function (list_view) {
list_view.page.add_inner_button(
__("Shift Assignment Tool"),
function () {
frappe.set_route("Form", "Shift Assignment Tool");
},
__("View"),
);

list_view.page.add_inner_button(
__("Roster"),
function () {
window.location.href = "/hr/roster";
},
__("View"),
);
},
onload: (list_view) => hrms.add_shift_tools_button_to_list(list_view),
};

This file was deleted.

103 changes: 63 additions & 40 deletions hrms/hr/doctype/shift_assignment_tool/shift_assignment_tool.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ frappe.ui.form.on("Shift Assignment Tool", {
"completed_bulk_shift_assignment",
"Shift Assignment",
);
hrms.handle_realtime_bulk_action_notification(
frm,
"completed_bulk_shift_schedule_assignment",
"Shift Schedule Assignment",
);
hrms.handle_realtime_bulk_action_notification(
frm,
"completed_bulk_shift_request_processing",
Expand Down Expand Up @@ -55,6 +60,10 @@ frappe.ui.form.on("Shift Assignment Tool", {
frm.trigger("get_employees");
},

shift_schedule(frm) {
frm.trigger("get_employees");
},

approver(frm) {
frm.trigger("get_employees");
},
Expand Down Expand Up @@ -93,38 +102,45 @@ frappe.ui.form.on("Shift Assignment Tool", {
const select_rows_section_head = document
.querySelector('[data-fieldname="select_rows_section"]')
.querySelector(".section-head");
select_rows_section_head.textContent = __("Select Employees");
frm.clear_custom_buttons();
frm.page.clear_primary_action();

if (frm.doc.action === "Assign Shift") {
frm.clear_custom_buttons();
if (frm.doc.action === "Assign Shift")
frm.page.set_primary_action(__("Assign Shift"), () => {
frm.trigger("assign_shift");
frm.trigger("bulk_assign");
});
else if (frm.doc.action === "Assign Shift Schedule")
frm.page.set_primary_action(__("Assign Shift Schedule"), () => {
frm.trigger("bulk_assign");
});
select_rows_section_head.textContent = __("Select Employees");
return;
else {
frm.page.add_inner_button(
__("Approve"),
() => {
frm.events.process_shift_requests(frm, "Approved");
},
__("Process Requests"),
);
frm.page.add_inner_button(
__("Reject"),
() => {
frm.events.process_shift_requests(frm, "Rejected");
},
__("Process Requests"),
);
frm.page.set_inner_btn_group_as_primary(__("Process Requests"));
frm.page.clear_menu();
select_rows_section_head.textContent = __("Select Shift Requests");
}

frm.page.clear_primary_action();
frm.page.add_inner_button(
__("Approve"),
() => {
frm.events.process_shift_requests(frm, "Approved");
},
__("Process Requests"),
);
frm.page.add_inner_button(
__("Reject"),
() => {
frm.events.process_shift_requests(frm, "Rejected");
},
__("Process Requests"),
);
frm.page.set_inner_btn_group_as_primary(__("Process Requests"));
frm.page.clear_menu();
select_rows_section_head.textContent = __("Select Shift Requests");
},

get_employees(frm) {
if (frm.doc.action === "Assign Shift" && !(frm.doc.shift_type && frm.doc.start_date))
if (
(frm.doc.action === "Assign Shift" && !(frm.doc.shift_type && frm.doc.start_date)) ||
(frm.doc.action === "Assign Shift Schedule" &&
!(frm.doc.shift_schedule && frm.doc.start_date))
)
return frm.events.render_employees_datatable(frm, []);

frm.call({
Expand All @@ -146,6 +162,13 @@ frappe.ui.form.on("Shift Assignment Tool", {
? "There are no employees without Shift Assignments for these dates based on the given filters."
: "Please select Shift Type and assignment date(s).",
);
} else if (frm.doc.action === "Assign Shift Schedule") {
columns = frm.events.get_assign_shift_datatable_columns();
no_data_message = __(
frm.doc.shift_schedule && frm.doc.start_date
? "There are no employees without active overlapping Shift Schedule Assignments based on the given filters."
: "Please select Shift Schedule and assignment date(s).",
);
} else {
columns = frm.events.get_process_shift_requests_datatable_columns();
no_data_message = "There are no open Shift Requests based on the given filters.";
Expand Down Expand Up @@ -224,7 +247,8 @@ frappe.ui.form.on("Shift Assignment Tool", {
align: "left",
}));
},
assign_shift(frm) {

bulk_assign(frm, employees) {
const rows = frm.employees_datatable.datamanager.data;
const selected_employees = [];
const checked_row_indexes = frm.employees_datatable.rowmanager.getCheckedRows();
Expand All @@ -233,21 +257,20 @@ frappe.ui.form.on("Shift Assignment Tool", {
});

hrms.validate_mandatory_fields(frm, selected_employees);
frappe.confirm(__("Assign Shift to {0} employee(s)?", [selected_employees.length]), () => {
frm.events.bulk_assign_shift(frm, selected_employees);
});
},

bulk_assign_shift(frm, employees) {
frm.call({
method: "bulk_assign_shift",
doc: frm.doc,
args: {
employees: employees,
frappe.confirm(
__("{0} to {1} employee(s)?", [__(frm.doc.action), selected_employees.length]),
() => {
frm.call({
method: "bulk_assign",
doc: frm.doc,
args: {
employees: selected_employees,
},
freeze: true,
freeze_message: __("Assigning..."),
});
},
freeze: true,
freeze_message: __("Assigning Shift"),
});
);
},

process_shift_requests(frm, status) {
Expand Down
Loading

0 comments on commit 6bc37fe

Please sign in to comment.