From b6abf278bece6eb9f4f21ba0cad959603c7f158c 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, 3 Mar 2026 10:04:20 +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_hr_attendance/models/yuthon_vacation_reports.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yuthon_hr_attendance/models/yuthon_vacation_reports.py b/yuthon_hr_attendance/models/yuthon_vacation_reports.py index 524f69bb3..11370c939 100644 --- a/yuthon_hr_attendance/models/yuthon_vacation_reports.py +++ b/yuthon_hr_attendance/models/yuthon_vacation_reports.py @@ -202,7 +202,7 @@ class YuthonVacationReports(models.Model): rec.update_line() def update_line(self): - if self.vacation_date == fields.Date.from_string('2026-01-01') or (self.vacation_date == fields.Date.from_string('2026-03-01') and self.employee_id.name == '天河物管'): + if self.vacation_date == fields.Date.from_string('2026-01-01') or (self.vacation_date == fields.Date.from_string('2026-03-01') and self.employee_id.company_id.name == '天河物管'): return self.manage_reject() # ========== 第一步:处理年假逻辑 ========== From 33352ed3a62c4952c5885286460808f196c5b832 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, 3 Mar 2026 10:59:15 +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 --- .../models/yuthon_vacation_reports.py | 101 ++++++++++++++++++ .../views/yuthon_vacation_reports_views.xml | 7 ++ .../wizard/yuthon_vacation_import_wizard.py | 11 +- 3 files changed, 115 insertions(+), 4 deletions(-) diff --git a/yuthon_hr_attendance/models/yuthon_vacation_reports.py b/yuthon_hr_attendance/models/yuthon_vacation_reports.py index 11370c939..ad9897e24 100644 --- a/yuthon_hr_attendance/models/yuthon_vacation_reports.py +++ b/yuthon_hr_attendance/models/yuthon_vacation_reports.py @@ -914,6 +914,107 @@ class YuthonVacationReports(models.Model): "target": "new", } + def update_holiday(self): + # 获取当前激活的记录 + vacation_ids = self.env["yuthon.vacation.reports"].browse( + self._context.get('active_ids', self._context.get('active_id'))) + current_year = datetime.now().year + for vacation in vacation_ids: + # 1. 处理上年年假剩余 (年假, 时间:上上年3月1日 到 上年2月28/29日) + if vacation.dynamic_previous_year > 0: + start_date = datetime(current_year - 2, 3, 1) + end_date = datetime(current_year - 1, 2, 28) + # 检查是否是闰年, + if (current_year - 1) % 4 == 0 and (current_year - 1) % 100 != 0 or (current_year - 1) % 400 == 0: + end_date = datetime(current_year - 1, 2, 29) + self._create_leave_allocation( + vacation=vacation, + leave_days=vacation.dynamic_previous_year, + allocation_type='accrual', + leave_name='年假', + start_date=start_date, + end_date=end_date + ) + + # 2. 处理本年年假剩余 (本年3月1日 到 明年2月28/29日) + if vacation.dynamic_remainder_year > 0: + start_date = datetime(current_year, 3, 1) + end_date = datetime(current_year + 1, 2, 28) + # 检查闰年 + if (current_year + 1) % 4 == 0 and (current_year + 1) % 100 != 0 or (current_year + 1) % 400 == 0: + end_date = datetime(current_year + 1, 2, 29) + + self._create_leave_allocation( + vacation=vacation, + leave_days=vacation.dynamic_remainder_year, + allocation_type='accrual', + leave_name='年假', + start_date=start_date, + end_date=end_date + ) + + # 3. 处理上年补休剩余 (休假, 时间:上年3月1日 到 上年2月28/29日) + if vacation.dynamic_previous_year1 > 0: + start_date = datetime(current_year - 2, 3, 1) + end_date = datetime(current_year - 1, 2, 28) + # 检查闰年 + if (current_year - 1) % 4 == 0 and (current_year - 1) % 100 != 0 or (current_year - 1) % 400 == 0: + end_date = datetime(current_year - 1, 2, 29) + + self._create_leave_allocation( + vacation=vacation, + leave_days=vacation.dynamic_previous_year1, + allocation_type='regular', + leave_name='休假', + start_date=start_date, + end_date=end_date + ) + + # 4. 处理本年补休剩余 ( 休假, 时间:本年3月1日 到 明年2月28/29日) + if vacation.this_year1 > 0: + start_date = datetime(current_year, 3, 1) + end_date = datetime(current_year + 1, 2, 28) + if (current_year + 1) % 4 == 0 and (current_year + 1) % 100 != 0 or (current_year + 1) % 400 == 0: + end_date = datetime(current_year + 1, 2, 29) + + self._create_leave_allocation( + vacation=vacation, + leave_days=vacation.this_year1, + allocation_type='regular', + leave_name='休假', + start_date=start_date, + end_date=end_date + ) + + def _create_leave_allocation(self, vacation, leave_days, allocation_type, leave_name, start_date, end_date): + """ + 封装创建hr.leave.allocation的逻辑 + :param vacation: 当前yuthon.vacation.reports记录 + :param leave_days: 假期天数 + :param allocation_type: 分配类型 (accrual/regular) + :param leave_name: 假期名称 (年假/休假) + :param start_date: 开始日期 + :param end_date: 结束日期 + """ + accrual_plan_id = self.env['hr.leave.accrual.plan'].search( + [('name', 'ilike', '天河物管')], limit=1 + ) + leave_type = self.env['hr.leave.type'].search([('display_name', 'ilike', leave_name), ('company_id.name', '=', '天河物管')], limit=1) + vals = { + 'name': leave_name, + 'number_of_days': leave_days, + 'holiday_status_id': leave_type.id, + 'allocation_type': allocation_type, + 'date_from': fields.Date.to_string(start_date), + 'date_to': fields.Date.to_string(end_date), + 'notes': leave_name, + } + if allocation_type == 'accrual' and accrual_plan_id: + vals['accrual_plan_id'] = accrual_plan_id.id + vals['employee_id'] = vacation.employee_id.id + self.env['hr.leave.allocation'].create(vals) + + @api.depends('other_fee_ids', 'other_fee_ids.holiday_type', 'other_fee_ids.lines', 'other_fee_ids.is_void', 'other_fee_ids.update_type') def _compute_other_leave(self): diff --git a/yuthon_hr_attendance/views/yuthon_vacation_reports_views.xml b/yuthon_hr_attendance/views/yuthon_vacation_reports_views.xml index 864363722..2ba25e498 100644 --- a/yuthon_hr_attendance/views/yuthon_vacation_reports_views.xml +++ b/yuthon_hr_attendance/views/yuthon_vacation_reports_views.xml @@ -807,6 +807,13 @@ code action = model.update_data() + + 更新休假 + + + code + action = model.update_holiday() + details.tree.tree details.tree diff --git a/yuthon_hr_attendance/wizard/yuthon_vacation_import_wizard.py b/yuthon_hr_attendance/wizard/yuthon_vacation_import_wizard.py index fe0681f6e..86aee4066 100644 --- a/yuthon_hr_attendance/wizard/yuthon_vacation_import_wizard.py +++ b/yuthon_hr_attendance/wizard/yuthon_vacation_import_wizard.py @@ -102,7 +102,7 @@ class YuthonVacationImportWizard(models.TransientModel): leave.write({ 'update_lines': update_value, }) - vacation_id.dynamic_previous_year = update_value / 8 + vacation_id.dynamic_remainder_year = update_value / 8 else: if update_value != 0: self.env[vacation_id.leave_ids._name].create({ @@ -113,7 +113,7 @@ class YuthonVacationImportWizard(models.TransientModel): 'update_lines': update_value, 'vacation_id': vacation_id.id, }) - vacation_id.dynamic_previous_year = update_value / 8 + vacation_id.dynamic_remainder_year = update_value / 8 target_overtimes = vacation_id.overtime_ids.filtered(lambda o: o.text == '上月额度继承') workday_value = float(row[2].value) * 8 @@ -123,7 +123,7 @@ class YuthonVacationImportWizard(models.TransientModel): overtime.unlink() else: overtime.write({'workday': workday_value}) - vacation_id.dynamic_previous_year1 = workday_value / 8 + vacation_id.this_year1 = workday_value / 8 else: if workday_value != 0: self.env[vacation_id.overtime_ids._name].create({ @@ -135,6 +135,9 @@ class YuthonVacationImportWizard(models.TransientModel): 'workday': workday_value, 'vacation_id': vacation_id.id, }) - vacation_id.dynamic_previous_year1 = workday_value / 8 + vacation_id.this_year1 = workday_value / 8 + + vacation_id.dynamic_previous_year = 0 + vacation_id.dynamic_previous_year1 = 0 vacation_id._compute_leave() vacation_id._compute_working_overtime()