Files
gzth/yuthon_salary/models/yuthon_payroll_project.py
T
2026-09-02 12:01:32 +08:00

259 lines
15 KiB
Python

from email.policy import default
from odoo import api, fields, models, _
from pypinyin import pinyin, Style
class YuthonPayrollCommon(models.Model):
_name = 'yuthon.payroll.common'
_description = '薪资常用项'
_order = 'sequence asc'
yuthon_company = fields.Selection([('thtz', 'thtz')], default="thtz")
company_id = fields.Many2one('res.company', string="公司", default=lambda self: self.env.company)
name = fields.Char(string='工资项名称')
sequence = fields.Char(string='序号', store=True)
department_id = fields.Many2one('hr.department', string="部门")
payroll_structure_ids = fields.Many2many('hr.payroll.structure', string="排除职级范围", store=True)
payroll_type_ids = fields.Many2many('yuthon.payroll.type.setting', string="排除薪资类别")
conditional_formulas = fields.Text(string='条件公式')
start_date = fields.Date(string="生效日期", default=fields.Date.today())
end_date = fields.Date(string="失效日期")
before_tax = fields.Boolean(string="税前")
is_enable = fields.Boolean(string="启用", default=True)
create_time = fields.Date(string="创建日期", default=fields.Datetime.now)
attributes = fields.Selection([('increment', '增'), ('deduction', '减')], string="工资项属性", default='increment')
@api.onchange('payroll_type_ids')
def _onchange_payroll_type_ids(self):
if self.payroll_type_ids:
structures = self.env['hr.payroll.structure'].search([('level_id', 'in', self.payroll_type_ids.ids)])
self.payroll_structure_ids = [(6, 0, structures.ids)]
else:
self.payroll_structure_ids = [(6, 0, [])]
def create_salary_common(self):
"""
更新常用项职级
:return:
# Available variables:
#----------------------
# payslip: hr.payslip object
# employee: hr.employee object
# contract: hr.contract object
# rules: dict containing the rules code (previously computed)
# categories: dict containing the computed salary rule categories (sum of amount of all rules belonging to that category).
# worked_days: dict containing the computed worked days
# inputs: dict containing the computed inputs.
# Note: returned value have to be set in the variable 'result'
result = contract.wage * 0.10
"""
insurances_ids = self.env["yuthon.payroll.common"].browse(self._context.get('active_ids', self._context.get('active_id')))
for ins in insurances_ids:
for sal in self.env["hr.payroll.structure"].search([('company_id', '=', ins.company_id.id)]):
if sal.id in ins.payroll_structure_ids.ids:
continue
rule_list = []
formula_salary = ''
if ins.name == '扣发绩效奖金':
formula_salary = "result = (employee.last_month_performance_deduction) * -1"
if ins.name == '扣发通信补贴':
formula_salary = "result = (employee.last_month_commuting_deduction) * -1"
if ins.name == '扣发基本工资':
formula_salary = "result = (employee.last_month_base_salary_deduction) * -1"
if ins.name == '工龄工资' and ins.company_id.id == 3:
formula_salary = "result = employee.company_old_year * 10 if employee.company_old_year >= 1 and employee.department_id.name != '领导班子' else 0"
if ins.name == '工龄工资' and ins.company_id.name == '集团本部':
formula_salary = "result = 0 if (employee.is_annual_salary or '劳务' in (employee.contract_id.structure_type_id.name or '') or '工勤返聘' in (employee.contract_id.structure_type_id.name or '')) else (employee.company_old_year * 10)"
if ins.name == '误餐费':
formula_salary = "result = employee.meal_number * 40 + employee.meal_supplement"
if ins.name == '通讯补贴':
formula_salary = "result = 0 if (employee.is_annual_salary or '劳务' in (employee.contract_id.structure_type_id.name or '') or '工勤返聘' in (employee.contract_id.structure_type_id.name or '')) else 300"
if ins.name == '全勤奖' and ins.company_id.name == '集团本部':
formula_salary = "result = 0 if (employee.is_annual_salary or '劳务' in (employee.contract_id.structure_type_id.name or '') or '工勤返聘' in (employee.contract_id.structure_type_id.name or '')) else (200 if employee.last_attendance else 0)"
if ins.name == '全勤奖' and ins.company_id.id == 3:
formula_salary = "result = 100 if employee.last_attendance else 0"
if ins.name == '加班费':
formula_salary = "result = 0 if (employee.is_annual_salary or employee.contract_id.structure_type_id.name == '工勤返聘') else (round(((employee.last_month_overtime - 40) * (payslip.base_salary / 21.75 / 8) * 1.5), 0) if employee.last_month_overtime > 40 else 0)"
if ins.name == '岗位工资':
formula_salary = "result = 0"
if ins.name == '安全生产管理补贴':
formula_salary = "result = employee.security_amount "
if ins.name == '工龄补贴' and ins.company_id.id == 3:
formula_salary = "result = min(400, max(0, ((employee.entry_date - employee.open_start_time).days // 30.4375 - employee.interrupt_work_month) // 12) * 10 + employee.salary_year * 20) if employee.department_id.name != '领导班子' else 0"
if ins.name == '岗位绩效':
formula_salary = "result = 0"
if ins.name == '高温补贴':
formula_salary = "result = 0"
if ins.name == '优秀部门经理/员工':
formula_salary = "result = 0"
if ins.name == '请假扣发':
formula_salary = "result = 0"
if ins.name == '值班(含节日加班)':
formula_salary = "result = 0"
if ins.name == '上月值班费':
formula_salary = "result = 0"
if ins.name == '环境作业津贴':
formula_salary = "result = 0"
if ins.name == '儿童节慰问金':
formula_salary = "result = 0"
if ins.name == '春节福利' and ins.company_id.id == 3:
formula_salary = "result = 680 if employee.salary_month == '1' and employee.department_id.name != '领导班子' else 0"
if ins.name == '质检员津贴':
formula_salary = "result = employee.quality_inspector_amount"
if ins.name == '工会会费' and (ins.company_id.id == 3 or ins.company_id.name == '集团本部'):
formula_salary = "result = round(abs(payslip.base_salary * 0.005) * -1, 2)"
if ins.name == '工会会费' and ins.company_id.name == '天河粮储':
formula_salary = "result = abs(20 if employee.user_role_id.name in ['总经理', '副总经理'] else \
15 if employee.user_role_id.name in ['部门经理', '部门副经理'] else \
5 if employee.job_id.name == '工勤' else \
10) * -1"
if ins.name == '岗位补贴':
formula_salary = "result = employee.subsidy_amount"
if ins.name == '应补(退)税额':
formula_salary = "result = 0"
if ins.name not in sal.rule_ids.mapped('name'):
rule_list.append([0, 0, {
'name': ins.name,
'category_id': self.env['hr.salary.rule.category'].search([('name', '=', '常用项')], limit=1).id,
'code': "".join([p[0][0] for p in pinyin(ins.name, style=Style.FIRST_LETTER)]).upper(),
'amount_select': 'code',
'company_id': ins.company_id.id,
'amount_python_compute': formula_salary,
'struct_id': sal.id,
}])
sal.write({'rule_ids': rule_list})
else:
sal.rule_ids.search([('name', '=', ins.name), ('company_id', '=', ins.company_id.id)]).write({'amount_python_compute': formula_salary})
@api.depends('start_date', 'end_date')
def compute_is_enable(self):
for rec in self:
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
class YuthonPayrollTemporary(models.Model):
_name = 'yuthon.payroll.temporary'
_description = '薪资临时项'
company_id = fields.Many2one('res.company', string="公司", default=lambda self: self.env.company)
name = fields.Char(string='工资项名称')
department_id = fields.Many2one('hr.department', string="部门")
attributes = fields.Selection([('increment', '增'), ('deduction', '减')], string="工资项属性", default='increment')
is_before_tax = fields.Boolean(string="税前")
start_date = fields.Date(string="生效日期", default=fields.Date.today())
end_date = fields.Date(string="失效日期")
def create_salary_temporary(self):
"""
更新薪资临时项
:return:
"""
insurances_ids = self.env["yuthon.payroll.temporary"].browse(self._context.get('active_ids', self._context.get('active_id')))
for ins in insurances_ids:
for sal in self.env["hr.payroll.structure"].search([('company_id', '=', ins.company_id.id)]):
rule_list = []
if ins.name not in sal.rule_ids.mapped('name'):
rule_list.append([0, 0, {
'name': ins.name,
'category_id': self.env['hr.salary.rule.category'].search([('name', '=', '临时项')], limit=1).id,
'code': "".join([p[0][0] for p in pinyin(ins.name, style=Style.FIRST_LETTER)]).upper(),
'amount_select': 'fix',
'amount_fix': 0,
'struct_id': sal.id,
}])
sal.write({'rule_ids': rule_list})
class YuthonPayrollInsurances (models.Model):
_name = 'yuthon.payroll.insurances'
_description = '五险一金'
company_id = fields.Many2one('res.company', string="公司", default=lambda self: self.env.company)
name = fields.Char(string='工资项名称')
is_base = fields.Boolean(string='独立基数')
basic_medical_insurance = fields.Float(string='基本医疗保险费', store=True)
basic_endowment_insurance = fields.Float(string='基本养老保险费', store=True)
unemployment_insurance = fields.Float(string='失业保险费', store=True)
housing_provident_fund = fields.Float(string='住房公积金', store=True)
proportion_company = fields.Float(string='公司缴纳比例')
proportion_employee = fields.Float(string='个人缴纳比例', digits=(16, 3))
proportion_company_ceiling = fields.Float(string='公司缴纳比例上限')
proportion_company_floor = fields.Float(string='公司缴纳比例下限')
company_base_ceiling = fields.Float(string='公司缴纳基数上限')
company_base_floor = fields.Float(string='公司缴纳基数下限')
employee_base_ceiling = fields.Float(string='个人缴纳基数上限')
employee_base_floor = fields.Float(string='个人缴纳基数下限')
documents_ids = fields.Many2many('ir.attachment', string="附件")
payroll_type_ids = fields.Many2many('yuthon.payroll.type.setting', string="排除薪资类别")
payroll_structure_ids = fields.Many2many('hr.payroll.structure', string="排除职级范围")
remarks = fields.Text(string="备注")
start_date = fields.Date(string="生效日期", default=fields.Date.today())
end_date = fields.Date(string="失效日期")
@api.onchange('payroll_type_ids')
def _onchange_payroll_type_ids(self):
if self.payroll_type_ids:
structures = self.env['hr.payroll.structure'].search([('level_id', 'in', self.payroll_type_ids.ids)])
self.payroll_structure_ids = [(6, 0, structures.ids)]
else:
self.payroll_structure_ids = [(6, 0, [])]
def create_salary_five(self):
"""
更新五险一金
:return:
"""
insurances_ids = self.env["yuthon.payroll.insurances"].browse(self._context.get('active_ids', self._context.get('active_id')))
for ins in insurances_ids:
salary_lv_ids = self.env["hr.payroll.structure"].search([('company_id', '=', ins.company_id.id)])
for sal in salary_lv_ids:
if sal.id in ins.payroll_structure_ids.ids:
continue
rule_list = []
formula_salary = ''
number = ins.proportion_employee * 0.01 * -1
code = 'None'
if ins.name == '基本医疗保险费':
code = 'JBYLIAO'
formula_salary = "result = 0"
if ins.name == '基本养老保险费':
code = 'JBYLAO'
formula_salary = "result = 0"
if ins.name == '失业保险费':
code = 'SYBX'
formula_salary = "result = 0"
if ins.name == '工伤保险费':
code = 'GSBX'
formula_salary = "result = employee.social_base_on * " + str(number)
if ins.name == '住房公积金':
code = 'ZFGJJ'
formula_salary = "result = (round((employee.salary_housing_fund * " + str(number) + "), 0)) if employee.is_accum_salary else 0"
if ins.name == '企业(职业)年金':
if ins.company_id.id == 3:
code = 'WGQYNJ'
formula_salary = "result = 0.0 if employee.total_coefficients == 0 else round(abs((employee.converted/employee.total_coefficients * employee.calculation_totals * 0.08 * 0.5)/12) * -1, 2)"
elif ins.company_id.name == '集团本部':
code = 'QYNJ'
formula_salary = "result = round(abs(employee.last_year_salary * 0.02) * -1, 0)"
else:
code = 'LCQYNJ'
formula_salary = "result = round(abs(employee.last_year_salary * 0.02) * -1, 2)"
if ins.name not in sal.rule_ids.mapped('name'):
rule_list.append([0, 0, {
'name': ins.name,
'category_id': self.env['hr.salary.rule.category'].search([('name', '=', '五险一金')], limit=1).id,
'code': code,
'company_id': ins.company_id.id,
'amount_select': 'code',
'amount_python_compute': formula_salary,
'struct_id': sal.id,
}])
sal.write({'rule_ids': rule_list})
else:
sal.rule_ids.search([('name', '=', ins.name), ('company_id', '=', ins.company_id.id)]).write({'amount_python_compute': formula_salary, 'code':code,})