From 59d9c95182edb6b941e4262572b0536e14d6a94d Mon Sep 17 00:00:00 2001 From: SalShai Date: Thu, 21 Dec 2023 13:49:18 +0300 Subject: [PATCH 1/8] Add missing Field! --- one_fm/one_fm/custom/employee.json | 196 +++++++++++++++++++++++++---- 1 file changed, 175 insertions(+), 21 deletions(-) diff --git a/one_fm/one_fm/custom/employee.json b/one_fm/one_fm/custom/employee.json index 25588a9b14..1eafb73e1a 100644 --- a/one_fm/one_fm/custom/employee.json +++ b/one_fm/one_fm/custom/employee.json @@ -4914,7 +4914,7 @@ "parentfield": null, "parenttype": null, "permlevel": 0, - "precision": "", + "precision": null, "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, @@ -4978,7 +4978,7 @@ "parentfield": null, "parenttype": null, "permlevel": 0, - "precision": "", + "precision": null, "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, @@ -5042,7 +5042,7 @@ "parentfield": null, "parenttype": null, "permlevel": 0, - "precision": "", + "precision": null, "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, @@ -5106,7 +5106,7 @@ "parentfield": null, "parenttype": null, "permlevel": 0, - "precision": "", + "precision": null, "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, @@ -5874,7 +5874,7 @@ "parentfield": null, "parenttype": null, "permlevel": 0, - "precision": "", + "precision": null, "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, @@ -5923,7 +5923,7 @@ "insert_after": "branch", "is_system_generated": 0, "is_virtual": 0, - "label": "", + "label": null, "length": 0, "mandatory_depends_on": null, "modified": "2022-11-02 10:33:49.532076", @@ -5938,7 +5938,7 @@ "parentfield": null, "parenttype": null, "permlevel": 0, - "precision": "", + "precision": null, "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, @@ -5987,7 +5987,7 @@ "insert_after": "department", "is_system_generated": 0, "is_virtual": 0, - "label": "", + "label": null, "length": 0, "mandatory_depends_on": null, "modified": "2022-11-02 10:34:50.679719", @@ -6002,7 +6002,7 @@ "parentfield": null, "parenttype": null, "permlevel": 0, - "precision": "", + "precision": null, "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, @@ -6066,7 +6066,7 @@ "parentfield": null, "parenttype": null, "permlevel": 0, - "precision": "", + "precision": null, "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, @@ -6130,7 +6130,7 @@ "parentfield": null, "parenttype": null, "permlevel": 0, - "precision": "", + "precision": null, "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, @@ -6258,7 +6258,7 @@ "parentfield": null, "parenttype": null, "permlevel": 0, - "precision": "", + "precision": null, "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, @@ -6322,7 +6322,7 @@ "parentfield": null, "parenttype": null, "permlevel": 0, - "precision": "", + "precision": null, "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, @@ -6386,7 +6386,7 @@ "parentfield": null, "parenttype": null, "permlevel": 0, - "precision": "", + "precision": null, "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, @@ -6450,7 +6450,7 @@ "parentfield": null, "parenttype": null, "permlevel": 0, - "precision": "", + "precision": null, "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, @@ -6514,7 +6514,7 @@ "parentfield": null, "parenttype": null, "permlevel": 0, - "precision": "", + "precision": null, "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, @@ -6553,7 +6553,7 @@ "hide_border": 0, "hide_days": 0, "hide_seconds": 0, - "idx": 51, + "idx": 52, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_global_search": 0, @@ -6578,7 +6578,7 @@ "parentfield": null, "parenttype": null, "permlevel": 0, - "precision": "", + "precision": null, "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, @@ -6617,7 +6617,7 @@ "hide_border": 0, "hide_days": 0, "hide_seconds": 0, - "idx": 56, + "idx": 57, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_global_search": 0, @@ -6642,6 +6642,134 @@ "parentfield": null, "parenttype": null, "permlevel": 0, + "precision": null, + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2023-12-21 11:58:21.605305", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Employee", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "iban", + "fieldtype": "Data", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 140, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "one_fm_basic_salary", + "is_system_generated": 0, + "is_virtual": 0, + "label": "IBAN", + "length": 0, + "mandatory_depends_on": null, + "modified": "2023-12-21 11:58:21.605305", + "modified_by": "Administrator", + "module": null, + "name": "Employee-iban", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "sort_options": 0, + "translatable": 1, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2023-12-21 13:40:25.032671", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Employee", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "column_break_heye", + "fieldtype": "Column Break", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 136, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "bank_name", + "is_system_generated": 0, + "is_virtual": 0, + "label": null, + "length": 0, + "mandatory_depends_on": null, + "modified": "2023-12-21 13:40:25.032671", + "modified_by": "Administrator", + "module": null, + "name": "Employee-column_break_heye", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, @@ -6666,7 +6794,7 @@ "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2023-12-03 13:09:45.515981", + "creation": "2023-12-21 13:46:00.383094", "default_value": null, "doc_type": "Employee", "docstatus": 0, @@ -6674,7 +6802,7 @@ "field_name": null, "idx": 0, "is_system_generated": 0, - "modified": "2023-12-03 13:09:45.515981", + "modified": "2023-12-21 13:46:00.383094", "modified_by": "Administrator", "module": null, "name": "Employee-main-field_order", @@ -6687,6 +6815,32 @@ "row_name": null, "value": "[\"workflow_state\", \"basic_details_tab\", \"basic_information\", \"employee\", \"naming_series\", \"first_name\", \"middle_name\", \"one_fm_third_name\", \"one_fm_forth_name\", \"last_name\", \"employee_name\", \"column_break_9\", \"one_fm_first_name_in_arabic\", \"one_fm_second_name_in_arabic\", \"one_fm_third_name_in_arabic\", \"one_fm_forth_name_in_arabic\", \"one_fm_last_name_in_arabic\", \"employee_name_in_arabic\", \"gender\", \"date_of_birth\", \"salutation\", \"column_break1\", \"date_of_joining\", \"image\", \"signature\", \"status\", \"employee_id\", \"is_in_ows\", \"erpnext_user\", \"user_id\", \"create_user\", \"create_user_permission\", \"device_os\", \"fcm_token\", \"company_details_section\", \"company\", \"department\", \"coulumn_break_ar2\", \"department_code\", \"employment_type\", \"employee_number\", \"column_break_25\", \"designation\", \"reports_to\", \"government_relation\", \"government_relations\", \"one_fm_pam_designation\", \"pam_file\", \"pam_file_number\", \"residency_expiry_date\", \"under_company_residency\", \"custom_employee_photo\", \"column_break_72\", \"one_fm_work_permit\", \"work_permit\", \"pam_type\", \"custom_employee_image\", \"work_permit_salary\", \"work_permit_expiry_date\", \"column_break_64\", \"one_fm_civil_id\", \"civil_id_expiry_date\", \"one_fm_centralized_number\", \"pifss_id_no\", \"is_in_kuwait\", \"grade\", \"arabic_names\", \"column_break_18\", \"branch\", \"column_break_ar1\", \"employment_details\", \"scheduled_confirmation_date\", \"column_break_32\", \"final_confirmation_date\", \"one_fm_visa_reference_number\", \"one_fm_date_of_issuance_of_visa\", \"one_fm_date_of_entry_in_kuwait\", \"one_fm_duration_of_work_permit\", \"contract_end_date\", \"col_break_22\", \"notice_number_of_days\", \"date_of_retirement\", \"one_fm_accommodation_policy\", \"contact_details\", \"cell_number\", \"column_break_40\", \"personal_email\", \"company_email\", \"column_break4\", \"prefered_contact_email\", \"prefered_email\", \"unsubscribed\", \"address_section\", \"current_address\", \"current_accommodation_type\", \"column_break_46\", \"permanent_address\", \"permanent_accommodation_type\", \"emergency_contact_details\", \"person_to_be_contacted\", \"column_break_55\", \"emergency_phone_number\", \"column_break_19\", \"relation\", \"attendance_and_leave_details\", \"attendance_device_id\", \"annual_leave_balance\", \"went_to_hajj\", \"leave_policy\", \"day_off_category\", \"number_of_days_off\", \"attendance_by_timesheet\", \"auto_attendance\", \"non_kuwaiti_residents\", \"column_break_44\", \"shift_working_html\", \"shift_working\", \"shift\", \"site\", \"project\", \"default_shift\", \"holiday_list\", \"approvers_section\", \"expense_approver\", \"leave_approver\", \"column_break_45\", \"shift_request_approver\", \"salary_information\", \"ctc\", \"salary_currency\", \"salary_mode\", \"salary_cb\", \"payroll_cost_center\", \"bank_details_section\", \"bank_name\", \"column_break_heye\", \"bank_ac_no\", \"one_fm_salary_type\", \"one_fm_basic_salary\", \"iban\", \"personal_details\", \"one_fm_nationality\", \"one_fm_passport_type\", \"marital_status\", \"family_background\", \"column_break6\", \"blood_group\", \"one_fm_religion\", \"one_fm_place_of_birth\", \"health_details\", \"employee_signature\", \"children_details_section\", \"number_of_children\", \"children_details\", \"nationality_details_section\", \"nationality_no\", \"nationality_subject\", \"nationality_cb\", \"date_of_naturalization\", \"health_insurance_section\", \"health_insurance_provider\", \"health_insurance_no\", \"passport_details_section\", \"passport_number\", \"valid_upto\", \"column_break_73\", \"date_of_issue\", \"place_of_issue\", \"profile_tab\", \"bio\", \"educational_qualification\", \"education\", \"one_fm__highest_educational_qualification\", \"previous_work_experience\", \"external_work_history\", \"history_in_company\", \"internal_work_history\", \"one_fm_employee_asset_details_section\", \"one_fm_employee_asset\", \"one_fm_handover_asset\", \"one_fm_employee_documents_section\", \"one_fm_employee_documents\", \"exit\", \"resignation_letter_date\", \"relieving_date\", \"exit_interview_details\", \"held_on\", \"new_workplace\", \"column_break_99\", \"leave_encashed\", \"encashment_date\", \"feedback_section\", \"reason_for_leaving\", \"column_break_104\", \"feedback\", \"lft\", \"rgt\", \"old_parent\", \"subscription_start_date\", \"subscription_end_date\", \"column_break_77\", \"connections_tab\", \"one_fm_erf\", \"one_fm_provide_accommodation_by_company\", \"checkin_location\", \"enrolled\", \"job_offer_details\", \"job_applicant\", \"job_offer\", \"job_offer_salary_structure\", \"bank_account\", \"column_break_120\"]" }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2023-12-21 13:35:24.887058", + "default_value": null, + "doc_type": "Employee", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "relieving_date", + "idx": 0, + "is_system_generated": 0, + "modified": "2023-12-21 13:35:24.887058", + "modified_by": "Administrator", + "module": null, + "name": "Employee-relieving_date-no_copy", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "no_copy", + "property_type": "Check", + "row_name": null, + "value": "1" + }, { "_assign": null, "_comments": null, From f1e738323021e32464dce319dc240e548322b065 Mon Sep 17 00:00:00 2001 From: Jamsheer PP Date: Sat, 23 Dec 2023 22:34:08 +0530 Subject: [PATCH 2/8] feat: auto payroll - differrent payroll cycle --- one_fm/api/doc_methods/payroll_entry.py | 72 ++++++++++++------- .../hr_and_payroll_additional_settings.py | 12 ++++ 2 files changed, 57 insertions(+), 27 deletions(-) diff --git a/one_fm/api/doc_methods/payroll_entry.py b/one_fm/api/doc_methods/payroll_entry.py index d4593994a9..b038fce9dc 100644 --- a/one_fm/api/doc_methods/payroll_entry.py +++ b/one_fm/api/doc_methods/payroll_entry.py @@ -16,7 +16,10 @@ from hrms.payroll.doctype.payroll_entry.payroll_entry import ( get_filter_condition, get_joining_relieving_condition, remove_payrolled_employees, get_salary_structure ) -from one_fm.one_fm.doctype.hr_and_payroll_additional_settings.hr_and_payroll_additional_settings import get_projects_not_configured_in_payroll_cycle_but_linked_in_employee +from one_fm.one_fm.doctype.hr_and_payroll_additional_settings.hr_and_payroll_additional_settings import ( + get_projects_not_configured_in_payroll_cycle_but_linked_in_employee, + get_projects_configured_in_payroll_cycle +) from itertools import groupby from operator import itemgetter from one_fm.processor import sendemail @@ -69,8 +72,15 @@ def fill_employee_details(self): and for which salary structure exists. """ self.set('employees', []) - # Find projects comes under the same payroll cycle - if str(get_start_date(self.start_date)) == str(frappe.db.get_single_value('HR and Payroll Additional Settings', 'default_payroll_start_day')): + + project_list = False + + # Find payroll cycle start day + payroll_start_day = str(get_start_date(self.start_date)) + + # Find projects comes under the default payroll cycle + if payroll_start_day == str(frappe.db.get_single_value('HR and Payroll Additional Settings', 'default_payroll_start_day')): + # Find all projects linked to payroll cycles query = ''' select project @@ -78,20 +88,24 @@ def fill_employee_details(self): `tabProject Payroll Cycle` ''' projects = frappe.db.sql(query, as_dict=True) - default_projects = get_projects_not_configured_in_payroll_cycle_but_linked_in_employee(', '.join(['"{}"'.format(project.project) for project in projects])) - project_list = ', '.join(['"{}"'.format(project.project) for project in default_projects]) + if not projects: + projects = [{'project': ''}] + + # Get projects not configured in payroll cycle but linked in employee + default_projects = get_projects_not_configured_in_payroll_cycle_but_linked_in_employee(', '.join(['"{}"'.format(project['project']) for project in projects])) + if default_projects: + project_list = ', '.join(['"{}"'.format(project.project) for project in default_projects]) + + # Find projects configured in default payroll cycle + configured_projects = get_projects_configured_in_payroll_cycle(payroll_start_day) + if configured_projects: + if project_list: + project_list += ', '+configured_projects + else: + project_list = configured_projects else: - query = ''' - select - project - from - `tabProject Payroll Cycle` - where - payroll_start_day = '{0}' - ''' - start_day = get_start_date(self.start_date) - projects = frappe.db.sql(query.format(start_day), as_dict=True) - project_list = ', '.join(['"{}"'.format(project.project) for project in projects]) + # Find projects configured in payroll start day + project_list = get_projects_configured_in_payroll_cycle(payroll_start_day) employees = get_emp_list(self, project_list) @@ -133,7 +147,7 @@ def get_emp_list(self, project_list=False): sal_struct = get_salary_structure( self.company, self.currency, self.salary_slip_based_on_timesheet, self.payroll_frequency ) - print(sal_struct) + if sal_struct: cond += "and t2.salary_structure IN %(sal_struct)s " cond += "and t2.payroll_payable_account = %(payroll_payable_account)s " @@ -290,6 +304,8 @@ def auto_create_payroll_entry(payroll_date=None): # Calculate payroll date payroll_date = (datetime(getdate().year, getdate().month, cint(payroll_date_day))).strftime("%Y-%m-%d") + # Find default from date and end date for payroll + default_payroll_start_day = frappe.db.get_single_value('HR and Payroll Additional Settings', 'default_payroll_start_day') # Get Payroll cycle list from HR and Payroll Settings and itrate for payroll cycle query = ''' @@ -298,23 +314,25 @@ def auto_create_payroll_entry(payroll_date=None): from `tabProject Payroll Cycle` ''' - payroll_start_day_list = frappe.db.sql(query, as_dict=True) - payroll_type = ["Basic", "Over-Time"] + data = frappe.db.sql(query, as_dict=True) + + payroll_start_day_list = [d['payroll_start_day'] for d in data] + for payroll_start_day in payroll_start_day_list: # Find from date and end date for payroll - start_date, end_date = get_payroll_start_end_date_by_start_day(payroll_date, payroll_start_day.payroll_start_day) + start_date, end_date = get_payroll_start_end_date_by_start_day(payroll_date, payroll_start_day) # Create Payroll Entry - create_monthly_payroll_entry(payroll_date, start_date, end_date, payroll_type) + create_monthly_payroll_entry(payroll_date, start_date, end_date) - # # Find default from date and end date for payroll - default_payroll_start_day = frappe.db.get_single_value('HR and Payroll Additional Settings', 'default_payroll_start_day') - default_start_date, default_end_date = get_payroll_start_end_date_by_start_day(payroll_date, default_payroll_start_day) + if default_payroll_start_day and default_payroll_start_day not in payroll_start_day_list: + default_start_date, default_end_date = get_payroll_start_end_date_by_start_day(payroll_date, default_payroll_start_day) - create_monthly_payroll_entry(payroll_date, default_start_date, default_end_date, payroll_type) + create_monthly_payroll_entry(payroll_date, default_start_date, default_end_date) -def create_monthly_payroll_entry(payroll_date, start_date, end_date, payroll_type): +def create_monthly_payroll_entry(payroll_date, start_date, end_date): try: + payroll_type = ["Basic", "Over-Time"] for types in payroll_type: payroll_entry = frappe.new_doc("Payroll Entry") payroll_entry.posting_date = getdate(payroll_date) @@ -643,7 +661,7 @@ def create_salary_slips(doc): create_salary_slips_for_employees(employees, payroll_entry = doc, publish_progress=False) # since this method is called via frm.call this doc needs to be updated manually doc.reload() - + def log_payroll_failure(process, payroll_entry, error): error_log = frappe.log_error( diff --git a/one_fm/one_fm/doctype/hr_and_payroll_additional_settings/hr_and_payroll_additional_settings.py b/one_fm/one_fm/doctype/hr_and_payroll_additional_settings/hr_and_payroll_additional_settings.py index 3d4bbed09e..44a4068d61 100644 --- a/one_fm/one_fm/doctype/hr_and_payroll_additional_settings/hr_and_payroll_additional_settings.py +++ b/one_fm/one_fm/doctype/hr_and_payroll_additional_settings/hr_and_payroll_additional_settings.py @@ -31,3 +31,15 @@ def get_projects_not_configured_in_payroll_cycle_but_linked_in_employee(project_ project NOT IN ({0}) ''' return frappe.db.sql(query.format(project_list), as_dict=True) + +def get_projects_configured_in_payroll_cycle(payroll_start_day): + query = ''' + select + project + from + `tabProject Payroll Cycle` + where + payroll_start_day = '{0}' + ''' + projects = frappe.db.sql(query.format(payroll_start_day), as_dict=True) + return ', '.join(['"{}"'.format(project.project) for project in projects]) From a7a88d25c833c9cb62829bf5fee6a02a8dd4ef36 Mon Sep 17 00:00:00 2001 From: Ebuka Date: Sun, 24 Dec 2023 06:48:04 +0100 Subject: [PATCH 3/8] Bug buster to HD ticket --- .../bug_buster_employee/bug_buster_employee.json | 11 +++++++++-- one_fm/permissions.py | 4 ++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/one_fm/developer/doctype/bug_buster_employee/bug_buster_employee.json b/one_fm/developer/doctype/bug_buster_employee/bug_buster_employee.json index 3445fc82a4..1e35f34516 100644 --- a/one_fm/developer/doctype/bug_buster_employee/bug_buster_employee.json +++ b/one_fm/developer/doctype/bug_buster_employee/bug_buster_employee.json @@ -12,7 +12,8 @@ "full_name", "to_date", "section_break_x5grl", - "employees" + "employees", + "default_support_team" ], "fields": [ { @@ -55,11 +56,17 @@ "fieldname": "to_date", "fieldtype": "Date", "label": "To Date" + }, + { + "fieldname": "default_support_team", + "fieldtype": "Link", + "label": "Default Support Team", + "options": "HD Team" } ], "issingle": 1, "links": [], - "modified": "2023-03-07 17:08:27.711904", + "modified": "2023-12-23 20:18:15.804068", "modified_by": "Administrator", "module": "Developer", "name": "Bug Buster Employee", diff --git a/one_fm/permissions.py b/one_fm/permissions.py index f4d539faf3..6b35cf6ff9 100644 --- a/one_fm/permissions.py +++ b/one_fm/permissions.py @@ -116,9 +116,9 @@ def get_docinfo(doc=None, doctype=None, name=None): "automated_messages": automated_messages, "total_comments": len(json.loads(doc.get("_comments") or "[]")), "versions": get_versions(doc), - "assignments": get_assignments(doc.doctype, doc.name), + "assignments": get_assignments(doc.doctype, str(doc.name)), "permissions": get_doc_permissions(doc), - "shared": frappe.share.get_users(doc.doctype, doc.name), + "shared": frappe.share.get_users(doc.doctype, str(doc.name)), "views": get_view_logs(doc.doctype, doc.name), "energy_point_logs": get_point_logs(doc.doctype, doc.name), "additional_timeline_content": get_additional_timeline_content(doc.doctype, doc.name), From 8c0f43caa18016e307aa4f5d6fc1db97ed73e587 Mon Sep 17 00:00:00 2001 From: Ebuka Date: Sun, 24 Dec 2023 18:50:11 +0100 Subject: [PATCH 4/8] Auto assign bug buster --- one_fm/api/doc_methods/hd_ticket.py | 36 +++++++++++++++++++ .../doctype/bug_buster/bug_buster.py | 15 ++++++-- one_fm/hooks.py | 4 +++ 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 one_fm/api/doc_methods/hd_ticket.py diff --git a/one_fm/api/doc_methods/hd_ticket.py b/one_fm/api/doc_methods/hd_ticket.py new file mode 100644 index 0000000000..d558f9407e --- /dev/null +++ b/one_fm/api/doc_methods/hd_ticket.py @@ -0,0 +1,36 @@ +import frappe +from frappe.utils import getdate +from frappe.desk.form.assign_to import add as add_assignment + + +def validate_hd_ticket(doc,event): + if not doc.is_new(): + existing_todo = frappe.get_all("ToDo",{'reference_name':doc.name,'reference_type':'HD Ticket'},['name']) + if not existing_todo: + bug_buster = frappe.get_all("Bug Buster",{'docstatus':1,'from_date':['<=',getdate()],'to_date':['>=',getdate()]},['employee']) + if bug_buster: + emp_user = frappe.get_value("Employee",bug_buster[0].employee,'user_id') + if emp_user: + add_assignment({ + 'doctype': "HD Ticket", + 'name': str(doc.name), + 'assign_to': [emp_user], + "description": "Please Review Issue", + }) + +def assign_to_bug_buster(doc, event): + """ + Assign Ticket to the bug buster if any exists + """ + bug_buster = frappe.get_all("Bug Buster",{'docstatus':1,'from_date':['<=',getdate()],'to_date':['>=',getdate()]},['employee']) + if bug_buster: + emp_user = frappe.get_value("Employee",bug_buster[0].employee,'user_id') + if emp_user: + existing_todo = frappe.get_all("ToDo",{'reference_name':doc.name,'reference_type':'HD Ticket'},['name']) + if not existing_todo: + add_assignment({ + 'doctype': "HD Ticket", + 'name': str(doc.name), + 'assign_to': [emp_user], + "description": "Please Review Issue details", + }) \ No newline at end of file diff --git a/one_fm/developer/doctype/bug_buster/bug_buster.py b/one_fm/developer/doctype/bug_buster/bug_buster.py index ad9930d9e4..9c2fb43f2f 100644 --- a/one_fm/developer/doctype/bug_buster/bug_buster.py +++ b/one_fm/developer/doctype/bug_buster/bug_buster.py @@ -59,7 +59,6 @@ def send_email(self): """, ) - def roster_bug_buster(): today = getdate() tomorrow = add_days(today, 1) @@ -70,4 +69,16 @@ def roster_bug_buster(): "employee":busters.next_bug_buster, "from_date": tomorrow, "to_date": add_days(tomorrow, 6) - }).submit() \ No newline at end of file + }).submit() + #set user in HD Team + emp_user = frappe.get_value("Employee",busters.next_bug_buster,'user_id') + if emp_user and busters.get('default_support_team'): + frappe.db.sql(f"Delete from `tabHD Team Member` where parent = '{busters.get('default_support_team')}' and parenttype ='HD Team' ") + frappe.get_doc({ + 'doctype':'HD Team Member', + 'parent':busters.get('default_support_team'), + 'parentfield':'users', + 'user':emp_user, + 'parenttype' :'HD Team' + }).insert() + \ No newline at end of file diff --git a/one_fm/hooks.py b/one_fm/hooks.py index e3bbb262d5..06fbdde8d3 100644 --- a/one_fm/hooks.py +++ b/one_fm/hooks.py @@ -231,6 +231,10 @@ "Leave Type": { "validate": "one_fm.utils.validate_leave_type_for_one_fm_paid_leave" }, + "HD Ticket": { + "after_insert": "one_fm.api.doc_methods.hd_ticket.assign_to_bug_buster", + "validate": "one_fm.api.doc_methods.hd_ticket.validate_hd_ticket" + }, "Employee Grade": { "validate": "one_fm.one_fm.utils.employee_grade_validate" }, From 0333c767a3999578a2d1e78a7348992cf48b0b86 Mon Sep 17 00:00:00 2001 From: Ebuka Date: Sun, 24 Dec 2023 19:28:04 +0100 Subject: [PATCH 5/8] Updated Function --- .../doctype/bug_buster/bug_buster.py | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/one_fm/developer/doctype/bug_buster/bug_buster.py b/one_fm/developer/doctype/bug_buster/bug_buster.py index 9c2fb43f2f..f50ad54a2f 100644 --- a/one_fm/developer/doctype/bug_buster/bug_buster.py +++ b/one_fm/developer/doctype/bug_buster/bug_buster.py @@ -71,14 +71,17 @@ def roster_bug_buster(): "to_date": add_days(tomorrow, 6) }).submit() #set user in HD Team - emp_user = frappe.get_value("Employee",busters.next_bug_buster,'user_id') - if emp_user and busters.get('default_support_team'): - frappe.db.sql(f"Delete from `tabHD Team Member` where parent = '{busters.get('default_support_team')}' and parenttype ='HD Team' ") - frappe.get_doc({ - 'doctype':'HD Team Member', - 'parent':busters.get('default_support_team'), - 'parentfield':'users', - 'user':emp_user, - 'parenttype' :'HD Team' - }).insert() + try: + emp_user = frappe.get_value("Employee",busters.next_bug_buster,'user_id') + if emp_user and busters.get('default_support_team'): + frappe.db.sql(f"Delete from `tabHD Team Member` where parent = '{busters.get('default_support_team')}' and parenttype ='HD Team' ") + frappe.get_doc({ + 'doctype':'HD Team Member', + 'parent':busters.get('default_support_team'), + 'parentfield':'users', + 'user':emp_user, + 'parenttype' :'HD Team' + }).insert() + except: + frappe.log_error(title="Error Assigning Bug Buster",message = frappe.get_traceback()) \ No newline at end of file From 4655a1a6fd69675acfb32820580480b15ebec4c7 Mon Sep 17 00:00:00 2001 From: Ebuka Date: Mon, 25 Dec 2023 17:04:25 +0100 Subject: [PATCH 6/8] Employee Form Read only --- .../onefm_general_setting.json | 13 ++++++++++--- one_fm/public/js/doctype_js/employee.js | 13 +++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/one_fm/one_fm/doctype/onefm_general_setting/onefm_general_setting.json b/one_fm/one_fm/doctype/onefm_general_setting/onefm_general_setting.json index 12d959867e..a3db6f60d4 100644 --- a/one_fm/one_fm/doctype/onefm_general_setting/onefm_general_setting.json +++ b/one_fm/one_fm/doctype/onefm_general_setting/onefm_general_setting.json @@ -8,7 +8,6 @@ "field_order": [ "mobile_app_version", "column_break_xyl05", - "mark_atttendance_per_employee", "section_break_2", "zenquote_keyword_category", "zenquotes_api_key", @@ -19,6 +18,7 @@ "attendance_manager", "attendance_manager_name", "employee_section", + "employee_master_role", "employee_access", "wiki_page_access" ], @@ -102,11 +102,18 @@ "fieldtype": "Table", "label": "Employee Access", "options": "ONEFM Employee Access" + }, + { + "description": "All users with this role have edit access on the Employee Form", + "fieldname": "employee_master_role", + "fieldtype": "Link", + "label": "Employee Master Role", + "options": "Role" } ], "issingle": 1, "links": [], - "modified": "2023-10-19 17:06:21.594157", + "modified": "2023-12-25 18:01:16.629421", "modified_by": "Administrator", "module": "One Fm", "name": "ONEFM General Setting", @@ -126,4 +133,4 @@ "sort_field": "modified", "sort_order": "DESC", "states": [] -} +} \ No newline at end of file diff --git a/one_fm/public/js/doctype_js/employee.js b/one_fm/public/js/doctype_js/employee.js index 2996ae7227..fabc2db21c 100644 --- a/one_fm/public/js/doctype_js/employee.js +++ b/one_fm/public/js/doctype_js/employee.js @@ -1,6 +1,7 @@ frappe.ui.form.on('Employee', { refresh: function(frm) { hideFields(frm); + is_employee_master(frm); set_grd_fields(frm) frm.trigger('set_queries'); set_mandatory(frm); @@ -122,6 +123,18 @@ const hideFields = frm => { $("[data-doctype='Employee Checkin']").hide(); } +let is_employee_master = frm =>{ + frappe.db.get_single_value("ONEFM General Setting",'employee_master_role').then(value=>{ + if(value){ + if(!frappe.user.has_role(value)){ + frm.disable_form() + + } + } + }) + +} + let set_grd_fields= frm=>{ frm.set_df_property('custom_employee_photo',"hidden",1) if(frappe.user_roles.includes("GRD Supervisor")){ From 7e22f5bdc0ff11a976676eb3c438d5299fd9864d Mon Sep 17 00:00:00 2001 From: Jamsheer PP Date: Tue, 26 Dec 2023 12:40:55 +0530 Subject: [PATCH 7/8] feat: screenshot mandatory for all justification --- .../one_fm/doctype/attendance_check/attendance_check.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/one_fm/one_fm/doctype/attendance_check/attendance_check.json b/one_fm/one_fm/doctype/attendance_check/attendance_check.json index 578dbf2f86..5bc80307b8 100644 --- a/one_fm/one_fm/doctype/attendance_check/attendance_check.json +++ b/one_fm/one_fm/doctype/attendance_check/attendance_check.json @@ -422,12 +422,12 @@ "mandatory_depends_on": "eval:doc.justification == \"Mobile isn't supporting the app\"" }, { - "depends_on": "eval:[\"Invalid media content\",\"Out-of-site location\", \"User not assigned to shift\", \"Suddenly, the App stop working!\",\"Other\"].includes(doc.justification)", + "depends_on": "justification", "description": "Upload screenshot with the same issue!", "fieldname": "screenshot", "fieldtype": "Attach", "label": "Screenshot", - "mandatory_depends_on": "eval:[\"Invalid media content\",\"Out-of-site location\", \"User not assigned to shift\", \"Suddenly, the App stop working!\"].includes(doc.justification)" + "mandatory_depends_on": "justification" }, { "depends_on": "eval:doc.justification == \"Other\"", @@ -452,7 +452,7 @@ "link_fieldname": "reference_docname" } ], - "modified": "2023-12-03 11:32:52.002023", + "modified": "2023-12-26 10:10:06.142090", "modified_by": "Administrator", "module": "One Fm", "name": "Attendance Check", From 290154c727d35ac0185fde225ac5005eca18d683 Mon Sep 17 00:00:00 2001 From: SalShai Date: Tue, 26 Dec 2023 11:29:38 +0300 Subject: [PATCH 8/8] Fix: OT Shift Assignment --- one_fm/api/tasks.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/one_fm/api/tasks.py b/one_fm/api/tasks.py index ae2b7b82df..273896c420 100644 --- a/one_fm/api/tasks.py +++ b/one_fm/api/tasks.py @@ -1021,24 +1021,22 @@ def process_overtime_shift(roster, date, time): for schedule in roster: #Check for employee's shift assignment of the day, if he has any. try: - if frappe.db.exists("Shift Assignment", {"employee":schedule.employee, "start_date": date}): - shift_assignment = frappe.get_doc("Shift Assignment", {"employee":schedule.employee, "start_date": date},["name","shift_type"]) + if frappe.db.exists('Employee', {'employee':schedule.employee, 'status':'Active'}): + shift_assignment = frappe.db.sql(f"""SELECT name, shift_type, end_datetime, roster_type from `tabShift Assignment` WHERE employee = '{schedule.employee}' AND date(end_datetime) = '{date}'""", as_dict=1) if shift_assignment: - shift_end_time = frappe.get_value("Shift Type",shift_assignment.shift_type, "end_time") + shift_end_time = frappe.get_value("Shift Type",shift_assignment[0].shift_type, "end_time") #check if the given shift has ended # Set status inactive before creating new shift if str(shift_end_time) == str(time): - frappe.set_value("Shift Assignment", shift_assignment.name,'end_date', date) - frappe.set_value("Shift Assignment", shift_assignment.name,'status', "Inactive") + frappe.set_value("Shift Assignment", shift_assignment[0].name,'end_date', date) + frappe.set_value("Shift Assignment", shift_assignment[0].name,'status', "Inactive") create_overtime_shift_assignment(schedule, date) - else: - create_overtime_shift_assignment(schedule, date) + else: + create_overtime_shift_assignment(schedule, date) except Exception as e: continue -def create_overtime_shift_assignment(schedule, date): - if (not frappe.db.exists("Shift Assignment",{"employee":schedule.employee, 'docstatus':1, "start_date":getdate(date), "status":"Active"}) and - frappe.db.exists('Employee', {'employee':schedule.employee, 'status':'Active'})): +def create_overtime_shift_assignment(schedule, date): try: shift_assignment = frappe.new_doc("Shift Assignment") shift_assignment.start_date = date