From 741db154c70137b71aea4ce1c585e71983cfec47 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: Sun, 8 Feb 2026 21:37:48 +0800
Subject: [PATCH] =?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/__manifest__.py | 1 +
yuthon_hr_attendance/models/__init__.py | 1 +
.../models/vacation_meal_active.py | 52 +++++++++++
.../models/yuthon_vacation_reports.py | 92 ++++++++++++++-----
.../security/ir.model.access.csv | 3 +-
.../views/vacation_meal_active_views.xml | 34 +++++++
.../views/yuthon_vacation_reports_views.xml | 35 ++-----
yuthon_work_brand/views/hr_menus.xml | 2 +-
8 files changed, 170 insertions(+), 50 deletions(-)
create mode 100644 yuthon_hr_attendance/models/vacation_meal_active.py
create mode 100644 yuthon_hr_attendance/views/vacation_meal_active_views.xml
diff --git a/yuthon_hr_attendance/__manifest__.py b/yuthon_hr_attendance/__manifest__.py
index b423024e2..9942613fd 100644
--- a/yuthon_hr_attendance/__manifest__.py
+++ b/yuthon_hr_attendance/__manifest__.py
@@ -70,6 +70,7 @@
'views/yuthon_parenting_allocate_views.xml',
'views/all_attendance_menu.xml',
'views/overtime_active_line_views.xml',
+ 'views/vacation_meal_active_views.xml',
'views/overtime_approval_inherit_header.xml',
diff --git a/yuthon_hr_attendance/models/__init__.py b/yuthon_hr_attendance/models/__init__.py
index feb5cc8d5..98a88c0cb 100644
--- a/yuthon_hr_attendance/models/__init__.py
+++ b/yuthon_hr_attendance/models/__init__.py
@@ -38,6 +38,7 @@ from . import yuthon_parenting_allocate
from . import vacation_overtime_active
from . import yuthon_overtime_line
from . import overtime_active_line
+from . import vacation_meal_active
# from odoo.tools import SQL
# import odoo
# odoo.models.READ_GROUP_AGGREGATE.update({
diff --git a/yuthon_hr_attendance/models/vacation_meal_active.py b/yuthon_hr_attendance/models/vacation_meal_active.py
new file mode 100644
index 000000000..b8b453263
--- /dev/null
+++ b/yuthon_hr_attendance/models/vacation_meal_active.py
@@ -0,0 +1,52 @@
+from datetime import datetime, timedelta, time
+from email.policy import default
+from operator import index
+from odoo import models, fields, api, _
+from odoo.exceptions import ValidationError
+import calendar
+from datetime import date
+from dateutil.relativedelta import relativedelta
+from odoo.exceptions import UserError, ValidationError
+
+
+class VacationMealActive(models.Model):
+ _name = 'vacation.meal.active'
+ _description = '误餐费归档'
+
+ meal_name = fields.Char(string='标题')
+ line_id = fields.Many2one('vacation.meal.line', string='关联误餐明细')
+ employee_id = fields.Many2one('hr.employee', string='员工')
+ workflow_id = fields.Many2one('soong.workflow', string='审批类型')
+ start_time = fields.Datetime(string='开始时间')
+ end_time = fields.Datetime(string='结束时间')
+ duration = fields.Float(string='时长')
+ update_lines = fields.Float(string='额度')
+ reasons = fields.Text(string='申请事由')
+ meal = fields.Selection([('yes', '是'), ('no', '否')], string="误餐费", default=None)
+ select_revoke = fields.Selection([('to_do', '待撤销'), ('done', '已撤销')], string='状态')
+ carry_forward_date = fields.Date(string="结转日期")
+ carry_forward_state = fields.Selection([('pending', '待结转'), ('completed', '已结转')
+ ], string='结转状态',
+ default='pending',
+ )
+
+ def revoke(self):
+ self.ensure_one()
+ self.select_revoke = 'done'
+ self.line_id.is_filing = True
+ report_id = self.env['yuthon.vacation.reports'].search([('employee_id', '=', self.employee_id.id),
+ ('vacation_date', '=', (self.start_time.date()).replace(day=1)),
+ ])
+ meal_id = self.env['vacation.meal.line'].search([('vacation_id', '=', report_id.id),
+ ('update_type', '=', 'reduce')
+ ])
+ if meal_id:
+ meal_id.unlink()
+
+ def all_revoke(self):
+ meal_ids = self.env["vacation.meal.active"].browse(
+ self._context.get('active_ids', self._context.get('active_id')))
+ for meal_id in meal_ids:
+ if meal_id.select_revoke == 'done':
+ raise UserError("该记录已撤销")
+ meal_id.revoke()
diff --git a/yuthon_hr_attendance/models/yuthon_vacation_reports.py b/yuthon_hr_attendance/models/yuthon_vacation_reports.py
index 8bdfc11cd..85336cdee 100644
--- a/yuthon_hr_attendance/models/yuthon_vacation_reports.py
+++ b/yuthon_hr_attendance/models/yuthon_vacation_reports.py
@@ -994,6 +994,8 @@ class YuthonVacationReports(models.Model):
'used_this_year1': last_month_record.used_this_year1,
}
rec.write(inherit_vals)
+ if rec.meal_number:
+ self._update_meal_lines(rec, [rec], rec.meal_number)
if rec.leave:
leave_hours = rec.leave * 8
self._update_leave_lines(rec, [rec], leave_hours)
@@ -1325,6 +1327,24 @@ class YuthonVacationReports(models.Model):
'text': f"上月额度继承",
})
+ def _update_meal_lines(self, report, allocations, number_of_hours_display):
+ for alloc in allocations:
+ existing_line = self.env['vacation.meal.line'].search([
+ ('vacation_id', '=', report.id),
+ ('employee_id', '=', report.employee_id.id),
+ ('text', '=', '上月额度继承'),
+ ], limit=1)
+ if existing_line:
+ continue
+ self.env['vacation.meal.line'].sudo().create({
+ 'vacation_id': report.id,
+ 'employee_id': report.employee_id.id,
+ 'update_type': 'add',
+ 'update_date': fields.Date.today(),
+ 'update_lines': number_of_hours_display,
+ 'text': f"上月额度继承",
+ })
+
def log(self):
return {
"type": "ir.actions.act_window",
@@ -1883,34 +1903,64 @@ class VacationMealLine(models.Model):
rec._compute_employee_id()
rec._compute_overtime()
- @api.model
def confirm(self):
- now = datetime.now()
- current_month = now.month
- current_year = now.year
- if current_month == 1:
- last_month = 12
- last_month_year = current_year - 1
- else:
- last_month = current_month - 1
- last_month_year = current_year
- last_month_first_day = datetime(last_month_year, last_month, 1)
- current_month_first_day = datetime(current_year, current_month, 1)
- valid_leaves = self.search([
- ('start_date', '>=', fields.Datetime.to_string(last_month_first_day)),
- ('start_date', '<', fields.Datetime.to_string(current_month_first_day)),
- ('id', 'in', self.ids)
- ])
- if valid_leaves:
- valid_leaves.write({'is_filing': True})
+ valid_leaves = self.env['vacation.meal.line'].browse(
+ self._context.get('active_ids', self._context.get('active_id')))
+ emp_month_summary = {}
+ for rec in valid_leaves:
+ rec_year = rec.start_time.year
+ rec_month = rec.start_time.month
+ rec.write({'is_filing': True})
+ emp_id = rec.employee_id.id
+ meal_active_vals = {
+ 'line_id': rec.id,
+ 'meal_name': rec.meal_name,
+ 'employee_id': emp_id,
+ 'workflow_id': rec.workflow_id.id if rec.workflow_id else False,
+ 'start_time': rec.start_time,
+ 'end_time': rec.end_time,
+ 'duration': rec.duration,
+ 'update_lines': rec.update_lines,
+ 'reasons': rec.reasons,
+ 'meal': rec.meal,
+ 'carry_forward_date': fields.Date.today(),
+ 'carry_forward_state': 'completed',
+ 'select_revoke': 'to_do'
+ }
+ self.env['vacation.meal.active'].create(meal_active_vals)
+
+ summary_key = (emp_id, rec_year, rec_month)
+ if summary_key not in emp_month_summary:
+ emp_month_summary[summary_key] = 0.0
+ emp_month_summary[summary_key] += rec.update_lines or 0.0
+
+ # 4. 第二步:遍历汇总结果,为每个【员工+年月】创建一条vacation.over.line
+ for (emp_id, rec_year, rec_month), total_amount in emp_month_summary.items():
+ if total_amount <= 1e-6:
+ continue
+ report_id = self.env['yuthon.vacation.reports'].search([
+ ('employee_id', '=', emp_id),
+ ('vacation_date', '=', fields.Date.from_string(f'{rec_year}-{rec_month}-01'))
+ ], limit=1)
+ if report_id:
+ self.env['vacation.meal.line'].create([{
+ 'vacation_id': report_id.id,
+ 'employee_id': emp_id,
+ 'update_type': 'reduce',
+ 'update_lines': total_amount,
+ 'update_date': fields.Date.today(),
+ 'is_void': False,
+ 'text': f'{rec_month}月份误餐结转',
+ }])
@api.depends('workflow_record_id')
def _compute_overtime(self):
for rec in self:
rec.start_date = False
res_model = rec.workflow_record_id.res_model
+ rec.meal = 'yes'
res_id = rec.workflow_record_id.res_id
- if res_model and res_id and res_model in self.env:
+ if res_model and res_id and res_model in self.env and rec.update_type == 'add':
if res_model == 'overtime.approval':
overtime_id = rec.env[res_model].search([('id', '=', res_id)], limit=1)
if overtime_id:
@@ -1940,7 +1990,7 @@ class VacationMealLine(models.Model):
rec.start_time = start_time
rec.end_time = end_time
rec.meal = go_approval_id.meal
-
+ rec.workflow_id = rec.workflow_record_id.workflow_id.id
rec.meal_name = rec.workflow_record_id.name or ''
diff --git a/yuthon_hr_attendance/security/ir.model.access.csv b/yuthon_hr_attendance/security/ir.model.access.csv
index 3adf884a5..b0da28464 100644
--- a/yuthon_hr_attendance/security/ir.model.access.csv
+++ b/yuthon_hr_attendance/security/ir.model.access.csv
@@ -91,4 +91,5 @@ access_yuthon_parenting_allocate,yuthon.parenting.allocate,model_yuthon_parentin
access_vacation_overtime_active,vacation.overtime.active,model_vacation_overtime_active,base.group_user,1,1,1,1
access_yuthon_overtime_line,yuthon.overtime.line,model_yuthon_overtime_line,base.group_user,1,1,1,1
-access_overtime_active_line,overtime.active.line,model_overtime_active_line,base.group_user,1,1,1,1
\ No newline at end of file
+access_overtime_active_line,overtime.active.line,model_overtime_active_line,base.group_user,1,1,1,1
+access_vacation_meal_active,vacation.meal.active,model_vacation_meal_active,base.group_user,1,1,1,1
\ No newline at end of file
diff --git a/yuthon_hr_attendance/views/vacation_meal_active_views.xml b/yuthon_hr_attendance/views/vacation_meal_active_views.xml
new file mode 100644
index 000000000..2d35b2b08
--- /dev/null
+++ b/yuthon_hr_attendance/views/vacation_meal_active_views.xml
@@ -0,0 +1,34 @@
+
+
+
+ vacation.meal.active.tree
+ vacation.meal.active
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 误餐费归档
+ vacation.meal.active
+ tree
+
+
diff --git a/yuthon_hr_attendance/views/yuthon_vacation_reports_views.xml b/yuthon_hr_attendance/views/yuthon_vacation_reports_views.xml
index 5ce8d298a..99cc47a41 100644
--- a/yuthon_hr_attendance/views/yuthon_vacation_reports_views.xml
+++ b/yuthon_hr_attendance/views/yuthon_vacation_reports_views.xml
@@ -4,9 +4,12 @@
vacation.meal.line.tree
vacation.meal.line
-
-
-
+
+
+
+
@@ -282,12 +285,12 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
@@ -700,7 +691,7 @@
误餐情况
vacation.meal.line
tree
- [('is_filing','=', False)]
+ [('is_filing','=', False),('update_type','=','add')]
{'search_default_now_month': 1,}
code
action = model.update_line()
-
- 误餐归档
- vacation.meal.line
- tree
- [('is_filing','=', True)]
- {'search_default_now_month': 1, 'search_default_group_by_employee_id':1}
-
-
-
考勤确认单台账
yuthon.vacation.reports
diff --git a/yuthon_work_brand/views/hr_menus.xml b/yuthon_work_brand/views/hr_menus.xml
index 0debf23f0..156e16703 100644
--- a/yuthon_work_brand/views/hr_menus.xml
+++ b/yuthon_work_brand/views/hr_menus.xml
@@ -760,7 +760,7 @@