From 878ed5d80133e9e7d0ff4b71ebbfd2e2fdcccff3 Mon Sep 17 00:00:00 2001 From: sonali Date: Thu, 30 May 2024 09:25:09 +0200 Subject: [PATCH 1/6] feat:update from and to year in weekly working hours from current fiscal year --- .../custom_python/weekly_working_hours.py | 11 ++++++---- hr_addon/hooks.py | 8 ++----- hr_addon/patches.txt | 3 ++- .../v15_0/add_custom_field_for_hr_settings.py | 21 +++++++++++++++++++ hr_addon/public/js/hr_settings.js | 19 +++++++++++++++++ hr_addon/public/js/list_view.js | 14 +------------ 6 files changed, 52 insertions(+), 24 deletions(-) create mode 100644 hr_addon/patches/v15_0/add_custom_field_for_hr_settings.py create mode 100644 hr_addon/public/js/hr_settings.js diff --git a/hr_addon/custom_scripts/custom_python/weekly_working_hours.py b/hr_addon/custom_scripts/custom_python/weekly_working_hours.py index 7cc6cdc..212443c 100644 --- a/hr_addon/custom_scripts/custom_python/weekly_working_hours.py +++ b/hr_addon/custom_scripts/custom_python/weekly_working_hours.py @@ -1,5 +1,5 @@ import frappe -from frappe.utils import getdate +from frappe.utils import today from frappe.model.document import Document @frappe.whitelist() @@ -17,6 +17,9 @@ def set_from_to_dates(): year_start_date = fiscal_year[0].year_start_date year_end_date = fiscal_year[0].year_end_date + # Get today's date + current_date = today() + # Update the valid_from and valid_to fields frappe.db.sql(""" UPDATE @@ -33,11 +36,11 @@ def set_from_to_dates(): WHERE permanent = 1 ) + AND creation BETWEEN %(year_start_date)s AND %(year_end_date)s """, { "year_start_date": year_start_date, - "year_end_date": year_end_date + "year_end_date": year_end_date, + "current_date": current_date }) frappe.db.commit() - - diff --git a/hr_addon/hooks.py b/hr_addon/hooks.py index f8e0d13..10b2fa3 100644 --- a/hr_addon/hooks.py +++ b/hr_addon/hooks.py @@ -30,7 +30,8 @@ # include js in page # page_js = {"page" : "public/js/file.js"} doctype_js = { - + "HR Settings": "public/js/hr_settings.js", + } # include js in doctype views # doctype_js = {"doctype" : "public/js/doctype.js"} @@ -199,13 +200,8 @@ } } -doctype_list_js = {"Weekly Working Hours" : "public/js/list_view.js"} - scheduler_events = { "hourly": [ "hr_addon.hr_addon.doctype.hr_addon_settings.hr_addon_settings.generate_workdays_scheduled_job" ], - "yearly": [ - "hr_addon.custom_scripts.custom_python.weekly_working_hours.set_from_to_dates", - ] } \ No newline at end of file diff --git a/hr_addon/patches.txt b/hr_addon/patches.txt index 576c225..49191c4 100644 --- a/hr_addon/patches.txt +++ b/hr_addon/patches.txt @@ -1 +1,2 @@ -hr_addon.patches.v15_0.add_custom_field_for_employee \ No newline at end of file +hr_addon.patches.v15_0.add_custom_field_for_employee +hr_addon.patches.v15_0.add_custom_field_for_hr_settings #12 \ No newline at end of file diff --git a/hr_addon/patches/v15_0/add_custom_field_for_hr_settings.py b/hr_addon/patches/v15_0/add_custom_field_for_hr_settings.py new file mode 100644 index 0000000..41175e6 --- /dev/null +++ b/hr_addon/patches/v15_0/add_custom_field_for_hr_settings.py @@ -0,0 +1,21 @@ +import frappe +from frappe.custom.doctype.custom_field.custom_field import create_custom_field +from frappe.custom.doctype.property_setter.property_setter import make_property_setter + +def execute(): + + frappe.reload_doc("HR", "doctype", "HR Settings") + + create_custom_field("HR Settings", + dict(fieldname="danger_zone_section", label="\u26a0\ufe0f Danger Zone \u26a0\ufe0f", + fieldtype="Section Break", insert_after="allow_employee_checkin_from_mobile_app", + ) + ) + + create_custom_field("HR Settings", + dict(fieldname="update_year", label="Update Year", + fieldtype="Button", insert_after="danger_zone_section",description="Clicking this button will retrieve the current fiscal year and update the 'From' and 'To' year fields for Weekly Working Hours records created this year." + ) + ) + + \ No newline at end of file diff --git a/hr_addon/public/js/hr_settings.js b/hr_addon/public/js/hr_settings.js new file mode 100644 index 0000000..59a687e --- /dev/null +++ b/hr_addon/public/js/hr_settings.js @@ -0,0 +1,19 @@ +// Copyright (c) 2024, Phamos GmbH and contributors +// For license information, please see license.txt + +frappe.ui.form.on('HR Settings', 'update_year', function(frm) { + console.log('update year') + frappe.call({ + method: "hr_addon.custom_scripts.custom_python.weekly_working_hours.set_from_to_dates", + args: {}, + callback(r) { + if(!r.exc){ + frappe.msgprint("Weekly working hours for permanent employees have been successfully updated.") + } + else{ + frappe.msgprint("Error occured while updating weekly working hours") + } + } + }); + +}); \ No newline at end of file diff --git a/hr_addon/public/js/list_view.js b/hr_addon/public/js/list_view.js index 49a7881..cd2da34 100644 --- a/hr_addon/public/js/list_view.js +++ b/hr_addon/public/js/list_view.js @@ -1,17 +1,5 @@ -frappe.provide("hr_addon.frappe.views"); frappe.listview_settings["Weekly Working Hours"] = { - onload: function (list_view) { - - list_view.page.add_button(__("Update Year"), function () { - frappe.call({ - method: "hr_addon.custom_scripts.custom_python.weekly_working_hours.set_from_to_dates", - args: {}, - callback(r) {} - }); - window.location.reload(); - }); - - }, + }; From 5575d76dea7c09442662f82f261fb2ad94376a2c Mon Sep 17 00:00:00 2001 From: sonali Date: Fri, 28 Jun 2024 11:43:23 +0200 Subject: [PATCH 2/6] feat:QR Code function added for Location to use of employee checkin --- .../custom_scripts/custom_python/location.py | 29 +++++++++++++++++++ hr_addon/hooks.py | 4 +++ hr_addon/patches.txt | 3 +- .../v15_0/add_custom_field_for_location.py | 13 +++++++++ hr_addon/public/js/employee_checkin.js | 12 ++++++++ 5 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 hr_addon/custom_scripts/custom_python/location.py create mode 100644 hr_addon/patches/v15_0/add_custom_field_for_location.py create mode 100644 hr_addon/public/js/employee_checkin.js diff --git a/hr_addon/custom_scripts/custom_python/location.py b/hr_addon/custom_scripts/custom_python/location.py new file mode 100644 index 0000000..c8c40e4 --- /dev/null +++ b/hr_addon/custom_scripts/custom_python/location.py @@ -0,0 +1,29 @@ +import qrcode +import frappe +from frappe.utils import get_url_to_form + +def generate_qr_code_for_location(doc, method): + location_name = doc.name + # Properly format the URL with the location parameter + base_url = frappe.utils.get_url() + qr_code_content = f"{base_url}/app/employee-checkin/new?device_id={location_name}" + img = qrcode.make(qr_code_content) + file_name = frappe.generate_hash("", 10) + file_path = frappe.get_site_path("public", "files", f"{file_name}.png") + img.save(file_path) + + qr_code_url = f"/files/{file_name}.png" + + # Update the document with the QR code URL + doc.db_set("qr_code_url", qr_code_url) + + # Attach the QR code to the Location document + frappe.get_doc({ + "doctype": "File", + "file_url": qr_code_url, + "attached_to_name": doc.name, + "attached_to_doctype": doc.doctype, + "file_name": f"{location_name}_qr_code.png", + "folder": "Home/Attachments" + }).insert() + diff --git a/hr_addon/hooks.py b/hr_addon/hooks.py index 10b2fa3..28a5111 100644 --- a/hr_addon/hooks.py +++ b/hr_addon/hooks.py @@ -31,6 +31,7 @@ # page_js = {"page" : "public/js/file.js"} doctype_js = { "HR Settings": "public/js/hr_settings.js", + "Employee Checkin": "public/js/employee_checkin.js", } # include js in doctype views @@ -197,6 +198,9 @@ "Leave Application": { "on_change": "hr_addon.hr_addon.api.export_calendar.export_calendar", "on_cancel": "hr_addon.hr_addon.api.export_calendar.export_calendar" + }, + "Location": { + "after_insert": "hr_addon.custom_scripts.custom_python.location.generate_qr_code_for_location", } } diff --git a/hr_addon/patches.txt b/hr_addon/patches.txt index 49191c4..b4c0032 100644 --- a/hr_addon/patches.txt +++ b/hr_addon/patches.txt @@ -1,2 +1,3 @@ hr_addon.patches.v15_0.add_custom_field_for_employee -hr_addon.patches.v15_0.add_custom_field_for_hr_settings #12 \ No newline at end of file +hr_addon.patches.v15_0.add_custom_field_for_hr_settings #12 +hr_addon.patches.v15_0.add_custom_field_for_location #1 \ No newline at end of file diff --git a/hr_addon/patches/v15_0/add_custom_field_for_location.py b/hr_addon/patches/v15_0/add_custom_field_for_location.py new file mode 100644 index 0000000..b187083 --- /dev/null +++ b/hr_addon/patches/v15_0/add_custom_field_for_location.py @@ -0,0 +1,13 @@ +import frappe +from frappe.custom.doctype.custom_field.custom_field import create_custom_field +from frappe.custom.doctype.property_setter.property_setter import make_property_setter + +def execute(): + + frappe.reload_doc("Assets", "doctype", "Location") + + create_custom_field("Location", + dict(fieldname="qr_code_url", label="QR Code URL", + fieldtype="Data", insert_after="location",read_only=1 + ) + ) diff --git a/hr_addon/public/js/employee_checkin.js b/hr_addon/public/js/employee_checkin.js new file mode 100644 index 0000000..6006bdb --- /dev/null +++ b/hr_addon/public/js/employee_checkin.js @@ -0,0 +1,12 @@ +frappe.ui.form.on('Employee Checkin', { + onload(frm) { + if (frm.is_new()) { + frappe.db.get_value("Employee", {"user_id": frappe.session.user}, "name", function(value) { + if (value) { + frm.set_value('employee', value.name); + } + }); + } + } + }); + \ No newline at end of file From 7bdbbf35fe850d52224acf1f614841011dd45bec Mon Sep 17 00:00:00 2001 From: sonali Date: Sat, 29 Jun 2024 21:43:28 +0200 Subject: [PATCH 3/6] feat:add validation on duplication employee checkin --- .../custom_python/employee_checkin.py | 28 +++++++++++++++++++ hr_addon/hooks.py | 5 +++- 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 hr_addon/custom_scripts/custom_python/employee_checkin.py diff --git a/hr_addon/custom_scripts/custom_python/employee_checkin.py b/hr_addon/custom_scripts/custom_python/employee_checkin.py new file mode 100644 index 0000000..584e1c2 --- /dev/null +++ b/hr_addon/custom_scripts/custom_python/employee_checkin.py @@ -0,0 +1,28 @@ +import qrcode +import frappe +from frappe.utils import get_url_to_form +from frappe import _ + +@frappe.whitelist() +def validate_duplicate_log(doc, method): + # Custom SQL query to check existence without using doc.time.date() + data = frappe.db.sql( + """ + SELECT + name as ec + FROM `tabEmployee Checkin` + WHERE + DATE(time) = DATE(%s) + AND employee = %s + AND name != %s + AND log_type = %s + """, + (doc.time, doc.employee, doc.name, doc.log_type), + as_dict=True + ) + + # Check if any record was found + if data and data[0].get('ec'): + text = "This employee already has a log with the same timestamp" + "
"+data[0].get('ec') + frappe.throw( text) + diff --git a/hr_addon/hooks.py b/hr_addon/hooks.py index 28a5111..5cddd2b 100644 --- a/hr_addon/hooks.py +++ b/hr_addon/hooks.py @@ -201,7 +201,10 @@ }, "Location": { "after_insert": "hr_addon.custom_scripts.custom_python.location.generate_qr_code_for_location", - } + }, + "Employee Checkin": { + "validate": "hr_addon.custom_scripts.custom_python.employee_checkin.validate_duplicate_log", + }, } scheduler_events = { From 394c1045e1f1bc8bd3e2cd4671bddd79ae6085b3 Mon Sep 17 00:00:00 2001 From: sonali Date: Sat, 29 Jun 2024 22:08:01 +0200 Subject: [PATCH 4/6] feat:add depend on condition to display devide_id to hr user or hr manager --- hr_addon/patches.txt | 2 +- hr_addon/patches/v15_0/add_custom_field_for_location.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/hr_addon/patches.txt b/hr_addon/patches.txt index b4c0032..939d1e2 100644 --- a/hr_addon/patches.txt +++ b/hr_addon/patches.txt @@ -1,3 +1,3 @@ hr_addon.patches.v15_0.add_custom_field_for_employee hr_addon.patches.v15_0.add_custom_field_for_hr_settings #12 -hr_addon.patches.v15_0.add_custom_field_for_location #1 \ No newline at end of file +hr_addon.patches.v15_0.add_custom_field_for_location #123 \ No newline at end of file diff --git a/hr_addon/patches/v15_0/add_custom_field_for_location.py b/hr_addon/patches/v15_0/add_custom_field_for_location.py index b187083..73c50bf 100644 --- a/hr_addon/patches/v15_0/add_custom_field_for_location.py +++ b/hr_addon/patches/v15_0/add_custom_field_for_location.py @@ -5,9 +5,15 @@ def execute(): frappe.reload_doc("Assets", "doctype", "Location") + frappe.reload_doc("HR", "doctype", "employee_checkin") + create_custom_field("Location", dict(fieldname="qr_code_url", label="QR Code URL", fieldtype="Data", insert_after="location",read_only=1 ) ) + + make_property_setter("Employee Checkin", "device_id", "depends_on", + 'eval:frappe.user.has_role("HR User") || frappe.user.has_role("HR Manager")', + "Data") From e9ebd324eef5be34b5c7ca969feef5a15d05bbf1 Mon Sep 17 00:00:00 2001 From: sonali Date: Mon, 1 Jul 2024 21:50:01 +0200 Subject: [PATCH 5/6] feat:removed custom validation on employee checkin - to prevent duplication of employee checkin --- .../custom_python/employee_checkin.py | 23 ------------------- hr_addon/hooks.py | 3 --- 2 files changed, 26 deletions(-) diff --git a/hr_addon/custom_scripts/custom_python/employee_checkin.py b/hr_addon/custom_scripts/custom_python/employee_checkin.py index 584e1c2..9bad22b 100644 --- a/hr_addon/custom_scripts/custom_python/employee_checkin.py +++ b/hr_addon/custom_scripts/custom_python/employee_checkin.py @@ -3,26 +3,3 @@ from frappe.utils import get_url_to_form from frappe import _ -@frappe.whitelist() -def validate_duplicate_log(doc, method): - # Custom SQL query to check existence without using doc.time.date() - data = frappe.db.sql( - """ - SELECT - name as ec - FROM `tabEmployee Checkin` - WHERE - DATE(time) = DATE(%s) - AND employee = %s - AND name != %s - AND log_type = %s - """, - (doc.time, doc.employee, doc.name, doc.log_type), - as_dict=True - ) - - # Check if any record was found - if data and data[0].get('ec'): - text = "This employee already has a log with the same timestamp" + "
"+data[0].get('ec') - frappe.throw( text) - diff --git a/hr_addon/hooks.py b/hr_addon/hooks.py index 5cddd2b..f8b39d8 100644 --- a/hr_addon/hooks.py +++ b/hr_addon/hooks.py @@ -202,9 +202,6 @@ "Location": { "after_insert": "hr_addon.custom_scripts.custom_python.location.generate_qr_code_for_location", }, - "Employee Checkin": { - "validate": "hr_addon.custom_scripts.custom_python.employee_checkin.validate_duplicate_log", - }, } scheduler_events = { From 88a2d7f41fecf007c0dc0846a8a7569993b72d95 Mon Sep 17 00:00:00 2001 From: sonali Date: Tue, 2 Jul 2024 17:09:55 +0200 Subject: [PATCH 6/6] feat:add df_property hidden on device_id in employee checkin --- hr_addon/patches.txt | 2 +- hr_addon/patches/v15_0/add_custom_field_for_location.py | 4 +--- hr_addon/public/js/employee_checkin.js | 8 ++++++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/hr_addon/patches.txt b/hr_addon/patches.txt index 939d1e2..fc3a90c 100644 --- a/hr_addon/patches.txt +++ b/hr_addon/patches.txt @@ -1,3 +1,3 @@ hr_addon.patches.v15_0.add_custom_field_for_employee hr_addon.patches.v15_0.add_custom_field_for_hr_settings #12 -hr_addon.patches.v15_0.add_custom_field_for_location #123 \ No newline at end of file +hr_addon.patches.v15_0.add_custom_field_for_location #1234 \ No newline at end of file diff --git a/hr_addon/patches/v15_0/add_custom_field_for_location.py b/hr_addon/patches/v15_0/add_custom_field_for_location.py index 73c50bf..e096a51 100644 --- a/hr_addon/patches/v15_0/add_custom_field_for_location.py +++ b/hr_addon/patches/v15_0/add_custom_field_for_location.py @@ -14,6 +14,4 @@ def execute(): ) ) - make_property_setter("Employee Checkin", "device_id", "depends_on", - 'eval:frappe.user.has_role("HR User") || frappe.user.has_role("HR Manager")', - "Data") + make_property_setter("Employee Checkin", "device_id", "depends_on",'',"Data") diff --git a/hr_addon/public/js/employee_checkin.js b/hr_addon/public/js/employee_checkin.js index 6006bdb..337dbfb 100644 --- a/hr_addon/public/js/employee_checkin.js +++ b/hr_addon/public/js/employee_checkin.js @@ -7,6 +7,10 @@ frappe.ui.form.on('Employee Checkin', { } }); } + + const hasHRRole = frappe.user.has_role("HR User") || frappe.user.has_role("HR Manager"); + if (!hasHRRole) { + frm.set_df_property('device_id', 'hidden', 1); + } } - }); - \ No newline at end of file +});