From bb43481ee1ea6402bbc217d77d40ebd5218160a3 Mon Sep 17 00:00:00 2001 From: zhouzhou <123@qq.com> Date: Mon, 25 Nov 2024 18:05:14 +0800 Subject: [PATCH] =?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_salary/__init__.py | 1 + yuthon_salary/__manifest__.py | 2 + .../models/inherit_hr_payroll_structure.py | 2 +- .../models/inherit_hr_salary_rule.py | 14 ++++- yuthon_salary/security/ir.model.access.csv | 3 +- .../static/others/salary_template.xlsx | Bin 0 -> 5568 bytes .../views/inherit_hr_salary_rule_views.xml | 40 +++++++++++++ yuthon_salary/wizard/__init__.py | 1 + yuthon_salary/wizard/yuthon_salary_wizard.py | 53 ++++++++++++++++++ .../wizard/yuthon_salary_wizard_views.xml | 34 +++++++++++ yuthon_will_task/data/will_task_time_data.xml | 2 +- yuthon_will_task/models/yuthon_task_time.py | 3 +- yuthon_will_task/models/yuthon_will_task.py | 31 +++++----- 13 files changed, 168 insertions(+), 18 deletions(-) create mode 100644 yuthon_salary/static/others/salary_template.xlsx create mode 100644 yuthon_salary/views/inherit_hr_salary_rule_views.xml create mode 100644 yuthon_salary/wizard/__init__.py create mode 100644 yuthon_salary/wizard/yuthon_salary_wizard.py create mode 100644 yuthon_salary/wizard/yuthon_salary_wizard_views.xml diff --git a/yuthon_salary/__init__.py b/yuthon_salary/__init__.py index cde864bae..35e7c9600 100644 --- a/yuthon_salary/__init__.py +++ b/yuthon_salary/__init__.py @@ -1,3 +1,4 @@ # -*- coding: utf-8 -*- from . import models +from . import wizard diff --git a/yuthon_salary/__manifest__.py b/yuthon_salary/__manifest__.py index 03e58889b..fb136cee8 100644 --- a/yuthon_salary/__manifest__.py +++ b/yuthon_salary/__manifest__.py @@ -15,6 +15,8 @@ 'security/ir.model.access.csv', 'security/yuthon_salary_company.xml', 'views/inherit_hr_payroll_structure_views.xml', + 'views/inherit_hr_salary_rule_views.xml', + 'wizard/yuthon_salary_wizard_views.xml', ], 'installable': True, 'application': True, diff --git a/yuthon_salary/models/inherit_hr_payroll_structure.py b/yuthon_salary/models/inherit_hr_payroll_structure.py index 6ceb0a7ec..ad050f45e 100644 --- a/yuthon_salary/models/inherit_hr_payroll_structure.py +++ b/yuthon_salary/models/inherit_hr_payroll_structure.py @@ -33,4 +33,4 @@ class HrPayrollStructure(models.Model): return (False, 0) return (False, 0) # 首位非0的放前面 res.sort(key=sort_by_sequence_number) - return res \ No newline at end of file + return res diff --git a/yuthon_salary/models/inherit_hr_salary_rule.py b/yuthon_salary/models/inherit_hr_salary_rule.py index 9d4be9d93..ff70f157c 100644 --- a/yuthon_salary/models/inherit_hr_salary_rule.py +++ b/yuthon_salary/models/inherit_hr_salary_rule.py @@ -3,5 +3,17 @@ import re class InheritHrSalaryRule(models.Model): _inherit = 'hr.salary.rule' + _order = 'sequence asc' - category_id = fields.Many2one('hr.salary.rule.category', required=False) + category_id = fields.Many2one('hr.salary.rule.category', required=False, string='类别') + yuthon_company = fields.Selection([('thtz', '天河投资集团'), ('thwg', '天河物管'), ('thlc', '天河粮储')], + string='所属公司') + + def action_yuthon_salary_wizard(self): + return { + "type": "ir.actions.act_window", + "name": "批量更新工资项", + "res_model": "yuthon.salary.wizard", + "view_mode": "form", + "target": "new", + } \ No newline at end of file diff --git a/yuthon_salary/security/ir.model.access.csv b/yuthon_salary/security/ir.model.access.csv index 58262d444..9ad83f062 100644 --- a/yuthon_salary/security/ir.model.access.csv +++ b/yuthon_salary/security/ir.model.access.csv @@ -1 +1,2 @@ -id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink \ No newline at end of file +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_yuthon_salary_wizard,access_yuthon_salary_wizard,model_yuthon_salary_wizard,base.group_user,1,1,1,1 \ No newline at end of file diff --git a/yuthon_salary/static/others/salary_template.xlsx b/yuthon_salary/static/others/salary_template.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..98392725a73730520937b5d2788596791d98abc6 GIT binary patch literal 5568 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 literal 0 HcmV?d00001 diff --git a/yuthon_salary/views/inherit_hr_salary_rule_views.xml b/yuthon_salary/views/inherit_hr_salary_rule_views.xml new file mode 100644 index 000000000..6d87df537 --- /dev/null +++ b/yuthon_salary/views/inherit_hr_salary_rule_views.xml @@ -0,0 +1,40 @@ + + + + hr.salary.rule.inherit + hr.salary.rule + + + + + + + 1 + + + 1 + + + + + + + + hr.salary.rule.inherit.form + hr.salary.rule + + + + + + + + + + 批量导入职级 + + + code + action = model.action_yuthon_salary_wizard() + + diff --git a/yuthon_salary/wizard/__init__.py b/yuthon_salary/wizard/__init__.py new file mode 100644 index 000000000..48a07b98d --- /dev/null +++ b/yuthon_salary/wizard/__init__.py @@ -0,0 +1 @@ +from . import yuthon_salary_wizard \ No newline at end of file diff --git a/yuthon_salary/wizard/yuthon_salary_wizard.py b/yuthon_salary/wizard/yuthon_salary_wizard.py new file mode 100644 index 000000000..129c614c0 --- /dev/null +++ b/yuthon_salary/wizard/yuthon_salary_wizard.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +from odoo import models, fields, api, _, SUPERUSER_ID +from odoo.exceptions import ValidationError, UserError +from pypinyin import pinyin, Style +import xlrd +import base64 +import datetime +from datetime import datetime + + +class YuthonSalaryWizard(models.Model): + _name = 'yuthon.salary.wizard' + + excel_file = fields.Binary(string="上传Excel表") + excel_name = fields.Char(string="文件名") + + def confirm(self): + """ + 导入excel文件,按行读取数据并处理 + """ + 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, sh.nrows): + row = sh.row(rx) + self.salary_user_data(row) + return { + 'name': '批量更新工资项', + 'type': 'ir.actions.act_window', + 'view_mode': 'tree', + 'res_model': 'hr.salary.rule', + } + + def salary_user_data(self,row): + name_pinyin = pinyin(row[1].value, style=Style.FIRST_LETTER) + abbreviation = "".join([p[0][0] for p in name_pinyin]).upper() + salary_name = self.env['hr.salary.rule'].search([('name', '=', row[1].value)]) + text = row[2].value + struct_id = self.env['hr.payroll.structure'].search([('name', '=', text)]) + yuthon_company_dict = {'天河投资集团': 'thtz', '天河物管': 'thwg', '天河粮储': 'thlc', '': ''} + yuthon_company_dict2 = {'天河投资集团': 'TT', '天河物管': 'TW', '天河粮储': 'TL', '': ''} + yuthon_company = yuthon_company_dict.get(row[3].value) + yuthon_company2 = yuthon_company_dict2.get(row[3].value) + salary_date = { + 'sequence': row[0].value, + 'code':yuthon_company2+abbreviation, + 'name': row[1].value, # 姓名 + 'struct_id': struct_id.id, # 部门 + 'yuthon_company': yuthon_company, + 'amount_fix' : row[4].value, # 固定金额 + } + salary_name.create(salary_date) diff --git a/yuthon_salary/wizard/yuthon_salary_wizard_views.xml b/yuthon_salary/wizard/yuthon_salary_wizard_views.xml new file mode 100644 index 000000000..cd8a9fc1b --- /dev/null +++ b/yuthon_salary/wizard/yuthon_salary_wizard_views.xml @@ -0,0 +1,34 @@ + + + + 工资项模板 下载 + self + /yuthon_salary/static/others/salary_template.xlsx + + + 审批意见弹窗 + yuthon.salary.wizard + +
+ +
+
+ + + + + + + + +
+
+
+
+
+
+
\ No newline at end of file diff --git a/yuthon_will_task/data/will_task_time_data.xml b/yuthon_will_task/data/will_task_time_data.xml index 8059874c7..18e5f33ed 100644 --- a/yuthon_will_task/data/will_task_time_data.xml +++ b/yuthon_will_task/data/will_task_time_data.xml @@ -8,7 +8,7 @@ model.will_task_time() - 2 + 1 minutes -1 diff --git a/yuthon_will_task/models/yuthon_task_time.py b/yuthon_will_task/models/yuthon_task_time.py index 9eb742512..536155849 100644 --- a/yuthon_will_task/models/yuthon_task_time.py +++ b/yuthon_will_task/models/yuthon_task_time.py @@ -18,4 +18,5 @@ class YuthonTaskTime(models.Model): 'day': '天', } for n in self: - n.name = str(n.number) + task_unit_dict[n.task_unit] + if n.number and n.task_unit: + n.name = str(n.number) + task_unit_dict[n.task_unit] diff --git a/yuthon_will_task/models/yuthon_will_task.py b/yuthon_will_task/models/yuthon_will_task.py index 0d1f271f8..175f9d45b 100644 --- a/yuthon_will_task/models/yuthon_will_task.py +++ b/yuthon_will_task/models/yuthon_will_task.py @@ -21,20 +21,25 @@ class YuthonWillTask(models.Model): start_time = fields.Datetime(string='开始时间', default=fields.Date.today()) end_time = fields.Datetime(string='结束时间', default=lambda self: datetime.combine(datetime.now().date(), time(11, 0, 0))) - remind_mapping = { - 'fifteen': timedelta(minutes=15), - 'thirty': timedelta(minutes=30), - 'one_hour': timedelta(hours=1), - 'two_hour': timedelta(hours=2), - 'one_day': timedelta(days=1), - } - def will_task_time(self): - for task in self.env['yuthon.will.task'].search([]): - time_difference = task.end_time - datetime.now() - for remind, duration in self.remind_mapping.items(): - if task.remind == remind and time_difference <= duration: - task.add_comment() + tasks = self.env['yuthon.will.task'].search([]) + for task in tasks: + for task_time in task.task_time_ids: + time_difference = task.end_time - datetime.now() + duration = self._compute_duration(task_time) + if time_difference <= duration: + task.add_comment() # 将task_time对象传递给add_comment方法 + break # 触发一个提醒后就跳出内循环 + + def _compute_duration(self, task_time): + if task_time.task_unit == 'min': + return timedelta(minutes=task_time.number) + elif task_time.task_unit == 'hour': + return timedelta(hours=task_time.number) + elif task_time.task_unit == 'day': + return timedelta(days=task_time.number) + else: + return timedelta.max def add_comment(self): self.ensure_one()