补休
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user