From 84207bfc7f811b70031cbb212bf078ea5b4d58a5 Mon Sep 17 00:00:00 2001 From: zhou <123@> Date: Wed, 19 Mar 2025 17:31:35 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yuthon_holiday/__manifest__.py | 1 + yuthon_holiday/models/inherit_hr_leave.py | 8 +++ yuthon_holiday/security/ir.model.access.csv | 1 + .../views/hr_leave_accrual_views.xml | 7 ++ yuthon_holiday/wizard/__init__.py | 3 +- yuthon_holiday/wizard/yuthon_leave_wizard.py | 71 +++++++++++++++++++ .../wizard/yuthon_leave_wizard_views.xml | 34 +++++++++ .../models/yuthon_hr_employee.py | 13 ++-- .../views/yuthon_hr_employee_views.xml | 2 + .../wizard/hr_employee_wizard.py | 4 +- .../views/invisible_sequence.xml | 6 +- 11 files changed, 139 insertions(+), 11 deletions(-) create mode 100644 yuthon_holiday/wizard/yuthon_leave_wizard.py create mode 100644 yuthon_holiday/wizard/yuthon_leave_wizard_views.xml diff --git a/yuthon_holiday/__manifest__.py b/yuthon_holiday/__manifest__.py index 3485b10d6..1c1d9e763 100644 --- a/yuthon_holiday/__manifest__.py +++ b/yuthon_holiday/__manifest__.py @@ -18,6 +18,7 @@ 'views/yuthon_holiday_setting_views.xml', 'wizard/yuthon_fixes_wizard_views.xml', 'wizard/leave_allocation_wizard_views.xml', + 'wizard/yuthon_leave_wizard_views.xml', ], 'assets': { 'web.assets_backend': [ diff --git a/yuthon_holiday/models/inherit_hr_leave.py b/yuthon_holiday/models/inherit_hr_leave.py index 8bf02b478..8268eac4f 100644 --- a/yuthon_holiday/models/inherit_hr_leave.py +++ b/yuthon_holiday/models/inherit_hr_leave.py @@ -11,6 +11,14 @@ from odoo.tools.misc import format_date class HrLeave(models.Model): _inherit = 'hr.leave' + def action_leave_wizard(self): + return { + "type": "ir.actions.act_window", + "name": "批量请假单", + "res_model": "yuthon.leave.wizard", + "view_mode": "form", + "target": "new", + } @api.model def default_get(self, fields_list): diff --git a/yuthon_holiday/security/ir.model.access.csv b/yuthon_holiday/security/ir.model.access.csv index 4c96ab10f..0b7747768 100644 --- a/yuthon_holiday/security/ir.model.access.csv +++ b/yuthon_holiday/security/ir.model.access.csv @@ -5,3 +5,4 @@ access_yuthon_fixes_approval,yuthon_fixes_approval,model_yuthon_fixes_approval,b access_yuthon_fixes_wizard,yuthon_fixes_wizard,model_yuthon_fixes_wizard,base.group_user,1,1,1,1 access_yuthon_holiday_setting,yuthon_holiday_setting,model_yuthon_holiday_setting,base.group_user,1,1,1,1 access_leave_allocation_wizard,leave_allocation_wizard,model_leave_allocation_wizard,base.group_user,1,1,1,1 +access_yuthon_leave_wizard,yuthon_leave_wizard,model_yuthon_leave_wizard,base.group_user,1,1,1,1 diff --git a/yuthon_holiday/views/hr_leave_accrual_views.xml b/yuthon_holiday/views/hr_leave_accrual_views.xml index b6f59b55c..b3e07ca39 100644 --- a/yuthon_holiday/views/hr_leave_accrual_views.xml +++ b/yuthon_holiday/views/hr_leave_accrual_views.xml @@ -97,4 +97,11 @@ + + 导入请假单 + + + code + action = model.action_leave_wizard() + diff --git a/yuthon_holiday/wizard/__init__.py b/yuthon_holiday/wizard/__init__.py index 01c45db30..62f7c487b 100644 --- a/yuthon_holiday/wizard/__init__.py +++ b/yuthon_holiday/wizard/__init__.py @@ -1,2 +1,3 @@ from . import yuthon_fixes_wizard -from . import leave_allocation_wizard \ No newline at end of file +from . import leave_allocation_wizard +from . import yuthon_leave_wizard \ No newline at end of file diff --git a/yuthon_holiday/wizard/yuthon_leave_wizard.py b/yuthon_holiday/wizard/yuthon_leave_wizard.py new file mode 100644 index 000000000..150fe3fcc --- /dev/null +++ b/yuthon_holiday/wizard/yuthon_leave_wizard.py @@ -0,0 +1,71 @@ +from odoo import models, fields, api, _, SUPERUSER_ID +from odoo.exceptions import ValidationError, UserError +import re +import xlrd +import base64 +import datetime +from datetime import datetime +import pandas as pd + + +class YuthonLeaveWizard(models.Model): + _name = 'yuthon.leave.wizard' + _description = '请假单导入' + + excel_file = fields.Binary(string="上传Excel表") + excel_name = fields.Char(string="文件名") + + def confirm(self): + """ + 导入excel文件,按行读取数据并处理 + :return: 导入员工信息表并更新 + """ + if not self.excel_file: + raise ValidationError('请上传文件。') + book = xlrd.open_workbook(file_contents=base64.decodebytes(self.excel_file)) + sh = book.sheet_by_index(0) + for rx in range(1,2): + row = sh.row(rx) + self.leave_import(row) + + def leave_import(self, row): + employee_id = self.env['hr.employee'].search([('name', '=', '苏琦')], limit=1) + status_name = re.search(r'\((.*?)\)', row[0].value).group(1) + number_of_days_display = float(re.search(r'((\d+\.\d+)天)', row[5].value).group(1)) + holiday_status_id = self.env['hr.leave.type'].search([('name', '=', status_name)]) + dt_from = datetime.strptime(row[3].value, '%Y-%m-%d %H:%M') + dt_to = datetime.strptime(row[4].value, '%Y-%m-%d %H:%M') + + def get_key_from_datetime(dt): + hour = dt.hour + minute = dt.minute + if minute == 0: + key = str(hour) + elif minute == 30: + key = str(hour + 0.5) + else: + return None + return key + key_from = get_key_from_datetime(dt_from) + key_to = get_key_from_datetime(dt_to) + hr_leave_model = self.env['hr.leave'] + selection_options = hr_leave_model._fields['request_hour_from'].selection + + def get_display_value(key): + for option in selection_options: + if option[0] == key: + return option[1] + return None + + request_hour_from = get_display_value(key_from) + request_hour_to = get_display_value(key_to) + self.env['hr.leave'].create({ + 'employee_id': employee_id.id, + 'holiday_status_id': holiday_status_id.id, + 'request_date_from': dt_to, + 'request_date_to': dt_from, + 'request_hour_from': request_hour_from.split(':')[0], + 'request_hour_to': request_hour_to.split(':')[0], + 'state':'validate', + 'request_unit_hours':True, + 'number_of_days_display': number_of_days_display}) \ No newline at end of file diff --git a/yuthon_holiday/wizard/yuthon_leave_wizard_views.xml b/yuthon_holiday/wizard/yuthon_leave_wizard_views.xml new file mode 100644 index 000000000..75b07c928 --- /dev/null +++ b/yuthon_holiday/wizard/yuthon_leave_wizard_views.xml @@ -0,0 +1,34 @@ + + + + 模板下载 + self + . + + + 初始化假期弹窗 + yuthon.leave.wizard + +
+ +
+
+ + + + + + + + +
+ +
+
+
+
\ No newline at end of file diff --git a/yuthon_hr_employee/models/yuthon_hr_employee.py b/yuthon_hr_employee/models/yuthon_hr_employee.py index 5964efd91..45a2dccc3 100644 --- a/yuthon_hr_employee/models/yuthon_hr_employee.py +++ b/yuthon_hr_employee/models/yuthon_hr_employee.py @@ -76,6 +76,7 @@ class YuthonHrEmployee(models.Model): entry_date = fields.Date(string="入职时间") confirmation_date = fields.Date(string="转正时间") company_old = fields.Char(string="司龄", compute='_compute_company_old') + company_old_year = fields.Integer(string="司龄(年)", compute='_compute_company_old') open_start_time = fields.Date(string="参加工作时间") cumulative_work_month = fields.Integer(string="累计工作月数", compute='_compute_social_insurance_info', store=True) @@ -113,6 +114,7 @@ class YuthonHrEmployee(models.Model): holiday_hours = fields.Float(string="假期额度") all_overtime_hours = fields.Float(string="总加班小时", compute="_compute_all_overtime_hours", store=True) replacement_card_count = fields.Integer(string="补卡次数") + is_annual_salary = fields.Boolean(string="是否年薪") # 假期 user_year_holiday_hours = fields.Float(string="已用年假") remainder_year_holiday_hours = fields.Float(string="剩余年假") @@ -287,18 +289,19 @@ class YuthonHrEmployee(models.Model): "target": "new", } - @api.depends('open_start_time') + @api.depends('entry_date') def _compute_company_old(self): """司龄计算""" for record in self: - if record.open_start_time: + if record.entry_date: today = datetime.now().date() - years_diff = today.year - record.open_start_time.year - months_diff = today.month - record.open_start_time.month - if today.month < record.open_start_time.month: + years_diff = today.year - record.entry_date.year + months_diff = today.month - record.entry_date.month + if today.month < record.entry_date.month: years_diff -= 1 months_diff += 12 record.company_old = str(years_diff) + '年' + str(months_diff) + '月' + record.company_old_year = years_diff else: record.company_old = None diff --git a/yuthon_hr_employee/views/yuthon_hr_employee_views.xml b/yuthon_hr_employee/views/yuthon_hr_employee_views.xml index 7e1151bdf..51fafa28e 100644 --- a/yuthon_hr_employee/views/yuthon_hr_employee_views.xml +++ b/yuthon_hr_employee/views/yuthon_hr_employee_views.xml @@ -115,6 +115,7 @@ + @@ -123,6 +124,7 @@ + diff --git a/yuthon_hr_employee/wizard/hr_employee_wizard.py b/yuthon_hr_employee/wizard/hr_employee_wizard.py index 5ae9a9ca9..689d5ad4f 100644 --- a/yuthon_hr_employee/wizard/hr_employee_wizard.py +++ b/yuthon_hr_employee/wizard/hr_employee_wizard.py @@ -25,7 +25,7 @@ class YuthonHrEmployeeWizard(models.Model): sh = book.sheet_by_index(0) for rx in range(2, sh.nrows): row = sh.row(rx) - self.salary_group_import(row) + self.employee_user_data(row) return { 'name': '批量更新员工', 'type': 'ir.actions.act_window', @@ -43,7 +43,7 @@ class YuthonHrEmployeeWizard(models.Model): number = row[0].value employee_date = { 'number':number, - 'open_start_time': date1, + 'entry_date': date1, 'interrupt_work_month': interrupt_work_month, } if employee_name: diff --git a/yuthon_work_brand/views/invisible_sequence.xml b/yuthon_work_brand/views/invisible_sequence.xml index f0c9e9f04..0dead1314 100644 --- a/yuthon_work_brand/views/invisible_sequence.xml +++ b/yuthon_work_brand/views/invisible_sequence.xml @@ -25,9 +25,9 @@ False - - False - + + + False From 471dde53c2437e5b732de50b8f1c328e8b6bf4f8 Mon Sep 17 00:00:00 2001 From: zhou <123@> Date: Wed, 19 Mar 2025 17:34:22 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yuthon_holiday/wizard/yuthon_leave_wizard.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yuthon_holiday/wizard/yuthon_leave_wizard.py b/yuthon_holiday/wizard/yuthon_leave_wizard.py index 150fe3fcc..dfc0cb865 100644 --- a/yuthon_holiday/wizard/yuthon_leave_wizard.py +++ b/yuthon_holiday/wizard/yuthon_leave_wizard.py @@ -29,7 +29,7 @@ class YuthonLeaveWizard(models.Model): self.leave_import(row) def leave_import(self, row): - employee_id = self.env['hr.employee'].search([('name', '=', '苏琦')], limit=1) + employee_id = self.env['hr.employee'].search([('name', '=', row[2].value)], limit=1) status_name = re.search(r'\((.*?)\)', row[0].value).group(1) number_of_days_display = float(re.search(r'((\d+\.\d+)天)', row[5].value).group(1)) holiday_status_id = self.env['hr.leave.type'].search([('name', '=', status_name)]) @@ -59,13 +59,13 @@ class YuthonLeaveWizard(models.Model): request_hour_from = get_display_value(key_from) request_hour_to = get_display_value(key_to) - self.env['hr.leave'].create({ + leave = self.env['hr.leave'].create({ 'employee_id': employee_id.id, 'holiday_status_id': holiday_status_id.id, 'request_date_from': dt_to, 'request_date_to': dt_from, 'request_hour_from': request_hour_from.split(':')[0], 'request_hour_to': request_hour_to.split(':')[0], - 'state':'validate', 'request_unit_hours':True, - 'number_of_days_display': number_of_days_display}) \ No newline at end of file + 'number_of_days_display': number_of_days_display}) + leave.action_approve() \ No newline at end of file