添加功能
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
'views/yuthon_payroll_project_views.xml',
|
||||
'views/yuthon_payroll_type_setting_views.xml',
|
||||
'views/yuthon_salary_party_views.xml',
|
||||
'views/yuthon_individual_tax_views.xml',
|
||||
'views/yuthon_salary_asset_views.xml',
|
||||
'views/salary_payroll_distribution_viwes.xml',
|
||||
'views/yuthon_salary_project_views.xml',
|
||||
|
||||
@@ -14,4 +14,5 @@ from . import salary_payroll_distribution
|
||||
from . import yuthon_welfare_expenses
|
||||
from . import inherit_hr_payslip_run
|
||||
from . import inherit_hr_payslip_line
|
||||
from . import yuthon_salary_party
|
||||
from . import yuthon_salary_party
|
||||
from . import yuthon_individual_tax
|
||||
@@ -0,0 +1,53 @@
|
||||
from email.policy import default
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from pypinyin import pinyin, Style
|
||||
|
||||
|
||||
class YuthonIndividualTax(models.Model):
|
||||
_name = 'yuthon.individual.tax'
|
||||
_description = '个税'
|
||||
|
||||
name =fields.Char(string="名称")
|
||||
company_id = fields.Many2one('res.company', string="公司", default=lambda self: self.env.company)
|
||||
start_date = fields.Date(string="生效日期", default=fields.Date.today())
|
||||
end_date = fields.Date(string="失效日期")
|
||||
create_time = fields.Date(string="创建日期", default=fields.Datetime.now)
|
||||
|
||||
def create_salary_temporary(self):
|
||||
"""
|
||||
更新薪资个税
|
||||
:return:
|
||||
"""
|
||||
individual_ids = self.env["yuthon.individual.tax"].browse(
|
||||
self._context.get('active_ids', self._context.get('active_id')))
|
||||
category_id = self.env['hr.salary.rule.category'].search([('name', '=', '个税')],limit=1)
|
||||
if not category_id:
|
||||
category_id = self.env['hr.salary.rule.category'].create({'name': '个税',
|
||||
'code': 'gs'
|
||||
})
|
||||
for ins in individual_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': category_id.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})
|
||||
|
||||
|
||||
@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
|
||||
|
||||
|
||||
@@ -37,4 +37,6 @@ access_rank_log_wizard,access_rank_log_wizard,model_rank_log_wizard,base.group_u
|
||||
access_basic_pension_wizard,access_basic_pension_wizard,model_basic_pension_wizard,base.group_user,1,1,1,1
|
||||
access_yuthon_salary_party,access_yuthon_salary_party,model_yuthon_salary_party,base.group_user,1,1,1,1
|
||||
access_salary_party_wizard,access_salary_party_wizard,model_salary_party_wizard,base.group_user,1,1,1,1
|
||||
access_salary_import_wizard,access_salary_import_wizard,model_salary_import_wizard,base.group_user,1,1,1,1
|
||||
access_salary_import_wizard,access_salary_import_wizard,model_salary_import_wizard,base.group_user,1,1,1,1
|
||||
|
||||
access_yuthon_individual_tax,access_yuthon_individual_tax,model_yuthon_individual_tax,base.group_user,1,1,1,1
|
||||
|
@@ -5,6 +5,11 @@
|
||||
<field name="model_id" ref="model_hr_payroll_structure_type"/>
|
||||
<field name="domain_force">[('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
<record model="ir.rule" id="hr_yuthon_individual_tax_rule">
|
||||
<field name="name">个税多公司</field>
|
||||
<field name="model_id" ref="model_yuthon_individual_tax"/>
|
||||
<field name="domain_force">[('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
<record model="ir.rule" id="salary_payroll_distribution_rule">
|
||||
<field name="name">薪资方法多公司</field>
|
||||
<field name="model_id" ref="model_salary_payroll_distribution"/>
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<record id="view_yuthon_individual_tax_tree" model="ir.ui.view">
|
||||
<field name="name">yuthon.individual.tax.tree</field>
|
||||
<field name="model">yuthon.individual.tax</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="个税" editable="bottom">
|
||||
<field name="name"/>
|
||||
<field name="company_id"/>
|
||||
<field name="start_date"/>
|
||||
<field name="end_date"/>
|
||||
<field name="create_time" column_invisible="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_yuthon_individual_tax_action" model="ir.actions.act_window">
|
||||
<field name="name">个税</field>
|
||||
<field name="res_model">yuthon.individual.tax</field>
|
||||
<field name="view_mode">tree</field>
|
||||
</record>
|
||||
<record id="view_yuthon_individual_tax_server" model="ir.actions.server">
|
||||
<field name="name">更新薪资常用项</field>
|
||||
<field name="model_id" ref="model_yuthon_individual_tax"/>
|
||||
<field name="binding_model_id" ref="model_yuthon_individual_tax"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">action = model.create_salary_temporary()</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from odoo import models, fields, api, _, SUPERUSER_ID
|
||||
from odoo import models, fields, api, _, SUPERUSER_ID, exceptions
|
||||
from odoo.exceptions import ValidationError, UserError
|
||||
from pypinyin import pinyin, Style
|
||||
import xlrd
|
||||
@@ -7,6 +7,7 @@ import base64
|
||||
import datetime
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
|
||||
class SalaryImportWizard(models.TransientModel):
|
||||
_name = 'salary.import.wizard'
|
||||
_description = '薪资导入弹窗'
|
||||
@@ -22,12 +23,31 @@ class SalaryImportWizard(models.TransientModel):
|
||||
sh = book.sheet_by_index(0)
|
||||
header_row = sh.row(0)
|
||||
excel_headers = [str(cell.value).strip() for cell in header_row if cell.value]
|
||||
invalid_headers = [header for header in excel_headers]
|
||||
global_valid_line_names = set()
|
||||
for rx in range(1, sh.nrows):
|
||||
row = sh.row(rx)
|
||||
self.salary_party_data(row, excel_headers)
|
||||
row = sh.row(rx)
|
||||
self.salary_party_data(row, excel_headers, global_valid_line_names)
|
||||
invalid_headers = [header for header in excel_headers if header not in global_valid_line_names]
|
||||
if invalid_headers:
|
||||
invalid_headers_str = ', '.join(invalid_headers)
|
||||
message = _(f"薪资导入完成!以下表头未匹配到任何有效薪资项目,未进行处理:\n{invalid_headers_str}")
|
||||
notification_type = 'warning'
|
||||
else:
|
||||
message = _("薪资导入完成!所有表头均匹配有效薪资项目。")
|
||||
notification_type = 'success'
|
||||
|
||||
def salary_party_data(self, row, excel_headers):
|
||||
return {
|
||||
'type': 'ir.actions.client',
|
||||
'tag': 'display_notification',
|
||||
'params': {
|
||||
'title': _("薪资导入结果提示"),
|
||||
'message': message,
|
||||
'type': notification_type,
|
||||
'sticky': False,
|
||||
}
|
||||
}
|
||||
|
||||
def salary_party_data(self, row, excel_headers, global_valid_line_names):
|
||||
employee_name = row[0].value
|
||||
employee = self.env['hr.employee'].search([('name', '=', employee_name)], limit=1)
|
||||
if employee:
|
||||
@@ -43,6 +63,7 @@ class SalaryImportWizard(models.TransientModel):
|
||||
'name': employee.name,
|
||||
'employee_id': employee.id,
|
||||
'contract_id': employee.contract_id.id,
|
||||
'salary_group_id': employee.contract_id.salary_group_id.id,
|
||||
'payslip_run_id': payslip_run_id.id,
|
||||
'date_from': datetime(2025, 8, 1).date() ,
|
||||
'date_to': datetime(2025, 8, 31).date(),
|
||||
@@ -55,6 +76,10 @@ class SalaryImportWizard(models.TransientModel):
|
||||
payslip.is_salary_push = True
|
||||
payslip.is_salary_release = False
|
||||
|
||||
current_payslip_lines = payslip.line_ids.filtered(lambda l: l.name)
|
||||
current_valid_names = {line.name.strip() for line in current_payslip_lines}
|
||||
global_valid_line_names.update(current_valid_names)
|
||||
|
||||
for line in payslip.line_ids:
|
||||
line_name = line.name
|
||||
if line_name not in excel_headers:
|
||||
|
||||
@@ -428,6 +428,11 @@
|
||||
parent="human_payroll_items_root_board"
|
||||
action="yuthon_salary.view_yuthon_payroll_temporary_action"
|
||||
sequence="30"/>
|
||||
<menuitem id="hr_payroll_individual_tax_board"
|
||||
name="个税"
|
||||
parent="human_payroll_items_root_board"
|
||||
action="yuthon_salary.view_yuthon_individual_tax_action"
|
||||
sequence="35"/>
|
||||
<menuitem id="human_pay_setting_work_setting"
|
||||
name="配置"
|
||||
parent="human_resources_salary_root_board"
|
||||
|
||||
Reference in New Issue
Block a user