!2697 添加功能

Merge pull request !2697 from 李鹏宇/dev_zhou
This commit is contained in:
李鹏宇
2025-05-11 14:08:02 +00:00
committed by Gitee
13 changed files with 250 additions and 10 deletions
@@ -10,7 +10,6 @@
</xpath>
<xpath expr="//field[@name='employee_id']" position="after">
<field name="contract_type_id" string="用工形式"/>
<field name="simplified_name" column_invisible="1"/>
</xpath>
<xpath expr="//field[@name='name']" position="attributes">
<attribute name="column_invisible">1</attribute>
+3
View File
@@ -29,6 +29,7 @@
'wizard/yuthon_payroll_wizard_views.xml',
'wizard/payroll_labor_wizard_views.xml',
'wizard/payroll_retired_wizard_views.xml',
'wizard/salary_year_wizard.xml',
'wizard/salary_compute_wizard_views.xml',
'wizard/salary_payslip_wizard_views.xml',
'wizard/select_delete_wizard_viwes.xml',
@@ -45,6 +46,7 @@
'yuthon_salary/static/src/js/salary_return_button.js',
'yuthon_salary/static/src/js/salary_retired_button.js',
'yuthon_salary/static/src/js/salary_validation_button.js',
'yuthon_salary/static/src/js/salary_year_button.js',
'yuthon_salary/static/src/xml/salary_create_button.xml',
'yuthon_salary/static/src/xml/salary_labor_button.xml',
'yuthon_salary/static/src/xml/salary_retired_button.xml',
@@ -52,6 +54,7 @@
'yuthon_salary/static/src/xml/salary_documents_button.xml',
'yuthon_salary/static/src/xml/salary_validation_button.xml',
'yuthon_salary/static/src/xml/salary_return_button.xml',
'yuthon_salary/static/src/xml/salary_year_button.xml',
],
},
'installable': True,
+46 -4
View File
@@ -22,13 +22,56 @@ class YuthonSalaryYear(models.Model):
# 粮储
performance_salary = fields.Float(string="绩效奖金")
# 综合
sum_salary = fields.Float(string="应发合计")
buckle_salary = fields.Float(string="扣个税")
solid_salary = fields.Float(string="实发年终奖")
sum_salary = fields.Float("应发合计", compute='_compute_company_specific_sum', store=True)
buckle_salary = fields.Float(string="扣个税", compute='_compute_buckle_salary', store=True)
solid_salary = fields.Float(string="实发年终奖", compute='_compute_solid_salary', store=True)
create_date = fields.Date(string="创建日期")
company_id = fields.Many2one('res.company', related="employee_id.company_id", string="公司")
personal_tax = fields.Many2one('yuthon.personal.rule', string="个人所得税规则")
# 计算字段
@api.depends('company_id', 'on_year_balance', 'former_year_balance', 'on_year_liquidation',
'former_year_liquidation', 'one_three_salary', 'job_salary', 'test_salary',
'software_salary', 'safe_salary', 'outstanding_salary', 'leadership_salary',
'performance_salary')
def _compute_company_specific_sum(self):
# 定义各公司的计算字段映射
company_rules = {
'集团本部': [
'on_year_balance', 'former_year_balance',
'on_year_liquidation', 'former_year_liquidation'
],
'天河物管': [
'one_three_salary', 'job_salary', 'test_salary',
'software_salary', 'safe_salary', 'outstanding_salary',
'leadership_salary'
],
'天河粮储': ['performance_salary']
}
for record in self:
company_name = record.company_id.name
sum_value = 0.0
fields_to_sum = company_rules.get(company_name, [])
for field_name in fields_to_sum:
sum_value += getattr(record, field_name, 0.0)
record.sum_salary = sum_value
@api.depends('sum_salary')
def _compute_buckle_salary(self):
for record in self:
rule = self.env['yuthon.personal.rule'].search([
('start_number', '<', record.sum_salary),
('end_number', '>', record.sum_salary),
], limit=1)
if rule:
record.buckle_salary = record.sum_salary * rule.tax_rate
else:
record.buckle_salary = 0
@api.depends('sum_salary', 'buckle_salary')
def _compute_solid_salary(self):
for record in self:
record.solid_salary = record.sum_salary - record.buckle_salary
class YuthonPersonalRule(models.Model):
@@ -39,6 +82,5 @@ class YuthonPersonalRule(models.Model):
end_number = fields.Float(string="结束范围")
tax_rate = fields.Float(string="税率")
compute_number = fields.Float(string="速算扣除数")
company_id = fields.Many2one('res.company', string="公司")
start_date = fields.Date(string="生效日期")
end_date = fields.Date(string="失效日期")
+2 -1
View File
@@ -24,4 +24,5 @@ access_yuthon_payroll_retired,access_yuthon_payroll_retired,model_yuthon_payroll
access_payroll_labor_wizard,access_payroll_labor_wizard,model_payroll_labor_wizard,base.group_user,1,1,1,1
access_payroll_retired_wizard,access_payroll_retired_wizard,model_payroll_retired_wizard,base.group_user,1,1,1,1
access_yuthon_salary_documents,access_yuthon_salary_documents,model_yuthon_salary_documents,base.group_user,1,1,1,1
access_salary_print_wizard, access_salary_print_wizard,model_salary_print_wizard,base.group_user,1,1,1,1
access_salary_print_wizard, access_salary_print_wizard,model_salary_print_wizard,base.group_user,1,1,1,1
access_salary_year_wizard,access_salary_year_wizard,model_salary_year_wizard,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
24 access_salary_print_wizard access_salary_print_wizard model_salary_print_wizard base.group_user 1 1 1 1
25 access_salary_year_wizard access_salary_year_wizard model_salary_year_wizard base.group_user 1 1 1 1
26
27
28
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,29 @@
/** @odoo-module */
import { ListController } from "@web/views/list/list_controller";
import { registry } from '@web/core/registry';
import { listView } from '@web/views/list/list_view';
export class CustomSalaryYearStatementsController extends ListController {
setup() {
super.setup();
}
openSalaryYearWizard() {
this.actionService.doAction({
type: 'ir.actions.act_window',
res_model: 'salary.year.wizard',
name: '年终奖导入弹窗',
view_mode: 'form',
view_type: 'form',
views: [[false, 'form']],
target: 'new', // 以弹窗形式打开
context: {},
});
}
}
registry.category("views").add("custom_salary_year_button", {
...listView,
Controller: CustomSalaryYearStatementsController,
buttonTemplate: "salary_year_module.ListView.Buttons",
});
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<templates>
<t t-name="salary_year_module.ListView.Buttons" t-inherit="web.ListView.Buttons">
<xpath expr="//div[hasclass('o_list_buttons')]" position="after">
<button type="button" class="btn btn-primary" style="margin-left: 10px;" t-on-click="openSalaryYearWizard">
导入
</button>
</xpath>
</t>
</templates>
@@ -4,7 +4,7 @@
<field name="name">yuthon.salary.year.tree</field>
<field name="model">yuthon.salary.year</field>
<field name="arch" type="xml">
<tree string="年终奖金计算" editable="bottom">
<tree string="年终奖金计算" editable="bottom" js_class="custom_salary_year_button">
<field name="employee_id"/>
<field name="on_year_balance" groups="yuthon_salary.group_jtbb_user"/>
<field name="former_year_balance" groups="yuthon_salary.group_jtbb_user"/>
@@ -21,7 +21,6 @@
<field name="performance_salary" groups="yuthon_salary.group_lc_user"/>
<field name="sum_salary"/>
<field name="buckle_salary"/>
<field name="solid_salary"/>
<field name="sum_salary"/>
@@ -47,7 +46,6 @@
<field name="end_number"/>
<field name="tax_rate"/>
<field name="compute_number"/>
<field name="company_id"/>
<field name="start_date"/>
<field name="end_date"/>
</tree>
+2 -1
View File
@@ -7,4 +7,5 @@ from . import put_return_wizard
from . import temporary_payslip_wizard
from . import payroll_labor_wizard
from . import payroll_retired_wizard
from . import salary_print_wizard
from . import salary_print_wizard
from . import salary_year_wizard
+103
View File
@@ -0,0 +1,103 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api, _, SUPERUSER_ID
from odoo.exceptions import ValidationError, UserError
from pypinyin import pinyin, Style
import xlrd
import base64
import datetime
from datetime import datetime
class SalaryYearWizard(models.Model):
_name = 'salary.year.wizard'
_description = '年终奖导入弹窗'
company_id = fields.Many2one('res.company', string='公司', default=lambda self: self.env.company, store=True)
company_name = fields.Char(string='公司名称', related='company_id.name', store=True)
excel_file = fields.Binary(string="上传Excel表")
excel_name = fields.Char(string="文件名")
def confirm(self):
if not self.excel_file:
raise ValidationError('请上传文件。')
book = xlrd.open_workbook(file_contents=base64.decodebytes(self.excel_file))
sh = book.sheet_by_index(0)
for rx in range(1, sh.nrows):
row = sh.row(rx)
if self.company_id.name == '集团本部':
self.salary_year_ttjt_data(row)
elif self.company_id.name == '天河物管':
self.salary_year_thwg_data(row)
else:
self.salary_year_thlc_data(row)
def salary_year_ttjt_data(self,row):
employee_id = self.env['hr.employee'].search([('name', '=', row[0].value)], limit=1)
on_year_balance = row[1].value
former_year_balance = row[2].value
on_year_liquidation = row[3].value
former_year_liquidation = row[4].value
salary_year_id = self.env["yuthon.salary.year"].search([('employee_id', '=', employee_id.id)])
if salary_year_id:
salary_year_id.write({
'on_year_balance': on_year_balance,
'former_year_balance': former_year_balance,
'on_year_liquidation': on_year_liquidation,
'former_year_liquidation': former_year_liquidation,
})
else:
self.env["yuthon.salary.year"].create({
'employee_id': employee_id.id,
'on_year_balance': on_year_balance,
'former_year_balance': former_year_balance,
'on_year_liquidation': on_year_liquidation,
'former_year_liquidation': former_year_liquidation,
})
def salary_year_thwg_data(self, row):
employee_id = self.env['hr.employee'].search([('name', '=', row[0].value)], limit=1)
one_three_salary = row[1].value
job_salary = row[2].value
test_salary = row[3].value
software_salary = row[4].value
safe_salary = row[5].value
outstanding_salary = row[6].value
leadership_salary = row[7].value
salary_year_id = self.env["yuthon.salary.year"].search([('employee_id', '=', employee_id.id)])
if not salary_year_id:
self.env["yuthon.salary.year"].create({
'employee_id': employee_id.id,
'one_three_salary': one_three_salary,
'job_salary': job_salary,
'test_salary': test_salary,
'software_salary': software_salary,
'safe_salary': safe_salary,
'outstanding_salary': outstanding_salary,
'leadership_salary': leadership_salary,
})
else:
salary_year_id.write({
'one_three_salary': one_three_salary,
'job_salary': job_salary,
'test_salary': test_salary,
'software_salary': software_salary,
'safe_salary': safe_salary,
'outstanding_salary': outstanding_salary,
'leadership_salary': leadership_salary,
})
def salary_year_thlc_data(self, row):
employee_id = self.env['hr.employee'].search([('name', '=', row[0].value)], limit=1)
performance_salary = row[1].value
salary_year_id = self.env["yuthon.salary.year"].search([('employee_id', '=', employee_id.id)])
if not salary_year_id:
salary_year_id = self.env["yuthon.salary.year"].create({
'employee_id': employee_id.id,
'performance_salary': performance_salary,
})
else:
salary_year_id.write({
'performance_salary': performance_salary,
})
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- 天河投资模板下载动作 -->
<record id="salary_year_wizard_downloads_tianhetouzi_action" model="ir.actions.act_url">
<field name="name">天河投资模板下载</field>
<field name="target">self</field>
<field name="url">/yuthon_salary/static/others/salary_year_thtz.xlsx</field>
</record>
<!-- 天河物管模板下载动作 -->
<record id="salary_year_wizard_downloads_tianhewuguan_action" model="ir.actions.act_url">
<field name="name">天河物管模板下载</field>
<field name="target">self</field>
<field name="url">/yuthon_salary/static/others/salary_year_thwg.xlsx</field>
</record>
<!-- 天河粮储模板下载动作 -->
<record id="salary_year_wizard_downloads_tianheliangchu_action" model="ir.actions.act_url">
<field name="name">天河粮储模板下载</field>
<field name="target">self</field>
<field name="url">/yuthon_salary/static/others/salary_year_thlc.xlsx</field>
</record>
<record id="salary_year_wizard_form" model="ir.ui.view">
<field name="name">弹窗</field>
<field name="model">salary.year.wizard</field>
<field name="arch" type="xml">
<form>
<sheet>
<header>
<button name="%(salary_year_wizard_downloads_tianhetouzi_action)d" string="模板下载" type="action"
class="btn btn-primary" invisible="company_name != '集团本部'"/>
<button name="%(salary_year_wizard_downloads_tianhewuguan_action)d" string="模板下载" type="action"
class="btn btn-primary" invisible="company_name != '天河物管'"/>
<button name="%(salary_year_wizard_downloads_tianheliangchu_action)d" string="模板下载" type="action"
class="btn btn-primary" invisible="company_name != '天河粮储'"/>
</header>
<group>
<group>
<field name="company_id" invisible="1"/>
<field name="company_name" invisible="1"/>
<field name="excel_file" filename="excel_name"/>
<field name="excel_name" invisible="1"/>
</group>
<group>
</group>
</group>
</sheet>
<footer>
<button name="confirm" string="确认" type="object" class="oe_highlight"/>
<button string="返回" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
</odoo>