This commit is contained in:
李鹏宇
2026-04-15 10:52:51 +08:00
4 changed files with 164 additions and 19 deletions
@@ -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
)
# 创建或更新当前用户的审批记录
+7
View File
@@ -412,6 +412,13 @@
<field name="state">code</field>
<field name="code">action = model.update_state()</field>
</record>
<record id="all_update_is_vacation" model="ir.actions.server">
<field name="name">标识改成True</field>
<field name="model_id" ref="hr_holidays.model_hr_leave"/>
<field name="binding_model_id" ref="hr_holidays.model_hr_leave"/>
<field name="state">code</field>
<field name="code">action = model.update_is_vacation()</field>
</record>
<menuitem
id="hr_holidays.hr_leave_menu_my"
parent="hr_holidays.menu_hr_holidays_my_leaves"
@@ -45,11 +45,11 @@ 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:
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()
@@ -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:
@@ -315,6 +315,9 @@ class YuthonVacationReports(models.Model):
self_overtime = rec.overtime_ids.filtered(lambda o: not o.workflow_record_id and o.text == '上月额度继承')
self_overtime.workday = (rec.dynamic_previous_year1 + rec.this_year1) * 8
self_meal = rec.meal_fee_ids.filtered(lambda o: not o.workflow_record_id and o.text == '上月额度继承')
self_meal.update_lines = rec.remain_missed_meals
valid_leave_lines = rec.leave_ids.filtered(
lambda l: l.workflow_record_id and l.update_type == 'reduce' and l.is_void != True
)
@@ -1401,6 +1404,13 @@ class YuthonVacationReports(models.Model):
employee_ids = calendar.resource_user_ids.ids
target_employee_ids.update(employee_ids)
for rec in self:
employee = rec.employee_id
vacation_date = rec.vacation_date
unpaid_leaves = self.env['hr.leave'].search([
('employee_id', '=', employee.id),
('holiday_status_id.name', '=', ['产假']),
('state', '=', 'validate')
])
last_month_last = rec.vacation_date - timedelta(days=1)
last_month_first = last_month_last.replace(day=1)
last_month_record = self.search([
@@ -1454,6 +1464,49 @@ class YuthonVacationReports(models.Model):
inherit_vals['valid_date1'] = last_month_record.valid_date1
rec.write(inherit_vals)
if unpaid_leaves:
for leave in unpaid_leaves:
leave_start = leave.date_from.date()
leave_end = leave.date_to.date()
current_month_start = vacation_date
current_month_end = (current_month_start + relativedelta(months=1)) - timedelta(days=1)
real_start = max(leave_start, current_month_start)
real_end = min(leave_end, current_month_end)
if real_start > 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: