From f845b6f94eed984ae01971ca0a1970f12361edcb Mon Sep 17 00:00:00 2001 From: zhou <123@> Date: Thu, 3 Jul 2025 16:40:08 +0800 Subject: [PATCH 01/12] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../models/property_lease_contract.py | 16 +++++++++++++++- .../views/property_lease_contract.xml | 8 ++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/yuthon_property_approval/models/property_lease_contract.py b/yuthon_property_approval/models/property_lease_contract.py index df01103b9..d5fa42503 100644 --- a/yuthon_property_approval/models/property_lease_contract.py +++ b/yuthon_property_approval/models/property_lease_contract.py @@ -52,7 +52,7 @@ class PropertyLeaseContract(models.Model): name = fields.Char(string='物业信息') code = fields.Char(string="流水号", default=lambda self: self.env['ir.sequence'].next_by_code('property_lease_contract_code')) - admin_id = fields.Many2one('res.users', string="管理员") + admin_id = fields.Many2one('res.users', string="管理员", compute='_compute_admin_id', store=True) tenure_type = fields.Selection([('self', '自有'), ('agency', '代管')], string='权属类型') contract_code = fields.Char(string="合同编号") contract_date = fields.Date(string="合同签订日期") @@ -212,6 +212,20 @@ class PropertyLeaseContract(models.Model): store=True) responsibility_book_name = fields.Char(string="安全生产责任书(住宅)名称", compute='_compute_attachment_names', store=True) + + def update_admin_id(self): + contract_ids = self.env["property.lease.contract"].browse( + self._context.get('active_ids', self._context.get('active_id'))) + for rec in contract_ids: + if rec.lease_ids: + rec.admin_id = rec.lease_ids[0].admin_line_id.id + + @api.depends('lease_ids') + def _compute_admin_id(self): + for rec in self: + if rec.lease_ids: + rec.admin_id = rec.lease_ids[0].admin_line_id.id + @api.depends( 'license_id.name', 'legal_entity_id.name', diff --git a/yuthon_property_approval/views/property_lease_contract.xml b/yuthon_property_approval/views/property_lease_contract.xml index f27e35d0a..75229eede 100644 --- a/yuthon_property_approval/views/property_lease_contract.xml +++ b/yuthon_property_approval/views/property_lease_contract.xml @@ -857,6 +857,14 @@ code action = model.all_end_approval() + + 同步更新管理员 + + + code + action = model.update_admin_id() + + From 2d0fd0d4dd60b3af76efdd15c1e6f83af70a4dc5 Mon Sep 17 00:00:00 2001 From: zhou <123@> Date: Thu, 3 Jul 2025 16:59:24 +0800 Subject: [PATCH 02/12] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yuthon_hr_employee_approval/models/yuthon_onboard_approval.py | 4 ++-- .../views/yuthon_onboard_approval_views.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/yuthon_hr_employee_approval/models/yuthon_onboard_approval.py b/yuthon_hr_employee_approval/models/yuthon_onboard_approval.py index cf7c96385..33e3f6137 100644 --- a/yuthon_hr_employee_approval/models/yuthon_onboard_approval.py +++ b/yuthon_hr_employee_approval/models/yuthon_onboard_approval.py @@ -31,7 +31,8 @@ class YuthonOnboardApproval(models.Model): work_end = fields.Boolean(string="结束") bank = fields.Char(string='开户行') use_user_type = fields.Selection(related='users_id.employee_id.use_user_type', string="用工形式") - department_id1 = fields.Many2one('hr.department', string="部门") + job = fields.Char(related='employee_name_id.name', string="岗位") + department_id1 = fields.Many2one(related='employee_name_id.department_id', string="部门") onboarding_status = fields.Selection([('none', '待入职'), ('onboarding', '已入职')], string='审批后员工状态', default='none') onboard_time = fields.Date(string='入职时间', default=fields.Datetime.now) probation_period = fields.Selection([('zero', '0个月'), ('one', '1个月'), @@ -50,7 +51,6 @@ class YuthonOnboardApproval(models.Model): is_issues = fields.Boolean(string='是否上会') issues_result = fields.Html(string="会议结果") related_issues_id = fields.Many2one('issue.library', string="关联议题") - job_id = fields.Many2one('hr.job', string="岗位") # 合同 contracted_status = fields.Selection([('first', '首' '签'), ('renew', '续签')], string='合同类型') diff --git a/yuthon_hr_employee_approval/views/yuthon_onboard_approval_views.xml b/yuthon_hr_employee_approval/views/yuthon_onboard_approval_views.xml index 4b10cae0a..4a9914e3d 100644 --- a/yuthon_hr_employee_approval/views/yuthon_onboard_approval_views.xml +++ b/yuthon_hr_employee_approval/views/yuthon_onboard_approval_views.xml @@ -75,7 +75,7 @@ - + From 547db6e7a2f90ce111b1a422d1b919cd892fdaaa Mon Sep 17 00:00:00 2001 From: zhou <123@> Date: Thu, 3 Jul 2025 17:40:13 +0800 Subject: [PATCH 03/12] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../models/yuthon_hr_employee.py | 51 +++++++++++++++++-- .../views/yuthon_hr_employee_views.xml | 5 ++ yuthon_salary/models/inherit_hr_payslip.py | 2 + .../models/yuthon_payroll_project.py | 10 ++-- yuthon_salary/wizard/salary_compute_wizard.py | 3 +- 5 files changed, 62 insertions(+), 9 deletions(-) diff --git a/yuthon_hr_employee/models/yuthon_hr_employee.py b/yuthon_hr_employee/models/yuthon_hr_employee.py index 675b31ab2..a9d75cc45 100644 --- a/yuthon_hr_employee/models/yuthon_hr_employee.py +++ b/yuthon_hr_employee/models/yuthon_hr_employee.py @@ -167,6 +167,10 @@ class YuthonHrEmployee(models.Model): # 工资计算分组 salary_group_id = fields.Many2one('yuthon.salary.group', string="工资单分组", store=True) salary_date = fields.Date(string="薪资计算时间", store=True) + salary_month = fields.Selection([('1', '一月'), ('2', '二月'), ('3', '三月'), ('4', '四月'), + ('5', '五月'), ('6', '六月'), ('7', '七月'), ('8', '八月'), + ('9', '九月'), ('10', '十月'), ('11', '十一月'), + ('12', '十二月')], string='薪资计算月份') salary_year_jin_ids = fields.Many2many( 'hr.employee', # 自关联到hr.employee relation='hr_employee_salary_year_jin_rel', # 显式指定关联表名 @@ -188,6 +192,12 @@ class YuthonHrEmployee(models.Model): last_month_base_salary_deduction = fields.Float(string="上月基本薪资扣款") last_month_performance_deduction = fields.Float(string="上月绩效扣款") last_month_commuting_deduction = fields.Float(string='上月通信扣款') + # 薪资计算 基数 + salary_medical_insurance = fields.Float(string='薪资医疗费基数', compute='_compute_insurance_salary') + salary_insurance = fields.Float(string='薪资养老费基数', compute='_compute_insurance_salary') + salary_work_injury_insurance = fields.Float(string='薪资保险金基数', compute='_compute_insurance_salary') + salary_housing_fund = fields.Float(string='薪资公积金基数', compute='_compute_insurance_salary') + # 显示基数 medical_insurance_base = fields.Float(string='基本医疗费基数', compute='_compute_insurance_bases') pension_insurance_base = fields.Float(string='基本养老费基数', compute='_compute_insurance_bases') work_injury_insurance_base = fields.Float(string='失业保险金基数', compute='_compute_insurance_bases') @@ -200,6 +210,7 @@ class YuthonHrEmployee(models.Model): subsidy_amount = fields.Float(string="岗位补贴金额", compute='_compute_subsidy_amount', store=True) security_amount = fields.Float(string="安全委员会金额", compute='_compute_subsidy_amount', store=True) + quality_inspector_amount = fields.Float(string="质检员金额", compute='_compute_subsidy_amount', store=True) @api.depends('quota_issued', 'user_year') def _compute_remainder_year(self): @@ -213,6 +224,7 @@ class YuthonHrEmployee(models.Model): def _compute_subsidy_amount(self): for record in self: amount = 0 + quality_amount = 0 # 获取主角色名称 primary_role_name = record.user_role_id.name if record.user_role_id else '' # 获取所有辅助角色名称列表 @@ -244,7 +256,7 @@ class YuthonHrEmployee(models.Model): for cert in record.skills_certificates_ids ) if quality and department_name == '仓储组': - amount += 100 + quality_amount += 100 if department_name == '领导班子': record.security_amount = 0 @@ -254,7 +266,7 @@ class YuthonHrEmployee(models.Model): record.security_amount = 0 record.subsidy_amount = amount - + record.quality_inspector_amount = quality_amount @api.depends('converted', 'salary_year_jin_ids') def _compute_total_coefficients(self): for record in self: @@ -291,7 +303,7 @@ class YuthonHrEmployee(models.Model): def _compute_overtime_this_month(self): for employee in self: employee.overtime_this_month = employee.normal_overtime_hours + employee.weekend_overtime_hours + employee.holiday_overtime_hours - + # 根据当前月份来选择具体的值 @api.depends('social_base_on', 'social_base_off') def _compute_insurance_bases(self): current_month = datetime.now().month @@ -322,6 +334,39 @@ class YuthonHrEmployee(models.Model): else: setattr(record, field_name, base) + # 根据薪资计算选择的月份 来获取确定的值 + @api.depends('social_base_on', 'social_base_off', 'salary_month') + def _compute_insurance_salary(self): + insurance_names = { + '薪资医疗保险费': 'salary_medical_insurance', + '薪资养老保险费': 'salary_insurance', + '薪资保险费': 'salary_work_injury_insurance', + '薪资公积金': 'salary_housing_fund' + } + name_mapping = { + '基本医疗保险费': '薪资医疗保险费', + '基本养老保险费': '薪资养老保险费', + '失业保险费': '薪资保险费', + '住房公积金': '薪资公积金' + } + insurance_records = self.env['yuthon.payroll.insurances'].search([('name', 'in',['基本医疗保险费', '基本养老保险费', '失业保险费', '住房公积金'])]) + for record in self: + for field_name in insurance_names.values(): + setattr(record, field_name, 0) + base = record.social_base_on if 1 <= int(record.salary_month) <= 6 else record.social_base_off + for insurance in insurance_records: + insurance_name_key = name_mapping.get(insurance.name) + field_name = insurance_names.get(insurance_name_key) + if field_name == 'housing_fund_base' and record.name in ['郭爱娣', '黄炎方']: + record.housing_fund_base = 4000 + continue + if base > insurance.employee_base_ceiling: + setattr(record, field_name, insurance.employee_base_ceiling) + elif base < insurance.employee_base_floor: + setattr(record, field_name, insurance.employee_base_floor) + else: + setattr(record, field_name, base) + @api.onchange('job_id') def _onchange_job_id(self): if self.job_id: diff --git a/yuthon_hr_employee/views/yuthon_hr_employee_views.xml b/yuthon_hr_employee/views/yuthon_hr_employee_views.xml index 1713d31e0..3e576d39b 100644 --- a/yuthon_hr_employee/views/yuthon_hr_employee_views.xml +++ b/yuthon_hr_employee/views/yuthon_hr_employee_views.xml @@ -162,6 +162,11 @@ + + + + + diff --git a/yuthon_salary/models/inherit_hr_payslip.py b/yuthon_salary/models/inherit_hr_payslip.py index 071fe4cd2..a96ea047c 100644 --- a/yuthon_salary/models/inherit_hr_payslip.py +++ b/yuthon_salary/models/inherit_hr_payslip.py @@ -182,6 +182,8 @@ class InheritHrPayslip(models.Model): rec.full_attendance_award = line.total if line.name == '加班费': rec.overtime_pay = line.total + if line.name == '质检员津贴': + rec.quality_allowance = line.total if line.name == '误餐费': rec.meal_misunderstanding_fee = line.total if line.name == '事假': diff --git a/yuthon_salary/models/yuthon_payroll_project.py b/yuthon_salary/models/yuthon_payroll_project.py index 96ef357ee..d279e6d90 100644 --- a/yuthon_salary/models/yuthon_payroll_project.py +++ b/yuthon_salary/models/yuthon_payroll_project.py @@ -96,7 +96,7 @@ class YuthonPayrollCommon(models.Model): if ins.name == '环境作业津贴': formula_salary = "result = 0" if ins.name == '质检员津贴': - formula_salary = "result = 0" + formula_salary = "result = employee.quality_inspector_amount" if ins.name == '工会会费' and ins.company_id.name in ['集团本部', '天河物管']: formula_salary = "result = round((payslip.base_salary * 0.005), 2)" if ins.name == '工会会费' and ins.company_id.name == '天河粮储': @@ -215,19 +215,19 @@ class YuthonPayrollInsurances (models.Model): code = 'None' if ins.name == '基本医疗保险费': code = 'JBYLIAO' - formula_salary = "result = employee.medical_insurance_base * " + str(number) + formula_salary = "result = employee.salary_medical_insurance * " + str(number) if ins.name == '基本养老保险费': code = 'JBYLAO' - formula_salary = "result = employee.pension_insurance_base * " + str(number) + formula_salary = "result = employee.salary_insurance * " + str(number) if ins.name == '失业保险费': code = 'SYBX' - formula_salary = "result = employee.work_injury_insurance_base * " + str(number) + formula_salary = "result = employee.salary_work_injury_insurance * " + str(number) if ins.name == '工伤保险费': code = 'GSBX' formula_salary = "result = employee.social_base_on * " + str(number) if ins.name == '住房公积金': code = 'ZFGJJ' - formula_salary = "result = (round((employee.housing_fund_base * " + str(number) + "), 0)) if employee.is_accum_salary else 0" + 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.name == '天河物管': code = 'WGQYNJ' diff --git a/yuthon_salary/wizard/salary_compute_wizard.py b/yuthon_salary/wizard/salary_compute_wizard.py index 44fa97756..f62db3d6a 100644 --- a/yuthon_salary/wizard/salary_compute_wizard.py +++ b/yuthon_salary/wizard/salary_compute_wizard.py @@ -41,7 +41,7 @@ class SalaryComputeWizard(models.Model): ('company_id', '=', self.company_id.id), ('is_salary', '=', True), ('entry_date', '<=', start_date), - ('contract_id.state', 'not in', ['draft', 'cancel']), + ('contract_id.state', 'not in', ['draft', 'cancel', 'close']), ('contract_id', '!=', False), ]) self.employee_ids = [(6, 0, employees.ids)] @@ -91,6 +91,7 @@ class SalaryComputeWizard(models.Model): ('date_to', '>=', start_date) ]) employee.salary_date = start_date + employee.salary_month = self.select_time employee.salary_year_jin_ids = [(6, 0, self.employee_ids.ids)] if existing_payslip: raise UserError(f"员工 {employee.name} 在 {start_date} 到 {end_date} 日期范围内已有工资单记录,无法创建新的工资单。") From 8530bcd29e8dd1f70cc84da0c92c84fce9b98c0c Mon Sep 17 00:00:00 2001 From: zhou <123@> Date: Thu, 3 Jul 2025 21:31:56 +0800 Subject: [PATCH 04/12] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yuthon_salary/__manifest__.py | 1 + yuthon_salary/models/inherit_hr_payslip.py | 22 +++++++++- yuthon_salary/security/ir.model.access.csv | 1 + .../others/temporary_payslip_template.xlsx | Bin 10095 -> 0 bytes .../static/others/工资项导入模板.xlsx | Bin 0 -> 9876 bytes .../views/inherit_hr_payslip_views.xml | 9 ++++ yuthon_salary/wizard/__init__.py | 3 +- .../wizard/initialize_payroll_wizard.py | 33 +++++++++++++++ .../initialize_payroll_wizard_views.xml | 24 +++++++++++ .../wizard/temporary_payslip_wizard.py | 39 +++++++++++------- .../wizard/temporary_payslip_wizard_views.xml | 2 +- 11 files changed, 116 insertions(+), 18 deletions(-) delete mode 100644 yuthon_salary/static/others/temporary_payslip_template.xlsx create mode 100644 yuthon_salary/static/others/工资项导入模板.xlsx create mode 100644 yuthon_salary/wizard/initialize_payroll_wizard.py create mode 100644 yuthon_salary/wizard/initialize_payroll_wizard_views.xml diff --git a/yuthon_salary/__manifest__.py b/yuthon_salary/__manifest__.py index 6114ccb8c..bc3f09971 100644 --- a/yuthon_salary/__manifest__.py +++ b/yuthon_salary/__manifest__.py @@ -34,6 +34,7 @@ 'wizard/yuthon_payroll_wizard_views.xml', 'wizard/payroll_labor_wizard_views.xml', 'wizard/payroll_retired_wizard_views.xml', + 'wizard/initialize_payroll_wizard_views.xml', 'wizard/payslip_send_wizard_views.xml', 'wizard/salary_year_wizard.xml', 'wizard/salary_compute_wizard_views.xml', diff --git a/yuthon_salary/models/inherit_hr_payslip.py b/yuthon_salary/models/inherit_hr_payslip.py index a96ea047c..1e76b400c 100644 --- a/yuthon_salary/models/inherit_hr_payslip.py +++ b/yuthon_salary/models/inherit_hr_payslip.py @@ -119,7 +119,7 @@ class InheritHrPayslip(models.Model): leave_absence = fields.Float(string='考勤补发') # 粮储常用项 - quality_allowance = fields.Float(string='质检员津贴') + quality_allowance = fields.Float(string='质检员津贴', compute="_compute_salary", store=True) environmental_allowance = fields.Float(string='环境作业津贴') last_duty = fields.Float(string='上月值班费') high_subsidy = fields.Float(string='高温补贴') @@ -491,4 +491,22 @@ class InheritHrPayslip(models.Model): unconfirmed_slips = self.search(domain) if unconfirmed_slips: unconfirmed_slips.write({'confirm_status': 'confirm'}) - return super().get_view(view_id, view_type, **options) \ No newline at end of file + return super().get_view(view_id, view_type, **options) + + def initialize_payroll_wizard(self): + payslip_ids = self.env["hr.payslip"].browse( + self._context.get('active_ids', self._context.get('active_id'))) + payslip_list = [] + for record in payslip_ids: + payslip_list.append([4, record.id]) + return { + 'name': '初始化工资单', + 'type': 'ir.actions.act_window', + 'view_mode': 'form', + 'res_model': 'initialize.payroll.wizard', + 'target': 'new', + 'context': { + 'default_payslip_ids': payslip_list + } + } + diff --git a/yuthon_salary/security/ir.model.access.csv b/yuthon_salary/security/ir.model.access.csv index b6664dae9..0850fb46f 100644 --- a/yuthon_salary/security/ir.model.access.csv +++ b/yuthon_salary/security/ir.model.access.csv @@ -31,3 +31,4 @@ access_yuthon_salary_project, access_yuthon_salary_project,model_yuthon_salary_p access_yuthon_salary_asset, access_yuthon_salary_asset,model_yuthon_salary_asset,base.group_user,1,1,1,1 access_salary_payroll_distribution,access_salary_payroll_distribution,model_salary_payroll_distribution,base.group_user,1,1,1,1 access_yuthon_welfare_expenses,access_yuthon_welfare_expenses,model_yuthon_welfare_expenses,base.group_user,1,1,1,1 +access_initialize_payroll_wizard,access_initialize_payroll_wizard,model_initialize_payroll_wizard,base.group_user,1,1,1,1 \ No newline at end of file diff --git a/yuthon_salary/static/others/temporary_payslip_template.xlsx b/yuthon_salary/static/others/temporary_payslip_template.xlsx deleted file mode 100644 index 6a8333b251403608eff5a7d8ceeec512236bef2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10095 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 Q+7pEf_DN2O>{;*s07(sh_W%F@ diff --git a/yuthon_salary/static/others/工资项导入模板.xlsx b/yuthon_salary/static/others/工资项导入模板.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..939ca44138a671baf3e2e9e440e6b25fc49bd1ad GIT binary patch literal 9876 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 + @@ -229,6 +230,7 @@