!4034 添加功能

Merge pull request !4034 from 李鹏宇/dev_zhou
This commit is contained in:
李鹏宇
2025-07-24 10:00:54 +00:00
committed by Gitee
4 changed files with 172 additions and 116 deletions
+1
View File
@@ -9,6 +9,7 @@
<field name="name"/>
<field name="model"/>
<field name="xml_id"/>
<field name="group_ids" widget="many2many_tags"/>
</tree>
</field>
</record>
+1 -1
View File
@@ -150,7 +150,7 @@ class InheritHrPayslip(models.Model):
medical_insurance_base = fields.Float(string='医疗保险缴费基数(单位缴纳)')
medical_insurance_payable = fields.Float(string='医疗保险应缴金额(单位缴纳)')
performance_deduction = fields.Float(string='扣发绩效奖金', compute='_compute_deduction', store=True)
performance_deduction = fields.Float(string='扣发绩效奖金')
commuting_deduction = fields.Float(string='扣发通信补贴', compute='_compute_deduction', store=True)
base_salary_deduction = fields.Float(string='扣发基本工资', compute='_compute_deduction', store=True)
specialized_deduction = fields.Float(string='累计专项扣除')
@@ -372,58 +372,67 @@
<button name="action_temporary_payslip_wizard" string="导入工资项" type="object" class="oe_highlight"/>
<button name="action_refresh_from_work_entries" string="重新计算" type="object" class="oe_highlight"/>
</header>
<button name="open_record" string="详情" type="object" class="oe_highlight"/>
<field name="employee_id" string="姓名" readonly="1" options="{'no_open': True}"/>
<field name="date_of_entry"/>
<field name="total_before_tax"/>
<field name="three_one"/>
<field name="b_year"/>
<field name="union_dues"/>
<field name="base_salary" required="1"/>
<field name="basic_endowment_insurance"/>
<field name="basic_medical_insurance"/>
<field name="unemployment_insurance"/>
<field name="housing_provident_fund"/>
<field name="work_injury_insurance"/>
<field name="maternity_allowance"/>
<field name="individual_income_tax"/>
<field name="add_income_tax"/>
<field name="minus_annuity_difference"/>
<field name="add_annuity_difference"/>
<field name="minus_att"/>
<field name="add_att"/>
<field name="last_year_jie"/>
<field name="rank_salary" required="1"/>
<field name="performance_bonuses" required="1"/>
<field name="based_pay" required="1"/>
<field name="seniority_salary" required="1"/>
<field name="commuting_allowance" required="1"/>
<field name="full_attendance_award"/>
<field name="overtime_pay"/>
<field name="meal_misunderstanding_fee"/>
<field name="condolence_fund"/>
<field name="children_welfare_fee"/>
<field name="base_salary_deduction"/>
<field name="retroactive_allowance"/>
<field name="specialized_deduction"/>
<field name="individual_tax_refund"/>
<field name="social_security"/>
<field name="liquidation_year"/>
<field name="safety_incentives"/>
<field name="year_compute"/>
<field name="year_jie"/>
<field name="performance_up"/>
<field name="jing_te"/>
<field name="year_gong"/>
<field name="study_on"/>
<field name="base_salary_deduction"/>
<field name="commuting_deduction"/>
<field name="performance_deduction"/>
<field name="retention_previous_year"/>
<field name="last_year_safety"/>
<field name="last_year_performance_evaluation"/>
<field name="last_year_jie"/>
<field name="basic_endowment_insurance"/>
<field name="basic_medical_insurance"/>
<field name="unemployment_insurance"/>
<field name="housing_provident_fund"/>
<field name="work_injury_insurance"/>
<field name="social_security"/>
<field name="retroactive_insurance"/>
<field name="specialized_deduction"/>
<field name="individual_income_tax"/>
<field name="add_income_tax"/>
<field name="minus_annuity_difference"/>
<field name="add_annuity_difference"/>
<field name="individual_tax_refund"/>
<field name="liquidation_year"/>
<field name="year_compute"/>
<field name="year_jie"/>
<field name="minus_att"/>
<field name="add_att"/>
<field name="maternity_allowance"/>
<field name="salary_state"/>
<field name="company_id" optional="hide"/>
<field name="is_bold"/>
<button name="open_record" string="详情" type="object" class="oe_highlight"/>
</tree>
</field>
</record>
@@ -439,28 +448,17 @@
<button name="action_temporary_payslip_wizard" string="导入工资项" type="object" class="oe_highlight"/>
<button name="action_refresh_from_work_entries" string="重新计算" type="object" class="oe_highlight"/>
</header>
<button name="open_record" string="详情" type="object" class="oe_highlight"/>
<field name="employee_id" string="姓名" readonly="1" options="{'no_open': True}"/>
<field name="date_of_entry"/>
<field name="total_before_tax"/>
<field name="three_one"/>
<field name="b_year"/>
<field name="union_dues"/>
<field name="base_salary" required="1"/>
<field name="basic_endowment_insurance"/>
<field name="basic_medical_insurance"/>
<field name="unemployment_insurance"/>
<field name="housing_provident_fund"/>
<field name="work_injury_insurance"/>
<field name="maternity_allowance"/>
<field name="position_salary"/>
<field name="individual_income_tax"/>
<field name="add_income_tax"/>
<field name="minus_annuity_difference"/>
<field name="add_annuity_difference"/>
<field name="minus_att"/>
<field name="spring_festival"/>
<field name="add_att"/>
<field name="last_year_jie"/>
<field name="position_subsidy"/>
<field name="seniority_allowance"/>
<field name="safety_subsidy"/>
@@ -468,14 +466,33 @@
<field name="job_performance"/>
<field name="duty"/>
<field name="commuting_allowance" required="1"/>
<field name="full_attendance_award"/>
<field name="overtime_pay"/>
<field name="condolence_fund"/>
<field name="excellent_employees"/>
<field name="spring_festival"/>
<field name="last_year_jie"/>
<field name="basic_endowment_insurance"/>
<field name="basic_medical_insurance"/>
<field name="unemployment_insurance"/>
<field name="housing_provident_fund"/>
<field name="work_injury_insurance"/>
<field name="individual_income_tax"/>
<field name="add_income_tax"/>
<field name="minus_annuity_difference"/>
<field name="add_annuity_difference"/>
<field name="minus_att"/>
<field name="add_att"/>
<field name="maternity_allowance"/>
<field name="salary_state"/>
<field name="company_id" optional="hide"/>
<field name="is_bold"/>
<button name="open_record" string="详情" type="object" class="oe_highlight"/>
</tree>
</field>
</record>
@@ -491,41 +508,49 @@
<button name="action_temporary_payslip_wizard" string="导入工资项" type="object" class="oe_highlight"/>
<button name="action_refresh_from_work_entries" string="重新计算" type="object" class="oe_highlight"/>
</header>
<button name="open_record" string="详情" type="object" class="oe_highlight"/>
<field name="employee_id" string="姓名" readonly="1" options="{'no_open': True}"/>
<field name="date_of_entry"/>
<field name="total_before_tax"/>
<field name="three_one"/>
<field name="b_year"/>
<field name="union_dues"/>
<field name="base_salary" required="1"/>
<field name="basic_endowment_insurance"/>
<field name="basic_medical_insurance"/>
<field name="unemployment_insurance"/>
<field name="housing_provident_fund"/>
<field name="work_injury_insurance"/>
<field name="maternity_allowance"/>
<field name="individual_income_tax"/>
<field name="add_income_tax"/>
<field name="minus_annuity_difference"/>
<field name="add_annuity_difference"/>
<field name="minus_att"/>
<field name="add_att"/>
<field name="last_year_jie"/>
<field name="position_subsidy"/>
<field name="position_salary"/>
<field name="position_subsidy"/>
<field name="performance_bonuses" required="1"/>
<field name="based_pay" required="1"/>
<field name="environmental_allowance"/>
<field name="quality_allowance"/>
<field name="high_subsidy"/>
<field name="last_duty"/>
<field name="distribution_part"/>
<field name="last_year_jie"/>
<field name="medical_fee"/>
<field name="retroactive_insurance"/>
<field name="distribution_part"/>
<field name="basic_endowment_insurance"/>
<field name="basic_medical_insurance"/>
<field name="unemployment_insurance"/>
<field name="housing_provident_fund"/>
<field name="work_injury_insurance"/>
<field name="individual_income_tax"/>
<field name="add_income_tax"/>
<field name="minus_annuity_difference"/>
<field name="add_annuity_difference"/>
<field name="minus_att"/>
<field name="add_att"/>
<field name="maternity_allowance"/>
<field name="salary_state"/>
<field name="company_id" optional="hide"/>
<field name="is_bold"/>
<button name="open_record" string="详情" type="object" class="oe_highlight"/>
</tree>
</field>
</record>
+93 -63
View File
@@ -67,11 +67,11 @@ class SalaryComputeWizard(models.Model):
def confirm(self):
for employee in self.employee_ids:
detail_id = self.env['hr.attendance.month.detail'].search([('employee_id', '=', employee.id),
('current_year', '=', self.select_year),
('current_month', '=', self.select_time)])
if detail_id.state == 'unconfirmed':
raise UserError(f'{employee.name}的{self.select_time}考勤还未确认,请先确认考勤再进行工资计算!')
# detail_id = self.env['hr.attendance.month.detail'].search([('employee_id', '=', employee.id),
# ('current_year', '=', self.select_year),
# ('current_month', '=', self.select_time)])
# if detail_id.state == 'unconfirmed':
# raise UserError(f'{employee.name}的{self.select_time}考勤还未确认,请先确认考勤再进行工资计算!')
is_bold = self.check_employee_dates(employee)
contract_id = self.env['hr.contract'].search([('employee_id', '=', employee.id)], limit=1)
year = int(self.select_year)
@@ -136,7 +136,11 @@ class SalaryComputeWizard(models.Model):
for internship_id in internship_ids:
employee = internship_id.employee_id
contract = employee.contract_id
# 更改扣发绩效奖金
performance_deduction = self.salary_performance_deduction(employee, self.select_year, self.select_time, internship_id.performance_bonuses)
internship_id.write({
'performance_deduction': performance_deduction,
})
# 获取离职日期
turnover_date = employee.contract_id.date_end
start_date = fields.Date.from_string(start_date)
@@ -192,66 +196,75 @@ class SalaryComputeWizard(models.Model):
internship_days = self._process_shift_days(internship_start, internship_end)
work_days = 21.75 - internship_days
if internship_id.line_ids:
if is_probation and not internship_id.employee_id.is_annual_salary:
target_names = {
'基本工资': 'base_salary',
'职级工资': 'rank_salary',
'岗位工资': 'position_salary',
'预发绩效奖金': 'performance_bonuses',
'通讯补贴': 'commuting_allowance',
'工龄工资': 'seniority_salary',
'工会会费': 'union_dues',
'住房公积金': 'housing_provident_fund',
'企业(职业)年金': 'b_year', # 企业年金
}
for line in internship_id.line_ids:
if line.name in target_names:
field_name = target_names[line.name]
if field_name == 'performance_bonuses':
if work_days != days:
result = round(line.total * work_days / days)
else:
result = 0
elif field_name in ['commuting_allowance', 'seniority_salary']:
if work_days != days:
result = line.total * internship_days / days + line.total * work_days / days
else:
result = line.total * internship_days / days
elif field_name in ['rank_salary', 'base_salary']:
if work_days != days:
result = round(math.ceil(line.total * 0.8) * internship_days / days + line.total * work_days / days)
else:
result = line.total * 0.8 * internship_days / days
elif field_name == 'union_dues': # 单独处理工会会费
base_salary = getattr(internship_id, 'base_salary', 0)
result = base_salary * 0.005
elif field_name == 'housing_provident_fund': # 单独处理住房公积金
# 获取合同入职日期的年份和月份
contract_year = str(contract_start_date.year)
contract_month = str(contract_start_date.month)
# 判断是否为入职当月
if contract_year == self.select_year and contract_month == self.select_time:
result = 0 # 入职当月住房公积金为0
elif field_name == 'b_year':
# 获取合同转正日期的年份和月份
if contract_end_date: # 确保转正日期存在
contract_end_year = str(contract_end_date.year)
contract_end_month = str(contract_end_date.month)
# 判断是否为转正当月
if contract_end_year == self.select_year and contract_end_month == self.select_time:
last_year_salary = internship_id.employee_id.last_year_salary or 0
result = last_year_salary * 0.002
if internship_id.line_ids:
if is_probation and not internship_id.employee_id.is_annual_salary:
target_names = {
'基本工资': 'base_salary',
'职级工资': 'rank_salary',
'岗位工资': 'position_salary',
'预发绩效奖金': 'performance_bonuses',
'通讯补贴': 'commuting_allowance',
'工龄工资': 'seniority_salary',
'工会会费': 'union_dues',
'住房公积金': 'housing_provident_fund',
'企业(职业)年金': 'b_year', # 企业年金
}
for line in internship_id.line_ids:
if line.name in target_names:
field_name = target_names[line.name]
# 初始化result为默认值,避免未赋值的情况
result = 0
if field_name == 'performance_bonuses':
if work_days != days:
result = round(line.total * work_days / days)
else:
result = 0
else:
if work_days != days:
result = line.total * 0.8 * internship_days / days + line.total * work_days / days
elif field_name in ['commuting_allowance', 'seniority_salary']:
if work_days != days:
result = line.total * internship_days / days + line.total * work_days / days
else:
result = line.total * internship_days / days
elif field_name in ['rank_salary', 'base_salary']:
if work_days != days:
result = round(math.ceil(
line.total * 0.8) * internship_days / days + line.total * work_days / days)
else:
result = line.total * 0.8 * internship_days / days
elif field_name == 'union_dues': # 单独处理工会会费
base_salary = getattr(internship_id, 'base_salary', 0)
result = base_salary * 0.005
elif field_name == 'housing_provident_fund': # 单独处理住房公积金
# 获取合同入职日期的年份和月份
contract_year = str(contract_start_date.year)
contract_month = str(contract_start_date.month)
# 判断是否为入职当月
if contract_year == self.select_year and contract_month == self.select_time:
result = 0 # 入职当月住房公积金为0
# 新增:非入职当月时的默认值(根据业务需求调整)
else:
result = line.total # 或其他合理默认值
elif field_name == 'b_year':
# 获取合同转正日期的年份和月份
if contract_end_date: # 确保转正日期存在
contract_end_year = str(contract_end_date.year)
contract_end_month = str(contract_end_date.month)
# 判断是否为转正当月
if contract_end_year == self.select_year and contract_end_month == self.select_time:
last_year_salary = internship_id.employee_id.last_year_salary or 0
result = last_year_salary * 0.002
else:
result = 0 # 非转正当月默认值
else:
result = 0 # 无转正日期时的默认值
else:
result = line.total * 0.8 * internship_days / days
if work_days != days:
result = line.total * 0.8 * internship_days / days + line.total * work_days / days
else:
result = line.total * 0.8 * internship_days / days
setattr(internship_id, field_name, result)
line.write({'total': result})
setattr(internship_id, field_name, result)
line.write({'total': result})
if is_turnover:
target_names = {
@@ -359,4 +372,21 @@ class SalaryComputeWizard(models.Model):
)
# 满足任一条件即返回 True
return entry_matches or confirmation_matches or retire_matches
return entry_matches or confirmation_matches or retire_matches
def salary_performance_deduction(self, employee, selected_year, selected_month, performance_bonuses):
attendance_month_obj = self.env["hr.attendance.month.detail"].search([
('employee_id', '=', employee.id),
('current_year', '=', selected_year),
('current_month', '=', selected_month),
('state', '=', 'confirmed')
], limit=1)
if attendance_month_obj:
year = int(selected_year)
month = int(selected_month)
last_day = calendar.monthrange(year, month)[1]
total_days = last_day
result = (performance_bonuses / total_days) * attendance_month_obj.maternity_leave if total_days != 0 else 0.0
return round(result, 2)
else:
return 0.00