Skip to content

Commit

Permalink
Merge pull request #2074 from frappe/version-15-hotfix
Browse files Browse the repository at this point in the history
chore: release v15
  • Loading branch information
krantheman authored Aug 15, 2024
2 parents e408016 + e574f28 commit a43034e
Show file tree
Hide file tree
Showing 10 changed files with 204 additions and 1,528 deletions.
28 changes: 27 additions & 1 deletion hrms/hr/doctype/employee_checkin/employee_checkin.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
// For license information, please see license.txt

frappe.ui.form.on("Employee Checkin", {
refresh: async (_frm) => {
refresh: async (frm) => {
if (!frm.doc.__islocal) frm.trigger("add_fetch_shift_button");

const allow_geolocation_tracking = await frappe.db.get_single_value(
"HR Settings",
"allow_geolocation_tracking",
Expand All @@ -14,6 +16,30 @@ frappe.ui.form.on("Employee Checkin", {
}
},

add_fetch_shift_button(frm) {
if (frm.doc.attendace) return;
frm.add_custom_button(__("Fetch Shift"), function () {
const previous_shift = frm.doc.shift;
frappe.call({
method: "fetch_shift",
doc: frm.doc,
freeze: true,
freeze_message: __("Fetching Shift"),
callback: function () {
if (previous_shift === frm.doc.shift) return;
frm.dirty();
frm.save();
frappe.show_alert({
message: __("Shift has been successfully updated to {0}.", [
frm.doc.shift,
]),
indicator: "green",
});
},
});
});
},

fetch_geolocation: async (frm) => {
if (!navigator.geolocation) {
frappe.msgprint({
Expand Down
58 changes: 36 additions & 22 deletions hrms/hr/doctype/employee_checkin/employee_checkin.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,30 +36,33 @@ def validate_duplicate_log(self):
_("This employee already has a log with the same timestamp.{0}").format("<Br>" + doc_link)
)

@frappe.whitelist()
def fetch_shift(self):
shift_actual_timings = get_actual_start_end_datetime_of_shift(
self.employee, get_datetime(self.time), True
)
if shift_actual_timings:
if (
shift_actual_timings.shift_type.determine_check_in_and_check_out
== "Strictly based on Log Type in Employee Checkin"
and not self.log_type
and not self.skip_auto_attendance
):
frappe.throw(
_("Log Type is required for check-ins falling in the shift: {0}.").format(
shift_actual_timings.shift_type.name
)
)
if not self.attendance:
self.shift = shift_actual_timings.shift_type.name
self.shift_actual_start = shift_actual_timings.actual_start
self.shift_actual_end = shift_actual_timings.actual_end
self.shift_start = shift_actual_timings.start_datetime
self.shift_end = shift_actual_timings.end_datetime
else:
if not (
shift_actual_timings := get_actual_start_end_datetime_of_shift(
self.employee, get_datetime(self.time), True
)
):
self.shift = None
return

if (
shift_actual_timings.shift_type.determine_check_in_and_check_out
== "Strictly based on Log Type in Employee Checkin"
and not self.log_type
and not self.skip_auto_attendance
):
frappe.throw(
_("Log Type is required for check-ins falling in the shift: {0}.").format(
shift_actual_timings.shift_type.name
)
)
if not self.attendance:
self.shift = shift_actual_timings.shift_type.name
self.shift_actual_start = shift_actual_timings.actual_start
self.shift_actual_end = shift_actual_timings.actual_end
self.shift_start = shift_actual_timings.start_datetime
self.shift_end = shift_actual_timings.end_datetime

@frappe.whitelist()
def set_geolocation_from_coordinates(self):
Expand Down Expand Up @@ -134,6 +137,17 @@ def add_log_based_on_employee_field(
return doc


@frappe.whitelist()
def bulk_fetch_shift(checkins: list[str] | str) -> None:
if isinstance(checkins, str):
checkins = frappe.json.loads(checkins)
for d in checkins:
doc = frappe.get_doc("Employee Checkin", d)
doc.fetch_shift()
doc.flags.ignore_validate = True
doc.save()


def mark_attendance_and_link_log(
logs,
attendance_status,
Expand Down
14 changes: 14 additions & 0 deletions hrms/hr/doctype/employee_checkin/employee_checkin_list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
frappe.listview_settings["Employee Checkin"] = {
onload: function (listview) {
listview.page.add_action_item(__("Fetch Shifts"), () => {
const checkins = listview.get_checked_items().map((checkin) => checkin.name);
frappe.call({
method: "hrms.hr.doctype.employee_checkin.employee_checkin.bulk_fetch_shift",
freeze: true,
args: {
checkins,
},
});
});
},
};
35 changes: 35 additions & 0 deletions hrms/hr/doctype/employee_checkin/test_employee_checkin.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

from hrms.hr.doctype.employee_checkin.employee_checkin import (
add_log_based_on_employee_field,
bulk_fetch_shift,
calculate_working_hours,
mark_attendance_and_link_log,
)
Expand Down Expand Up @@ -490,6 +491,40 @@ def test_consecutive_shift_assignments_overlapping_within_grace_period(self):
log = make_checkin(employee, timestamp)
self.assertEqual(log.shift, shift2.name)

def test_bulk_fetch_shift(self):
emp1 = make_employee("[email protected]", company="_Test Company")
emp2 = make_employee("[email protected]", company="_Test Company")

# 8 - 12
shift1 = setup_shift_type(shift_type="Shift 1")
# 12:30 - 16:30
shift2 = setup_shift_type(shift_type="Shift 2", start_time="12:30:00", end_time="16:30:00")

frappe.db.set_value("Employee", emp1, "default_shift", shift1.name)
frappe.db.set_value("Employee", emp2, "default_shift", shift1.name)

date = getdate()
timestamp = datetime.combine(date, get_time("12:30:00"))

log1 = make_checkin(emp1, timestamp)
self.assertEqual(log1.shift, shift1.name)
log2 = make_checkin(emp2, timestamp)
self.assertEqual(log2.shift, shift1.name)

mark_attendance_and_link_log([log2], "Present", date)

make_shift_assignment(shift2.name, emp1, date)
make_shift_assignment(shift2.name, emp2, date)

bulk_fetch_shift([log1.name, log2.name])

log1.reload()
# shift changes according to the new assignment
self.assertEqual(log1.shift, shift2.name)
log2.reload()
# shift does not change since attendance is already marked
self.assertEqual(log2.shift, shift1.name)


def make_n_checkins(employee, n, hours_to_reverse=1):
logs = [make_checkin(employee, now_datetime() - timedelta(hours=hours_to_reverse, minutes=n + 1))]
Expand Down
21 changes: 11 additions & 10 deletions hrms/hr/doctype/expense_claim/expense_claim.js
Original file line number Diff line number Diff line change
Expand Up @@ -274,17 +274,18 @@ frappe.ui.form.on("Expense Claim", {
}
});
},

get_taxes: function (frm) {
if (frm.doc.taxes) {
frappe.call({
method: "calculate_taxes",
doc: frm.doc,
callback: () => {
refresh_field("taxes");
frm.trigger("update_employee_advance_claimed_amount");
},
});
}
if (!frm.doc.taxes.length) return;

frappe.call({
method: "calculate_taxes",
doc: frm.doc,
callback: () => {
refresh_field("taxes");
frm.trigger("update_employee_advance_claimed_amount");
},
});
},

get_advances: function (frm) {
Expand Down
6 changes: 3 additions & 3 deletions hrms/hr/workspace/employee_lifecycle/employee_lifecycle.json
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@
},
{
"hidden": 0,
"is_query_report": 0,
"is_query_report": 1,
"label": "Daily Work Summary Replies",
"link_count": 0,
"link_to": "Daily Work Summary Replies",
Expand Down Expand Up @@ -287,7 +287,7 @@
"type": "Link"
}
],
"modified": "2022-09-16 11:35:33.462001",
"modified": "2024-08-11 11:35:33.462001",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee Lifecycle",
Expand Down Expand Up @@ -350,4 +350,4 @@
}
],
"title": "Employee Lifecycle"
}
}
10 changes: 5 additions & 5 deletions hrms/hr/workspace/expense_claims/expense_claims.json
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@
},
{
"hidden": 0,
"is_query_report": 0,
"is_query_report": 1,
"label": "Accounts Receivable",
"link_count": 0,
"link_to": "Accounts Receivable",
Expand All @@ -179,7 +179,7 @@
},
{
"hidden": 0,
"is_query_report": 0,
"is_query_report": 1,
"label": "Accounts Payable",
"link_count": 0,
"link_to": "Accounts Payable",
Expand All @@ -189,7 +189,7 @@
},
{
"hidden": 0,
"is_query_report": 0,
"is_query_report": 1,
"label": "General Ledger",
"link_count": 0,
"link_to": "General Ledger",
Expand Down Expand Up @@ -256,7 +256,7 @@
"type": "Link"
}
],
"modified": "2024-02-05 09:10:45.636550",
"modified": "2024-08-11 11:40:45.636550",
"modified_by": "Administrator",
"module": "HR",
"name": "Expense Claims",
Expand Down Expand Up @@ -295,4 +295,4 @@
}
],
"title": "Expense Claims"
}
}
6 changes: 3 additions & 3 deletions hrms/hr/workspace/hr/hr.json
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@
},
{
"hidden": 0,
"is_query_report": 0,
"is_query_report": 1,
"label": "Employee Exits",
"link_count": 0,
"link_to": "Employee Exits",
Expand Down Expand Up @@ -385,7 +385,7 @@
"type": "Link"
}
],
"modified": "2022-12-06 16:55:59.080694",
"modified": "2024-10-10 16:55:59.080694",
"modified_by": "Administrator",
"module": "HR",
"name": "HR",
Expand Down Expand Up @@ -449,4 +449,4 @@
}
],
"title": "HR"
}
}
10 changes: 5 additions & 5 deletions hrms/payroll/workspace/salary_payout/salary_payout.json
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@
},
{
"hidden": 0,
"is_query_report": 0,
"is_query_report": 1,
"label": "General Ledger",
"link_count": 0,
"link_to": "General Ledger",
Expand All @@ -292,7 +292,7 @@
},
{
"hidden": 0,
"is_query_report": 0,
"is_query_report": 1,
"label": "Accounts Payable",
"link_count": 0,
"link_to": "Accounts Payable",
Expand All @@ -302,7 +302,7 @@
},
{
"hidden": 0,
"is_query_report": 0,
"is_query_report": 1,
"label": "Accounts Receivable",
"link_count": 0,
"link_to": "Accounts Receivable",
Expand Down Expand Up @@ -370,7 +370,7 @@
"type": "Link"
}
],
"modified": "2024-07-22 18:07:37.351654",
"modified": "2024-08-11 11:45:37.351654",
"modified_by": "Administrator",
"module": "Payroll",
"name": "Salary Payout",
Expand Down Expand Up @@ -409,4 +409,4 @@
}
],
"title": "Salary Payout"
}
}
Loading

0 comments on commit a43034e

Please sign in to comment.