添加功能

This commit is contained in:
李鹏宇
2026-01-04 16:22:32 +08:00
parent e8b6d49698
commit 30bb70beb6
6 changed files with 172 additions and 63 deletions
+1
View File
@@ -71,6 +71,7 @@
'wizard/attendance_controls_wizard.xml',
'wizard/attendance_correct_wizard.xml',
'wizard/vacation_put_wizard_views.xml',
'wizard/vacation_reports_wizard.xml',
'wizard/vacation_confirm_wizard_views.xml',
'wizard/planning_slot_update_display_name_wizard.xml',
'wizard/yuthon_run_wizard.xml',
@@ -33,7 +33,7 @@ class YuthonVacationReports(models.Model):
year_workday = fields.Float(string="本年工作日", digits=(16, 3))
year_sum = fields.Float(string="本年应休合计", digits=(16, 3), compute="_compute_year_sum")
used_this_year1 = fields.Float(string="本年已休", digits=(16, 3), compute="_compute_year_sum")
remainder_year1 = fields.Float(string="本年剩余(补休)", digits=(16, 3))
remainder_year1 = fields.Float(string="本年剩余(补休)", digits=(16, 3), compute="_compute_year_sum")
company_id = fields.Many2one(related="employee_id.company_id", string="公司", store=True)
late_allowed = fields.Float(related="employee_id.late_allowed", string="允许迟到次数")
@@ -133,7 +133,6 @@ class YuthonVacationReports(models.Model):
record.year_sum = record.last_holiday + record.last_workday + record.year_holiday + record.year_workday
record.remainder_year1 = record.year_sum - record.used_this_year1
@api.constrains('employee_id', 'vacation_date')
def _check_duplicate_monthly_record(self):
"""检查是否存在同一员工当月的重复记录"""
@@ -176,6 +175,38 @@ class YuthonVacationReports(models.Model):
def confirm_state(self):
for rec in self:
current_user = self.env.user
is_admin = current_user.has_group('base.group_system') or current_user.has_group('base.group_admin')
if not is_admin:
if rec.vacation_date.month == 1:
last_month_year = rec.vacation_date.year - 1
last_month = 12
else:
last_month_year = rec.vacation_date.year
last_month = rec.vacation_date.month - 1
last_day_of_last_month = calendar.monthrange(last_month_year, last_month)[1]
last_month_start = fields.Date.from_string(f'{last_month_year}-{last_month:02d}-01')
last_month_end = fields.Date.from_string(f'{last_month_year}-{last_month:02d}-{last_day_of_last_month}')
leave_batch_domain = [
('users_id', '=', current_user.id),
('start_date', '>=', last_month_start),
('end_date', '<=', last_month_end),
('work_end', '!=', True)
]
invalid_leave_batches = self.env['hr.leave.batch'].search(leave_batch_domain)
if invalid_leave_batches:
raise UserError('有假单未结束, 请先结束假期批次')
current_employee_id = self.env['hr.employee'].search([('user_id', '=', current_user.id)], limit=1).id
overtime_domain = [
('employee_ids', 'in', current_employee_id),
('start_time', '>=', last_month_start),
('start_time', '<=', last_month_end),
('work_end', '!=', True)
]
invalid_overtimes = self.env['overtime.approval'].search(overtime_domain)
if invalid_overtimes:
raise UserError('有加班单未结束,请先结束加班批次')
rec.manage_reject()
@api.depends('vacation_date')
@@ -292,22 +323,44 @@ class YuthonVacationReports(models.Model):
records = self.env["yuthon.vacation.reports"].browse(
self._context.get('active_ids', self._context.get('active_id', self.ids))
)
for record in records:
last_month_last = record.vacation_date - timedelta(days=1)
last_month_first = last_month_last.replace(day=1)
last_month_record = self.search([
('employee_id', '=', record.employee_id.id),
('vacation_date', '>=', fields.Date.to_string(last_month_first)),
('vacation_date', '<=', fields.Date.to_string(last_month_last)),
('vacation_state', '=', 'confirmed')
], limit=1)
inherit_vals = {
'previous_year': last_month_record.remainder_year,
'last_workday': last_month_record.remainder_year1,
'remainder_year': 0.0,
'remainder_year1': 0.0,
}
record.write(inherit_vals)
for rec in records:
leave_line_domain = [
('vacation_id', '=', rec.id),
('text', '=', "上月额度继承"),
('employee_id', '=', rec.employee_id.id)
]
existing_leave_line = self.env['vacation.leave.line'].search(leave_line_domain, limit=1)
if existing_leave_line:
existing_leave_line.unlink()
if rec.year_distribution:
self.env['vacation.leave.line'].create({
'vacation_id': rec.id,
'employee_id': rec.employee_id.id,
'update_type': 'add',
'update_date': fields.Date.today(),
'update_lines': rec.year_distribution * 8,
'is_void': False,
'allocation_type': 'allocation',
'text': "上月额度继承"
})
over_line_domain = [
('vacation_id', '=', rec.id),
('employee_id', '=', rec.employee_id.id)
]
existing_over_lines = self.env['vacation.over.line'].search(over_line_domain)
if existing_over_lines:
existing_over_lines.unlink()
if rec.year_holiday or rec.year_workday:
over_line_create_vals = {
'vacation_id': rec.id,
'employee_id': rec.employee_id.id,
'update_type': 'add',
'workday': rec.year_workday * 8,
'public_holidays': rec.year_holiday * 8,
'legal_day': 0.0,
'text': "上月额度继承"
}
self.env['vacation.over.line'].create(over_line_create_vals)
def _compute_attendance_fields1(self):
records = self.env["yuthon.vacation.reports"].browse(
@@ -320,11 +373,13 @@ class YuthonVacationReports(models.Model):
})
def update_data(self):
records = self.env["yuthon.vacation.reports"].browse(
self._context.get('active_ids', self._context.get('active_id', self.ids))
)
for rec in records:
rec._compute_working_overtime()
return {
"type": "ir.actions.act_window",
"name": "导入",
"res_model": "vacation.reports.wizard",
"view_mode": "form",
"target": "new",
}
@api.depends('other_fee_ids', 'other_fee_ids.holiday_type', 'other_fee_ids.lines',
'other_fee_ids.is_void', 'other_fee_ids.update_type')
@@ -466,38 +521,6 @@ class YuthonVacationReports(models.Model):
:return:
'''
for rec in self:
current_user = self.env.user
is_admin = current_user.has_group('base.group_system') or current_user.has_group('base.group_admin')
if not is_admin:
if rec.vacation_date.month == 1:
last_month_year = rec.vacation_date.year - 1
last_month = 12
else:
last_month_year = rec.vacation_date.year
last_month = rec.vacation_date.month - 1
last_day_of_last_month = calendar.monthrange(last_month_year, last_month)[1]
last_month_start = fields.Date.from_string(f'{last_month_year}-{last_month:02d}-01')
last_month_end = fields.Date.from_string(f'{last_month_year}-{last_month:02d}-{last_day_of_last_month}')
leave_batch_domain = [
('users_id', '=', current_user.id),
('start_date', '>=', last_month_start),
('end_date', '<=', last_month_end),
('work_end', '!=', True)
]
invalid_leave_batches = self.env['hr.leave.batch'].search(leave_batch_domain)
if invalid_leave_batches:
raise UserError('有假单未结束, 请先结束假期批次')
current_employee_id = self.env['hr.employee'].search([('user_id', '=', current_user.id)], limit=1).id
overtime_domain = [
('employee_ids', 'in', current_employee_id),
('start_time', '>=', last_month_start),
('start_time', '<=', last_month_end),
('work_end', '!=', True)
]
invalid_overtimes = self.env['overtime.approval'] .search(overtime_domain)
if invalid_overtimes:
raise UserError('有加班单未结束,请先结束加班批次')
last_month_last = rec.vacation_date - timedelta(days=1)
last_month_first = last_month_last.replace(day=1)
last_month_record = self.search([
@@ -512,15 +535,12 @@ class YuthonVacationReports(models.Model):
last_month_year = last_month_last.year
is_cross_year = current_year != last_month_year
if is_cross_year:
last_month_record.write({
'remainder_year': last_month_record.leave,
'remainder_year1': last_month_record.working_overtime,
})
inherit_vals = {
'previous_year': last_month_record.remainder_year,
'last_workday': last_month_record.remainder_year1,
'remainder_year': 0.0,
'remainder_year1': 0.0,
'last_workday': last_month_record.year_workday,
'last_holiday': last_month_record.year_holiday,
'year_holiday': 0.0,
'year_workday': 0.0,
}
rec.write(inherit_vals)
@@ -80,4 +80,6 @@ access_staff_dining_report,staff.dining.report,model_staff_dining_report,base.gr
access_vacation_confirm_wizard,vacation.confirm.wizard,model_vacation_confirm_wizard,base.group_user,1,1,1,1
access_vacation_put_wizard,vacation.put.wizard,model_vacation_put_wizard,base.group_user,1,1,1,1
access_message_reminder_tasks,message.reminder.tasks,model_message_reminder_tasks,base.group_user,1,1,1,1
access_applet_security_quick_perm_wizard,access_applet_security_quick_perm_wizard,model_applet_security_quick_perm_wizard,base.group_user,1,1,1,1
access_applet_security_quick_perm_wizard,access_applet_security_quick_perm_wizard,model_applet_security_quick_perm_wizard,base.group_user,1,1,1,1
access_vacation_reports_wizard,vacation.reports.wizard,model_vacation_reports_wizard,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
80
81
82
83
84
85
+1
View File
@@ -9,3 +9,4 @@ from . import planning_slot_update_display_name_wizard
from . import vacation_confirm_wizard
from . import vacation_put_wizard
from . import applet_security_quick_perm_wizard
from . import vacation_reports_wizard
@@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api, _, SUPERUSER_ID
from odoo.exceptions import ValidationError, UserError
from pypinyin import pinyin, Style
import xlrd
import base64
import datetime
from datetime import datetime
class VacationReportsWizard(models.TransientModel):
_name = 'vacation.reports.wizard'
_description = '考勤报表导入'
excel_file = fields.Binary(string="上传Excel表")
excel_name = fields.Char(string="文件名")
report_ids = fields.Many2many('yuthon.vacation.reports', string='报表')
def confirm(self):
"""
导入excel文件,按行读取数据并处理
:return: 导入员工信息表并更新
"""
if not self.excel_file:
raise ValidationError('请上传文件。')
book = xlrd.open_workbook(file_contents=base64.decodebytes(self.excel_file))
sh = book.sheet_by_index(0)
for rx in range(1, sh.nrows):
row = sh.row(rx)
self.leave_import(row)
def leave_import(self, row):
employee_id = self.env['hr.employee'].search([('name', '=', row[0].value)])
year_distribution = row[1].value
start_date = fields.Date.from_string("2025-12-1")
report_id = self.env['yuthon.vacation.reports'].search([('employee_id', '=', employee_id.id),
('vacation_date', '=', start_date)
])
if report_id:
report_id.write({'year_distribution': year_distribution})
def over_import(self, row):
employee_id = self.env['hr.employee'].search([('name', '=', row[0].value)])
year_holiday = float(row[12].value)
year_workday = float(row[11].value)
if not year_workday and not year_holiday:
year_workday = float(row[10].value)
start_date = fields.Date.from_string("2025-12-1")
report_id = self.env['yuthon.vacation.reports'].search([('employee_id', '=', employee_id.id),
('vacation_date', '=', start_date)
])
if report_id:
report_id.write(
{'year_holiday': year_holiday / 8
,'year_workday': year_workday / 8
})
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="vacation_reports_wizard_form" model="ir.ui.view">
<field name="name">导入</field>
<field name="model">vacation.reports.wizard</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<group>
<field name="excel_file" filename="excel_name"/>
<field name="excel_name" invisible="1"/>
</group>
<group>
</group>
</group>
</sheet>
<footer>
<button name="confirm" string="确认" type="object" class="oe_highlight"/>
<button string="返回" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
</odoo>