This commit is contained in:
李鹏宇
2026-06-02 18:22:34 +08:00
parent d07e1e4917
commit c2440ea3a4
3 changed files with 81 additions and 17 deletions
+36 -10
View File
@@ -5,6 +5,7 @@
# @Author :zzw
from odoo import models, fields, api, _
from typing import Dict, List
from datetime import timedelta
class TxPlanningSlot(models.Model):
@@ -29,19 +30,44 @@ class TxPlanningSlot(models.Model):
def action_compensatory_leave(self):
"""
补休按钮 - 将当前排班转为补休记录
TODO: 具体业务逻辑由客户确认后补充
补休按钮 - 打开假期分配表单,填写补休信息后验证写入考勤确认单台账
"""
self.ensure_one()
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': '补休',
'message': f'已为 {self.resource_id.name} 创建补休申请(待实现)',
'sticky': False,
'type': 'success',
# 从排班资源获取员工
employee = self.resource_id.employee_id if self.resource_id else None
if not employee:
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': '提示',
'message': '该排班未关联有效员工,无法创建补休申请',
'sticky': False,
'type': 'warning',
}
}
# 获取排班日期
slot_date = (self.start_datetime + timedelta(hours=8)).date() if self.start_datetime else None
# 获取"补休"假期类型
holiday_status_id = self.env['hr.leave.type'].search([('name', '=', '补休')])
# 获取 hr.leave.allocation 的 form 视图
form_id = self.env.ref('hr_holidays.hr_leave_allocation_view_form_manager').id
return {
'type': 'ir.actions.act_window',
'name': '计划班调补休申请',
'res_model': 'hr.leave.allocation',
'view_mode': 'form',
'views': [(form_id, 'form')],
'target': 'current',
'context': {
'default_holiday_status_id': holiday_status_id.id,
'default_employee_ids': [(6, 0, [employee.id])],
'default_employee_id': employee.id,
'default_allocation_type': 'regular',
'default_name': '计划班调补休',
'default_number_of_days_display': 8,
'default_date_from': slot_date,
},
}
@api.depends('role_id', 'employee_id')
@@ -8,6 +8,12 @@ class HrLeaveAllocation(models.Model):
HOURS_PER_DAY = 8.0
is_reduce_compensatory = fields.Boolean(
string='减少补休',
default=False,
help='标识此补休分配是否为扣减操作。填写负数时自动勾选,写入考勤确认单时走 reduce 逻辑。'
)
@api.depends('holiday_status_id', 'allocation_type', 'number_of_hours_display', 'number_of_days_display', 'date_to')
def _compute_from_holiday_status_id(self):
super()._compute_from_holiday_status_id()
@@ -34,6 +40,30 @@ class HrLeaveAllocation(models.Model):
start_time = fields.Date(string="开始时间")
end_time = fields.Date(string="结束时间")
@api.model_create_multi
def create(self, vals_list):
"""拦截补休的负数天数,绕过 SQL CHECK 约束"""
for vals in vals_list:
if vals.get('number_of_days', 0) < 0:
holiday_status_id = vals.get('holiday_status_id')
if holiday_status_id:
status = self.env['hr.leave.type'].browse(holiday_status_id)
if status.name == '补休':
vals['is_reduce_compensatory'] = True
vals['number_of_days'] = abs(vals['number_of_days'])
return super().create(vals_list)
def write(self, vals):
"""拦截补休的负数天数,绕过 SQL CHECK 约束(allocation_type=regular 时 number_of_days 必须 > 0)"""
if vals.get('number_of_days', 0) < 0:
for rec in self:
if rec.holiday_status_id.name == '补休':
vals = dict(vals)
vals['is_reduce_compensatory'] = True
vals['number_of_days'] = abs(vals['number_of_days'])
break
return super().write(vals)
@api.onchange('users_role_ids')
def onchange_employee_ids(self):
users_role_list = []
@@ -285,9 +315,9 @@ class HrLeaveAllocation(models.Model):
logger.info("按旧方式删除年假明细行并重新计算")
elif leave.holiday_status_id.name == '补休':
# 精确查找并删除当前表单添加的补休明细行
# 精确查找并删除当前表单添加的补休明细行(增加和减少类型都处理)
lines_to_delete = reports_id.overtime_ids.filtered(
lambda o: o.update_type == 'add' and o.allocation_id.id == leave.id
lambda o: o.update_type in ('add', 'reduce') and o.allocation_id.id == leave.id
)
logger.info(f"找到需要删除的补休明细行数量: {len(lines_to_delete)}")
if lines_to_delete:
@@ -358,15 +388,23 @@ class HrLeaveAllocation(models.Model):
if reports_id:
rest_hours = leave.number_of_days_display * 8
# 根据 is_reduce_compensatory 判断增加还是减少
# (number_of_days 已被 write 拦截转为正数以绕过 SQL CHECK 约束)
if leave.is_reduce_compensatory:
update_type = 'reduce'
workday = rest_hours
else:
update_type = 'add'
workday = rest_hours
reports_id.write({
'valid_date1': leave.date_to,
'overtime_ids': [(0, 0, {
'vacation_id': reports_id.id,
'allocation_id': leave.id,
'update_type': 'add',
'update_type': update_type,
'update_date': fields.Datetime.now(),
'valid_date': leave.date_to,
'workday': rest_hours,
'workday': workday,
'text': leave.name or '补休分配'
})]
})
@@ -27,11 +27,11 @@
<xpath expr="//footer/button[@name='auto_plan_id']" position="replace"></xpath>
<xpath expr="//footer/button[@name='action_unpublish']" position="replace"></xpath>
<!-- 补休按钮:加在模板选择字段后面 -->
<!-- 计划班调补休申请按钮:加在模板选择字段后面 -->
<xpath expr="//field[@name='template_id'][last()]" position="after">
<div class="d-flex justify-content-end">
<button name="action_compensatory_leave" string="补休" type="object"
class="btn-primary" confirm="确认将此班次转为补休?"/>
<button name="action_compensatory_leave" string="申请补休" type="object"
class="btn-primary"/>
</div>
</xpath>
</field>