Skip to content

Commit

Permalink
Merge pull request #2550 from frappe/version-15-hotfix
Browse files Browse the repository at this point in the history
chore: release v15
  • Loading branch information
asmitahase authored Dec 27, 2024
2 parents 8fc6669 + 6027906 commit 3f9c8d5
Show file tree
Hide file tree
Showing 44 changed files with 1,106 additions and 430 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 @@ -221,7 +221,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
31 changes: 26 additions & 5 deletions hrms/hr/doctype/leave_allocation/leave_allocation.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,22 +72,43 @@ frappe.ui.form.on("Leave Allocation", {
label: "New Leaves to be Allocated",
fieldname: "new_leaves",
fieldtype: "Float",
reqd: 1,
},
{
label: "From Date",
fieldname: "from_date",
fieldtype: "Date",
default: frappe.datetime.get_today(),
},
{
label: "To Date",
fieldname: "to_date",
fieldtype: "Date",
read_only: 1,
default: frm.doc.to_date,
},
],
primary_action_label: "Allocate",
primary_action({ new_leaves }) {
primary_action({ new_leaves, from_date }) {
frappe.call({
method: "allocate_leaves_manually",
doc: frm.doc,
args: { new_leaves },
callback: function () {
frm.reload_doc();
args: { new_leaves, from_date },
callback: function (r) {
if (!r.exc) {
dialog.hide();
frm.reload_doc();
}
},
});
dialog.hide();
},
});
dialog.fields_dict.new_leaves.set_value(monthly_earned_leave);
dialog.fields_dict.from_date.datepicker?.update({
minDate: frappe.datetime.str_to_obj(frm.doc.from_date),
maxDate: frappe.datetime.str_to_obj(frm.doc.to_date),
});

dialog.show();
},
__("Actions"),
Expand Down
17 changes: 15 additions & 2 deletions hrms/hr/doctype/leave_allocation/leave_allocation.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,15 @@ def create_leave_ledger_entry(self, submit=True):
create_leave_ledger_entry(self, args, submit)

@frappe.whitelist()
def allocate_leaves_manually(self, new_leaves):
def allocate_leaves_manually(self, new_leaves, from_date=None):
if from_date and not (getdate(self.from_date) <= getdate(from_date) <= getdate(self.to_date)):
frappe.throw(
_("Cannot allocate leaves outside the allocation period {0} - {1}").format(
frappe.bold(formatdate(self.from_date)), frappe.bold(formatdate(self.to_date))
),
title=_("Invalid Dates"),
)

new_allocation = flt(self.total_leaves_allocated) + flt(new_leaves)
new_allocation_without_cf = flt(
flt(self.get_existing_leave_count()) + flt(new_leaves),
Expand All @@ -339,13 +347,18 @@ def allocate_leaves_manually(self, new_leaves):
):
self.db_set("total_leaves_allocated", new_allocation, update_modified=False)

date = frappe.flags.current_date or getdate()
date = from_date or frappe.flags.current_date or getdate()
create_additional_leave_ledger_entry(self, new_leaves, date)

text = _("{0} leaves were manually allocated by {1} on {2}").format(
frappe.bold(new_leaves), frappe.session.user, frappe.bold(formatdate(date))
)
self.add_comment(comment_type="Info", text=text)
frappe.msgprint(
_("{0} leaves allocated successfully").format(frappe.bold(new_leaves)),
indicator="green",
alert=True,
)

else:
msg = _("Total leaves allocated cannot exceed annual allocation of {0}.").format(
Expand Down
17 changes: 15 additions & 2 deletions hrms/hr/doctype/leave_allocation/test_earned_leaves.py
Original file line number Diff line number Diff line change
Expand Up @@ -495,10 +495,23 @@ def test_allocate_leaves_manually(self):
get_leave_balance_on(self.employee.name, self.leave_type, frappe.flags.current_date), 6
)

leave_allocation.allocate_leaves_manually(6)
leave_allocation.allocate_leaves_manually(5)
self.assertEqual(
get_leave_balance_on(self.employee.name, self.leave_type, frappe.flags.current_date), 12
get_leave_balance_on(self.employee.name, self.leave_type, frappe.flags.current_date), 11
)

# manually set from_date - applicable from the next day
leave_allocation.allocate_leaves_manually(1, add_days(frappe.flags.current_date, 1))
# balance should be 11 on the current date
self.assertEqual(
get_leave_balance_on(self.employee.name, self.leave_type, frappe.flags.current_date), 11
)
# allocated leave should be applicable from the next day
self.assertEqual(
get_leave_balance_on(self.employee.name, self.leave_type, add_days(frappe.flags.current_date, 1)),
12,
)

self.assertRaises(frappe.ValidationError, leave_allocation.allocate_leaves_manually, 1)

def tearDown(self):
Expand Down
7 changes: 4 additions & 3 deletions hrms/hr/doctype/leave_type/leave_type.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,13 @@
{
"fieldname": "max_leaves_allowed",
"fieldtype": "Float",
"label": "Maximum Leave Allocation Allowed"
"label": "Maximum Leave Allocation Allowed per Leave Period"
},
{
"description": "Minimum working days required since Date of Joining to apply for this leave",
"fieldname": "applicable_after",
"fieldtype": "Int",
"label": "Applicable After (Working Days)"
"label": "Allow Leave Application After (Working Days)"
},
{
"fieldname": "max_continuous_days_allowed",
Expand Down Expand Up @@ -234,7 +235,7 @@
"icon": "fa fa-flag",
"idx": 1,
"links": [],
"modified": "2023-10-23 15:34:04.281308",
"modified": "2024-12-18 19:51:44.162375",
"modified_by": "Administrator",
"module": "HR",
"name": "Leave Type",
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-07-04 14:30:40.840689",
"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),
};
Loading

0 comments on commit 3f9c8d5

Please sign in to comment.