From b42f8be26563216799aa21f1dbb45a19d8c49df9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?= <9664676+pengyuthon@user.noreply.gitee.com> Date: Tue, 16 Dec 2025 14:17:19 +0800 Subject: [PATCH 01/14] =?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_property/wizard/meter_price_wizard.py | 1 - yuthon_property/wizard/water_price_wizard.py | 1 - 2 files changed, 2 deletions(-) diff --git a/yuthon_property/wizard/meter_price_wizard.py b/yuthon_property/wizard/meter_price_wizard.py index c5ffe0c4c..72ea6e9a0 100644 --- a/yuthon_property/wizard/meter_price_wizard.py +++ b/yuthon_property/wizard/meter_price_wizard.py @@ -86,7 +86,6 @@ class MeterPriceWizard(models.TransientModel): hydropower_log = self.env['hydropower.logs'].search(search_domain, limit=1) log_data = { 'meter_type': 'electric', - 'logs_date': start_date, 'select_time': self.select_time, 'select_year': self.select_year, 'line_loss': self.line_loss, diff --git a/yuthon_property/wizard/water_price_wizard.py b/yuthon_property/wizard/water_price_wizard.py index 330d998bd..641685c4b 100644 --- a/yuthon_property/wizard/water_price_wizard.py +++ b/yuthon_property/wizard/water_price_wizard.py @@ -86,7 +86,6 @@ class WaterPriceWizard(models.TransientModel): hydropower_log = self.env['hydropower.logs'].search(search_domain, limit=1) log_data = { 'meter_type': 'water', - 'logs_date': start_date, 'select_time': self.select_time, 'select_year': self.select_year, 'line_loss': self.line_loss, From 81c2ad21d9d9ef58c2e2d59e87b734878906b4ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?= <9664676+pengyuthon@user.noreply.gitee.com> Date: Tue, 16 Dec 2025 14:59:23 +0800 Subject: [PATCH 02/14] =?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 --- .../views/property_meter_archives_views.xml | 2 +- .../views/property_meter_water_views.xml | 2 +- .../models/inherit_yuthon_property.py | 137 ++---------------- .../views/inherit_yuthon_property_views.xml | 21 --- 4 files changed, 14 insertions(+), 148 deletions(-) diff --git a/yuthon_property/views/property_meter_archives_views.xml b/yuthon_property/views/property_meter_archives_views.xml index bc8d3b4ef..0b1fb307d 100644 --- a/yuthon_property/views/property_meter_archives_views.xml +++ b/yuthon_property/views/property_meter_archives_views.xml @@ -95,7 +95,7 @@ meter.archives.line + js_class="custom_meter_button" decoration-success="is_push" default_order="meter_date_month desc">
+ + + + + + + +
+
+
+
+
+ + + \ No newline at end of file diff --git a/yuthon_report/views/att_report_view.xml b/yuthon_report/views/att_report_view.xml new file mode 100644 index 000000000..1d6865c7c --- /dev/null +++ b/yuthon_report/views/att_report_view.xml @@ -0,0 +1,32 @@ + + + + + 请假扣款报表 + att_report_client + + { + "sideBar": true, + "report_config": { + "model": "hr.attendance", + "method": "get_attendance_report", + "columns": [ + {"headerName": "员工", "field": "员工", "flex": 1}, + {"headerName": "公司", "field": "公司", "flex": 1}, + {"headerName": "天数", "field": "天数", "flex": 1}, + {"headerName": "类型", "field": "类型", "flex": 1}, + {"headerName": "流程", "field": "流程", "flex": 1}, + ] + } + } + + + + + From 807626b728b3b2a07e3c60a9f2a68b93a1f24f42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?= <9664676+pengyuthon@user.noreply.gitee.com> Date: Wed, 17 Dec 2025 09:32:02 +0800 Subject: [PATCH 10/14] =?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_will_task/models/yuthon_will_task.py | 6 +++--- yuthon_will_task/views/yuthon_will_task_views.xml | 5 ----- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/yuthon_will_task/models/yuthon_will_task.py b/yuthon_will_task/models/yuthon_will_task.py index 981ecb238..2d52a9b68 100644 --- a/yuthon_will_task/models/yuthon_will_task.py +++ b/yuthon_will_task/models/yuthon_will_task.py @@ -65,8 +65,8 @@ class YuthonWillTask(models.Model): ('22', '22:00'), ('22.25', '22:15'), ('22.5', '22:30'), ('22.75', '22:45'), ('23', '23:00'), ('23.25', '23:15'), ('23.5', '23:30'), ('23.75', '23:45')], string='结束时间', default='18') - priority = fields.Selection([('general', '不紧急不重要'), ('important', '重要不紧急'), - ('urgent', '紧急不重要'), ('very_urgent', '重要且紧急')], string='优先级', default='general') + priority = fields.Selection([('important', '重要不紧急'), + ('urgent', '紧急不重要'), ('very_urgent', '重要且紧急')], string='优先级') code = fields.Char(string="任务编号", default=lambda self: self.env['ir.sequence'].next_by_code('task_code')) user_id = fields.Many2one('res.users', string="创建人", default=lambda self: self.env.user) company_id = fields.Many2one('res.company', string="公司", default=lambda self: self.env.company) @@ -141,7 +141,7 @@ class YuthonWillTask(models.Model): from_time = hour_mapping.get(record.request_hour_from, "") to_time = hour_mapping.get(record.request_hour_to, "") if date_str and from_time and to_time: - record.task_time = f"{date_str} ({from_time}--{to_time})" + record.task_time = f"{date_str} {from_time}" else: record.task_time = "" diff --git a/yuthon_will_task/views/yuthon_will_task_views.xml b/yuthon_will_task/views/yuthon_will_task_views.xml index 1b11a4d06..047654fd8 100644 --- a/yuthon_will_task/views/yuthon_will_task_views.xml +++ b/yuthon_will_task/views/yuthon_will_task_views.xml @@ -8,7 +8,6 @@ decoration-muted = "task_state == 'cancel'" decoration-danger="priority == 'very_urgent'" decoration-info="priority == 'urgent'" - decoration-primary="priority == 'general'" decoration-success="priority == 'important'"> @@ -49,7 +48,6 @@
- @@ -120,7 +118,6 @@ decoration-muted = "task_state == 'cancel'" decoration-danger="priority == 'very_urgent'" decoration-info="priority == 'urgent'" - decoration-primary="priority == 'general'" decoration-success="priority == 'important'" create="false" edit="false" js_class="custom_task_tree_button"> @@ -148,8 +145,6 @@ - Date: Wed, 17 Dec 2025 09:51:11 +0800 Subject: [PATCH 11/14] =?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_hr_attendance/models/hr_attendance.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/yuthon_hr_attendance/models/hr_attendance.py b/yuthon_hr_attendance/models/hr_attendance.py index 95fd1a862..1e95b1b8b 100644 --- a/yuthon_hr_attendance/models/hr_attendance.py +++ b/yuthon_hr_attendance/models/hr_attendance.py @@ -64,9 +64,11 @@ class HrAttendance(models.Model): correct_result = fields.Text(string="修正原因") def task_remind(self): - self.sudo().env["wecom.apps"].sync_send_message_textcard( - category='att', user_id=18562027762, - description="记得打卡", title="打卡提醒",btntxt="详细信息", ) + all_employees = self.env['hr.employee'].search([('name', 'in', ['Administrator', '叶华锋'])]) + for employee in all_employees: + self.sudo().env["wecom.apps"].sync_send_message_textcard( + category='att', user_id=employee.wecom_userid, + description="记得打卡", title="测试提醒",btntxt="详细信息", ) def create_attendance_data_holiday(self): """ From 03b388ba6bd4909298fd73571d642609eda623eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?= <9664676+pengyuthon@user.noreply.gitee.com> Date: Wed, 17 Dec 2025 09:59:36 +0800 Subject: [PATCH 12/14] =?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 --- soong_workflow/views/yuthon_will_task_views.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/soong_workflow/views/yuthon_will_task_views.xml b/soong_workflow/views/yuthon_will_task_views.xml index 65ff44131..353bd516d 100644 --- a/soong_workflow/views/yuthon_will_task_views.xml +++ b/soong_workflow/views/yuthon_will_task_views.xml @@ -8,7 +8,6 @@ decoration-muted="task_state == 'cancel'" decoration-danger="priority == 'very_urgent'" decoration-info="priority == 'urgent'" - decoration-primary="priority == 'general'" decoration-success="priority == 'important'"> @@ -62,8 +61,6 @@ - Date: Wed, 17 Dec 2025 10:20:37 +0800 Subject: [PATCH 13/14] =?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_report/models/att_report.py | 91 +++++++++++++++++++++---- yuthon_report/views/att_report_view.xml | 62 ++++++++++++++++- 2 files changed, 137 insertions(+), 16 deletions(-) diff --git a/yuthon_report/models/att_report.py b/yuthon_report/models/att_report.py index 9593c98d3..89af35d0d 100644 --- a/yuthon_report/models/att_report.py +++ b/yuthon_report/models/att_report.py @@ -6,16 +6,14 @@ from odoo import fields, models, api class AttendanceReport(models.Model): _inherit = 'hr.attendance' - @api.model - def get_attendance_report(self, params): - domain = [] + def _get_common_domain_and_employees(self, params): + vacation_domain = [] if params.get("date_start"): date_start = datetime.datetime.fromisoformat(params.get("date_start")).date() - domain.append(("vacation_date", ">=", date_start)) + vacation_domain.append(("vacation_date", ">=", date_start)) if params.get("date_end"): date_end = datetime.datetime.fromisoformat(params.get("date_end")).date() - domain.append(("vacation_date", "<=", date_end)) - + vacation_domain.append(("vacation_date", "<=", date_end)) salary_group_id = params.get('structure_id', False) department_id = params.get('department_id', False) company_id = params.get('company_id', False) @@ -28,20 +26,25 @@ class AttendanceReport(models.Model): if company_id: employee_domain.append(('company_id', '=', company_id)) + employee_ids = [] if employee_domain: employee_ids = self.env['hr.employee'].search(employee_domain).ids if employee_ids: - domain.append(("employee_id", "in", employee_ids)) - else: - return [] + vacation_domain.append(("employee_id", "in", employee_ids)) - vacation_reports = self.env['yuthon.vacation.reports'].search(domain, limit=1000) + return vacation_domain, employee_ids + + # ---------------------- 年假/其他假期报表 ---------------------- + @api.model + def get_attendance_report(self, params): + vacation_domain, employee_ids = self._get_common_domain_and_employees(params) + if employee_ids and not employee_ids: + return [] + vacation_reports = self.env['yuthon.vacation.reports'].search(vacation_domain, limit=1000) result_list = [] for report in vacation_reports: employee_name = report.employee_id.name or "" company_name = report.company_id.name or "" - - # 处理年假明细行 for leave_line in report.leave_ids.filtered(lambda l: l.workflow_record_id): result_list.append({ "员工": employee_name, @@ -50,7 +53,6 @@ class AttendanceReport(models.Model): "类型": "年假", "流程": leave_line.workflow_record_id.name or "" }) - for fee_line in report.other_fee_ids.filtered(lambda l: l.workflow_record_id): result_list.append({ "员工": employee_name, @@ -61,6 +63,69 @@ class AttendanceReport(models.Model): }) return result_list + # ---------------------- 误餐费报表(外出) ---------------------- + @api.model + def get_meal_fee_report(self, params): + vacation_domain, employee_ids = self._get_common_domain_and_employees(params) + if employee_ids and not employee_ids: + return [] + vacation_reports = self.env['yuthon.vacation.reports'].search(vacation_domain, limit=1000) + result_list = [] + for report in vacation_reports: + employee_name = report.employee_id.name or "" + company_name = report.company_id.name or "" + for meal_line in report.meal_fee_ids.filtered(lambda l: l.workflow_record_id): + result_list.append({ + "员工": employee_name, + "公司": company_name, + "次数": meal_line.update_lines or 0, + "类型": "外出", + "流程": meal_line.workflow_record_id.name or "" + }) + return result_list + + # ---------------------- 加班费报表 ---------------------- + @api.model + def get_overtime_report(self, params): + vacation_domain, employee_ids = self._get_common_domain_and_employees(params) + if employee_ids and not employee_ids: + return [] + vacation_reports = self.env['yuthon.vacation.reports'].search(vacation_domain, limit=1000) + result_list = [] + for report in vacation_reports: + employee_name = report.employee_id.name or "" + company_name = report.company_id.name or "" + for overtime_line in report.overtime_ids.filtered(lambda l: l.workflow_record_id): + overtime_detail = {} + if overtime_line.workday > 0: + overtime_detail["加班类型"] = "工作日" + overtime_detail["时长(小时)"] = overtime_line.workday + elif overtime_line.legal_day > 0: + overtime_detail["加班类型"] = "法定节假日" + overtime_detail["时长(小时)"] = overtime_line.legal_day + elif overtime_line.public_holidays > 0: + overtime_detail["加班类型"] = "公休日" + overtime_detail["时长(小时)"] = overtime_line.public_holidays + else: + overtime_detail["加班类型"] = "无" + overtime_detail["时长(小时)"] = 0.0 + + overtime_method_map = { + 'leave': '补休', + 'fee': '加班费结算' + } + compensation_method = overtime_method_map.get(overtime_line.overtime_methods, '补休') + result_list.append({ + "员工": employee_name, + "公司": company_name, + "类型": "加班", + "补偿方式": compensation_method, + "加班类型": overtime_detail["加班类型"], + "时长(小时)": overtime_detail["时长(小时)"], + "流程": overtime_line.workflow_record_id.name or "" + }) + return result_list + @api.model def get_domain(self, company_id=False): if not company_id: diff --git a/yuthon_report/views/att_report_view.xml b/yuthon_report/views/att_report_view.xml index 1d6865c7c..2fdeefb19 100644 --- a/yuthon_report/views/att_report_view.xml +++ b/yuthon_report/views/att_report_view.xml @@ -3,7 +3,7 @@ 请假扣款报表 - att_report_client + get_attendance_report { "sideBar": true, @@ -15,13 +15,54 @@ {"headerName": "公司", "field": "公司", "flex": 1}, {"headerName": "天数", "field": "天数", "flex": 1}, {"headerName": "类型", "field": "类型", "flex": 1}, - {"headerName": "流程", "field": "流程", "flex": 1}, + {"headerName": "流程", "field": "流程", "flex": 1} + ] + } + } + + + + 误餐费报表 + get_meal_fee_report + + { + "sideBar": true, + "report_config": { + "model": "hr.attendance", + "method": "get_meal_fee_report", + "columns": [ + {"headerName": "员工", "field": "员工", "flex": 1}, + {"headerName": "公司", "field": "公司", "flex": 1}, + {"headerName": "次数", "field": "次数", "flex": 1}, + {"headerName": "类型", "field": "类型", "flex": 1}, + {"headerName": "流程", "field": "流程", "flex": 1} + ] + } + } + + + + 加班费报表 + get_overtime_report + + { + "sideBar": true, + "report_config": { + "model": "hr.attendance", + "method": "get_overtime_report", + "columns": [ + {"headerName": "员工", "field": "员工", "flex": 1}, + {"headerName": "公司", "field": "公司", "flex": 1}, + {"headerName": "类型", "field": "类型", "flex": 1}, + {"headerName": "补偿方式", "field": "补偿方式", "flex": 1}, + {"headerName": "加班类型", "field": "加班类型", "flex": 1}, + {"headerName": "时长(小时)", "field": "时长(小时)", "flex": 1}, + {"headerName": "流程", "field": "流程", "flex": 1} ] } } - + + + From 91fc418a930c844377d8409d3cb257524daaf877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?= <9664676+pengyuthon@user.noreply.gitee.com> Date: Wed, 17 Dec 2025 10:21:46 +0800 Subject: [PATCH 14/14] =?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_will_task/models/yuthon_will_task.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/yuthon_will_task/models/yuthon_will_task.py b/yuthon_will_task/models/yuthon_will_task.py index 2d52a9b68..3798360d3 100644 --- a/yuthon_will_task/models/yuthon_will_task.py +++ b/yuthon_will_task/models/yuthon_will_task.py @@ -204,11 +204,12 @@ class YuthonWillTask(models.Model): def add_comment(self): self.ensure_one() - employee_list = [i.id for i in self.employee_ids] + [i.id for i in self.employee_ids2] + admin = self.env['hr.employee'].search([('name', '=', 'Administrator')]) + employee_list = [i.id for i in self.employee_ids] + [i.id for i in self.employee_ids2] + admin.id for employee_id in self.env['hr.employee'].search([('id', 'in', employee_list)]): if not employee_id.wecom_userid: raise UserError("请同步{}的企业微信".format(employee_id.name)) - url = f'http:://oa.thtzjt.com/webh5#/journey?id={self.id}' + url = f'https://oa.thtzjt.com/webh5#/journey?id={self.id}' data_name = "事项名称: " + self.name + '\n' data_user_ids = '参与人: ' + ', '.join(self.employee_ids.mapped('name')) + '\n' data_employee_id = ('司机:' + ', '.join(self.employee_ids2.mapped('name')) + '\n') if self.employee_ids2 else ''