添加功能

This commit is contained in:
李鹏宇
2026-02-08 21:37:48 +08:00
parent 1c700e3b3c
commit 741db154c7
8 changed files with 170 additions and 50 deletions
+1
View File
@@ -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',
+1
View File
@@ -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({
@@ -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()
@@ -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 ''
@@ -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
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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
91
92
93
94
95
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="view_vacation_meal_active_tree" model="ir.ui.view">
<field name="name">vacation.meal.active.tree</field>
<field name="model">vacation.meal.active</field>
<field name="arch" type="xml">
<tree string="误餐记录" editable="bottom">
<header>
<button name="revoke" type="object" string="批量撤销" dclass="oe_highlight"/>
</header>
<field name="meal_name"/>
<field name="employee_id"/>
<field name="workflow_id"/>
<field name="start_time"/>
<field name="end_time"/>
<field name="duration"/>
<field name="update_lines"/>
<field name="reasons"/>
<field name="meal"/>
<field name="carry_forward_date"/>
<field name="carry_forward_state"/>
<field name="line_id" column_invisible="1"/>
<field name="select_revoke" widget="badge"
decoration-danger="select_revoke == 'done'" decoration-success="select_revoke == 'to_do'"/>
<button name="revoke" type="object" string="撤销" class="oe_highlight" invisible="select_revoke == 'done'"/>
</tree>
</field>
</record>
<record id="view_vacation_meal_active_action" model="ir.actions.act_window">
<field name="name">误餐费归档</field>
<field name="res_model">vacation.meal.active</field>
<field name="view_mode">tree</field>
</record>
</odoo>
@@ -4,9 +4,12 @@
<field name="name">vacation.meal.line.tree</field>
<field name="model">vacation.meal.line</field>
<field name="arch" type="xml">
<tree string="误餐情况" create="false" delete="false" js_class="custom_vacation_meal_button">
<field name="employee_id"/>
<field name="meal_name"/>
<tree string="误餐情况" create="false" delete="false">
<header>
<button name="confirm" type="object" string="归档" dclass="oe_highlight"/>
</header>
<field name="meal_name" column_invisible="1"/>
<field name="employee_id" string="申请人"/>
<field name="workflow_id"/>
<field name="start_date" column_invisible="1"/>
<field name="start_time"/>
@@ -282,12 +285,12 @@
<field name="workflow_record_id"
domain="[('workflow_id.name', '=', '外出'), ('create_uid.employee_id', '=', employee_id)]"/>
<field name="update_type" readonly="0"/>
<field name="update_date" readonly="0"/>
<field name="update_lines"/>
<field name="valid_date"/>
<field name="adjust_date"/>
<field name="is_void"/>
<field name="text"/>
<field name="update_date" readonly="0"/>
<button name="unlink" string="删除" type="object" class="btn-primary"
groups="yuthon_holiday.group_yuthon_holiday_admin"/>
<button name="unlink" string="撤销" invisible="is_confirm == True" type="object"
@@ -347,18 +350,6 @@
</tree>
</field>
</page>
<!-- <page string="出勤消息日志" invisible="1">-->
<!-- <field name="attendance_message_log_ids">-->
<!-- <tree editable="bottom" create="false" edit="false" delete="false">-->
<!-- <field name="vacation_id" column_invisible="1"/>-->
<!-- <field name="employee_id"/>-->
<!-- <field name="update_date"/>-->
<!-- <field name="message_type"/>-->
<!-- <field name="message_url"/>-->
<!-- <button name="unlink" string="删除" type="object" class="btn-primary" groups="yuthon_holiday.group_yuthon_holiday_admin"/>-->
<!-- </tree>-->
<!-- </field>-->
<!-- </page>-->
<page string="管理员修改字段" groups="base.group_system">
<group col="2">
<group>
@@ -700,7 +691,7 @@
<field name="name">误餐情况</field>
<field name="res_model">vacation.meal.line</field>
<field name="view_mode">tree</field>
<field name="domain">[('is_filing','=', False)]</field>
<field name="domain">[('is_filing','=', False),('update_type','=','add')]</field>
<field name="context">{'search_default_now_month': 1,}</field>
<field name="search_view_id" ref="view_yuthon_vacation_meal_search"/>
<field name="view_ids" eval="[(5, 0, 0),
@@ -713,16 +704,6 @@
<field name="state">code</field>
<field name="code">action = model.update_line()</field>
</record>
<record id="view_yuthon_vacation_meal_active_action" model="ir.actions.act_window">
<field name="name">误餐归档</field>
<field name="res_model">vacation.meal.line</field>
<field name="view_mode">tree</field>
<field name="domain">[('is_filing','=', True)]</field>
<field name="context">{'search_default_now_month': 1, 'search_default_group_by_employee_id':1}</field>
<field name="search_view_id" ref="view_yuthon_vacation_meal_search"/>
<field name="view_ids" eval="[(5, 0, 0),
(0, 0, {'view_mode': 'tree', 'view_id': ref('yuthon_hr_attendance.view_vacation_meal_line_tree')}),]"/>
</record>
<record id="view_yuthon_vacation_reports_action" model="ir.actions.act_window">
<field name="name">考勤确认单台账</field>
<field name="res_model">yuthon.vacation.reports</field>
+1 -1
View File
@@ -760,7 +760,7 @@
<menuitem id="yuthon_menu_active_menu"
parent="yuthon_vacation_active_menu"
name="误餐归档"
action="yuthon_hr_attendance.view_yuthon_vacation_meal_active_action"
action="yuthon_hr_attendance.view_vacation_meal_active_action"
sequence="30"
/>