From c7b05160c9ba08b54b4ce8784c5d240d796ff035 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: Fri, 8 May 2026 12:13:31 +0800 Subject: [PATCH 01/87] =?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/yuthon_vacation_reports.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/yuthon_hr_attendance/models/yuthon_vacation_reports.py b/yuthon_hr_attendance/models/yuthon_vacation_reports.py index 7d4cb2a5f..9fffa389d 100644 --- a/yuthon_hr_attendance/models/yuthon_vacation_reports.py +++ b/yuthon_hr_attendance/models/yuthon_vacation_reports.py @@ -407,6 +407,7 @@ class YuthonVacationReports(models.Model): rec._compute_leave() rec._compute_meal_fee() + rec._compute_parental_leave() rec._compute_working_overtime() def update_vacation(self): @@ -1535,10 +1536,10 @@ class YuthonVacationReports(models.Model): if rec.remain_missed_meals: self._update_meal_lines(rec, [rec], rec.remain_missed_meals) - if rec.leave: + if rec.leave != 0: leave_hours = rec.leave * 8 self._update_leave_lines(rec, [rec], leave_hours) - if rec.working_overtime: + if rec.working_overtime != 0: overtime_hours = rec.working_overtime * 8 self._update_over_lines(rec, [rec], overtime_hours) if rec.employee_id.id not in target_employee_ids: From 43f20fd8ab4fd0040dc0cc9dc654e5107b464a04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?= Date: Fri, 8 May 2026 14:52:11 +0800 Subject: [PATCH 02/87] =?UTF-8?q?=E7=AB=AF=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mqtt/config.sample.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mqtt/config.sample.ini b/mqtt/config.sample.ini index b28cb0a6a..00f58dde7 100644 --- a/mqtt/config.sample.ini +++ b/mqtt/config.sample.ini @@ -9,7 +9,7 @@ password = gzsthtz@126.com [mqtt] # MQTT Broker connection details -host = 43.143.225.150 +host = 192.168.1.212 port = 1883 username = odoo password = odoo123 From 61ef6284fde9761128369d6bc1a5b3487798f280 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: Fri, 8 May 2026 15:06:23 +0800 Subject: [PATCH 03/87] =?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 --- .../models/yuthon_vacation_reports.py | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/yuthon_hr_attendance/models/yuthon_vacation_reports.py b/yuthon_hr_attendance/models/yuthon_vacation_reports.py index 9fffa389d..234bc56a7 100644 --- a/yuthon_hr_attendance/models/yuthon_vacation_reports.py +++ b/yuthon_hr_attendance/models/yuthon_vacation_reports.py @@ -1981,15 +1981,18 @@ class YuthonVacationReports(models.Model): ('text', '=', '上月额度继承'), ], limit=1) if existing_line: - continue - self.env['vacation.parenting.line'].sudo().create({ - 'vacation_id': report.id, - 'employee_id': report.employee_id.id, - 'update_date': update_date, - 'end_date': end_date, - 'lines': number_of_hours_display, - 'text': f"上月额度继承", - }) + existing_line.write({ + 'lines': number_of_hours_display, + }) + else: + self.env['vacation.parenting.line'].sudo().create({ + 'vacation_id': report.id, + 'employee_id': report.employee_id.id, + 'update_date': update_date, + 'end_date': end_date, + 'lines': number_of_hours_display, + 'text': f"上月额度继承", + }) def _update_meal_lines(self, report, allocations, number_of_hours_display): for alloc in allocations: From 6205758ba29be26d675abdd2d0ef2eca7a66dbc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?= Date: Fri, 8 May 2026 15:11:05 +0800 Subject: [PATCH 04/87] =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- attendance_iot/controllers/kaoqin_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/attendance_iot/controllers/kaoqin_test.py b/attendance_iot/controllers/kaoqin_test.py index 338d4ee29..7fb7a43b8 100644 --- a/attendance_iot/controllers/kaoqin_test.py +++ b/attendance_iot/controllers/kaoqin_test.py @@ -56,7 +56,7 @@ class BusController(Controller): except Exception as e: _logger.info(f'抛出异常,异常原因:{e}') return e - _logger.info(f'考勤机发送过来的数据集合{data}-------我把photo去掉因为太长可') + # _logger.info(f'考勤机发送过来的数据集合{data}-------我把photo去掉因为太长可') user_id = data.get('logs')[0].get('user_id') recog_time = data.get('logs')[0].get('recog_time') if recog_time: From 840c5ca9d4a91c86389edfe8bb7d2f4bcede15e7 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: Fri, 8 May 2026 15:24:04 +0800 Subject: [PATCH 05/87] =?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/yuthon_vacation_reports.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yuthon_hr_attendance/models/yuthon_vacation_reports.py b/yuthon_hr_attendance/models/yuthon_vacation_reports.py index 234bc56a7..1654bac7f 100644 --- a/yuthon_hr_attendance/models/yuthon_vacation_reports.py +++ b/yuthon_hr_attendance/models/yuthon_vacation_reports.py @@ -400,7 +400,7 @@ class YuthonVacationReports(models.Model): # 2. 剩余部分扣减本年补休剩余(this_year1) if remaining_overtime_deduct > 0 and rec.this_year1 > 0: - deduct_from_current1 = min(rec.this_year1, remaining_overtime_deduct) + deduct_from_current1 = remaining_overtime_deduct rec.this_year1 -= deduct_from_current1 rec.used_this_year1 += deduct_from_current1 # 累加到本年已休 remaining_overtime_deduct -= deduct_from_current1 @@ -1706,7 +1706,7 @@ class YuthonVacationReports(models.Model): if other_line.holiday_type and other_line.holiday_type.name == '调休': adjust_holiday_days += other_line.lines or 0 - record.working_overtime = max(total_add / 8, 0) + adjust_holiday_days + record.working_overtime = (total_add / 8) + adjust_holiday_days record.done_working_overtime = total_add1 / 8 record.statutory_leave = legal_total/8 record.cop_leave = total_add2 / 8 From 6fead088ce43345c9e993a08906b0925c615111e 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: Fri, 8 May 2026 15:36:24 +0800 Subject: [PATCH 06/87] =?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 --- .../models/yuthon_vacation_reports.py | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/yuthon_hr_attendance/models/yuthon_vacation_reports.py b/yuthon_hr_attendance/models/yuthon_vacation_reports.py index 1654bac7f..7e5c29d16 100644 --- a/yuthon_hr_attendance/models/yuthon_vacation_reports.py +++ b/yuthon_hr_attendance/models/yuthon_vacation_reports.py @@ -29,22 +29,22 @@ class YuthonVacationReports(models.Model): department_id = fields.Many2one(related='employee_id.department_id', string="部门", store=True) open_start_time = fields.Date(related='employee_id.open_start_time',string="参加工作时间") company_old = fields.Char(related='employee_id.company_old', string="工作年限") - previous_year = fields.Float(string="上年剩余", digits=(16, 3)) # 固定值 - dynamic_previous_year = fields.Float(string="上年年假剩余d", digits=(16, 3)) # 动态值 - dynamic_remainder_year = fields.Float(string="本年年假剩余d", digits=(16, 3)) # 动态值 + previous_year = fields.Float(string="上年剩余", digits=(16, 1)) # 固定值 + dynamic_previous_year = fields.Float(string="上年年假剩余d", digits=(16, 1)) # 动态值 + dynamic_remainder_year = fields.Float(string="本年年假剩余d", digits=(16, 1)) # 动态值 valid_date = fields.Date(string="有效期至") - year_distribution = fields.Float(string="本年发放d", digits=(16, 3)) - used_this_year = fields.Float(string="本年已用d", digits=(16, 3)) - remainder_year = fields.Float(string="剩余(年假)d", digits=(16, 3), compute="_compute_remainder_year") - last_holiday = fields.Float(string="上年公休日d", digits=(16, 3)) # 固定值 - last_workday = fields.Float(string="上年工作日d", digits=(16, 3)) # 固定值 + year_distribution = fields.Float(string="本年发放d", digits=(16, 1)) + used_this_year = fields.Float(string="本年已用d", digits=(16, 1)) + remainder_year = fields.Float(string="剩余(年假)d", digits=(16, 1), compute="_compute_remainder_year") + last_holiday = fields.Float(string="上年公休日d", digits=(16, 1)) # 固定值 + last_workday = fields.Float(string="上年工作日d", digits=(16, 1)) # 固定值 valid_date1 = fields.Date(string="有效期至") - year_holiday = fields.Float(string="本年公休日d", digits=(16, 3)) - year_workday = fields.Float(string="本年工作日d", digits=(16, 3)) - year_sum = fields.Float(string="本年调休合计d", digits=(16, 3), compute="_compute_year_sum") - previous_year1 = fields.Float(string="上年剩余(补休)d", digits=(16, 3)) # 固定值 - dynamic_previous_year1 = fields.Float(string="上年补休剩余d", digits=(16, 3)) # 动态值 - this_year1 = fields.Float(string="本年补休剩余d", digits=(16, 3)) # 动态值 + year_holiday = fields.Float(string="本年公休日d", digits=(16, 1)) + year_workday = fields.Float(string="本年工作日d", digits=(16, 1)) + year_sum = fields.Float(string="本年调休合计d", digits=(16, 1), compute="_compute_year_sum") + previous_year1 = fields.Float(string="上年剩余(补休)d", digits=(16, 1)) # 固定值 + dynamic_previous_year1 = fields.Float(string="上年补休剩余d", digits=(16, 1)) # 动态值 + this_year1 = fields.Float(string="本年补休剩余d", digits=(16, 1)) # 动态值 dynamic_previous_year1_hour = fields.Float( string="上年补休剩余h", @@ -56,7 +56,7 @@ class YuthonVacationReports(models.Model): digits=(16, 1), compute='_compute_hour_fields', ) - used_this_year1 = fields.Float(string="本年已休d", digits=(16, 3)) + used_this_year1 = fields.Float(string="本年已休d", digits=(16, 1)) company_id = fields.Many2one(related="employee_id.company_id", string="公司", store=True) late_allowed = fields.Float(related="employee_id.late_allowed", string="允许迟到次数") @@ -75,21 +75,21 @@ class YuthonVacationReports(models.Model): vacation_date = fields.Date(string='日期', default=lambda self: fields.Date.today().replace(day=1)) show_date = fields.Date(string='日期', compute='_compute_display_date', store=True) display_date = fields.Char(string='日期', compute='_compute_display_date') - done_leave = fields.Float(string='年假', compute='_compute_leave', store=True, digits=(16, 3), group_operator=None) - done_working_overtime = fields.Float(string='加班时', compute='_compute_working_overtime', digits=(16, 3), + done_leave = fields.Float(string='年假', compute='_compute_leave', store=True, digits=(16, 1), group_operator=None) + done_working_overtime = fields.Float(string='加班时', compute='_compute_working_overtime', digits=(16, 1), store=True, group_operator=None) - leave = fields.Float(string='剩余年假d', compute='_compute_leave', store=True, digits=(16, 3), group_operator=None) + leave = fields.Float(string='剩余年假d', compute='_compute_leave', store=True, digits=(16, 1), group_operator=None) working_overtime = fields.Float(string='剩余补休d', compute='_compute_working_overtime', store=True, - digits=(16, 3), group_operator=None) + digits=(16, 1), group_operator=None) remain_missed_meals = fields.Float(string="剩余误餐次数", compute='_compute_meal_fee', store=True, group_operator=None) medical_fee = fields.Float(string="体检费", compute='_compute_medical_fee', store=True, group_operator=None) duty = fields.Float(string="值班", compute='_compute_duty_fee', store=True, group_operator=None) duty_off_leave = fields.Float(string='值班调休', compute='_compute_duty_fee', store=True, group_operator=None) compensatory_leave = fields.Float(string="调休d", compute='_compute_other_leave', store=True, group_operator=None) - leave_of_absence = fields.Float(string="事假d", digits=(16, 3), compute='_compute_other_leave', store=True, + leave_of_absence = fields.Float(string="事假d", digits=(16, 1), compute='_compute_other_leave', store=True, group_operator=None) - statutory_leave = fields.Float(string="加班时(法定)d", compute='_compute_other_leave', store=True, group_operator=None, digits=(16, 3)) - cop_leave = fields.Float(string='补休d', digits=(16, 3), store=True, compute='_compute_working_overtime', + statutory_leave = fields.Float(string="加班时(法定)d", compute='_compute_other_leave', store=True, group_operator=None, digits=(16, 1)) + cop_leave = fields.Float(string='补休d', digits=(16, 1), store=True, compute='_compute_working_overtime', group_operator=None) marriage_leave = fields.Float(string='婚假d', compute='_compute_other_leave', store=True, group_operator=None) maternity_leave = fields.Float(string='产假d', compute='_compute_other_leave', store=True, group_operator=None) @@ -98,11 +98,11 @@ class YuthonVacationReports(models.Model): bereavement_leave = fields.Float(string='丧假d', compute='_compute_other_leave', store=True, group_operator=None) home_visit_leave = fields.Float(string='探亲假d', compute='_compute_other_leave', store=True, group_operator=None) parents_meeting_leave = fields.Float(string='家长会假d', compute='_compute_other_leave', store=True, group_operator=None) - general_sick_leave = fields.Float(string='病假(普通)d', digits=(16, 3), compute='_compute_other_leave', store=True, group_operator=None) - hospital_sick_leave = fields.Float(string='病假(住院期)d', digits=(16, 3), compute='_compute_other_leave', store=True, group_operator=None) - recovery_sick_leave = fields.Float(string='病假(出院恢复期)d', digits=(16, 3), compute='_compute_other_leave', store=True, group_operator=None) - parental_leave = fields.Float(string='育儿假d', digits=(16, 3), compute='_compute_parental_leave', store=True, group_operator=None) - remaining_parental_leave = fields.Float(string='剩余育儿假d', digits=(16, 3), compute='_compute_parental_leave', store=True, group_operator=None) + general_sick_leave = fields.Float(string='病假(普通)d', digits=(16, 1), compute='_compute_other_leave', store=True, group_operator=None) + hospital_sick_leave = fields.Float(string='病假(住院期)d', digits=(16, 1), compute='_compute_other_leave', store=True, group_operator=None) + recovery_sick_leave = fields.Float(string='病假(出院恢复期)d', digits=(16, 1), compute='_compute_other_leave', store=True, group_operator=None) + parental_leave = fields.Float(string='育儿假d', digits=(16, 1), compute='_compute_parental_leave', store=True, group_operator=None) + remaining_parental_leave = fields.Float(string='剩余育儿假d', digits=(16, 1), compute='_compute_parental_leave', store=True, group_operator=None) exam_leave = fields.Integer(string='考试假d', compute='_compute_other_leave', store=True, group_operator=None) right_days = fields.Float(string='转正天数', group_operator=None, compute='compute_attendance_fields') internship_days = fields.Float(string='实习天数', group_operator=None) From 3785f5a5567d8e83ed99bff03869942a0660406b 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: Fri, 8 May 2026 15:41:01 +0800 Subject: [PATCH 07/87] =?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 --- .../models/yuthon_vacation_reports.py | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/yuthon_hr_attendance/models/yuthon_vacation_reports.py b/yuthon_hr_attendance/models/yuthon_vacation_reports.py index 7e5c29d16..e73a00c40 100644 --- a/yuthon_hr_attendance/models/yuthon_vacation_reports.py +++ b/yuthon_hr_attendance/models/yuthon_vacation_reports.py @@ -29,22 +29,22 @@ class YuthonVacationReports(models.Model): department_id = fields.Many2one(related='employee_id.department_id', string="部门", store=True) open_start_time = fields.Date(related='employee_id.open_start_time',string="参加工作时间") company_old = fields.Char(related='employee_id.company_old', string="工作年限") - previous_year = fields.Float(string="上年剩余", digits=(16, 1)) # 固定值 - dynamic_previous_year = fields.Float(string="上年年假剩余d", digits=(16, 1)) # 动态值 - dynamic_remainder_year = fields.Float(string="本年年假剩余d", digits=(16, 1)) # 动态值 + previous_year = fields.Float(string="上年剩余", digits=(16, 3)) # 固定值 + dynamic_previous_year = fields.Float(string="上年年假剩余d", digits=(16, 3)) # 动态值 + dynamic_remainder_year = fields.Float(string="本年年假剩余d", digits=(16, 3)) # 动态值 valid_date = fields.Date(string="有效期至") - year_distribution = fields.Float(string="本年发放d", digits=(16, 1)) - used_this_year = fields.Float(string="本年已用d", digits=(16, 1)) - remainder_year = fields.Float(string="剩余(年假)d", digits=(16, 1), compute="_compute_remainder_year") - last_holiday = fields.Float(string="上年公休日d", digits=(16, 1)) # 固定值 - last_workday = fields.Float(string="上年工作日d", digits=(16, 1)) # 固定值 + year_distribution = fields.Float(string="本年发放d", digits=(16, 3)) + used_this_year = fields.Float(string="本年已用d", digits=(16, 3)) + remainder_year = fields.Float(string="剩余(年假)d", digits=(16, 3), compute="_compute_remainder_year") + last_holiday = fields.Float(string="上年公休日d", digits=(16, 3)) # 固定值 + last_workday = fields.Float(string="上年工作日d", digits=(16, 3)) # 固定值 valid_date1 = fields.Date(string="有效期至") - year_holiday = fields.Float(string="本年公休日d", digits=(16, 1)) - year_workday = fields.Float(string="本年工作日d", digits=(16, 1)) - year_sum = fields.Float(string="本年调休合计d", digits=(16, 1), compute="_compute_year_sum") - previous_year1 = fields.Float(string="上年剩余(补休)d", digits=(16, 1)) # 固定值 - dynamic_previous_year1 = fields.Float(string="上年补休剩余d", digits=(16, 1)) # 动态值 - this_year1 = fields.Float(string="本年补休剩余d", digits=(16, 1)) # 动态值 + year_holiday = fields.Float(string="本年公休日d", digits=(16, 3)) + year_workday = fields.Float(string="本年工作日d", digits=(16, 3)) + year_sum = fields.Float(string="本年调休合计d", digits=(16, 3), compute="_compute_year_sum") + previous_year1 = fields.Float(string="上年剩余(补休)d", digits=(16, 3)) # 固定值 + dynamic_previous_year1 = fields.Float(string="上年补休剩余d", digits=(16, 3)) # 动态值 + this_year1 = fields.Float(string="本年补休剩余d", digits=(16, 3)) # 动态值 dynamic_previous_year1_hour = fields.Float( string="上年补休剩余h", @@ -56,7 +56,7 @@ class YuthonVacationReports(models.Model): digits=(16, 1), compute='_compute_hour_fields', ) - used_this_year1 = fields.Float(string="本年已休d", digits=(16, 1)) + used_this_year1 = fields.Float(string="本年已休d", digits=(16, 3)) company_id = fields.Many2one(related="employee_id.company_id", string="公司", store=True) late_allowed = fields.Float(related="employee_id.late_allowed", string="允许迟到次数") @@ -75,21 +75,21 @@ class YuthonVacationReports(models.Model): vacation_date = fields.Date(string='日期', default=lambda self: fields.Date.today().replace(day=1)) show_date = fields.Date(string='日期', compute='_compute_display_date', store=True) display_date = fields.Char(string='日期', compute='_compute_display_date') - done_leave = fields.Float(string='年假', compute='_compute_leave', store=True, digits=(16, 1), group_operator=None) + done_leave = fields.Float(string='年假', compute='_compute_leave', store=True, digits=(16, 3), group_operator=None) done_working_overtime = fields.Float(string='加班时', compute='_compute_working_overtime', digits=(16, 1), store=True, group_operator=None) - leave = fields.Float(string='剩余年假d', compute='_compute_leave', store=True, digits=(16, 1), group_operator=None) + leave = fields.Float(string='剩余年假d', compute='_compute_leave', store=True, digits=(16, 3), group_operator=None) working_overtime = fields.Float(string='剩余补休d', compute='_compute_working_overtime', store=True, - digits=(16, 1), group_operator=None) + digits=(16, 3), group_operator=None) remain_missed_meals = fields.Float(string="剩余误餐次数", compute='_compute_meal_fee', store=True, group_operator=None) medical_fee = fields.Float(string="体检费", compute='_compute_medical_fee', store=True, group_operator=None) duty = fields.Float(string="值班", compute='_compute_duty_fee', store=True, group_operator=None) duty_off_leave = fields.Float(string='值班调休', compute='_compute_duty_fee', store=True, group_operator=None) compensatory_leave = fields.Float(string="调休d", compute='_compute_other_leave', store=True, group_operator=None) - leave_of_absence = fields.Float(string="事假d", digits=(16, 1), compute='_compute_other_leave', store=True, + leave_of_absence = fields.Float(string="事假d", digits=(16, 3), compute='_compute_other_leave', store=True, group_operator=None) - statutory_leave = fields.Float(string="加班时(法定)d", compute='_compute_other_leave', store=True, group_operator=None, digits=(16, 1)) - cop_leave = fields.Float(string='补休d', digits=(16, 1), store=True, compute='_compute_working_overtime', + statutory_leave = fields.Float(string="加班时(法定)d", compute='_compute_other_leave', store=True, group_operator=None, digits=(16, 3)) + cop_leave = fields.Float(string='补休d', digits=(16, 3), store=True, compute='_compute_working_overtime', group_operator=None) marriage_leave = fields.Float(string='婚假d', compute='_compute_other_leave', store=True, group_operator=None) maternity_leave = fields.Float(string='产假d', compute='_compute_other_leave', store=True, group_operator=None) @@ -98,11 +98,11 @@ class YuthonVacationReports(models.Model): bereavement_leave = fields.Float(string='丧假d', compute='_compute_other_leave', store=True, group_operator=None) home_visit_leave = fields.Float(string='探亲假d', compute='_compute_other_leave', store=True, group_operator=None) parents_meeting_leave = fields.Float(string='家长会假d', compute='_compute_other_leave', store=True, group_operator=None) - general_sick_leave = fields.Float(string='病假(普通)d', digits=(16, 1), compute='_compute_other_leave', store=True, group_operator=None) - hospital_sick_leave = fields.Float(string='病假(住院期)d', digits=(16, 1), compute='_compute_other_leave', store=True, group_operator=None) - recovery_sick_leave = fields.Float(string='病假(出院恢复期)d', digits=(16, 1), compute='_compute_other_leave', store=True, group_operator=None) - parental_leave = fields.Float(string='育儿假d', digits=(16, 1), compute='_compute_parental_leave', store=True, group_operator=None) - remaining_parental_leave = fields.Float(string='剩余育儿假d', digits=(16, 1), compute='_compute_parental_leave', store=True, group_operator=None) + general_sick_leave = fields.Float(string='病假(普通)d', digits=(16, 3), compute='_compute_other_leave', store=True, group_operator=None) + hospital_sick_leave = fields.Float(string='病假(住院期)d', digits=(16, 3), compute='_compute_other_leave', store=True, group_operator=None) + recovery_sick_leave = fields.Float(string='病假(出院恢复期)d', digits=(16, 3), compute='_compute_other_leave', store=True, group_operator=None) + parental_leave = fields.Float(string='育儿假d', digits=(16, 3), compute='_compute_parental_leave', store=True, group_operator=None) + remaining_parental_leave = fields.Float(string='剩余育儿假d', digits=(16, 3), compute='_compute_parental_leave', store=True, group_operator=None) exam_leave = fields.Integer(string='考试假d', compute='_compute_other_leave', store=True, group_operator=None) right_days = fields.Float(string='转正天数', group_operator=None, compute='compute_attendance_fields') internship_days = fields.Float(string='实习天数', group_operator=None) From 41957b3e94d83d6aa361eb60043598d1f26c7cbe 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: Fri, 8 May 2026 16:04:36 +0800 Subject: [PATCH 08/87] =?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/controllers/portal.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/yuthon_hr_attendance/controllers/portal.py b/yuthon_hr_attendance/controllers/portal.py index fefe39db2..10ee574ce 100644 --- a/yuthon_hr_attendance/controllers/portal.py +++ b/yuthon_hr_attendance/controllers/portal.py @@ -79,6 +79,8 @@ class CustomerPortal(portal.CustomerPortal): num = float(value or 0) * multiply if num == 0: return "0" + if unit == "小时": + return f"{round(num, 1)}{unit}" return f"{num}{unit}" data = { From 3132663c3f1cbdd465f9f9f47c1df66732ea6a0f 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: Fri, 8 May 2026 16:36:03 +0800 Subject: [PATCH 09/87] =?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 --- .../wizard/soong_workflow_comment_wizard.py | 107 +++++++++--------- 1 file changed, 55 insertions(+), 52 deletions(-) diff --git a/soong_workflow/wizard/soong_workflow_comment_wizard.py b/soong_workflow/wizard/soong_workflow_comment_wizard.py index 386b53fe7..6bf481c93 100644 --- a/soong_workflow/wizard/soong_workflow_comment_wizard.py +++ b/soong_workflow/wizard/soong_workflow_comment_wizard.py @@ -585,6 +585,60 @@ class SoongWorkflowCommentWizard(models.TransientModel): current_user = self.env.user current_datetime = fields.Datetime.now() is_admin = current_user.has_group('base.group_system') + # 归档判断 + last_log = record_id.log_ids[-1] if record_id.log_ids else None + if last_log: + same_name_logs = record_id.log_ids.filtered( + lambda log: log.name == last_log.name and log.node_btn_name == '4' and log.id != last_log.id + ) + all_approved = all(log.approval_state in ['2', '3'] for log in same_name_logs) or not same_name_logs + if all_approved: + workflow_record = self.env['soong.workflow.record'].search([('code', '=', record_id.code)], + limit=1) + has_archive_btn = any(btn_name.name == '归档' for btn_name in self.node_btn_id.node_id.button_ids) + if has_archive_btn: + log_id = record_id.log_ids.filtered(lambda l: l.name == '归档') + employee_id = self.env['hr.employee'].sudo().search( + [('user_id', '=', record_id.log_ids[0].done_by.id)], limit=1) + if workflow_record: + workflow_record.write({ + 'approve_state': 'end', + 'employee_ids': [(6, 0, [employee_id.id])], + 'soong_state': 'to_active', + 'node_id': False, + }) + if not log_id: + self.env["soong.workflow.log"].create({ + 'name': '归档', + "code": self.code, + "model": self.res_model, + "res_id": self.res_id, + "workflow_id": self.node_btn_id.workflow_id.id, + "done_by": record_id.log_ids[0].done_by.id, + "approval_state": "0", + "node_btn_id": self.node_btn_id.id, + }) + is_work_remind = True + else: + log_id.write({ + 'document_ids': [(6, 0, self.document_ids.ids)], + "approval_state": "2", + 'lase_click_date': fields.Datetime.now(), + }) + workflow_record.write({ + 'soong_state': 'active', + 'employee_ids': False, + }) + else: + if workflow_record: + workflow_record.sudo().write({ + 'approve_state': 'end', + 'employee_ids': False, + 'node_id': False, + 'soong_state': 'done', + }) + record_id.work_end = True + if is_admin: user_log = record_id.log_ids.filtered( lambda log: log.done_by == current_user and log.node_btn_name != '1' and log.approval_state == '0' @@ -679,58 +733,7 @@ class SoongWorkflowCommentWizard(models.TransientModel): title=record_id._description + "传阅/抄送", description=description, url=url, btntxt="查看详情") - # if not record_id.log_ids2.search([('approval_state', '=', '0')]) or record_id.log_ids2: - last_log = record_id.log_ids[-1] if record_id.log_ids else None - if last_log: - same_name_logs = record_id.log_ids.filtered( - lambda log: log.name == last_log.name and log.node_btn_name == '4' and log.id != last_log.id - ) - all_approved = all(log.approval_state in ['2', '3'] for log in same_name_logs) or not same_name_logs - if all_approved: - workflow_record = self.env['soong.workflow.record'].search([('code', '=', record_id.code)], - limit=1) - has_archive_btn = any(btn_name.name == '归档' for btn_name in self.node_btn_id.node_id.button_ids) - if has_archive_btn: - log_id = record_id.log_ids.filtered(lambda l: l.name == '归档') - employee_id = self.env['hr.employee'].sudo().search([('user_id', '=', record_id.log_ids[0].done_by.id)], limit=1) - if workflow_record: - workflow_record.write({ - 'approve_state': 'end', - 'employee_ids': [(6, 0, [employee_id.id])], - 'soong_state': 'to_active', - 'node_id': False, - }) - if not log_id: - self.env["soong.workflow.log"].create({ - 'name': '归档', - "code": self.code, - "model": self.res_model, - "res_id": self.res_id, - "workflow_id": self.node_btn_id.workflow_id.id, - "done_by": record_id.log_ids[0].done_by.id, - "approval_state": "0", - "node_btn_id": self.node_btn_id.id, - }) - is_work_remind = True - else: - log_id.write({ - 'document_ids': [(6, 0, self.document_ids.ids)], - "approval_state": "2", - 'lase_click_date': fields.Datetime.now(), - }) - workflow_record.write({ - 'soong_state': 'active', - 'employee_ids': False, - }) - else: - if workflow_record: - workflow_record.sudo().write({ - 'approve_state': 'end', - 'employee_ids': False, - 'node_id': False, - 'soong_state': 'done', - }) - record_id.work_end = True + # 给申请人发消息 if is_work_remind: biz_record = self.env[self.res_model].browse(self.res_id) From a95b3c733fc85a0513ba483f9bd05ed771a64e16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?= Date: Fri, 8 May 2026 17:11:54 +0800 Subject: [PATCH 10/87] =?UTF-8?q?=E8=80=83=E5=8B=A4=E6=9C=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- attendance_iot/__manifest__.py | 1 + attendance_iot/models/__init__.py | 1 + attendance_iot/models/attendance_iot.py | 15 +++++++ attendance_iot/models/attendance_iot_log.py | 10 +++++ attendance_iot/security/ir.model.access.csv | 3 +- .../views/attendance_iot_log_views.xml | 39 +++++++++++++++++++ attendance_iot/views/attendance_iot_views.xml | 2 + yuthon_work_brand/views/hr_menus.xml | 6 +++ 8 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 attendance_iot/models/attendance_iot_log.py create mode 100644 attendance_iot/views/attendance_iot_log_views.xml diff --git a/attendance_iot/__manifest__.py b/attendance_iot/__manifest__.py index dad4d55fd..217ab66fe 100644 --- a/attendance_iot/__manifest__.py +++ b/attendance_iot/__manifest__.py @@ -18,6 +18,7 @@ 'views/attendance_iot_user_views.xml', 'views/attendance_iot_manager_views.xml', 'views/attendance_iot_views.xml', + 'views/attendance_iot_log_views.xml', # 'views/inherit_hr_employee_views.xml', 'wizard/attendance_iot_manager_wizard_views.xml', 'views/iot_message.xml' diff --git a/attendance_iot/models/__init__.py b/attendance_iot/models/__init__.py index d8f3cb71c..4b7e9166a 100644 --- a/attendance_iot/models/__init__.py +++ b/attendance_iot/models/__init__.py @@ -4,3 +4,4 @@ from . import attendance_iot from . import attendance_iot_datas from . import attendance_iot_manager from . import iot_message +from . import attendance_iot_log diff --git a/attendance_iot/models/attendance_iot.py b/attendance_iot/models/attendance_iot.py index a5b2c4a74..2c5e00c35 100644 --- a/attendance_iot/models/attendance_iot.py +++ b/attendance_iot/models/attendance_iot.py @@ -20,6 +20,7 @@ class AttendanceIot(models.Model): company_id = fields.Many2one('res.company', string="公司") remake = fields.Text(string='备注') employee_ids = fields.Many2many('hr.employee', string="员工") + is_connected = fields.Boolean(string="连接状态", default=False) def action_init_device(self): ''' @@ -102,3 +103,17 @@ class AttendanceIot(models.Model): 'value': 'off' }, ensure_ascii=False) }]) + + def action_view_logs(self): + """查看该设备的日志""" + self.ensure_one() + return { + 'name': '考勤机日志', + 'type': 'ir.actions.act_window', + 'res_model': 'attendance.iot.log', + 'view_mode': 'tree,form', + 'domain': [('attendance_iot_id', '=', self.id)], + 'context': {'default_attendance_iot_id': self.id}, + } + + diff --git a/attendance_iot/models/attendance_iot_log.py b/attendance_iot/models/attendance_iot_log.py new file mode 100644 index 000000000..88ac63640 --- /dev/null +++ b/attendance_iot/models/attendance_iot_log.py @@ -0,0 +1,10 @@ +from odoo import api, fields, models + + +class AttendanceIotLog(models.Model): + _name = 'attendance.iot.log' + _description = '考勤机日志' + _order = 'create_date desc' + + attendance_iot_id = fields.Many2one('attendance.iot', string="考勤机设备", required=True, ondelete='cascade') + content = fields.Text(string="内容") diff --git a/attendance_iot/security/ir.model.access.csv b/attendance_iot/security/ir.model.access.csv index 1bf0c0b7d..d7ad21eda 100644 --- a/attendance_iot/security/ir.model.access.csv +++ b/attendance_iot/security/ir.model.access.csv @@ -5,4 +5,5 @@ access_attendance_iot_manager_wizard,attendance.iot.manager.wizard,model_attenda access_attendance_iot_datas,attendance.iot.datas,model_attendance_iot_datas,base.group_user,1,1,1,1 access_attendance_iot_user,attendance.iot.user,model_attendance_iot_user,base.group_user,1,1,1,1 access_iot_message,iot.message.user,model_iot_message,base.group_user,1,1,1,1 -access_attendance_iot_import_user_wizard,access.attendance.iot.import.user.wizard,model_attendance_iot_import_user_wizard,base.group_user,1,1,1,1 \ No newline at end of file +access_attendance_iot_import_user_wizard,access.attendance.iot.import.user.wizard,model_attendance_iot_import_user_wizard,base.group_user,1,1,1,1 +access_attendance_iot_log,attendance.iot.log,model_attendance_iot_log,base.group_user,1,1,1,1 \ No newline at end of file diff --git a/attendance_iot/views/attendance_iot_log_views.xml b/attendance_iot/views/attendance_iot_log_views.xml new file mode 100644 index 000000000..4304efb73 --- /dev/null +++ b/attendance_iot/views/attendance_iot_log_views.xml @@ -0,0 +1,39 @@ + + + + + attendance.iot.log.tree + attendance.iot.log + + + + + + + + + + + + attendance.iot.log.form + attendance.iot.log + +
+ + + + + + + +
+
+
+ + + + 考勤机日志 + attendance.iot.log + tree,form + +
diff --git a/attendance_iot/views/attendance_iot_views.xml b/attendance_iot/views/attendance_iot_views.xml index 3d1ee80c1..e844132a6 100644 --- a/attendance_iot/views/attendance_iot_views.xml +++ b/attendance_iot/views/attendance_iot_views.xml @@ -16,7 +16,9 @@ + + + + + + + +
+
+
+
+ 统计时间: + +
+
+ 统计片区: + +
+
+ 所属公司: + +
+
+ 创建时间: + +
+
+
+
+ + +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+ + +
+
+ +

加载中...

+
+
+ + +
+
+ +

请点击查询按钮获取报表数据

+
+
+ + + \ No newline at end of file From 03d6290a16e461bf962d1e45e45aed424a17ab0f Mon Sep 17 00:00:00 2001 From: pengyuthon Date: Thu, 14 May 2026 08:58:39 +0800 Subject: [PATCH 87/87] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=B7=A5=E4=BD=9C?= =?UTF-8?q?=E6=B5=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- soong_workflow/models/soong_workflow_mixin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soong_workflow/models/soong_workflow_mixin.py b/soong_workflow/models/soong_workflow_mixin.py index 33812f8ba..c47faab69 100644 --- a/soong_workflow/models/soong_workflow_mixin.py +++ b/soong_workflow/models/soong_workflow_mixin.py @@ -1460,7 +1460,7 @@ class SoongWorkflowMixin(models.AbstractModel): arr = [] ext_ids = group._get_external_ids() for ext_id in ext_ids: - arr.append(ext_ids[ext_id][0]) + arr.append(ext_ids[ext_id]) return arr if view_type == "form":