添加功能
This commit is contained in:
@@ -48,6 +48,7 @@
|
||||
'soong_workflow/static/src/css/record_scss.scss',
|
||||
'soong_workflow/static/src/css/button_css.scss',
|
||||
'soong_workflow/static/src/js/view_button.js',
|
||||
'soong_workflow/static/src/js/select_create_dialog.js',
|
||||
'soong_workflow/static/src/diagram_plus_dialog/*',
|
||||
],
|
||||
},
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { SelectCreateDialog } from "@web/views/view_dialogs/select_create_dialog";
|
||||
|
||||
patch(SelectCreateDialog.prototype, {
|
||||
get viewProps() {
|
||||
// ################### 使用context <field name="user_id" context="{'select_dialog': 'list'}"/>
|
||||
const { select_dialog } = this.props.context;
|
||||
const type = select_dialog && ["kanban", "list"].includes(select_dialog) ? select_dialog : this.env.isSmall ? "kanban" : "list";
|
||||
// ###############################
|
||||
|
||||
// #################### 全局改
|
||||
// const type = "list";
|
||||
|
||||
const props = {
|
||||
loadIrFilters: true,
|
||||
...this.baseViewProps,
|
||||
context: this.props.context,
|
||||
domain: this.props.domain,
|
||||
dynamicFilters: this.props.dynamicFilters,
|
||||
resModel: this.props.resModel,
|
||||
searchViewId: this.props.searchViewId,
|
||||
type,
|
||||
};
|
||||
if (type === "list") {
|
||||
props.allowSelectors = this.props.multiSelect;
|
||||
} else if (type === "kanban") {
|
||||
props.forceGlobalClick = true;
|
||||
}
|
||||
return props;
|
||||
},
|
||||
});
|
||||
@@ -95,10 +95,14 @@
|
||||
'yuthon_hr_attendance/static/src/xml/button_detail_wechat.xml',
|
||||
'yuthon_hr_attendance/static/src/components/*/*.xml',
|
||||
'yuthon_hr_attendance/static/src/css/*.css',
|
||||
'yuthon_hr_attendance/static/src/js/button_meal_confirm.js',
|
||||
'yuthon_hr_attendance/static/src/xml/button_meal_confirm.xml',
|
||||
'yuthon_hr_attendance/static/src/js/button_vacation_confirm.js',
|
||||
'yuthon_hr_attendance/static/src/xml/button_vacation_confirm.xml',
|
||||
'yuthon_hr_attendance/static/src/js/planning_gantt_renderer.js',
|
||||
'yuthon_hr_attendance/static/src/xml/planning_gantt_renderer.xml',
|
||||
'yuthon_hr_attendance/static/src/js/button_statement_confirm.js',
|
||||
'yuthon_hr_attendance/static/src/xml/button_statement_confirm.xml',
|
||||
'yuthon_hr_attendance/static/src/js/button_vacation_put.js',
|
||||
'yuthon_hr_attendance/static/src/xml/button_vacation_put.xml',
|
||||
'yuthon_hr_attendance/static/src/planning_gantt/planning_gantt_controller.xml',
|
||||
|
||||
@@ -15,6 +15,7 @@ class InheritHrLeave(models.Model):
|
||||
is_filing = fields.Boolean(string="归档")
|
||||
application_reason = fields.Char(string="申请原因", compute="_compute_application_reason")
|
||||
|
||||
@api.model
|
||||
def confirm(self):
|
||||
now = datetime.now()
|
||||
current_month = now.month
|
||||
|
||||
@@ -973,7 +973,6 @@ class VacationOverline(models.Model):
|
||||
valid_date = fields.Date(string='有效期至')
|
||||
adjust_date = fields.Date(string='调整至')
|
||||
leave_date = fields.Date(string='请假日期')
|
||||
total = fields.Float(string='总时长', compute='_compute_total')
|
||||
overtime_methods = fields.Selection([('leave', '补休'), ('fee', '加班费结算')], string='加班补偿方式', default='leave')
|
||||
text = fields.Text(string='备注')
|
||||
is_confirm = fields.Boolean(string="是否确认")
|
||||
@@ -983,7 +982,7 @@ class VacationOverline(models.Model):
|
||||
start_time = fields.Datetime(string="开始时间", compute="_compute_overtime", store=True)
|
||||
end_time = fields.Datetime(string="结束时间", compute="_compute_overtime", store=True)
|
||||
carry_forward_date = fields.Date(string="结转日期")
|
||||
duration = fields.Float(string="加班时长", compute="_compute_overtime", store=True)
|
||||
duration = fields.Float(string="时长", compute="_compute_overtime", store=True)
|
||||
carry_forward_quantity = fields.Float(string="结转时长")
|
||||
validity = fields.Char(string="有效期")
|
||||
carry_result = fields.Selection([('success', '成功'), ('failed', '失败')], string="结转结果")
|
||||
@@ -994,6 +993,7 @@ class VacationOverline(models.Model):
|
||||
)
|
||||
remaining_quantity = fields.Float(string='剩余数', compute="_compute_remaining_quantity", store=True)
|
||||
|
||||
@api.model
|
||||
def confirm(self):
|
||||
domain = [
|
||||
'|',
|
||||
@@ -1013,7 +1013,7 @@ class VacationOverline(models.Model):
|
||||
if not filtered_records:
|
||||
return
|
||||
records_to_update = filtered_records.filtered(
|
||||
lambda r: fields.float_compare(r.total, r.carry_forward_quantity) == 0
|
||||
lambda r: fields.float_compare(r.duration, r.carry_forward_quantity) == 0
|
||||
)
|
||||
if records_to_update:
|
||||
records_to_update.write({'is_filing': True})
|
||||
@@ -1033,22 +1033,10 @@ class VacationOverline(models.Model):
|
||||
rec._compute_employee_id()
|
||||
rec._compute_last_balance()
|
||||
|
||||
@api.depends('public_holidays', 'workday', 'last_balance', 'valid_date')
|
||||
def _compute_total(self):
|
||||
current_date = date.today()
|
||||
for record in self:
|
||||
last_balance_contribution = record.last_balance
|
||||
if record.valid_date and current_date > record.valid_date:
|
||||
last_balance_contribution = 0.0
|
||||
if record.is_initial_number:
|
||||
record.total = record.duration
|
||||
else:
|
||||
record.total = record.public_holidays + record.workday + last_balance_contribution
|
||||
|
||||
@api.depends('total', 'carry_forward_quantity')
|
||||
@api.depends('duration', 'carry_forward_quantity')
|
||||
def _compute_remaining_quantity(self):
|
||||
for rec in self:
|
||||
rec.remaining_quantity = rec.total - rec.carry_forward_quantity
|
||||
rec.remaining_quantity = rec.duration - rec.carry_forward_quantity
|
||||
|
||||
@api.depends('vacation_id')
|
||||
def _compute_last_balance(self):
|
||||
@@ -1079,6 +1067,11 @@ class VacationOverline(models.Model):
|
||||
rec.overtime_name = '2025年12月结余初始数'
|
||||
rec.start_time = datetime(2025, 12, 1, 1, 0, 0)
|
||||
rec.end_time = datetime(2025, 12, 1, 9, 0, 0)
|
||||
if rec.vacation_id and rec.vacation_id.valid_date1:
|
||||
current_date = fields.Date.today()
|
||||
if current_date > rec.vacation_id.valid_date1:
|
||||
rec._compute_last_balance()
|
||||
rec.duration = max(0, rec.duration - rec.last_balance)
|
||||
|
||||
elif rec.workflow_record_id and rec.update_type == 'add':
|
||||
res_model = rec.workflow_record_id.res_model
|
||||
@@ -1235,6 +1228,7 @@ class VacationMealLine(models.Model):
|
||||
rec._compute_employee_id()
|
||||
rec._compute_overtime()
|
||||
|
||||
@api.model
|
||||
def confirm(self):
|
||||
now = datetime.now()
|
||||
current_month = now.month
|
||||
@@ -1247,10 +1241,11 @@ class VacationMealLine(models.Model):
|
||||
last_month_year = current_year
|
||||
last_month_first_day = datetime(last_month_year, last_month, 1)
|
||||
current_month_first_day = datetime(current_year, current_month, 1)
|
||||
valid_leaves = self.filtered(lambda l:
|
||||
fields.Datetime.to_datetime(l.start_date) >= last_month_first_day and
|
||||
fields.Datetime.to_datetime(l.start_date) < current_month_first_day
|
||||
)
|
||||
valid_leaves = self.search([
|
||||
('start_date', '>=', fields.Datetime.to_string(last_month_first_day)),
|
||||
('start_date', '<', fields.Datetime.to_string(current_month_first_day)),
|
||||
('id', 'in', self.ids)
|
||||
])
|
||||
if valid_leaves:
|
||||
valid_leaves.write({'is_filing': True})
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/** @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 CustomAttendanceMealConfirmController extends ListController {
|
||||
setup() {
|
||||
super.setup();
|
||||
}
|
||||
|
||||
async getAction(lock_type) {
|
||||
const action = await this.orm.call('vacation.meal.line', 'confirm', [lock_type], {context: this.props.context});
|
||||
action["context"] = {
|
||||
...action.context,
|
||||
...this.model.root.context,
|
||||
}
|
||||
return action
|
||||
}
|
||||
}
|
||||
|
||||
registry.category("views").add("custom_vacation_meal_button", {
|
||||
...listView,
|
||||
Controller: CustomAttendanceMealConfirmController,
|
||||
buttonTemplate: "meal_confirm_module.ListView.Buttons",
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
/** @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 CustomAttendanceStatementConfirmController extends ListController {
|
||||
setup() {
|
||||
super.setup();
|
||||
}
|
||||
|
||||
async getAction(lock_type) {
|
||||
const action = await this.orm.call('hr.leave', 'confirm', [lock_type], {context: this.props.context});
|
||||
action["context"] = {
|
||||
...action.context,
|
||||
...this.model.root.context,
|
||||
}
|
||||
return action
|
||||
}
|
||||
}
|
||||
|
||||
registry.category("views").add("custom_statement_confirm_button", {
|
||||
...listView,
|
||||
Controller: CustomAttendanceStatementConfirmController,
|
||||
buttonTemplate: "statement_confirm_module.ListView.Buttons",
|
||||
});
|
||||
@@ -29,7 +29,7 @@ export class CustomAttendanceVacationPutController extends ListController {
|
||||
view_mode: 'tree,form',
|
||||
view_type: 'tree',
|
||||
views: [[false, 'tree']],
|
||||
target: 'new', // 弹窗形式打开
|
||||
target: 'current',
|
||||
context: {'tree_view_ref': "yuthon_hr_attendance.view_hr_leave_statement_tree"},
|
||||
domain: [
|
||||
'&',
|
||||
@@ -47,7 +47,7 @@ export class CustomAttendanceVacationPutController extends ListController {
|
||||
view_mode: 'tree',
|
||||
view_type: 'form',
|
||||
views: [[false, 'tree']],
|
||||
target: 'new',
|
||||
target: 'current',
|
||||
context: {'tree_view_ref': "yuthon_hr_attendance.view_yuthon_vacation_overtime_briefly_tree"},
|
||||
domain: [
|
||||
'|',
|
||||
@@ -87,7 +87,7 @@ export class CustomAttendanceVacationPutController extends ListController {
|
||||
view_mode: 'tree',
|
||||
view_type: 'form',
|
||||
views: [[false, 'tree']],
|
||||
target: 'new',
|
||||
target: 'current',
|
||||
context: {'tree_view_ref': "yuthon_hr_attendance.view_vacation_meal_line_tree",
|
||||
'group_by': ['employee_id'],
|
||||
},
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<templates>
|
||||
<t t-name="meal_confirm_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="getAction">
|
||||
确认
|
||||
</button>
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<templates>
|
||||
<t t-name="statement_confirm_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="getAction">
|
||||
确认
|
||||
</button>
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
@@ -4,7 +4,7 @@
|
||||
<field name="name">hr.leave.statement.tree</field>
|
||||
<field name="model">hr.leave</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="请假情况" editable="bottom" limit="15" create="false" delete="false">
|
||||
<tree string="请假情况" editable="bottom" limit="15" create="false" delete="false" js_class="custom_statement_confirm_button">
|
||||
<field name="caption"/>
|
||||
<field name="employee_id"/>
|
||||
<field name="employee_company_id"/>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<field name="name">vacation.meal.line.tree</field>
|
||||
<field name="model">vacation.meal.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="误餐情况" create="false" delete="false">
|
||||
<tree string="误餐情况" create="false" delete="false" js_class="custom_vacation_meal_button">
|
||||
<field name="employee_id"/>
|
||||
<field name="meal_name"/>
|
||||
<field name="start_date" column_invisible="1"/>
|
||||
@@ -545,7 +545,6 @@
|
||||
<field name="valid_date" groups="yuthon_salary.group_lc_user,yuthon_salary.group_wg_user"/>
|
||||
<field name="workday"/>
|
||||
<field name="public_holidays"/>
|
||||
<field name="total"/>
|
||||
<field name="carry_forward_quantity"/>
|
||||
<field name="carry_forward_date"/>
|
||||
<field name="remaining_quantity"/>
|
||||
@@ -638,7 +637,7 @@
|
||||
<field name="model_id" ref="yuthon_hr_attendance.model_vacation_over_line"/>
|
||||
<field name="binding_model_id" ref="yuthon_hr_attendance.model_vacation_over_line"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">action = model.is_visible()</field>
|
||||
<field name="code">action = model.update_is_visible()</field>
|
||||
</record>
|
||||
<record id="view_yuthon_vacation_meal_action" model="ir.actions.act_window">
|
||||
<field name="name">误餐情况</field>
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
'views/yuthon_salary_project_views.xml',
|
||||
'views/yuthon_payroll_labor_views.xml',
|
||||
'views/yuthon_salary_documents_views.xml',
|
||||
'views/yuthon_salary_active_views.xml',
|
||||
'views/yuthon_welfare_expenses_views.xml',
|
||||
'views/yuthon_payroll_retired_views.xml',
|
||||
'views/yuthon_meal_expenses_views.xml',
|
||||
|
||||
@@ -16,4 +16,5 @@ from . import inherit_hr_payslip_run
|
||||
from . import inherit_hr_payslip_line
|
||||
from . import yuthon_salary_party
|
||||
from . import yuthon_individual_tax
|
||||
from . import yuthon_meal_expenses
|
||||
from . import yuthon_meal_expenses
|
||||
from . import yuthon_salary_active
|
||||
@@ -15,14 +15,32 @@ class InheritHrPayslipRun(models.Model):
|
||||
string="阶段")
|
||||
|
||||
def Fileline(self):
|
||||
domain = [('is_salary_push', '=', True), ('is_salary_release', '=', True), ('payslip_run_id', '=', self.id)]
|
||||
month_cn_to_num = self._get_month_cn_to_num()
|
||||
target_name = self.name
|
||||
year_str = ""
|
||||
month_str = ""
|
||||
if target_name and "年-" in target_name:
|
||||
year_part, month_part = target_name.split("年-", 1)
|
||||
year_str = year_part.replace("年", "")
|
||||
month_str = month_cn_to_num.get(month_part.strip(), "")
|
||||
domain = [('company_id', '=', self.company_id.id)]
|
||||
if year_str:
|
||||
domain.append(('select_year', '=', year_str))
|
||||
if month_str:
|
||||
domain.append(('select_time', '=', month_str))
|
||||
return {
|
||||
"name": "薪资归档明细",
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'hr.payslip',
|
||||
'res_model': 'yuthon.salary.active',
|
||||
"view_mode": "tree",
|
||||
"domain": domain,
|
||||
"context": "{'tree_view_ref': 'yuthon_salary.my_hr_payslip_view_tree'}"
|
||||
}
|
||||
|
||||
def _get_month_cn_to_num(self):
|
||||
return {
|
||||
'一月': '1', '二月': '2', '三月': '3', '四月': '4',
|
||||
'五月': '5', '六月': '6', '七月': '7', '八月': '8',
|
||||
'九月': '9', '十月': '10', '十一月': '11', '十二月': '12'
|
||||
}
|
||||
|
||||
def write(self, vals):
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from odoo import models, fields, api, _, SUPERUSER_ID
|
||||
from odoo.exceptions import ValidationError, UserError
|
||||
from odoo.exceptions import ValidationError
|
||||
import calendar
|
||||
from pypinyin import pinyin, Style
|
||||
import math
|
||||
import xlrd
|
||||
import base64
|
||||
import datetime
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
|
||||
class YuthonSalaryActive(models.Model):
|
||||
_name = 'yuthon.salary.active'
|
||||
_description = '薪资存档表'
|
||||
|
||||
employee_id = fields.Many2one('hr.employee', string='员工', required=True)
|
||||
company_id = fields.Many2one('res.company', string='公司', related='employee_id.company_id', store=True)
|
||||
select_time = fields.Selection([('1', '一月'), ('2', '二月'), ('3', '三月'), ('4', '四月'),
|
||||
('5', '五月'), ('6', '六月'), ('7', '七月'), ('8', '八月'),
|
||||
('9', '九月'), ('10', '十月'), ('11', '十一月'),
|
||||
('12', '十二月')], string='月份',
|
||||
default=lambda self: self._get_default_month())
|
||||
select_year = fields.Selection(selection=[(str(i), str(i)) for i in range(2024, 2040)], string='年份')
|
||||
basic_salary = fields.Float(string='基本工资')
|
||||
rank_salary = fields.Float(string='职级工资')
|
||||
pre_performance_bonus = fields.Float(string='预发绩效奖金')
|
||||
meal_allowance = fields.Float(string='误餐费')
|
||||
post_salary = fields.Float(string='岗位工资')
|
||||
communication_subsidy = fields.Float(string='通讯补贴')
|
||||
seniority_wage = fields.Float(string='工龄工资')
|
||||
overtime_pay = fields.Float(string='加班费')
|
||||
full_attendance_bonus = fields.Float(string='全勤奖')
|
||||
basic_year_end_bonus = fields.Float(string='基础年终奖')
|
||||
|
||||
liquidation_salary_leader = fields.Float(string='2024年清算工资(领导)')
|
||||
balance_salary = fields.Float(string='2025年结余工资')
|
||||
liquidation_salary_staff = fields.Float(string='2024年清算工资(职工)') #
|
||||
business_special_bonus = fields.Float(string='2025经营特别奖')
|
||||
|
||||
deduct_performance_bonus = fields.Float(string='扣发绩效奖金')
|
||||
deduct_communication_subsidy = fields.Float(string='扣发通讯补贴')
|
||||
attendance_deduction = fields.Float(string='考勤扣发')
|
||||
|
||||
# 合计/社保/税费类字段(float 类型)
|
||||
total_pre_tax_salary = fields.Float(string='税前工资合计')
|
||||
basic_endowment_insurance = fields.Float(string='基本养老保险费')
|
||||
basic_medical_insurance = fields.Float(string='基本医疗保险费')
|
||||
unemployment_insurance = fields.Float(string='失业保险费')
|
||||
housing_fund = fields.Float(string='住房公积金')
|
||||
enterprise_annuity = fields.Float(string='企业(职业)年金')
|
||||
tax_adjustment = fields.Float(string='应补(退)税额')
|
||||
trade_union_dues = fields.Float(string='工会会费')
|
||||
|
||||
# 实发/福利类字段(float 类型)
|
||||
actual_paid_salary = fields.Float(string='实发工资')
|
||||
reimbursed_medical_exam_fee = fields.Float(string='已报销体检费')
|
||||
remaining_medical_exam_fee = fields.Float(string='剩余体检费')
|
||||
|
||||
|
||||
def payslip_wizard(self):
|
||||
return {
|
||||
"type": "ir.actions.act_window",
|
||||
"name": "工资条发送",
|
||||
"res_model": "payslip.send.wizard",
|
||||
"view_mode": "form",
|
||||
"target": "new",
|
||||
"context": {
|
||||
'default_employee_id': self.employee_id.id,
|
||||
}
|
||||
}
|
||||
|
||||
def _get_default_month(self):
|
||||
current_month = datetime.now().month
|
||||
return str(current_month)
|
||||
@@ -44,4 +44,5 @@ access_party_send_wizard,access_party_send_wizard,model_party_send_wizard,base.g
|
||||
|
||||
access_yuthon_meal_expenses,access_yuthon_meal_expenses,model_yuthon_meal_expenses,base.group_user,1,1,1,1
|
||||
access_party_meal_wizard,access_party_meal_wizard,model_party_meal_wizard,base.group_user,1,1,1,1
|
||||
access_salary_meal_wizard,access_salary_meal_wizard,model_salary_meal_wizard,base.group_user,1,1,1,1
|
||||
access_salary_meal_wizard,access_salary_meal_wizard,model_salary_meal_wizard,base.group_user,1,1,1,1
|
||||
access_yuthon_salary_active,access_yuthon_salary_active,model_yuthon_salary_active,base.group_user,1,1,1,1
|
||||
|
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<record id="view_yuthon_salary_active_tree" model="ir.ui.view">
|
||||
<field name="name">yuthon.salary.active.tree</field>
|
||||
<field name="model">yuthon.salary.active</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="工资单归档" create="0" edit="0" delete="0">
|
||||
<!-- 核心关联字段:员工 -->
|
||||
<button type="object" name="payslip_wizard" string="发放" class="oe_highlight"/>
|
||||
<field name="employee_id" string="员工"/>
|
||||
<field name="company_id" column_invisible="1"/>
|
||||
|
||||
<!-- 基础薪资字段 -->
|
||||
<field name="basic_salary" string="基本工资"/>
|
||||
<field name="rank_salary" string="职级工资"/>
|
||||
<field name="pre_performance_bonus" string="预发绩效奖金"/>
|
||||
<field name="meal_allowance" string="误餐费"/>
|
||||
<field name="post_salary" string="岗位工资"/>
|
||||
<field name="communication_subsidy" string="通讯补贴"/>
|
||||
<field name="seniority_wage" string="工龄工资"/>
|
||||
<field name="overtime_pay" string="加班费"/>
|
||||
<field name="full_attendance_bonus" string="全勤奖"/>
|
||||
<field name="basic_year_end_bonus" string="基础年终奖"/>
|
||||
|
||||
<field name="liquidation_salary_leader" string="2024年清算工资(领导)"/>
|
||||
<field name="balance_salary" string="2025年结余工资"/>
|
||||
<field name="liquidation_salary_staff" string="2024年清算工资(职工)"/>
|
||||
<field name="business_special_bonus" string="2025经营特别奖"/>
|
||||
|
||||
<!-- 扣发类字段 -->
|
||||
<field name="deduct_performance_bonus" string="扣发绩效奖金"/>
|
||||
<field name="deduct_communication_subsidy" string="扣发通讯补贴"/>
|
||||
<field name="attendance_deduction" string="考勤扣发"/>
|
||||
|
||||
<!-- 合计/社保/税费类字段 -->
|
||||
<field name="total_pre_tax_salary" string="税前工资合计"/>
|
||||
<field name="basic_endowment_insurance" string="基本养老保险费"/>
|
||||
<field name="basic_medical_insurance" string="基本医疗保险费"/>
|
||||
<field name="unemployment_insurance" string="失业保险费"/>
|
||||
<field name="housing_fund" string="住房公积金"/>
|
||||
<field name="enterprise_annuity" string="企业(职业)年金"/>
|
||||
<field name="tax_adjustment" string="应补(退)税额"/>
|
||||
<field name="trade_union_dues" string="工会会费"/>
|
||||
|
||||
<field name="actual_paid_salary" string="实发工资"/>
|
||||
<field name="reimbursed_medical_exam_fee" string="已报销体检费"/>
|
||||
<field name="remaining_medical_exam_fee" string="剩余体检费"/>
|
||||
<field name="select_time" column_invisible="1"/>
|
||||
<field name="select_year" column_invisible="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="yuthon_salary_active_action" model="ir.actions.act_window">
|
||||
<field name="name">薪资归档</field>
|
||||
<field name="res_model">yuthon.salary.active</field>
|
||||
<field name="view_mode">tree</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -12,19 +12,15 @@ class PayslipSendWizard(models.Model):
|
||||
employee_ids = fields.Many2many('hr.employee', string='员工')
|
||||
payslip_run_id = fields.Many2one('hr.payslip.run', string='工资单')
|
||||
payslip_ids = fields.Many2many('hr.payslip', string='工资条')
|
||||
salary_id = fields.Many2one('yuthon.salary.active', string='工资条')
|
||||
|
||||
def button_send(self):
|
||||
for payslip in self.payslip_ids:
|
||||
# 获取工资单关联的员工
|
||||
employee = payslip.employee_id
|
||||
if not employee.wecom_userid:
|
||||
raise UserError(f"请同步{employee.name}的企业微信")
|
||||
url = f"https://oa.thtzjt.com/webh5/#/salary?id={payslip.id}"
|
||||
self.sudo().env["wecom.apps"].sync_send_message_textcard(category='default',
|
||||
user_id=employee.wecom_userid,
|
||||
description=self.employee_id.name + '请确认薪资:',
|
||||
title="薪资确认",
|
||||
url=url, btntxt="详细信息")
|
||||
url = f"https://oa.thtzjt.com/webh5/#/salary?id={self.salary_id.id}"
|
||||
self.sudo().env["wecom.apps"].sync_send_message_textcard(category='default',
|
||||
user_id=self.employee.wecom_userid,
|
||||
description=self.employee_id.name + '请确认薪资:',
|
||||
title="薪资确认",
|
||||
url=url, btntxt="详细信息")
|
||||
|
||||
def button_all_send(self):
|
||||
for payslip in self.payslip_ids:
|
||||
|
||||
@@ -379,6 +379,11 @@
|
||||
parent="human_resources_salary_root_board"
|
||||
action="hr_payroll.action_hr_payslip_run_tree"
|
||||
sequence="7"/>
|
||||
<menuitem id="human_yuthon_salary_active_board"
|
||||
name="薪资归档"
|
||||
parent="human_resources_salary_root_board"
|
||||
action="yuthon_salary.yuthon_salary_active_action"
|
||||
sequence="99"/>
|
||||
<menuitem id="human_pay_slips_root_board_jtbb"
|
||||
name="员工薪资"
|
||||
groups="yuthon_salary.group_jtbb_user"
|
||||
|
||||
Reference in New Issue
Block a user