From 4a63de7b18b6582acc0e087b2ec046c33fc6cab9 Mon Sep 17 00:00:00 2001 From: Viny Date: Fri, 5 Apr 2024 12:29:45 +0530 Subject: [PATCH 01/14] fix: add lending doctypes to ESS user-type on install (cherry picked from commit 2e6141a8abbb62ecda889227e12ea6e4924ceb79) --- hrms/setup.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/hrms/setup.py b/hrms/setup.py index eac4326068..dc53f757a2 100644 --- a/hrms/setup.py +++ b/hrms/setup.py @@ -559,6 +559,13 @@ def get_user_types_data(): } +def get_lending_doctypes_for_ess(): + return { + "Loan": ["read"], + "Loan Application": ["read"], + } + + def create_custom_role(data): if data.get("role") and not frappe.db.exists("Role", data.get("role")): frappe.get_doc( @@ -587,7 +594,14 @@ def create_user_type(user_type, data): def create_role_permissions_for_doctype(doc, data): - for doctype, perms in data.get("doctypes").items(): + append_user_doctypes_to_user_type(data.get("doctypes").items(), doc) + + if doc.role == "Employee Self Service" and "lending" in frappe.get_installed_apps(): + append_user_doctypes_to_user_type(get_lending_doctypes_for_ess().items(), doc) + + +def append_user_doctypes_to_user_type(doctypes, doc): + for doctype, perms in doctypes: args = {"document_type": doctype} for perm in perms: args[perm] = 1 From 5418b773d3a89f9ccf8fbb82297e354358aab3e8 Mon Sep 17 00:00:00 2001 From: Viny Date: Fri, 5 Apr 2024 17:17:16 +0530 Subject: [PATCH 02/14] fix: add other lending doctypes to the list (cherry picked from commit 98d4ae28c60cc9b3631fa13e0b00fd15e125a5db) --- hrms/setup.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/hrms/setup.py b/hrms/setup.py index dc53f757a2..1916bb0b57 100644 --- a/hrms/setup.py +++ b/hrms/setup.py @@ -563,6 +563,27 @@ def get_lending_doctypes_for_ess(): return { "Loan": ["read"], "Loan Application": ["read"], + "Loan Balance Adjustment": ["read"], + "Loan Disbursement": ["read"], + "Loan Interest Accrual": ["read"], + "Loan Refund": ["read"], + "Loan Repayment": ["read"], + "Loan Repayment Detail": ["read"], + "Loan Security": ["read"], + "Loan Security Pledge": ["read"], + "Loan Security Price": ["read"], + "Loan Security ShortFall": ["read"], + "Loan Security Type": ["read"], + "Loan Security Unpledge": ["read"], + "Loan Type": ["read"], + "Loan Write Off": ["read"], + "Pledge": ["read"], + "Process Loan Interest Accrual": ["read"], + "Process Loan Security Shortfall": ["read"], + "Proposed Pledge": ["read"], + "Repayment Schedule": ["read"], + "Sanctioned Loan Amount": ["read"], + "Unpledge": ["read"], } From b183ffe574ab7275ceb04390cf1bfb294f87989e Mon Sep 17 00:00:00 2001 From: Viny Selopal Date: Mon, 8 Apr 2024 11:12:55 +0530 Subject: [PATCH 03/14] fix: add loan doctypes to ESS user type on lending app install (cherry picked from commit db3d5a9cb6bf63752c9e676a2454dd57f96e0c4f) --- hrms/setup.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/hrms/setup.py b/hrms/setup.py index 1916bb0b57..5b8561c151 100644 --- a/hrms/setup.py +++ b/hrms/setup.py @@ -306,11 +306,23 @@ def create_salary_slip_loan_fields(): create_custom_fields(SALARY_SLIP_LOAN_FIELDS, ignore_validate=True) +def add_lending_doctypes_to_ess(): + doc = frappe.get_doc("User Type", "Employee Self Service") + + loan_doctypes = get_lending_doctypes_for_ess() + append_user_doctypes_to_user_type(loan_doctypes.items(), doc) + + doc.name = "Employee Self Service" + doc.save(ignore_permissions=True) + + def after_app_install(app_name): """Set up loan integration with payroll""" if app_name != "lending": return + add_lending_doctypes_to_ess() + print("Updating payroll setup for loans") create_custom_fields(SALARY_SLIP_LOAN_FIELDS, ignore_validate=True) From 0df91dcd156ab9d2ec4aaf131363df8312b256b5 Mon Sep 17 00:00:00 2001 From: Viny Selopal Date: Mon, 8 Apr 2024 15:38:22 +0530 Subject: [PATCH 04/14] refactor: nomenclature in setup.py (cherry picked from commit 1dbffdce83595f54fb8e9e833e69f7675e0a9794) --- hrms/setup.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/hrms/setup.py b/hrms/setup.py index 5b8561c151..5b6c0b9961 100644 --- a/hrms/setup.py +++ b/hrms/setup.py @@ -306,11 +306,11 @@ def create_salary_slip_loan_fields(): create_custom_fields(SALARY_SLIP_LOAN_FIELDS, ignore_validate=True) -def add_lending_doctypes_to_ess(): +def add_lending_docperms_to_ess(): doc = frappe.get_doc("User Type", "Employee Self Service") - loan_doctypes = get_lending_doctypes_for_ess() - append_user_doctypes_to_user_type(loan_doctypes.items(), doc) + loan_doctypes = get_lending_docperms_for_ess() + append_docperms_to_user_type(loan_doctypes, doc) doc.name = "Employee Self Service" doc.save(ignore_permissions=True) @@ -321,7 +321,7 @@ def after_app_install(app_name): if app_name != "lending": return - add_lending_doctypes_to_ess() + add_lending_docperms_to_ess() print("Updating payroll setup for loans") create_custom_fields(SALARY_SLIP_LOAN_FIELDS, ignore_validate=True) @@ -571,7 +571,7 @@ def get_user_types_data(): } -def get_lending_doctypes_for_ess(): +def get_lending_docperms_for_ess(): return { "Loan": ["read"], "Loan Application": ["read"], @@ -627,14 +627,14 @@ def create_user_type(user_type, data): def create_role_permissions_for_doctype(doc, data): - append_user_doctypes_to_user_type(data.get("doctypes").items(), doc) + append_docperms_to_user_type(data.get("doctypes").items(), doc) if doc.role == "Employee Self Service" and "lending" in frappe.get_installed_apps(): - append_user_doctypes_to_user_type(get_lending_doctypes_for_ess().items(), doc) + append_docperms_to_user_type(get_lending_docperms_for_ess().items(), doc) -def append_user_doctypes_to_user_type(doctypes, doc): - for doctype, perms in doctypes: +def append_docperms_to_user_type(docperms, doc): + for doctype, perms in docperms.items: args = {"document_type": doctype} for perm in perms: args[perm] = 1 From fa288c24cc6f0d3f39e13bcb5135390288231de7 Mon Sep 17 00:00:00 2001 From: Viny Selopal Date: Tue, 9 Apr 2024 15:27:54 +0530 Subject: [PATCH 05/14] fix: setup.py bug in create_role_permissions_for_doctype function (cherry picked from commit 992abd7470ecfc96eb3e22ba928722284eeae985) --- hrms/setup.py | 34 +++++++--------------------------- 1 file changed, 7 insertions(+), 27 deletions(-) diff --git a/hrms/setup.py b/hrms/setup.py index 5b6c0b9961..257cd55487 100644 --- a/hrms/setup.py +++ b/hrms/setup.py @@ -309,8 +309,8 @@ def create_salary_slip_loan_fields(): def add_lending_docperms_to_ess(): doc = frappe.get_doc("User Type", "Employee Self Service") - loan_doctypes = get_lending_docperms_for_ess() - append_docperms_to_user_type(loan_doctypes, doc) + loan_docperms = get_lending_docperms_for_ess() + append_docperms_to_user_type(loan_docperms, doc) doc.name = "Employee Self Service" doc.save(ignore_permissions=True) @@ -574,28 +574,8 @@ def get_user_types_data(): def get_lending_docperms_for_ess(): return { "Loan": ["read"], - "Loan Application": ["read"], - "Loan Balance Adjustment": ["read"], - "Loan Disbursement": ["read"], - "Loan Interest Accrual": ["read"], - "Loan Refund": ["read"], - "Loan Repayment": ["read"], - "Loan Repayment Detail": ["read"], - "Loan Security": ["read"], - "Loan Security Pledge": ["read"], - "Loan Security Price": ["read"], - "Loan Security ShortFall": ["read"], - "Loan Security Type": ["read"], - "Loan Security Unpledge": ["read"], - "Loan Type": ["read"], - "Loan Write Off": ["read"], - "Pledge": ["read"], - "Process Loan Interest Accrual": ["read"], - "Process Loan Security Shortfall": ["read"], - "Proposed Pledge": ["read"], - "Repayment Schedule": ["read"], - "Sanctioned Loan Amount": ["read"], - "Unpledge": ["read"], + "Loan Application": ["read", "write", "create", "delete", "submit"], + "Loan Product": ["read"], } @@ -627,14 +607,14 @@ def create_user_type(user_type, data): def create_role_permissions_for_doctype(doc, data): - append_docperms_to_user_type(data.get("doctypes").items(), doc) + append_docperms_to_user_type(data.get("doctypes"), doc) if doc.role == "Employee Self Service" and "lending" in frappe.get_installed_apps(): - append_docperms_to_user_type(get_lending_docperms_for_ess().items(), doc) + append_docperms_to_user_type(get_lending_docperms_for_ess(), doc) def append_docperms_to_user_type(docperms, doc): - for doctype, perms in docperms.items: + for doctype, perms in docperms.items(): args = {"document_type": doctype} for perm in perms: args[perm] = 1 From 58f6ee95f35d6178ab602a894ece17314c0e2ed8 Mon Sep 17 00:00:00 2001 From: Viny Selopal Date: Tue, 9 Apr 2024 15:31:27 +0530 Subject: [PATCH 06/14] fix: add a patch to add lending docperms to ESS user on migrating (cherry picked from commit 394b32a7d6a8e5d5aa2b7c97b6d1751a59437459) --- hrms/patches.txt | 3 ++- hrms/patches/v15_0/add_loan_docperms_to_ess.py | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 hrms/patches/v15_0/add_loan_docperms_to_ess.py diff --git a/hrms/patches.txt b/hrms/patches.txt index e0c3137db7..b26178d765 100644 --- a/hrms/patches.txt +++ b/hrms/patches.txt @@ -22,4 +22,5 @@ hrms.patches.v15_0.rename_and_update_leave_encashment_fields hrms.patches.v14_0.update_title_in_employee_onboarding_and_separation_templates hrms.patches.v15_0.make_hr_settings_tab_in_company_master hrms.patches.v15_0.enable_allow_checkin_setting -hrms.patches.v15_0.set_default_asset_action_in_fnf \ No newline at end of file +hrms.patches.v15_0.set_default_asset_action_in_fnf +hrms.patches.v15_0.add_loan_docperms_to_ess diff --git a/hrms/patches/v15_0/add_loan_docperms_to_ess.py b/hrms/patches/v15_0/add_loan_docperms_to_ess.py new file mode 100644 index 0000000000..b64cfd04e2 --- /dev/null +++ b/hrms/patches/v15_0/add_loan_docperms_to_ess.py @@ -0,0 +1,5 @@ +from hrms.setup import add_lending_docperms_to_ess + + +def execute(): + add_lending_docperms_to_ess() From 5c4e0342045fc34db3a50dc05e5fdcee65b2ea45 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Wed, 1 May 2024 15:41:27 +0530 Subject: [PATCH 07/14] fix: check if lending app is installed before setting up permissions (cherry picked from commit 383b265385d6e966aa7f46032b6098ccb3faaa67) --- hrms/patches/v15_0/add_loan_docperms_to_ess.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hrms/patches/v15_0/add_loan_docperms_to_ess.py b/hrms/patches/v15_0/add_loan_docperms_to_ess.py index b64cfd04e2..898eb26a88 100644 --- a/hrms/patches/v15_0/add_loan_docperms_to_ess.py +++ b/hrms/patches/v15_0/add_loan_docperms_to_ess.py @@ -1,5 +1,8 @@ +import frappe + from hrms.setup import add_lending_docperms_to_ess def execute(): - add_lending_docperms_to_ess() + if "lending" in frappe.get_installed_apps(): + add_lending_docperms_to_ess() From e1c82a057ab333eddffa27548c67d30359989775 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Wed, 1 May 2024 19:15:35 +0530 Subject: [PATCH 08/14] fix: remove lending app perms on uninstall and avoid adding duplicate perms (cherry picked from commit d410cec1de71bb6a30df0d0230e844cb6e9cc6fe) --- hrms/setup.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/hrms/setup.py b/hrms/setup.py index 257cd55487..089ad477e4 100644 --- a/hrms/setup.py +++ b/hrms/setup.py @@ -312,7 +312,18 @@ def add_lending_docperms_to_ess(): loan_docperms = get_lending_docperms_for_ess() append_docperms_to_user_type(loan_docperms, doc) - doc.name = "Employee Self Service" + doc.save(ignore_permissions=True) + + +def remove_lending_docperms_from_ess(): + doc = frappe.get_doc("User Type", "Employee Self Service") + + loan_docperms = get_lending_docperms_for_ess() + + for row in list(doc.user_doctypes): + if row.document_type in loan_docperms: + doc.user_doctypes.remove(row) + doc.save(ignore_permissions=True) @@ -321,10 +332,9 @@ def after_app_install(app_name): if app_name != "lending": return - add_lending_docperms_to_ess() - print("Updating payroll setup for loans") create_custom_fields(SALARY_SLIP_LOAN_FIELDS, ignore_validate=True) + add_lending_docperms_to_ess() def before_app_uninstall(app_name): @@ -334,6 +344,7 @@ def before_app_uninstall(app_name): print("Updating payroll setup for loans") delete_custom_fields(SALARY_SLIP_LOAN_FIELDS) + remove_lending_docperms_from_ess() def make_fixtures(): @@ -614,7 +625,12 @@ def create_role_permissions_for_doctype(doc, data): def append_docperms_to_user_type(docperms, doc): + existing_doctypes = [d.document_type for d in doc.user_doctypes] + for doctype, perms in docperms.items(): + if doctype in existing_doctypes: + continue + args = {"document_type": doctype} for perm in perms: args[perm] = 1 From 8feab40356dd0462cc0b81a0f2fd86e118f601f6 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Wed, 1 May 2024 19:58:29 +0530 Subject: [PATCH 09/14] refactor: rearrange setup functions as per context (cherry picked from commit 118d86444ba7e9c3b0b05f5b805bdbbc2f084004) --- hrms/setup.py | 252 +++++++++++++++++++++++++------------------------- 1 file changed, 126 insertions(+), 126 deletions(-) diff --git a/hrms/setup.py b/hrms/setup.py index 089ad477e4..9f8489b436 100644 --- a/hrms/setup.py +++ b/hrms/setup.py @@ -31,6 +31,26 @@ def before_uninstall(): delete_company_fixtures() +def after_app_install(app_name): + """Set up loan integration with payroll""" + if app_name != "lending": + return + + print("Updating payroll setup for loans") + create_custom_fields(SALARY_SLIP_LOAN_FIELDS, ignore_validate=True) + add_lending_docperms_to_ess() + + +def before_app_uninstall(app_name): + """Clean up loan integration with payroll""" + if app_name != "lending": + return + + print("Updating payroll setup for loans") + delete_custom_fields(SALARY_SLIP_LOAN_FIELDS) + remove_lending_docperms_from_ess() + + def get_custom_fields(): """HR specific custom fields that need to be added to the masters in ERPNext""" return { @@ -301,52 +321,6 @@ def get_custom_fields(): } -def create_salary_slip_loan_fields(): - if "lending" in frappe.get_installed_apps(): - create_custom_fields(SALARY_SLIP_LOAN_FIELDS, ignore_validate=True) - - -def add_lending_docperms_to_ess(): - doc = frappe.get_doc("User Type", "Employee Self Service") - - loan_docperms = get_lending_docperms_for_ess() - append_docperms_to_user_type(loan_docperms, doc) - - doc.save(ignore_permissions=True) - - -def remove_lending_docperms_from_ess(): - doc = frappe.get_doc("User Type", "Employee Self Service") - - loan_docperms = get_lending_docperms_for_ess() - - for row in list(doc.user_doctypes): - if row.document_type in loan_docperms: - doc.user_doctypes.remove(row) - - doc.save(ignore_permissions=True) - - -def after_app_install(app_name): - """Set up loan integration with payroll""" - if app_name != "lending": - return - - print("Updating payroll setup for loans") - create_custom_fields(SALARY_SLIP_LOAN_FIELDS, ignore_validate=True) - add_lending_docperms_to_ess() - - -def before_app_uninstall(app_name): - """Clean up loan integration with payroll""" - if app_name != "lending": - return - - print("Updating payroll setup for loans") - delete_custom_fields(SALARY_SLIP_LOAN_FIELDS) - remove_lending_docperms_from_ess() - - def make_fixtures(): records = [ # expense claim type @@ -526,6 +500,106 @@ def update_hr_defaults(): hr_settings.save() +def set_single_defaults(): + for dt in ("HR Settings", "Payroll Settings"): + default_values = frappe.get_all( + "DocField", + filters={"parent": dt}, + fields=["fieldname", "default"], + as_list=True, + ) + if default_values: + try: + doc = frappe.get_doc(dt, dt) + for fieldname, value in default_values: + doc.set(fieldname, value) + doc.flags.ignore_mandatory = True + doc.save() + except frappe.ValidationError: + pass + + +def create_default_role_profiles(): + for role_profile_name, roles in DEFAULT_ROLE_PROFILES.items(): + if frappe.db.exists("Role Profile", role_profile_name): + continue + + role_profile = frappe.new_doc("Role Profile") + role_profile.role_profile = role_profile_name + for role in roles: + role_profile.append("roles", {"role": role}) + + role_profile.insert(ignore_permissions=True) + + +def get_post_install_patches(): + return ( + "erpnext.patches.v13_0.move_tax_slabs_from_payroll_period_to_income_tax_slab", + "erpnext.patches.v13_0.move_doctype_reports_and_notification_from_hr_to_payroll", + "erpnext.patches.v13_0.move_payroll_setting_separately_from_hr_settings", + "erpnext.patches.v13_0.update_start_end_date_for_old_shift_assignment", + "erpnext.patches.v13_0.updates_for_multi_currency_payroll", + "erpnext.patches.v13_0.update_reason_for_resignation_in_employee", + "erpnext.patches.v13_0.set_company_in_leave_ledger_entry", + "erpnext.patches.v13_0.rename_stop_to_send_birthday_reminders", + "erpnext.patches.v13_0.set_training_event_attendance", + "erpnext.patches.v14_0.set_payroll_cost_centers", + "erpnext.patches.v13_0.update_employee_advance_status", + "erpnext.patches.v13_0.update_expense_claim_status_for_paid_advances", + "erpnext.patches.v14_0.delete_employee_transfer_property_doctype", + "erpnext.patches.v13_0.set_payroll_entry_status", + # HRMS + "create_country_fixtures", + "update_allocate_on_in_leave_type", + "update_performance_module_changes", + ) + + +def run_post_install_patches(): + print("\nPatching Existing Data...") + + POST_INSTALL_PATCHES = get_post_install_patches() + frappe.flags.in_patch = True + + try: + for patch in POST_INSTALL_PATCHES: + patch_name = patch.split(".")[-1] + if not patch_name: + continue + + frappe.get_attr(f"hrms.patches.post_install.{patch_name}.execute")() + finally: + frappe.flags.in_patch = False + + +# LENDING APP SETUP & CLEANUP +def create_salary_slip_loan_fields(): + if "lending" in frappe.get_installed_apps(): + create_custom_fields(SALARY_SLIP_LOAN_FIELDS, ignore_validate=True) + + +def add_lending_docperms_to_ess(): + doc = frappe.get_doc("User Type", "Employee Self Service") + + loan_docperms = get_lending_docperms_for_ess() + append_docperms_to_user_type(loan_docperms, doc) + + doc.save(ignore_permissions=True) + + +def remove_lending_docperms_from_ess(): + doc = frappe.get_doc("User Type", "Employee Self Service") + + loan_docperms = get_lending_docperms_for_ess() + + for row in list(doc.user_doctypes): + if row.document_type in loan_docperms: + doc.user_doctypes.remove(row) + + doc.save(ignore_permissions=True) + + +# ESS USER TYPE SETUP & CLEANUP def add_non_standard_user_types(): user_types = get_user_types_data() @@ -612,16 +686,14 @@ def create_user_type(user_type, data): } ) - create_role_permissions_for_doctype(doc, data) - doc.flags.ignore_links = True - doc.save(ignore_permissions=True) - + docperms = data.get("doctypes") + if doc.role == "Employee Self Service" and "lending" in frappe.get_installed_apps(): + docperms.update(get_lending_docperms_for_ess()) -def create_role_permissions_for_doctype(doc, data): - append_docperms_to_user_type(data.get("doctypes"), doc) + append_docperms_to_user_type(docperms, doc) - if doc.role == "Employee Self Service" and "lending" in frappe.get_installed_apps(): - append_docperms_to_user_type(get_lending_docperms_for_ess(), doc) + doc.flags.ignore_links = True + doc.save(ignore_permissions=True) def append_docperms_to_user_type(docperms, doc): @@ -652,65 +724,6 @@ def update_select_perm_after_install(): frappe.flags.update_select_perm_after_migrate = False -def set_single_defaults(): - for dt in ("HR Settings", "Payroll Settings"): - default_values = frappe.db.sql( - """ - select fieldname, `default` from `tabDocField` - where parent=%s""", - dt, - ) - if default_values: - try: - doc = frappe.get_doc(dt, dt) - for fieldname, value in default_values: - doc.set(fieldname, value) - doc.flags.ignore_mandatory = True - doc.save() - except frappe.ValidationError: - pass - - -def get_post_install_patches(): - return ( - "erpnext.patches.v13_0.move_tax_slabs_from_payroll_period_to_income_tax_slab", - "erpnext.patches.v13_0.move_doctype_reports_and_notification_from_hr_to_payroll", - "erpnext.patches.v13_0.move_payroll_setting_separately_from_hr_settings", - "erpnext.patches.v13_0.update_start_end_date_for_old_shift_assignment", - "erpnext.patches.v13_0.updates_for_multi_currency_payroll", - "erpnext.patches.v13_0.update_reason_for_resignation_in_employee", - "erpnext.patches.v13_0.set_company_in_leave_ledger_entry", - "erpnext.patches.v13_0.rename_stop_to_send_birthday_reminders", - "erpnext.patches.v13_0.set_training_event_attendance", - "erpnext.patches.v14_0.set_payroll_cost_centers", - "erpnext.patches.v13_0.update_employee_advance_status", - "erpnext.patches.v13_0.update_expense_claim_status_for_paid_advances", - "erpnext.patches.v14_0.delete_employee_transfer_property_doctype", - "erpnext.patches.v13_0.set_payroll_entry_status", - # HRMS - "create_country_fixtures", - "update_allocate_on_in_leave_type", - "update_performance_module_changes", - ) - - -def run_post_install_patches(): - print("\nPatching Existing Data...") - - POST_INSTALL_PATCHES = get_post_install_patches() - frappe.flags.in_patch = True - - try: - for patch in POST_INSTALL_PATCHES: - patch_name = patch.split(".")[-1] - if not patch_name: - continue - - frappe.get_attr(f"hrms.patches.post_install.{patch_name}.execute")() - finally: - frappe.flags.in_patch = False - - def delete_custom_fields(custom_fields: dict): """ :param custom_fields: a dict like `{'Salary Slip': [{fieldname: 'loans', ...}]}` @@ -727,19 +740,6 @@ def delete_custom_fields(custom_fields: dict): frappe.clear_cache(doctype=doctype) -def create_default_role_profiles(): - for role_profile_name, roles in DEFAULT_ROLE_PROFILES.items(): - if frappe.db.exists("Role Profile", role_profile_name): - continue - - role_profile = frappe.new_doc("Role Profile") - role_profile.role_profile = role_profile_name - for role in roles: - role_profile.append("roles", {"role": role}) - - role_profile.insert(ignore_permissions=True) - - DEFAULT_ROLE_PROFILES = { "HR": [ "HR User", From 283c4674fe15a8f2f4705b8d93e189c87f54be1b Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 2 May 2024 19:47:50 +0530 Subject: [PATCH 10/14] fix: set intro message for leave application (backport #1696) (#1742) * fix: set intro message for leave application * fix: set intro message for leave application * fix: make the message consistent --------- Co-authored-by: Rucha Mahabal (cherry picked from commit ab834b8f74e31a035ef25d5b163c1a3fe13a89ca) Co-authored-by: Nihantra C. Patel <141945075+Nihantra-Patel@users.noreply.github.com> --- hrms/hr/doctype/leave_application/leave_application.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hrms/hr/doctype/leave_application/leave_application.js b/hrms/hr/doctype/leave_application/leave_application.js index fa8af8f15e..c6e356d0d5 100755 --- a/hrms/hr/doctype/leave_application/leave_application.js +++ b/hrms/hr/doctype/leave_application/leave_application.js @@ -102,6 +102,15 @@ frappe.ui.form.on("Leave Application", { frm.set_intro(""); if (frm.doc.__islocal && !in_list(frappe.user_roles, "Employee")) { frm.set_intro(__("Fill the form and save it")); + } else if ( + frm.perm[0] && + frm.perm[0].submit && + !frm.is_dirty() && + !frm.is_new() && + !frappe.model.has_workflow(this.doctype) && + frm.doc.docstatus === 0 + ) { + frm.set_intro(__("Submit this Leave Application to confirm.")); } frm.trigger("set_employee"); From 1049d46cf64b4753dbf463deee7259bb057fca38 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 7 May 2024 12:02:52 +0530 Subject: [PATCH 11/14] chore: grant Employee role read permission for Payroll Period (backport #1746) (#1748) * chore: grant Employee role read permission for Payroll Period (#1746) (cherry picked from commit ce8647884e93792037c9fd8b820b5f8f31e948e8) # Conflicts: # hrms/payroll/doctype/payroll_period/payroll_period.json * chore: fix conflicts --------- Co-authored-by: Rucha Mahabal --- .../doctype/payroll_period/payroll_period.json | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/hrms/payroll/doctype/payroll_period/payroll_period.json b/hrms/payroll/doctype/payroll_period/payroll_period.json index 0e0948475c..ee729a586d 100644 --- a/hrms/payroll/doctype/payroll_period/payroll_period.json +++ b/hrms/payroll/doctype/payroll_period/payroll_period.json @@ -53,7 +53,7 @@ } ], "links": [], - "modified": "2020-06-29 17:17:12.689089", + "modified": "2024-05-05 14:50:12.419714", "modified_by": "Administrator", "module": "Payroll", "name": "Payroll Period", @@ -71,6 +71,15 @@ "share": 1, "write": 1 }, + { + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Employee", + "share": 1 + }, { "create": 1, "delete": 1, From 62fcc476c0698ecf702fa0255221ce3592cf728e Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Mon, 6 May 2024 12:00:53 +0530 Subject: [PATCH 12/14] fix(Auto Attendance): incorrect previous shift computation for a timestamp leading to incorrect absent marking (cherry picked from commit cda77bbb1673483117f2e83e45d3d913407606b5) --- hrms/hr/doctype/shift_assignment/shift_assignment.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hrms/hr/doctype/shift_assignment/shift_assignment.py b/hrms/hr/doctype/shift_assignment/shift_assignment.py index f6b2d34f5f..5cdd5d7d9b 100644 --- a/hrms/hr/doctype/shift_assignment/shift_assignment.py +++ b/hrms/hr/doctype/shift_assignment/shift_assignment.py @@ -459,7 +459,11 @@ def get_prev_or_next_shift( for date_range in shift_dates: # midnight shifts will span more than a day start_date, end_date = date_range[0], add_days(date_range[1], 1) - reverse = next_shift_direction == "reverse" + + if reverse := (next_shift_direction == "reverse"): + end_date = min(end_date, for_timestamp.date()) + elif next_shift_direction == "forward": + start_date = max(start_date, for_timestamp.date()) for dt in generate_date_range(start_date, end_date, reverse=reverse): shift_details = get_employee_shift( From fdf0381fba7097c63a48ff11386b02a5c5715ae5 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Tue, 7 May 2024 21:17:29 +0530 Subject: [PATCH 13/14] test: prev & curr shift edge cases (cherry picked from commit ab2f10975ded330f9522003f8a228973a8726248) --- .../shift_assignment/test_shift_assignment.py | 33 +++++++++++++++++++ hrms/hr/doctype/shift_type/test_shift_type.py | 23 +++++++++++++ 2 files changed, 56 insertions(+) diff --git a/hrms/hr/doctype/shift_assignment/test_shift_assignment.py b/hrms/hr/doctype/shift_assignment/test_shift_assignment.py index 2473c728dc..a33aba7abf 100644 --- a/hrms/hr/doctype/shift_assignment/test_shift_assignment.py +++ b/hrms/hr/doctype/shift_assignment/test_shift_assignment.py @@ -295,3 +295,36 @@ def test_consecutive_day_and_night_shifts(self): self.assertEqual(checkin.shift_type, checkout.shift_type) self.assertEqual(checkin.actual_start.date(), today) self.assertEqual(checkout.actual_end.date(), today) + + def test_shift_details_on_consecutive_days_with_overlapping_timings(self): + # defaults + employee = make_employee("test_shift_assignment@example.com", company="_Test Company") + today = getdate() + yesterday = add_days(today, -1) + + # shift 1 + shift_type = setup_shift_type(shift_type="Morning", start_time="07:00:00", end_time="12:00:00") + make_shift_assignment(shift_type.name, employee, add_days(yesterday, -1), yesterday) + + # shift 2 + shift_type = setup_shift_type(shift_type="Afternoon", start_time="09:30:00", end_time="14:00:00") + make_shift_assignment(shift_type.name, employee, today, add_days(today, 1)) + + # current_shift shift log - checkin in the grace period of current shift, non-overlapping with prev shift + current_shift = get_actual_start_end_datetime_of_shift( + employee, get_datetime(f"{today} 14:01:00"), True + ) + self.assertEqual(current_shift.shift_type.name, "Afternoon") + self.assertEqual(current_shift.actual_start, get_datetime(f"{today} 08:30:00")) + self.assertEqual(current_shift.actual_end, get_datetime(f"{today} 15:00:00")) + + # previous shift + checkin = get_actual_start_end_datetime_of_shift( + employee, get_datetime(f"{yesterday} 07:01:00"), True + ) + checkout = get_actual_start_end_datetime_of_shift( + employee, get_datetime(f"{yesterday} 13:00:00"), True + ) + self.assertTrue(checkin.shift_type.name == checkout.shift_type.name == "Morning") + self.assertEqual(checkin.actual_start, get_datetime(f"{yesterday} 06:00:00")) + self.assertEqual(checkout.actual_end, get_datetime(f"{yesterday} 13:00:00")) diff --git a/hrms/hr/doctype/shift_type/test_shift_type.py b/hrms/hr/doctype/shift_type/test_shift_type.py index 1d3903c873..f961d5218a 100644 --- a/hrms/hr/doctype/shift_type/test_shift_type.py +++ b/hrms/hr/doctype/shift_type/test_shift_type.py @@ -371,6 +371,29 @@ def test_mark_absent_for_dates_with_no_attendance_for_midnight_shift(self): self.assertEqual(len(absent_records), 2) def test_do_not_mark_absent_before_shift_actual_end_time(self): + from hrms.hr.doctype.employee_checkin.test_employee_checkin import make_checkin + + employee = make_employee("test_employee_checkin@example.com", company="_Test Company") + today = getdate() + yesterday = add_days(today, -1) + + # shift 1 + shift_1 = setup_shift_type(shift_type="Morning", start_time="07:00:00", end_time="12:30:00") + make_shift_assignment(shift_1.name, employee, add_days(yesterday, -1), yesterday) + + # shift 2 + shift_2 = setup_shift_type(shift_type="Afternoon", start_time="09:30:00", end_time="18:00:00") + make_shift_assignment(shift_2.name, employee, today, add_days(today, 1)) + + # update last sync of checkin for shift 2 + shift_2.process_attendance_after = add_days(today, -2) + shift_2.last_sync_of_checkin = datetime.combine(today, get_time("09:01:00")) + shift_2.save() + shift_2.process_auto_attendance() + + self.assertIsNone(frappe.db.get_value("Attendance", {"attendance_date": today, "employee": employee})) + + def test_do_not_mark_absent_before_shift_actual_end_time_for_midnight_shift(self): """ Tests employee is not marked absent for a shift spanning 2 days before its actual end time From dec4c0dd98d02fc71655815f17caa13631d22177 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 8 May 2024 14:32:04 +0530 Subject: [PATCH 14/14] fix: update project URLs in pyproject (backport #1761) (#1762) (cherry picked from commit f6872735487fd17098bd8729a945c73b54ef82bb) Co-authored-by: Rucha Mahabal --- pyproject.toml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index e7cf0b8fdc..d65d7de2b0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -58,6 +58,13 @@ section-order = [ "local-folder", ] + +[project.urls] +Homepage = "https://frappehr.com/" +Repository = "https://github.com/frappe/hrms.git" +"Bug Reports" = "https://github.com/frappe/hrms/issues" + + [tool.bench.frappe-dependencies] frappe = ">=15.0.0,<16.0.0" erpnext = ">=15.0.0,<16.0.0" \ No newline at end of file