添加功能
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
<xpath expr="//field[@name='paperformat_id']" position="after">
|
||||
<field name="template_docx"
|
||||
invisible="report_type not in ['docx']" string="报表模板"/>
|
||||
|
||||
f
|
||||
<field name="out_report_type"
|
||||
invisible="report_type not in ['docx']" string="输出报告类型"/>
|
||||
|
||||
|
||||
@@ -46,7 +46,10 @@ class XLSXReportController(http.Controller):
|
||||
content_disposition(report_name + '.xlsx'))
|
||||
]
|
||||
)
|
||||
report_obj.get_xlsx_report(options, response)
|
||||
if report_name == '薪资':
|
||||
report_obj.get_xlsx_salary_report(options, response)
|
||||
else:
|
||||
report_obj.get_xlsx_report(options, response)
|
||||
response.set_cookie('fileToken', token)
|
||||
return response
|
||||
except Exception as e:
|
||||
|
||||
@@ -30,6 +30,8 @@ import io
|
||||
import json
|
||||
import datetime
|
||||
from odoo.tools import date_utils
|
||||
from collections import defaultdict
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class ReportExcel(models.Model):
|
||||
@@ -345,3 +347,208 @@ class ReportExcel(models.Model):
|
||||
self.fields_ids = []
|
||||
if self.fields_ids:
|
||||
self.field_order = str(self.fields_ids._origin.ids)
|
||||
|
||||
def get_xlsx_salary_report(self, data, response):
|
||||
company_name = self.env.user.company_id.name
|
||||
output = io.BytesIO()
|
||||
workbook = xlsxwriter.Workbook(output, {'in_memory': True, 'default_sheet_index': -1})
|
||||
# 定义基本格式
|
||||
title_format = workbook.add_format({
|
||||
'font_size': 16,
|
||||
'align': 'center',
|
||||
'valign': 'vcenter',
|
||||
'bold': True
|
||||
})
|
||||
# 定义序号列的格式,使其居中
|
||||
serial_number_format = workbook.add_format({
|
||||
'font_size': 10,
|
||||
'border': 1,
|
||||
'align': 'center',
|
||||
'valign': 'vcenter'
|
||||
})
|
||||
header_format = workbook.add_format({'font_size': 11, 'bold': True, 'border': 1})
|
||||
data_format = workbook.add_format({'font_size': 10, 'border': 1})
|
||||
domain = self._get_payslip_domain(data)
|
||||
records = self.env[data['model_name']].search(domain)
|
||||
# # 按 salary_group_id 分组
|
||||
grouped_records = defaultdict(list)
|
||||
for record in records:
|
||||
group_id = record.salary_group_id.id if record.salary_group_id else None
|
||||
grouped_records[group_id].append(record)
|
||||
for group_id, group_records in grouped_records.items():
|
||||
if group_id:
|
||||
group_name = self.env['yuthon.salary.group'].browse(group_id).name
|
||||
else:
|
||||
group_name = '未分组'
|
||||
# 创建新的工作表
|
||||
sheet = workbook.add_worksheet(group_name[:31])
|
||||
# 写入公司和年月信息
|
||||
sheet.merge_range(0, 0, 0, len(data['field_label']) - 1, f'员工{data["current_year"]}年{data["current_month"]}工资表({company_name})', title_format)
|
||||
# 写入表头
|
||||
headers = ['序号']+data['field_label']
|
||||
col_num = 0
|
||||
for label in headers:
|
||||
sheet.write(1, col_num, label, header_format)
|
||||
col_num += 1
|
||||
|
||||
row_num = 2
|
||||
serial_number = 1
|
||||
for record in group_records:
|
||||
col_num = 0
|
||||
sheet.write(row_num, col_num, serial_number, serial_number_format)
|
||||
col_num += 1
|
||||
for field_name in data['fields_name']:
|
||||
field = self.env[data['model_name']]._fields.get(field_name)
|
||||
value = record[field_name]
|
||||
if isinstance(value, datetime.date):
|
||||
value = value.strftime('%Y-%m-%d')
|
||||
elif field:
|
||||
if field.type == 'many2one':
|
||||
if value:
|
||||
value = value.display_name
|
||||
else:
|
||||
value = ""
|
||||
elif field.type == 'many2many':
|
||||
value = ', '.join([rec.display_name for rec in value]) if value else ""
|
||||
elif field.type == 'one2many':
|
||||
value = ', '.join([rec.display_name for rec in value]) if value else ""
|
||||
elif field.type == 'selection':
|
||||
# 获取选择字段的选项列表
|
||||
selection_options = dict(field.selection)
|
||||
# 将值转换为对应的显示标签
|
||||
value = selection_options.get(value, value)
|
||||
sheet.write(row_num, col_num, value, data_format)
|
||||
col_num += 1
|
||||
row_num += 1
|
||||
serial_number += 1 # 序号递增
|
||||
# 创建劳务信息工作表
|
||||
labor_sheet = workbook.add_worksheet('劳务信息')
|
||||
labor_fields = ['employee_id', 'labor_amount']
|
||||
labor_labels = ['员工姓名', '劳务金额']
|
||||
labor_headers = ['序号'] + labor_labels
|
||||
# 写入劳务费大标题
|
||||
labor_title = f'员工{data["current_year"]}年{data["current_month"]}月劳务费({company_name})'
|
||||
labor_sheet.merge_range(0, 0, 0, len(labor_headers) - 1, labor_title, title_format)
|
||||
title_width = len(labor_title) + 2 # 适当增加一些宽度余量
|
||||
labor_sheet.set_column(0, len(labor_headers) - 1, title_width)
|
||||
# 写入表头
|
||||
col_num = 0
|
||||
for label in labor_headers:
|
||||
labor_sheet.write(1, col_num, label, header_format)
|
||||
col_num += 1
|
||||
labor_records = self.env['yuthon.payroll.labor'].search([
|
||||
('current_year', '=', data['current_year']),
|
||||
('current_month', '=', data['current_month'])
|
||||
])
|
||||
row_num = 2
|
||||
serial_number = 1
|
||||
for labor_record in labor_records:
|
||||
col_num = 0
|
||||
labor_sheet.write(row_num, col_num, serial_number, serial_number_format)
|
||||
col_num += 1
|
||||
for field_name in labor_fields:
|
||||
field = self.env['yuthon.payroll.labor']._fields.get(field_name)
|
||||
value = labor_record[field_name]
|
||||
if isinstance(value, datetime.date):
|
||||
value = value.strftime('%Y-%m-%d')
|
||||
elif field:
|
||||
if field.type == 'many2one':
|
||||
if value:
|
||||
value = value.display_name
|
||||
else:
|
||||
value = ""
|
||||
elif field.type == 'many2many':
|
||||
value = ', '.join([rec.display_name for rec in value]) if value else ""
|
||||
elif field.type == 'one2many':
|
||||
value = ', '.join([rec.display_name for rec in value]) if value else ""
|
||||
elif field.type == 'selection':
|
||||
selection_options = dict(field.selection)
|
||||
value = selection_options.get(value, value)
|
||||
labor_sheet.write(row_num, col_num, value, data_format)
|
||||
col_num += 1
|
||||
row_num += 1
|
||||
serial_number += 1
|
||||
|
||||
# 创建退休人员费用工作表
|
||||
retired_sheet = workbook.add_worksheet('退休人员费用')
|
||||
retired_fields = ['name', 'retired_amount']
|
||||
retired_labels = ['姓名', '费用']
|
||||
retired_headers = ['序号'] + retired_labels
|
||||
# 根据标题长度动态计算并设置列宽
|
||||
retired_title = f'员工{data["current_year"]}年{data["current_month"]}月退休费用({company_name})'
|
||||
retired_sheet.merge_range(0, 0, 0, len(labor_headers) - 1, retired_title, title_format)
|
||||
title_width = len(retired_title) + 2 # 适当增加一些宽度余量
|
||||
retired_sheet.set_column(0, len(retired_headers) - 1, title_width)
|
||||
# 写入表头
|
||||
col_num = 0
|
||||
for label in retired_headers:
|
||||
retired_sheet.write(1, col_num, label, header_format)
|
||||
col_num += 1
|
||||
retired_records = self.env['yuthon.payroll.retired'].search([
|
||||
('current_year', '=', data['current_year']),
|
||||
('current_month', '=', data['current_month'])
|
||||
])
|
||||
row_num = 2
|
||||
serial_number = 1
|
||||
for retired_record in retired_records:
|
||||
col_num = 0
|
||||
retired_sheet.write(row_num, col_num, serial_number, serial_number_format)
|
||||
col_num += 1
|
||||
for field_name in retired_fields:
|
||||
field = self.env['yuthon.payroll.retired']._fields.get(field_name)
|
||||
value = retired_record[field_name]
|
||||
if isinstance(value, datetime.date):
|
||||
value = value.strftime('%Y-%m-%d')
|
||||
elif field:
|
||||
if field.type == 'many2one':
|
||||
if value:
|
||||
value = value.display_name
|
||||
else:
|
||||
value = ""
|
||||
elif field.type == 'many2many':
|
||||
value = ', '.join([rec.display_name for rec in value]) if value else ""
|
||||
elif field.type == 'one2many':
|
||||
value = ', '.join([rec.display_name for rec in value]) if value else ""
|
||||
elif field.type == 'selection':
|
||||
selection_options = dict(field.selection)
|
||||
value = selection_options.get(value, value)
|
||||
retired_sheet.write(row_num, col_num, value, data_format)
|
||||
col_num += 1
|
||||
row_num += 1
|
||||
serial_number += 1
|
||||
|
||||
# 关闭工作簿
|
||||
workbook.close()
|
||||
# 将文件指针移动到文件开头
|
||||
output.seek(0)
|
||||
# 将文件内容写入响应流
|
||||
response.stream.write(output.read())
|
||||
# 关闭文件对象
|
||||
output.close()
|
||||
|
||||
|
||||
def _get_payslip_domain(self, data):
|
||||
current_month = data['current_month']
|
||||
current_year = data['current_year']
|
||||
# 把数字月份转换为中文月份
|
||||
month_mapping = {
|
||||
'1': '一月',
|
||||
'2': '二月',
|
||||
'3': '三月',
|
||||
'4': '四月',
|
||||
'5': '五月',
|
||||
'6': '六月',
|
||||
'7': '七月',
|
||||
'8': '八月',
|
||||
'9': '九月',
|
||||
'10': '十月',
|
||||
'11': '十一月',
|
||||
'12': '十二月'
|
||||
}
|
||||
chinese_month = month_mapping.get(current_month)
|
||||
target_name = f"{current_year}年-{chinese_month}"
|
||||
return [
|
||||
('is_salary_push', '=', True),
|
||||
('is_salary_release', '=', True),
|
||||
('payslip_run_id.name', '=', target_name)
|
||||
]
|
||||
@@ -32,6 +32,7 @@
|
||||
'wizard/salary_payslip_wizard_views.xml',
|
||||
'wizard/select_delete_wizard_viwes.xml',
|
||||
'wizard/put_return_wizard_viwes.xml',
|
||||
'wizard/salary_print_wizard_views.xml',
|
||||
],
|
||||
'assets': {
|
||||
'web.assets_backend': [
|
||||
@@ -42,11 +43,13 @@
|
||||
'yuthon_salary/static/src/js/salary_labor_button.js',
|
||||
'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/xml/salary_create_button.xml',
|
||||
'yuthon_salary/static/src/xml/salary_labor_button.xml',
|
||||
'yuthon_salary/static/src/xml/salary_retired_button.xml',
|
||||
'yuthon_salary/static/src/xml/salary_payslip_button.xml',
|
||||
'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',
|
||||
],
|
||||
},
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import ValidationError, UserError
|
||||
|
||||
import json
|
||||
from odoo.tools import date_utils
|
||||
|
||||
class InheritHrPayslip(models.Model):
|
||||
_inherit = 'hr.payslip'
|
||||
@@ -332,4 +333,13 @@ class InheritHrPayslip(models.Model):
|
||||
record.write({
|
||||
'is_salary_release': False,
|
||||
'salary_state': 'to_signed',
|
||||
})
|
||||
})
|
||||
|
||||
def button_salary_print(self):
|
||||
return {
|
||||
"type": "ir.actions.act_window",
|
||||
"name": "导入薪资",
|
||||
"res_model": "salary.print.wizard",
|
||||
"view_mode": "form",
|
||||
"target": "new",
|
||||
}
|
||||
@@ -18,4 +18,5 @@ access_yuthon_payroll_labor,access_yuthon_payroll_labor,model_yuthon_payroll_lab
|
||||
access_yuthon_payroll_retired,access_yuthon_payroll_retired,model_yuthon_payroll_retired,base.group_user,1,1,1,1
|
||||
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_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
|
||||
|
@@ -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 CustomSalaryValidationController extends ListController {
|
||||
setup() {
|
||||
super.setup();
|
||||
}
|
||||
|
||||
openSalaryValidationWizard() {
|
||||
this.actionService.doAction({
|
||||
type: 'ir.actions.act_window',
|
||||
res_model: 'salary.print.wizard',
|
||||
name: '薪资审定打印弹窗',
|
||||
view_mode: 'form',
|
||||
view_type: 'form',
|
||||
views: [[false, 'form']],
|
||||
target: 'new', // 以弹窗形式打开
|
||||
context: {},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
registry.category("views").add("custom_salary_validation_button", {
|
||||
...listView,
|
||||
Controller: CustomSalaryValidationController,
|
||||
buttonTemplate: "salary_validation_module.ListView.Buttons",
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<templates>
|
||||
<t t-name="salary_validation_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="openSalaryValidationWizard">
|
||||
打印
|
||||
</button>
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<!--薪资审定-->
|
||||
<record id="hr_payroll_inherit" model="ir.ui.view">
|
||||
<field name="name">hr.payroll.inherit</field>
|
||||
<field name="model">hr.payslip</field>
|
||||
@@ -79,6 +80,60 @@
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
<!--薪资发放-->
|
||||
<record id="view_hr_payslip_tree3" model="ir.ui.view">
|
||||
<field name="name">hr.payslip.tree</field>
|
||||
<field name="model">hr.payslip</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="薪资发放" default_order="employee_id" js_class="custom_salary_validation_button">
|
||||
<header>
|
||||
<button name="button_salary_print" type="object" string="打印" class="btn-primary"/>
|
||||
</header>
|
||||
<field name="employee_id" string="姓名" widget="ztree_select"/>
|
||||
<field name="company_id" string="公司"/>
|
||||
<field name="struct_id" string="职级"/>
|
||||
<field name="bank_account_id"/>
|
||||
<field name="actual_salary" decoration-danger="1"/>
|
||||
<field name="base_salary" required="1"/>
|
||||
<field name="rank_salary" required="1"/>
|
||||
<field name="post_salary" required="1"/>
|
||||
<field name="performance_bonuses" required="1"/>
|
||||
<field name="commuting_allowance" required="1"/>
|
||||
<field name="seniority_salary" required="1"/>
|
||||
<field name="full_attendance_award"/>
|
||||
<field name="overtime_pay"/>
|
||||
<field name="high_temperature_allowance"/>
|
||||
<field name="temporary_performance_bonus"/>
|
||||
<field name="year_compute" decoration-danger="1"/>
|
||||
<field name="year_jie" decoration-danger="1"/>
|
||||
<field name="jing_te" decoration-danger="1"/>
|
||||
<field name="year_gong" decoration-danger="1"/>
|
||||
<field name="study_on" decoration-danger="1"/>
|
||||
<field name="base_salary_deduction" decoration-success="1"/>
|
||||
<field name="commuting_deduction" decoration-success="1"/>
|
||||
<field name="performance_deduction" decoration-success="1"/>
|
||||
<field name="total_before_tax" decoration-danger="1" decoration-bf="1"/>
|
||||
<field name="basic_endowment_insurance"/>
|
||||
<field name="basic_medical_insurance"/>
|
||||
<field name="unemployment_insurance"/>
|
||||
<field name="b_year"/>
|
||||
<field name="union_dues"/>
|
||||
<field name="tax_payable" decoration-danger="1" decoration-bf="1"/>
|
||||
<field name="deduction_standard"/>
|
||||
<field name="specialized_deduction"/>
|
||||
<field name="child_education"/>
|
||||
<field name="elderly_support"/>
|
||||
<field name="housing_loan_interest"/>
|
||||
<field name="housing_rent"/>
|
||||
<field name="continuing_education"/>
|
||||
<field name="infant_care"/>
|
||||
<field name="meal_misunderstanding_fee"/>
|
||||
<field name="salary_state"/>
|
||||
<field name="is_salary_release" column_invisible="1"/>
|
||||
<field name="is_salary_push" column_invisible="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="hr_payroll_inherit_form" model="ir.ui.view">
|
||||
<field name="name">hr.payroll.inherit.form</field>
|
||||
<field name="model">hr.payslip</field>
|
||||
@@ -310,7 +365,7 @@
|
||||
<field name="domain">[('is_salary_push', '=', True), ('is_salary_release', '=', True)]</field>
|
||||
<field name="context">{'search_default_group_by_employee': 1}</field>
|
||||
<field name="view_ids" eval="[(5, 0, 0),
|
||||
(0, 0, {'view_mode': 'tree', 'view_id': ref('hr_payroll.view_hr_payslip_tree')}),
|
||||
(0, 0, {'view_mode': 'tree', 'view_id': ref('yuthon_salary.view_hr_payslip_tree3')}),
|
||||
(0, 0, {'view_mode': 'form', 'view_id': ref('hr_payroll.view_hr_payslip_form')})]"/>
|
||||
</record>
|
||||
<record id="action_view_hr_payslip_month_form1" model="ir.actions.act_window">
|
||||
|
||||
@@ -6,4 +6,5 @@ from . import select_delete_wizard
|
||||
from . import put_return_wizard
|
||||
from . import temporary_payslip_wizard
|
||||
from . import payroll_labor_wizard
|
||||
from . import payroll_retired_wizard
|
||||
from . import payroll_retired_wizard
|
||||
from . import salary_print_wizard
|
||||
@@ -0,0 +1,171 @@
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import ValidationError, UserError
|
||||
import json
|
||||
from odoo.tools import date_utils
|
||||
import datetime
|
||||
|
||||
|
||||
class SalaryPrintWizard(models.Model):
|
||||
_name = 'salary.print.wizard'
|
||||
_description = '薪资打印弹窗'
|
||||
|
||||
current_year = fields.Integer(string='年份', default=lambda self: datetime.datetime.now().year)
|
||||
current_month = fields.Selection([
|
||||
('1', '1月份'),
|
||||
('2', '2月份'),
|
||||
('3', '3月份'),
|
||||
('4', '4月份'),
|
||||
('5', '5月份'),
|
||||
('6', '6月份'),
|
||||
('7', '7月份'),
|
||||
('8', '8月份'),
|
||||
('9', '9月份'),
|
||||
('10', '10月份'),
|
||||
('11', '11月份'),
|
||||
('12', '12月份')
|
||||
], string="月份", default=lambda self: str(datetime.datetime.now().month))
|
||||
|
||||
def print_fixed_report(self):
|
||||
fields_list = [
|
||||
'employee_id',
|
||||
'company_id',
|
||||
'struct_id',
|
||||
'bank_account_id',
|
||||
'actual_salary',
|
||||
'base_salary',
|
||||
'rank_salary',
|
||||
'post_salary',
|
||||
'performance_bonuses',
|
||||
'commuting_allowance',
|
||||
'seniority_salary',
|
||||
'full_attendance_award',
|
||||
'overtime_pay',
|
||||
'high_temperature_allowance',
|
||||
'temporary_performance_bonus',
|
||||
'year_compute',
|
||||
'year_jie',
|
||||
'jing_te',
|
||||
'year_gong',
|
||||
'study_on',
|
||||
'base_salary_deduction',
|
||||
'commuting_deduction',
|
||||
'performance_deduction',
|
||||
'total_before_tax',
|
||||
'basic_endowment_insurance',
|
||||
'basic_medical_insurance',
|
||||
'unemployment_insurance',
|
||||
'b_year',
|
||||
'union_dues',
|
||||
'tax_payable',
|
||||
'deduction_standard',
|
||||
'specialized_deduction',
|
||||
'child_education',
|
||||
'elderly_support',
|
||||
'housing_loan_interest',
|
||||
'housing_rent',
|
||||
'continuing_education',
|
||||
'infant_care',
|
||||
'meal_misunderstanding_fee',
|
||||
'salary_state'
|
||||
]
|
||||
data = {
|
||||
'report_name': '薪资',
|
||||
'model_name': 'hr.payslip', # 指定模型
|
||||
'current_month': self.current_month,
|
||||
'current_year': self.current_year,
|
||||
'fields_name': [
|
||||
'employee_id',
|
||||
'company_id',
|
||||
'struct_id',
|
||||
'bank_account_id',
|
||||
'actual_salary',
|
||||
'base_salary',
|
||||
'rank_salary',
|
||||
'post_salary',
|
||||
'performance_bonuses',
|
||||
'commuting_allowance',
|
||||
'seniority_salary',
|
||||
'full_attendance_award',
|
||||
'overtime_pay',
|
||||
'high_temperature_allowance',
|
||||
'temporary_performance_bonus',
|
||||
'year_compute',
|
||||
'year_jie',
|
||||
'jing_te',
|
||||
'year_gong',
|
||||
'study_on',
|
||||
'base_salary_deduction',
|
||||
'commuting_deduction',
|
||||
'performance_deduction',
|
||||
'total_before_tax',
|
||||
'basic_endowment_insurance',
|
||||
'basic_medical_insurance',
|
||||
'unemployment_insurance',
|
||||
'b_year',
|
||||
'union_dues',
|
||||
'tax_payable',
|
||||
'deduction_standard',
|
||||
'specialized_deduction',
|
||||
'child_education',
|
||||
'elderly_support',
|
||||
'housing_loan_interest',
|
||||
'housing_rent',
|
||||
'continuing_education',
|
||||
'infant_care',
|
||||
'meal_misunderstanding_fee',
|
||||
'salary_state'
|
||||
],
|
||||
'field_label': [
|
||||
'姓名',
|
||||
'公司',
|
||||
'职级',
|
||||
'银行账号',
|
||||
'实发工资',
|
||||
'基本工资',
|
||||
'职级工资',
|
||||
'岗位工资',
|
||||
'预发绩效奖金',
|
||||
'通信补贴',
|
||||
'工龄工资',
|
||||
'全勤奖',
|
||||
'加班费',
|
||||
'高温补贴',
|
||||
'临时绩效奖',
|
||||
'年度清算',
|
||||
'年度结余',
|
||||
'经营特别奖',
|
||||
'年功奖',
|
||||
'学习进步奖',
|
||||
'扣发基本工资',
|
||||
'扣发通信补贴',
|
||||
'扣发绩效奖金',
|
||||
'本期收入',
|
||||
'基本养老保险费',
|
||||
'基本医疗保险费',
|
||||
'失业保险费',
|
||||
'企业(职业)年金',
|
||||
'工会会费',
|
||||
'应补(退)税额',
|
||||
'减除费用标准',
|
||||
'累计专项扣除',
|
||||
'累计子女教育',
|
||||
'累计赡养老人',
|
||||
'累计住房贷款利息',
|
||||
'累计住房租金',
|
||||
'累计继续教育',
|
||||
'累计3岁以下婴幼儿照护',
|
||||
'误餐费',
|
||||
'状态'
|
||||
],
|
||||
'field_order': str([i for i in range(1, len(fields_list) + 1)])
|
||||
}
|
||||
return {
|
||||
'type': 'ir.actions.report',
|
||||
'data': {
|
||||
'model': 'report.excel', # 这里需要替换为实际的报表模型名称
|
||||
'options': json.dumps(data, default=date_utils.json_default),
|
||||
'output_format': 'xlsx',
|
||||
'report_name': '薪资',
|
||||
},
|
||||
'report_type': 'xlsx',
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<record id="view_salary_print_wizard_form" model="ir.ui.view">
|
||||
<field name="name">salary.print.wizard.form</field>
|
||||
<field name="model">salary.print.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="current_year"/>
|
||||
<field name="current_month"/>
|
||||
</group>
|
||||
</sheet>
|
||||
<footer>
|
||||
<button name="print_fixed_report" string="确认" type="object" class="oe_highlight"/>
|
||||
<button string="返回" class="btn-secondary" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user