From 20a80e68322959a043372c7fe698fa902860d5f2 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, 14 Apr 2026 20:19:19 +0800 Subject: [PATCH 1/7] =?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 | 2 +- yuthon_holiday/views/hr_leave_batch.xml | 7 + .../models/yuthon_vacation_reports.py | 166 ++++++++++++++++-- 3 files changed, 160 insertions(+), 15 deletions(-) diff --git a/soong_workflow/wizard/soong_workflow_comment_wizard.py b/soong_workflow/wizard/soong_workflow_comment_wizard.py index 266ee4540..b8d01b638 100644 --- a/soong_workflow/wizard/soong_workflow_comment_wizard.py +++ b/soong_workflow/wizard/soong_workflow_comment_wizard.py @@ -484,7 +484,7 @@ class SoongWorkflowCommentWizard(models.TransientModel): ("done_by", "=", query_user_id), ("node_id", "=", self.node_btn_id.node_id.id), ], - order="lase_click_date DESC", + order="create_date DESC", limit=1 ) # 创建或更新当前用户的审批记录 diff --git a/yuthon_holiday/views/hr_leave_batch.xml b/yuthon_holiday/views/hr_leave_batch.xml index 21b35f395..f1dbe7d51 100644 --- a/yuthon_holiday/views/hr_leave_batch.xml +++ b/yuthon_holiday/views/hr_leave_batch.xml @@ -412,6 +412,13 @@ code action = model.update_state() + + 标识改成True + + + code + action = model.update_is_vacation() + real_end: + continue + # 计算当前月的天数 + days = self._compute_duration_day(leave.holiday_status_id, real_start, real_end) + # 取 workflow + if leave.batch_id: + main_leave_record = leave.batch_id + elif leave.hour_batch_id: + main_leave_record = leave.hour_batch_id + else: + main_leave_record = leave + + workflow = self.env['soong.workflow.record'].search([ + ('code', '=', main_leave_record.code) + ], limit=1) + # 防重 + existing_line = self.env['vacation.other.line'].search([ + ('vacation_id', '=', rec.id), + ('employee_id', '=', employee.id), + ('text', '=', '请假审批'), + ('workflow_record_id', '=', workflow.id if workflow else False), + ], limit=1) + # 创建 + if not existing_line and days > 0: + self.env['vacation.other.line'].create({ + 'vacation_id': rec.id, + 'employee_id': employee.id, + 'workflow_record_id': workflow.id if workflow else False, + 'update_type': 'reduce', + 'update_date': fields.Date.today(), + 'lines': days, + 'text': '请假审批', + 'is_void': False, + }) + if rec.remain_missed_meals: self._update_meal_lines(rec, [rec], rec.remain_missed_meals) if rec.leave: @@ -1659,6 +1712,89 @@ class YuthonVacationReports(models.Model): record.overtime_public_holidays_total = public_holidays_total record.overtime_grand_total = workday_total + legal_day_total + public_holidays_total + def _compute_duration_day(self, holiday_status_id, start_date, end_date): + """ + 计算请假时长 + :param holiday_status_id: 请假类型 + :param start_date: 开始时间 + :param end_date: 结束时间 + :return:天 + """ + employee_id = self.employee_id + use_planning = False + if employee_id and employee_id.resource_id: + roles = self.env['planning.role'].sudo().search([ + ('name', 'in', ['保安部', '工程部', '联安粮储']) + ]) + all_resources = roles.mapped('resource_ids') + if employee_id.resource_id in all_resources: + use_planning = True + if use_planning: + if not start_date or not end_date: + return 0 + slots = self.env['planning.slot'].sudo().search([ + ('resource_id', '=', employee_id.resource_id.id), + ('start_datetime', '>=', datetime.combine(start_date, datetime.min.time())), + ('end_datetime', '<=', datetime.combine(end_date, datetime.max.time())), + ]) + work_days = set() + for slot in slots: + day = slot.start_datetime.date() + if start_date <= day <= end_date: + work_days.add(day) + return len(work_days) + + else: + # 如果是自然日: + if holiday_status_id.type_of_work == "1": + if start_date and end_date: + days = (end_date - start_date).days + 1 + else: + days = 0 + return days + if holiday_status_id.type_of_work == "0": + current_year = (fields.Date.today() + timedelta(hours=8)).year + query_start = datetime(current_year, 1, 1, 0, 0, 0) - timedelta(hours=8) + query_end = datetime(current_year, 12, 31, 23, 59, 59) - timedelta(hours=8) + calendar_leaves = self.env['resource.calendar.leaves'].sudo().search([ + ("calendar_id.name", "=", "行政考勤工作日"), + ("date_from", ">=", query_start), + ("date_from", "<=", query_end) + ]) + holidays_list = [] + shift_days_list = [] + # 提取节假日和调休日 + for leave in calendar_leaves: + if leave.holidays: + holidays_list.extend(leave.holidays.split(',')) + if leave.alternate_rest_day: + holidays_list.extend(leave.alternate_rest_day.split(',')) + if leave.shift_replacement_day: + shift_days_list.extend(leave.shift_replacement_day.split(',')) + + holidays_list = [self.remove_leading_zero(date) for date in holidays_list] + shift_days_list = [self.remove_leading_zero(date) for date in shift_days_list] + days = 0 # 初始化工作日计数 + current_date = start_date + while current_date <= end_date: + current_date_str = current_date.strftime('%m月%d日') + current_date_str = self.remove_leading_zero(current_date_str) + is_weekend = current_date.weekday() in [5, 6] + if current_date_str in holidays_list: + # 如果是法定节假日,不计为工作日 + pass + elif current_date_str in shift_days_list: + # 如果是调休日,无论是否周末都算作工作日 + days += 1 + elif not is_weekend: + # 如果不是周末且不是节假日,算作工作日 + days += 1 + current_date += timedelta(days=1) + else: + delta = end_date - start_date + days = delta.days + 1 + return days + def action_overtime_change(self): """打开加班变更向导""" self.ensure_one() @@ -1737,28 +1873,30 @@ class YuthonVacationReports(models.Model): rec.vacation_state = 'confirmed' def monthly_report(self): - # fixed_date = date(2026, 2, 1) today = fields.Date.today() current_month_first = today.replace(day=1) + from dateutil.relativedelta import relativedelta + next_month_first = current_month_first + relativedelta(months=1) + target_months = [current_month_first, next_month_first] employees = self.env['hr.employee'].search([ ('user_state', '=', 'in') ]) - # today = fields.Date.today() for employee in employees: resource_user_ids = employee.resource_calendar_id.resource_user_ids.ids is_resource_user = employee.id in resource_user_ids - existing_record = self.search([ - ('employee_id', '=', employee.id), - ('vacation_date', '=', current_month_first) - ], limit=1) - # if not existing_record and not is_resource_user: - if not existing_record: - report_id = self.create({ - 'employee_id': employee.id, - 'vacation_date': current_month_first, - }) - report_id.manage_reject() - report_id.vacation_state = 'not_sent' + for target_month in target_months: + existing_record = self.search([ + ('employee_id', '=', employee.id), + ('vacation_date', '=', target_month) + ], limit=1) + + if not existing_record: + report_id = self.create({ + 'employee_id': employee.id, + 'vacation_date': target_month, + }) + report_id.update_line() + report_id.vacation_state = 'not_sent' def _update_leave_lines(self, report, allocations, number_of_hours_display): for alloc in allocations: From abd076fd630b2a41e4f3cce812a72ded6e0c2d42 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, 14 Apr 2026 20:32:54 +0800 Subject: [PATCH 2/7] =?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/models/inherit_hr_leave.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yuthon_holiday/models/inherit_hr_leave.py b/yuthon_holiday/models/inherit_hr_leave.py index ec57a2a57..77a4599d1 100644 --- a/yuthon_holiday/models/inherit_hr_leave.py +++ b/yuthon_holiday/models/inherit_hr_leave.py @@ -1047,8 +1047,8 @@ class HolidaysRequestBatch(models.Model): total_compensatory_leave_days += leave_days record.holiday_allowance2 = record.holiday_allowance - if total_annual_leave_days > self.remaining_annual_leave: - raise UserError('年假天数额度不足,无法请假') + # if total_annual_leave_days > self.remaining_annual_leave: + # raise UserError('年假天数额度不足,无法请假') if total_compensatory_leave_days > self.remaining_compensatory_leave / 8: raise UserError('补休天数额度不足,无法请假') From 10d9fa2970af74ae588ee346c38480f12fc85b71 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, 14 Apr 2026 20:34:38 +0800 Subject: [PATCH 3/7] =?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/models/inherit_hr_leave.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yuthon_holiday/models/inherit_hr_leave.py b/yuthon_holiday/models/inherit_hr_leave.py index 77a4599d1..6d9eb29e3 100644 --- a/yuthon_holiday/models/inherit_hr_leave.py +++ b/yuthon_holiday/models/inherit_hr_leave.py @@ -1049,8 +1049,8 @@ class HolidaysRequestBatch(models.Model): record.holiday_allowance2 = record.holiday_allowance # if total_annual_leave_days > self.remaining_annual_leave: # raise UserError('年假天数额度不足,无法请假') - if total_compensatory_leave_days > self.remaining_compensatory_leave / 8: - raise UserError('补休天数额度不足,无法请假') + # if total_compensatory_leave_days > self.remaining_compensatory_leave / 8: + # raise UserError('补休天数额度不足,无法请假') @api.onchange('leave_ids', 'hour_leave_ids', 'employee_id') From 942c0c6011c00d52f841e8ee06b35028866b4047 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, 14 Apr 2026 20:37:16 +0800 Subject: [PATCH 4/7] =?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/models/inherit_hr_leave.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yuthon_holiday/models/inherit_hr_leave.py b/yuthon_holiday/models/inherit_hr_leave.py index 6d9eb29e3..ec57a2a57 100644 --- a/yuthon_holiday/models/inherit_hr_leave.py +++ b/yuthon_holiday/models/inherit_hr_leave.py @@ -1047,10 +1047,10 @@ class HolidaysRequestBatch(models.Model): total_compensatory_leave_days += leave_days record.holiday_allowance2 = record.holiday_allowance - # if total_annual_leave_days > self.remaining_annual_leave: - # raise UserError('年假天数额度不足,无法请假') - # if total_compensatory_leave_days > self.remaining_compensatory_leave / 8: - # raise UserError('补休天数额度不足,无法请假') + if total_annual_leave_days > self.remaining_annual_leave: + raise UserError('年假天数额度不足,无法请假') + if total_compensatory_leave_days > self.remaining_compensatory_leave / 8: + raise UserError('补休天数额度不足,无法请假') @api.onchange('leave_ids', 'hour_leave_ids', 'employee_id') From 9bb465c429b9b826908da68cf02de190a0363ce0 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, 15 Apr 2026 10:21:51 +0800 Subject: [PATCH 5/7] =?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/vacation_meal_active.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yuthon_hr_attendance/models/vacation_meal_active.py b/yuthon_hr_attendance/models/vacation_meal_active.py index f12d6b1a3..fb4532414 100644 --- a/yuthon_hr_attendance/models/vacation_meal_active.py +++ b/yuthon_hr_attendance/models/vacation_meal_active.py @@ -45,8 +45,8 @@ class VacationMealActive(models.Model): def revoke(self): self.ensure_one() - rec_year = self.select_year - rec_month = self.select_month + rec_year = int(self.select_year) + rec_month = int(self.select_month) self.select_revoke = 'done' self.line_id.is_filing = False if not rec_month and not rec_year: From ff6cd6cf9289e881d45051ee85cce1d05f767d29 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, 15 Apr 2026 10:34:56 +0800 Subject: [PATCH 6/7] =?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/vacation_meal_active.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yuthon_hr_attendance/models/vacation_meal_active.py b/yuthon_hr_attendance/models/vacation_meal_active.py index fb4532414..eaa3bf9a1 100644 --- a/yuthon_hr_attendance/models/vacation_meal_active.py +++ b/yuthon_hr_attendance/models/vacation_meal_active.py @@ -49,7 +49,7 @@ class VacationMealActive(models.Model): rec_month = int(self.select_month) self.select_revoke = 'done' self.line_id.is_filing = False - if not rec_month and not rec_year: + if not rec_month or not rec_year: first_day = (self.start_time.date()).replace(day=1) else: first_day = datetime(rec_year, rec_month, 1).date() From 1acffd66a922c79ef4acd7b0ee48e03958c378a6 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, 15 Apr 2026 10:36:37 +0800 Subject: [PATCH 7/7] =?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/vacation_meal_active.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yuthon_hr_attendance/models/vacation_meal_active.py b/yuthon_hr_attendance/models/vacation_meal_active.py index eaa3bf9a1..d1e8bc4da 100644 --- a/yuthon_hr_attendance/models/vacation_meal_active.py +++ b/yuthon_hr_attendance/models/vacation_meal_active.py @@ -62,7 +62,7 @@ class VacationMealActive(models.Model): ]) if meal_id: future_reps = self.env['yuthon.vacation.reports'].search([ - ('employee_id', '=', self.employee_id), + ('employee_id', '=', self.employee_id.id), ('vacation_date', '>=', first_day) ], order='vacation_date asc') for rep in future_reps: