192 lines
8.5 KiB
Python
192 lines
8.5 KiB
Python
from odoo import api, fields, models, _
|
|
import re
|
|
from pypinyin import pinyin, Style
|
|
|
|
|
|
class HrPayrollStructure(models.Model):
|
|
_inherit = 'hr.payroll.structure'
|
|
_order = 'sequence asc'
|
|
|
|
company_id = fields.Many2one('res.company', string="公司", default=lambda self: self.env.company)
|
|
yuthon_company = fields.Selection([('thtz', 'thtz')], default="thtz")
|
|
type_id = fields.Many2one('hr.payroll.structure.type', string="职级类型")
|
|
level_id = fields.Many2one('yuthon.payroll.type.setting', string="级别")
|
|
lv_name = fields.Char(related='level_id.name', string='级别名称', store=True)
|
|
name = fields.Char(string="职级名称")
|
|
sequence = fields.Char(string='级别序号', store=True)
|
|
create_time = fields.Date(string="生效日期", default=fields.Date.today())
|
|
end_time = fields.Date(string="失效日期")
|
|
is_enable = fields.Boolean(string="启用", default=True)
|
|
currency_id = fields.Many2one("res.currency", string="货币", required=True, default=lambda self: self.env.company.currency_id)
|
|
base_salary = fields.Monetary(string="基本工资", currency_field="currency_id")
|
|
rank_salary = fields.Monetary(string="职级工资", currency_field="currency_id")
|
|
communication_subsidy = fields.Monetary(string="通讯补贴", currency_field="currency_id")
|
|
position_salary = fields.Monetary(string="岗位工资", currency_field="currency_id")
|
|
position_subsidy = fields.Monetary(string="岗位补贴", currency_field="currency_id")
|
|
integrated_subsidy = fields.Monetary(string="综合补贴", currency_field="currency_id")
|
|
advance_performance_bonuses = fields.Monetary(string="预发绩效奖金", currency_field="currency_id")
|
|
|
|
@api.model
|
|
def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True):
|
|
res = super(HrPayrollStructure, self).read_group(domain, fields, groupby, offset=offset, limit=limit, orderby=orderby,
|
|
lazy=lazy)
|
|
if 'lv' in groupby:
|
|
def sort_by_sequence_number(item):
|
|
lv = item.get('lv')
|
|
if lv:
|
|
rec = self.search([('lv', '=', lv)], limit=1)
|
|
if rec and rec.sequence:
|
|
match = re.findall(r'\d+', rec.sequence)
|
|
if match:
|
|
number_str = "".join(match)
|
|
try:
|
|
number = int(number_str)
|
|
return (not number_str.startswith('0'), number)
|
|
except ValueError:
|
|
return (False, 0)
|
|
return (False, 0) # 首位非0的放前面
|
|
res.sort(key=sort_by_sequence_number)
|
|
return res
|
|
|
|
def _handle_salary_rule(self, field_name, amount):
|
|
category_id = self.env['hr.salary.rule.category'].search([('name', '=', '职级')], limit=1)
|
|
if amount:
|
|
name_pinyin = pinyin(field_name, style=Style.FIRST_LETTER)
|
|
code = "".join([p[0][0] for p in name_pinyin]).upper()
|
|
salary_id = self.env['hr.salary.rule'].search(
|
|
[('name', '=', field_name), ('struct_id', '=', self.id.origin)], limit=1)
|
|
if not salary_id:
|
|
self.env['hr.salary.rule'].create({
|
|
'name': field_name,
|
|
'category_id': category_id.id,
|
|
'code': code,
|
|
'amount_fix': amount,
|
|
'struct_id': self.id.origin
|
|
})
|
|
else:
|
|
salary_id.write({
|
|
'amount_fix': amount
|
|
})
|
|
|
|
@api.onchange('base_salary')
|
|
def _onchange_base_salary(self):
|
|
self._handle_salary_rule('基本工资', self.base_salary)
|
|
|
|
@api.onchange('rank_salary')
|
|
def _onchange_rank_salary(self):
|
|
self._handle_salary_rule('职级工资', self.rank_salary)
|
|
|
|
@api.onchange('communication_subsidy')
|
|
def _onchange_communication_subsidy(self):
|
|
self._handle_salary_rule('通讯补贴', self.communication_subsidy)
|
|
|
|
@api.onchange('position_salary')
|
|
def _onchange_position_salary(self):
|
|
self._handle_salary_rule('岗位工资', self.position_salary)
|
|
|
|
@api.onchange('position_subsidy')
|
|
def _onchange_position_subsidy(self):
|
|
self._handle_salary_rule('岗位补贴', self.position_subsidy)
|
|
|
|
@api.onchange('integrated_subsidy')
|
|
def _onchange_integrated_subsidy(self):
|
|
self._handle_salary_rule('综合补贴', self.integrated_subsidy)
|
|
|
|
@api.onchange('advance_performance_bonuses')
|
|
def _onchange_advance_performance_bonuses(self):
|
|
self._handle_salary_rule('预发绩效奖金', self.advance_performance_bonuses)
|
|
|
|
def open_record(self):
|
|
return {
|
|
"type": "ir.actions.act_window",
|
|
"res_model": 'hr.payroll.structure',
|
|
"res_id": self.id,
|
|
"name": "职级详情",
|
|
"view_mode": "form",
|
|
}
|
|
|
|
def action_yuthon_payroll_wizard(self):
|
|
return {
|
|
"type": "ir.actions.act_window",
|
|
"name": "导入薪资",
|
|
"res_model": "yuthon.payroll.wizard",
|
|
"view_mode": "form",
|
|
"target": "new",
|
|
}
|
|
|
|
def generate_salary_rules(self, company_code, field_mapping):
|
|
# 搜索符合条件的薪资结构
|
|
company_id = self.env['res.company'].search([('name', '=', company_code)], limit=1)
|
|
structure_ids = self.env['hr.payroll.structure'].search([('company_id', '=', company_id.id)])
|
|
for structure in structure_ids:
|
|
# # 清空当前结构的规则
|
|
# structure.rule_ids.unlink()
|
|
# 初始化规则列表
|
|
rule_list = []
|
|
for rule_name, field_attr in field_mapping.items():
|
|
field_amount = getattr(structure, field_attr)
|
|
if field_amount is not None:
|
|
name_pinyin = pinyin(rule_name, style=Style.FIRST_LETTER)
|
|
code = "".join([p[0][0] for p in name_pinyin]).upper()
|
|
category_id = self.env['hr.salary.rule.category'].search([('name', '=', '职级')], limit=1)
|
|
rule_list.append([0, 0, {
|
|
'name': rule_name,
|
|
'category_id': category_id.id,
|
|
'code': code,
|
|
'amount_fix': field_amount,
|
|
'struct_id': structure.id,
|
|
'company_id': structure.company_id.id
|
|
}])
|
|
if rule_list:
|
|
structure.write({'rule_ids': rule_list})
|
|
|
|
def salary_rule_data(self):
|
|
# 定义不同公司的字段映射
|
|
company_mappings = {
|
|
'天河物管': { # 天河物管
|
|
'基本工资': 'base_salary',
|
|
'岗位工资': 'position_salary',
|
|
'综合补贴': 'integrated_subsidy',
|
|
'通讯补贴': 'communication_subsidy'
|
|
},
|
|
'天河粮储': { # 天河梁储
|
|
'基本工资': 'base_salary',
|
|
'岗位工资': 'position_salary',
|
|
'岗位补贴': 'position_subsidy',
|
|
'预发绩效奖金': 'advance_performance_bonuses'
|
|
}
|
|
}
|
|
|
|
for company_code, field_mapping in company_mappings.items():
|
|
self.generate_salary_rules(company_code, field_mapping)
|
|
|
|
def action_select_delete_wizard(self):
|
|
return {
|
|
"type": "ir.actions.act_window",
|
|
"name": "选择删除",
|
|
"res_model": "select.delete.wizard",
|
|
"view_mode": "form",
|
|
"target": "new",
|
|
}
|
|
|
|
def delete_structure(self):
|
|
payroll_ids = self.env["hr.payroll.structure"].browse(
|
|
self._context.get('active_ids', self._context.get('active_id')))
|
|
for payroll in payroll_ids:
|
|
for rule in payroll.rule_ids:
|
|
rule.sudo().unlink()
|
|
|
|
def update_payroll_items(self):
|
|
payroll_ids = self.env["hr.payroll.structure"].browse(
|
|
self._context.get('active_ids', self._context.get('active_id')))
|
|
category_id = self.env['hr.salary.rule.category'].search([('name', '=', '常用项')], limit=1)
|
|
for payroll in payroll_ids:
|
|
self.env['hr.salary.rule'].create({
|
|
'name': '质检员津贴',
|
|
'code': 'ZJYJT',
|
|
'category_id': category_id.id,
|
|
'struct_id': payroll.id,
|
|
'sequence': 1,
|
|
'amount_select': 'fix',
|
|
})
|