添加功能

This commit is contained in:
李鹏宇
2026-01-24 22:07:03 +08:00
parent f6bcbd0086
commit 82c5fa773d
22 changed files with 396 additions and 95 deletions
+6 -6
View File
@@ -353,7 +353,7 @@ class HolidaysRequestBatch(models.Model):
column1='leave_id',
column2='attachment_id'
)
holiday_allowance = fields.Char(string="可用额度", compute='_compute_holiday_allowance', store=True)
holiday_allowance = fields.Text(string="可用额度", compute='_compute_holiday_allowance', store=True)
active = fields.Boolean('Active', default=True, tracking=True)
def _get_default_name_title(self):
@@ -365,7 +365,7 @@ class HolidaysRequestBatch(models.Model):
@api.onchange('is_day')
def _onchange_is_day(self):
if not self.is_day:
self.leave_ids = [(5, 0, 0)] # 清空One2many字段
self.leave_ids = [(5, 0, 0)]
@api.onchange('is_hour')
def _onchange_is_hour(self):
@@ -411,7 +411,7 @@ class HolidaysRequestBatch(models.Model):
other_leave_types = [
'产假', '事假', '法定假', '调休', '补休', '值班调休',
'婚假', '陪产假', '计生假', '丧假', '探亲假',
'家长会假', '病假(普通)', '病假(住院期)',
'家长会假', '病假(普通)', '病假(住院期)', '育儿假',
'病假(出院恢复期)', '考试假'
]
for leave_type in other_leave_types:
@@ -855,9 +855,9 @@ class HolidaysRequestBatch(models.Model):
('vacation_date', '=', vacation_date.replace(day=1))
], limit=1)
if reports_id:
leave_days = reports_id.leave
overtime_days = reports_id.working_overtime
record.holiday_allowance = f"年假{leave_days:.3f}天, 补休{overtime_days:.3f}天"
record.holiday_allowance = (f"本年剩余(年假){reports_id.remainder_year:.3f}天, 上年剩余(年假){reports_id.previous_year:.3f}天\n"
f"本年剩余(补休){reports_id.remainder_year1:.3f}天, 上年剩余(补休){reports_id.previous_year1:.3f}天\n "
f"育儿假{reports_id.remaining_parental_leave:.3f}天")
def action_print_leave_batch(self):
"""按钮触发打印请假单"""
+2
View File
@@ -58,6 +58,7 @@
'views/card_remind_form.xml',
'views/yuthon_customer_planning_views.xml',
'views/planning_slot_template_views.xml',
'views/vacation_overtime_active_views.xml',
'views/hr_attendance_month_views.xml',
'views/wifi_message_view.xml',
'views/back_approval.xml',
@@ -65,6 +66,7 @@
'views/meal_approval.xml',
'views/applet_address_views.xml',
'views/yuthon_holiday_statement.xml',
'views/yuthon_parenting_allocate_views.xml',
'views/all_attendance_menu.xml',
'views/overtime_approval_inherit_header.xml',
+2 -1
View File
@@ -34,7 +34,8 @@ from . import staff_dining_report
from . import message_reminder_tasks
from . import yuthon_holiday_statement
from . import yuthon_meal_case
from . import yuthon_parenting_allocate
from . import vacation_overtime_active
# from odoo.tools import SQL
# import odoo
# odoo.models.READ_GROUP_AGGREGATE.update({
@@ -0,0 +1,24 @@
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 VacationOvertimeActive(models.Model):
_name = 'vacation.overtime.active'
_description = '加班情况归档'
employee_id = fields.Many2one('hr.employee', string='员工')
department_id = fields.Many2one('hr.department', related='employee_id.department_id', string="部门")
company_id = fields.Many2one('res.company', related='employee_id.company_id', string="公司")
workflow_record_id = fields.Many2one('soong.workflow.record', string='流程')
overtime_name = fields.Char(string="标题")
carry_forward_date = fields.Date(string="结转日期")
carry_forward_quantity = fields.Float(string="结转时长")
carry_result = fields.Selection([('success', '成功'), ('failed', '失败')], string="结转结果")
remaining_quantity = fields.Float(string="剩余数")
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
from odoo import api, fields, models, tools, _
from datetime import datetime, time, timedelta
from odoo.exceptions import UserError
class YuthonParentingAllocate(models.Model):
_name = 'yuthon.parenting.allocate'
_description = '育儿额度分配规则'
company_id = fields.Many2one("res.company", string="公司", default=lambda self: self.env.company)
cycle_years = fields.Integer(string='周期年数', default=1, help='按出生日计算的周期年数,如1表示1年')
cycle_unit = fields.Integer(string='周期单位', default=1, help='周期的描述单位,如“1”周期')
valid_limit = fields.Integer(string='有效期限(岁)', default=1, help='规则生效的截止条件')
distribute = fields.Integer(string='年/发放额度')
start_date = fields.Date(string="生效日期", copy=False, default=fields.Date.today())
end_date = fields.Date(string="失效日期", copy=False, default=fields.Date.from_string('2099-01-01'))
is_enable = fields.Boolean(string="是否启用", compute="compute_is_enable", store=True)
birth_certificate = fields.Text(string='备注', default='需要在花名册配置紧急联系人才能生效')
@api.depends('start_date', 'end_date')
def compute_is_enable(self):
for rec in self:
if not rec.end_date:
rec.is_enable = True
else:
if rec.start_date and rec.end_date:
if rec.start_date <= fields.Date.today() < rec.end_date:
rec.is_enable = True
else:
rec.is_enable = False
@@ -31,6 +31,7 @@ class YuthonVacationReports(models.Model):
year_holiday = fields.Float(string="本年公休日", digits=(16, 3))
year_workday = fields.Float(string="本年工作日", digits=(16, 3))
year_sum = fields.Float(string="本年调休合计", digits=(16, 3), compute="_compute_year_sum")
previous_year1 = fields.Float(string="上年剩余(补休)", digits=(16, 3))
used_this_year1 = fields.Float(string="本年已休", digits=(16, 3))
remainder_year1 = fields.Float(string="剩余(补休)", digits=(16, 3), compute="_compute_year_sum")
@@ -40,6 +41,7 @@ class YuthonVacationReports(models.Model):
overtime_ids = fields.One2many('vacation.over.line', 'vacation_id', string='加班明细')
meal_fee_ids = fields.One2many('vacation.meal.line', 'vacation_id', string='误餐明细')
medical_fee_ids = fields.One2many('vacation.medical.line', 'vacation_id', string='体检费明细')
parenting_line_ids = fields.One2many('vacation.parenting.line', 'vacation_id', string='育儿假明细')
other_fee_ids = fields.One2many('vacation.other.line', 'vacation_id', string='其他明细')
vacation_date = fields.Date(string='日期', default=lambda self: fields.Date.today().replace(day=1))
display_date = fields.Char(string='日期', compute='_compute_display_date')
@@ -68,6 +70,8 @@ class YuthonVacationReports(models.Model):
general_sick_leave = fields.Float(string='病假(普通)', digits=(16, 3), compute='_compute_other_leave', store=True, group_operator=None)
hospital_sick_leave = fields.Float(string='病假(住院期)', digits=(16, 3), compute='_compute_other_leave', store=True, group_operator=None)
recovery_sick_leave = fields.Float(string='病假(出院恢复期)', digits=(16, 3), compute='_compute_other_leave', store=True, group_operator=None)
parental_leave = fields.Float(string='育儿假', digits=(16, 3), compute='_compute_parental_leave', store=True, group_operator=None)
remaining_parental_leave = fields.Float(string='剩余育儿假', digits=(16, 3), compute='_compute_parental_leave', store=True, group_operator=None)
exam_leave = fields.Integer(string='考试假', compute='_compute_other_leave', store=True, group_operator=None)
right_days = fields.Float(string='转正天数', group_operator=None, compute='compute_attendance_fields')
internship_days = fields.Float(string='实习天数', group_operator=None)
@@ -97,6 +101,33 @@ class YuthonVacationReports(models.Model):
tracking=3,
default='not_sent')
@api.depends('other_fee_ids', 'other_fee_ids.holiday_type', 'other_fee_ids.lines',
'other_fee_ids.is_void', 'other_fee_ids.update_type', 'parenting_line_ids',
'parenting_line_ids.update_date', 'parenting_line_ids.end_date', 'parenting_line_ids.lines')
def _compute_parental_leave(self):
today = date.today()
for rec in self:
used_amount = 0.0
deduct_fee_lines = rec.other_fee_ids.filtered(
lambda l:
l.holiday_type.name == '育儿假'
and l.update_type == 'reduce'
and not l.is_void
and l.lines > 0
)
if deduct_fee_lines:
used_amount = sum(line.lines for line in deduct_fee_lines)
rec.parental_leave = used_amount
total_amount = 0.0
valid_parenting_lines = rec.parenting_line_ids.filtered(
lambda l:
l.update_date <= today
and (l.end_date >= today if l.end_date else True)
)
if valid_parenting_lines:
total_amount = sum(line.lines for line in valid_parenting_lines)
rec.remaining_parental_leave = max(total_amount - used_amount, 0.0)
def update_vacation_state(self):
records = self.env["yuthon.vacation.reports"].browse(
self._context.get('active_ids', self._context.get('active_id', self.ids))
@@ -142,6 +173,7 @@ class YuthonVacationReports(models.Model):
for record in self:
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
record.previous_year1 = record.last_holiday + record.last_workday
@api.constrains('employee_id', 'vacation_date')
def _check_duplicate_monthly_record(self):
@@ -993,8 +1025,22 @@ class VacationOverline(models.Model):
)
remaining_quantity = fields.Float(string='剩余数', compute="_compute_remaining_quantity", store=True)
def open_record(self):
tree_id = self.env.ref("yuthon_vacation_reports.view_yuthon_vacation_overtime_tree").id
return {
'type': 'ir.actions.act_window',
'name': 'Overtime Record',
'res_model': 'vacation.meal.line',
'view_mode': 'tree',
'views': [[tree_id, 'tree']],
'domain': [('employee_id', '=', self.employee_id.id),
('carry_forward_state', '=', 'pending')
],
}
@api.model
def confirm(self):
# 1. 构建筛选域
domain = [
'|',
['is_initial_number', '=', True],
@@ -1012,11 +1058,39 @@ class VacationOverline(models.Model):
filtered_records = self.search(domain)
if not filtered_records:
return
records_to_update = filtered_records.filtered(
lambda r: fields.float_compare(r.duration, r.carry_forward_quantity) == 0
valid_records = filtered_records.filtered(
lambda r: r.carry_forward_quantity and r.carry_forward_quantity != 0.0
)
if records_to_update:
records_to_update.write({'is_filing': True})
if not valid_records:
return
active_model = self.env['vacation.overtime.active']
for rec in valid_records:
if rec.remaining_quantity == 0:
rec.is_filing = True
match_domain = [
('employee_id', '=', rec.employee_id.id if rec.employee_id else False),
('workflow_record_id', '=', rec.workflow_record_id.id if rec.workflow_record_id else False),
('carry_forward_date', '=', rec.carry_forward_date or fields.Date.today()),
('overtime_name', '=', rec.overtime_name or '')
]
existing_active = active_model.search(match_domain, limit=1)
active_vals = {
'employee_id': rec.employee_id.id if rec.employee_id else False,
'workflow_record_id': rec.workflow_record_id.id if rec.workflow_record_id else False,
'overtime_name': rec.overtime_name or '',
'remaining_quantity': rec.remaining_quantity,
'carry_forward_date': rec.carry_forward_date or fields.Date.today(),
'carry_forward_quantity': rec.carry_forward_quantity,
'carry_result': 'success'
}
if existing_active:
existing_active.write(active_vals)
else:
active_model.create(active_vals)
def update_is_visible(self):
over_ids = self.env["vacation.over.line"].browse(
@@ -1320,6 +1394,19 @@ class VacationMealLine(models.Model):
return super(VacationMealLine, self).unlink()
class VacationParentingLine(models.Model):
_name = 'vacation.parenting.line'
_description = '育儿明细'
vacation_id = fields.Many2one('yuthon.vacation.reports', string='关联假期额度记录')
employee_id = fields.Many2one('hr.employee', string='员工')
update_date = fields.Date(string='发放日期')
end_date = fields.Date(string='失效日期')
lines = fields.Float(string='额度')
text = fields.Text(string='备注')
is_confirm = fields.Boolean(string="是否确认")
class VacationMedicalLine(models.Model):
_name = 'vacation.medical.line'
_description = '体检费明细'
@@ -85,4 +85,7 @@ access_applet_security_quick_perm_wizard,access_applet_security_quick_perm_wizar
access_vacation_reports_wizard,vacation.reports.wizard,model_vacation_reports_wizard,base.group_user,1,1,1,1
access_yuthon_holiday_statement,access_yuthon_holiday_statement,model_yuthon_holiday_statement,base.group_user,1,1,1,1
access_yuthon_meal_case,access_yuthon_meal_case,model_yuthon_meal_case,base.group_user,1,1,1,1
access_pay_carryover_wizard,pay.carryover.wizard,model_pay_carryover_wizard,base.group_user,1,1,1,1
access_pay_carryover_wizard,pay.carryover.wizard,model_pay_carryover_wizard,base.group_user,1,1,1,1
access_vacation_parenting_line,vacation.parenting.line,model_vacation_parenting_line,base.group_user,1,1,1,1
access_yuthon_parenting_allocate,yuthon.parenting.allocate,model_yuthon_parenting_allocate,base.group_user,1,1,1,1
access_vacation_overtime_active,vacation.overtime.active,model_vacation_overtime_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
85
86
87
88
89
90
91
@@ -7,17 +7,10 @@ export class CustomAttendanceMealConfirmController extends ListController {
setup() {
super.setup();
}
async getAction(lock_type) {
const action = await this.orm.call('vacation.meal.line', 'confirm', [lock_type], {context: this.props.context});
action["context"] = {
...action.context,
...this.model.root.context,
}
return action
await this.orm.call('vacation.meal.line', 'confirm', []);
}
}
registry.category("views").add("custom_vacation_meal_button", {
...listView,
Controller: CustomAttendanceMealConfirmController,
@@ -8,13 +8,9 @@ export class CustomAttendanceStatementConfirmController extends ListController {
super.setup();
}
async getAction(lock_type) {
const action = await this.orm.call('hr.leave', 'confirm', [lock_type], {context: this.props.context});
action["context"] = {
...action.context,
...this.model.root.context,
}
return action
await this.orm.call('hr.leave', 'confirm', []);
}
}
@@ -9,12 +9,7 @@ export class CustomAttendanceVacationConfirmController extends ListController {
}
async getAction(lock_type) {
const action = await this.orm.call('vacation.over.line', 'confirm', [lock_type], {context: this.props.context});
action["context"] = {
...action.context,
...this.model.root.context,
}
return action
await this.orm.call('vacation.over.line', 'confirm', []);
}
}
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="view_vacation_overtime_active_tree" model="ir.ui.view">
<field name="name">vacation.overtime.active.tree</field>
<field name="model">vacation.overtime.active</field>
<field name="arch" type="xml">
<tree string="加班情况(归档)" editable="bottom">
<field name="overtime_name"/>
<field name="employee_id"/>
<field name="department_id"/>
<field name="carry_forward_quantity"/>
<field name="remaining_quantity"/>
<field name="carry_forward_date"/>
<field name="carry_result"/>
</tree>
</field>
</record>
<record id="view_vacation_overtime_active_action" model="ir.actions.act_window">
<field name="name">加班情况(归档)</field>
<field name="res_model">vacation.overtime.active</field>
<field name="view_mode">tree</field>
<field name="view_id" ref="view_vacation_overtime_active_tree"/>
</record>
</odoo>
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id ="yuthon_parenting_allocate_tree" model="ir.ui.view">
<field name="name">yuthon.parenting.allocate.tree</field>
<field name="model">yuthon.parenting.allocate</field>
<field name="arch" type="xml">
<tree editable="bottom">
<field name="cycle_years"/>
<field name="cycle_unit"/>
<field name="valid_limit"/>
<field name="distribute"/>
<field name="birth_certificate"/>
<field name="company_id"/>
</tree>
</field>
</record>
<record id ="yuthon_parenting_allocate_action" model="ir.actions.act_window">
<field name="name">育儿假规则</field>
<field name="res_model">yuthon.parenting.allocate</field>
<field name="view_mode">tree</field>
</record>
</odoo>
@@ -75,6 +75,7 @@
<field name="leave_of_absence" options='{ "fg_color": "white: leave_of_absence == False"}'/>
<field name="statutory_leave" string="加班时(法定假)" options='{ "fg_color": "white: statutory_leave == False"}'/>
<field name="cop_leave" options='{ "fg_color": "white: cop_leave == False"}'/>
<field name="parental_leave" options='{ "fg_color": "white: parental_leave == False"}'/>
<field name="duty_off_leave" options='{ "fg_color": "white: duty_off_leave == False"}'/>
<field name="marriage_leave" options='{ "fg_color": "white: marriage_leave == False"}'/>
<field name="maternity_leave" options='{ "fg_color": "white: maternity_leave == False"}'/>
@@ -124,6 +125,7 @@
<field name="leave_of_absence" options='{ "fg_color": "white: leave_of_absence == False"}'/>
<field name="statutory_leave" string="加班时(法定假)" options='{ "fg_color": "white: statutory_leave == False"}'/>
<field name="cop_leave" options='{ "fg_color": "white: cop_leave == False"}'/>
<field name="parental_leave" options='{ "fg_color": "white: parental_leave == False"}'/>
<field name="duty_off_leave" options='{ "fg_color": "white: duty_off_leave == False"}'/>
<field name="marriage_leave" options='{ "fg_color": "white: marriage_leave == False"}'/>
<field name="maternity_leave" options='{ "fg_color": "white: maternity_leave == False"}'/>
@@ -183,7 +185,9 @@
<group>
<field name="test_days"/>
</group>
<group/>
<group>
<field name="remaining_parental_leave"/>
</group>
</group>
<notebook>
<page string="年假">
@@ -323,6 +327,19 @@
</group>
</group>
</page>
<page string="育儿假">
<field name="parenting_line_ids" context="{'default_employee_id': employee_id}">
<tree editable="bottom" delete="false" edit="false" create="false">
<field name="employee_id" column_invisible="1"/>
<field name="vacation_id" column_invisible="1"/>
<field name="update_date"/>
<field name="end_date"/>
<field name="lines"/>
<field name="text"/>
<field name="is_confirm" column_invisible="1"/>
</tree>
</field>
</page>
<page string="汇总" >
<group>
<field name="is_late_card"/>
@@ -486,6 +503,19 @@
</tree>
</field>
</page>
<page string="育儿假">
<field name="parenting_line_ids" context="{'default_employee_id': employee_id}">
<tree editable="bottom" delete="false" edit="false" create="false">
<field name="employee_id" column_invisible="1"/>
<field name="vacation_id" column_invisible="1"/>
<field name="update_date"/>
<field name="end_date"/>
<field name="lines"/>
<field name="text"/>
<field name="is_confirm" column_invisible="1"/>
</tree>
</field>
</page>
<!-- <page string="出勤消息日志" invisible="1">-->
<!-- <field name="attendance_message_log_ids">-->
<!-- <tree>-->
@@ -548,22 +578,7 @@
<field name="carry_forward_quantity"/>
<field name="carry_forward_date"/>
<field name="remaining_quantity"/>
</tree>
</field>
</record>
<record id="view_yuthon_vacation_overtime_active_tree" model="ir.ui.view">
<field name="name">vacation.over.line.overtime.tree</field>
<field name="model">vacation.over.line</field>
<field name="arch" type="xml">
<tree string="加班情况(归档)" editable="bottom">
<field name="overtime_name"/>
<field name="employee_id" invisible="1"/>
<field name="department_id"/>
<field name="carry_forward_quantity"/>
<field name="carry_forward_date"/>
<field name="is_filing" column_invisible="1"/>
<field name="is_visible" column_invisible="1"/>
<field name="carry_result"/>
<button name="open_record" type="object" string="详情" class="btn-primary"/>
</tree>
</field>
</record>
@@ -615,15 +630,6 @@
<field name="context">{'search_default_now_month': 1, 'search_default_group_by_employee_id':1}</field>
<field name="view_id" ref="view_yuthon_vacation_overtime_tree"/>
<field name="search_view_id" ref="view_yuthon_vacation_overtime_search"/>
</record>
<record id="action_overtime_approval_active_report" model="ir.actions.act_window">
<field name="name">加班情况(归档)</field>
<field name="res_model">vacation.over.line</field>
<field name="view_mode">tree</field>
<field name="domain">['|', ('workflow_record_id','!=', False), ('is_initial_number', '=', True), ('update_type', '=', 'add'), ('is_filing','=', True), ('is_visible', '=', False)]</field>
<field name="context">{'search_default_group_by_employee_id':1}</field>
<field name="view_id" ref="view_yuthon_vacation_overtime_active_tree"/>
<field name="search_view_id" ref="view_yuthon_vacation_overtime_search"/>
</record>
<record id="update_vacation_over_line" model="ir.actions.server">
<field name="name">触发计算逻辑</field>
@@ -22,7 +22,7 @@ class PayCarryoverWizard(models.TransientModel):
is_2025_december = rec.vacation_date.year == 2026 and rec.vacation_date.month == 1
if rec.overtime_ids:
for overtime in rec.overtime_ids:
if overtime.text == '上月额度继承' and overtime.total > 40:
if overtime.text == '上月额度继承' and overtime.duration > 40:
reduce_workday = overtime.workday - 40
new_overtime = self.env['vacation.over.line'].create([{
'vacation_id': rec.id,
+40 -25
View File
@@ -876,10 +876,15 @@ class YuthonHrEmployee(models.Model):
def update_parental_leave(self):
today = datetime.now().date()
active_contracts = self.env['hr.contract'].search([
('employee_id.name','=', '和博延'),
('state', '=', 'open'),
('contract_type_id.name', 'ilike', '正式合同'),
('employee_id', '!=', False)
])
allocate_config = self.env['yuthon.parenting.allocate'].search([], limit=1)
valid_limit = allocate_config.valid_limit # 截至年龄(如3)
cycle_years = allocate_config.cycle_years # 周期年数(如1)
distribute = allocate_config.distribute #
if not active_contracts:
return
employees = active_contracts.mapped('employee_id')
@@ -905,50 +910,60 @@ class YuthonHrEmployee(models.Model):
except (ValueError, IndexError):
continue
age_delta = today - birth_date
if age_delta > timedelta(days=3 * 365):
valid_end_date = birth_date + relativedelta(years=valid_limit)
if today > valid_end_date:
continue
cycle1_end = birth_date + relativedelta(years=1) # 第1年到期日
cycle2_end = birth_date + relativedelta(years=2) # 第2年到期日
cycle3_end = birth_date + relativedelta(years=3) # 第3年到期日(3岁生日)
cycle_list = []
current_cycle_start = birth_date
total_cycles = int(valid_limit / cycle_years)
if today <= cycle1_end:
date_from = birth_date
date_to = cycle1_end - timedelta(days=1)
elif today <= cycle2_end:
date_from = cycle1_end
date_to = cycle2_end - timedelta(days=1)
else:
date_from = cycle2_end
date_to = cycle3_end - timedelta(days=1)
for i in range(1, total_cycles + 1):
current_cycle_end = current_cycle_start + relativedelta(years=cycle_years)
cycle_list.append({
'cycle_num': i,
'start': current_cycle_start,
'end': current_cycle_end
})
current_cycle_start = current_cycle_end
date_from = birth_date
date_to = valid_end_date - timedelta(days=1)
for cycle in cycle_list:
if today <= cycle['end']:
date_from = cycle['start']
date_to = cycle['end'] - timedelta(days=1)
break
total_days = distribute
if total_days <= 0:
continue
total_days = (date_to - date_from).days + 1
holiday_status_id = self.env['hr.leave.type'].search([('name', '=', '育儿假')], limit=1)
# 更新报表
other_list = []
parenting_line_ids = []
reports_id = self.env['yuthon.vacation.reports'].search([
('employee_id', '=', employee.id),
('vacation_date', '=', fields.Date.today().replace(day=1))
], limit=1) #
if reports_id:
existing_line = reports_id.other_fee_ids.search([
('holiday_type', '=', holiday_status_id.id),
existing_line = reports_id.parenting_line_ids.search([
('vacation_id', '=', reports_id.id),
('employee_id', '=', employee.id),
('update_date', '=', date_from),
('update_type', '=', 'add')
('end_date', '=', date_to),
('text','=', '育儿假分配')
], limit=1)
if not existing_line:
other_list.append([0, 0, {
parenting_line_ids.append([0, 0, {
'vacation_id': reports_id.id,
'holiday_type': holiday_status_id.id,
'employee_id': employee.id,
'update_date': date_from,
'update_type': 'add',
'end_date': date_to,
'lines': total_days,
'text': '育儿假'
'text': '育儿假分配'
}])
if other_list:
reports_id.write({'other_fee_ids': other_list})
if parenting_line_ids :
reports_id.write({'parenting_line_ids': parenting_line_ids})
# 6. 检查是否已存在相同分配记录,避免重复
existing_allocation = self.env['hr.leave.allocation'].search([
+1
View File
@@ -43,6 +43,7 @@
'wizard/temporary_payslip_wizard_views.xml',
'wizard/salary_import_wizard_views.xml',
'wizard/yuthon_payroll_wizard_views.xml',
'wizard/salary_active_wizard_views.xml',
'wizard/basic_pension_wizard_views.xml',
'wizard/payroll_labor_wizard_views.xml',
'wizard/payroll_retired_wizard_views.xml',
+21 -5
View File
@@ -99,14 +99,30 @@ class YuthonSalaryActive(models.Model):
self.write({'confirm_status': 'un_confirm'})
def open_archive_record(self):
tree_id = self.env.ref("yuthon_salary.view_yuthon_salary_active_tree").id
self.ensure_one()
float_fields_with_value = []
for field_name, field in self._fields.items():
if field.type == 'float' and self[field_name] != 0 and self[field_name] is not False:
float_fields_with_value.append({
'field_name': field_name,
'field_string': field.string,
'field_value': self[field_name]
})
return {
'name': '工资条',
'type': 'ir.actions.act_window',
'res_model': 'yuthon.salary.active',
'views': [[tree_id, 'tree']],
'view_mode': 'tree',
'domain': [('employee_id', '=', self.employee_id.id)],
'res_model': 'salary.active.wizard',
'view_mode': 'form',
'target': 'new',
'context': {
'default_actual_wages': self.actual_paid_salary,
'default_select_year': self.select_year,
'default_select_time': self.select_time,
'default_active_line': [(0, 0, {
'name': item['field_string'],
'amount': item['field_value']
}) for item in float_fields_with_value]
}
}
def _get_default_month(self):
+4 -1
View File
@@ -45,4 +45,7 @@ access_party_send_wizard,access_party_send_wizard,model_party_send_wizard,base.g
access_yuthon_meal_expenses,access_yuthon_meal_expenses,model_yuthon_meal_expenses,base.group_user,1,1,1,1
access_party_meal_wizard,access_party_meal_wizard,model_party_meal_wizard,base.group_user,1,1,1,1
access_salary_meal_wizard,access_salary_meal_wizard,model_salary_meal_wizard,base.group_user,1,1,1,1
access_yuthon_salary_active,access_yuthon_salary_active,model_yuthon_salary_active,base.group_user,1,1,1,1
access_yuthon_salary_active,access_yuthon_salary_active,model_yuthon_salary_active,base.group_user,1,1,1,1
access_salary_active_wizard,access__salary_active_wizard,model_salary_active_wizard,base.group_user,1,1,1,1
access_salary_active_line,access_salary_active_line,model_salary_active_line,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
45 access_salary_active_line access_salary_active_line model_salary_active_line base.group_user 1 1 1 1
46
47
48
49
50
51
+2 -1
View File
@@ -17,4 +17,5 @@ from . import salary_party_wizard
from . import salary_import_wizard
from . import party_send_wizard
from . import party_meal_wizard
from . import salary_meal_wizard
from . import salary_meal_wizard
from . import salary_active_wizard
@@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
from dateutil.relativedelta import relativedelta
from odoo import models, fields, api, _, SUPERUSER_ID
from odoo.exceptions import ValidationError, UserError
from odoo.exceptions import ValidationError
import calendar
from pypinyin import pinyin, Style
import math
import xlrd
import base64
import datetime
from datetime import datetime, timedelta
class SalaryActiveWizard(models.TransientModel):
_name = 'salary.active.wizard'
_description = '工资条查询'
active_line = fields.One2many('salary.active.line', 'active_id', string='明细')
select_time = fields.Selection([('1', '一月'), ('2', '二月'), ('3', '三月'), ('4', '四月'),
('5', '五月'), ('6', '六月'), ('7', '七月'), ('8', '八月'),
('9', '九月'), ('10', '十月'), ('11', '十一月'),
('12', '十二月')], string='月份',
default=lambda self: self._get_default_month())
select_year = fields.Selection(selection=[(str(i), str(i)) for i in range(2024, 2040)], string='年份')
select_name = fields.Char(compute='_get_default_name')
actual_wages = fields.Float(string='实发工资')
@api.depends('select_year', 'select_time')
def _get_default_name(self):
for rec in self:
rec.select_name = rec.select_year + '年' + rec.select_time + '月'
class SalaryActiveLine(models.TransientModel):
_name = 'salary.active.line'
_description = '明细'
sequence = fields.Char(string='序号', store=True)
active_id = fields.Many2one('salary.active.wizard', string='工资条')
name = fields.Char(string='工资条')
amount = fields.Float(string='金额')
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="salary_active_wizard_form" model="ir.ui.view">
<field name="name">工资条查询</field>
<field name="model">salary.active.wizard</field>
<field name="arch" type="xml">
<form>
<sheet>
<field name="select_year" invisible="1"/>
<field name="select_time" invisible="1"/>
<field name="select_name" invisible="1"/>
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
<field name="select_name" readonly="1" style="font-weight: bold; font-size: 18px;"/>
<div style="text-align: right;">
<span style="font-size: 14px; color: #666; margin-right: 8px;"/>
<h1 style="display: inline; font-weight: bold; font-size: 20px; margin: 0;">
<field name="actual_wages" readonly="1"/>
</h1>
</div>
</div>
<field name="active_line" string=" ">
<tree editable="bottom" create="0" edit="0" delete="0">
<field name="sequence" widget="handle"/>
<field name="active_id" column_invisible="1"/>
<field name="name"/>
<field name="amount" readonly="1"/>
</tree>
</field>
</sheet>
</form>
</field>
</record>
</odoo>
+9 -4
View File
@@ -166,17 +166,17 @@
sequence="14"/>
<menuitem id="menu_yuthon_overtime_report_board_work_brand"
name="加班情况"
name="加班明细"
parent="hr_attendance_root_board_menu"
action="yuthon_hr_attendance.action_overtime_approval_report"
sequence="15"/>
<menuitem id="menu_yuthon_holiday_statement_board"
name="请假情况"
name="请假明细"
parent="hr_attendance_root_board_menu"
action="yuthon_hr_attendance.view_yuthon_holiday_statement_action"
sequence="16"/>
<menuitem id="menu_yuthon_meal_case_board"
name="误餐情况"
name="误餐明细"
parent="hr_attendance_root_board_menu"
action="yuthon_hr_attendance.view_yuthon_vacation_meal_action"
sequence="17"/>
@@ -311,6 +311,11 @@
parent="attendance_resources_setting_root_board"
action="hr_holidays.hr_leave_allocation_action_approve_department"
sequence="20"/>
<menuitem id="yuthon_parenting_allocate_board"
name="育儿假规则"
parent="attendance_resources_setting_root_board"
action="yuthon_hr_attendance.yuthon_parenting_allocate_action"
sequence="21"/>
<menuitem id="holiday_set_vacation_board"
name="公共假期"
parent="attendance_resources_setting_root_board"
@@ -735,7 +740,7 @@
<menuitem id="yuthon_overtime_active_menu"
parent="yuthon_vacation_active_menu"
name="加班归档"
action="yuthon_hr_attendance.action_overtime_approval_active_report"
action="yuthon_hr_attendance.view_vacation_overtime_active_action"
sequence="20"
/>
<menuitem id="yuthon_menu_active_menu"