添加功能
This commit is contained in:
@@ -157,7 +157,7 @@ class YuthonProperty(models.Model):
|
||||
'admin_id': latest_info.admin_id,
|
||||
'company_id': latest_info.company_id,
|
||||
})
|
||||
contract_line_ids = self.env['property.lease.contract.line'].search([('address_id', '=', rec.id)])
|
||||
contract_line_ids = self.env['property.lease.contract.line'].search([('address_id', F'=', rec.id)])
|
||||
for contract_line_id in contract_line_ids:
|
||||
contract_line_id.admin_line_id = latest_info.admin_id
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
'views/yuthon_welfare_expenses_views.xml',
|
||||
'views/yuthon_payroll_retired_views.xml',
|
||||
'views/yuthon_salary_year_views.xml',
|
||||
'wizard/rank_log_wizard_views.xml',
|
||||
'wizard/yuthon_salary_wizard_views.xml',
|
||||
'wizard/temporary_payslip_wizard_views.xml',
|
||||
'wizard/yuthon_payroll_wizard_views.xml',
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<record forcecreate="True" id="update_rank_log_time" model="ir.cron">
|
||||
<field name="name">定时任务:更新职级日志</field>
|
||||
<field name="model_id" ref="model_hr_payroll_structure"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">model.rank_log_time()</field>
|
||||
<field eval="True" name="active"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="interval_number">1</field>
|
||||
<field name="interval_type">months</field>
|
||||
<field name="nextcall" eval="(DateTime.now()).strftime('%Y-%m-%d 00:00:00')"/>
|
||||
<field name="numbercall">-1</field>
|
||||
<field eval="False" name="doall"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -1,6 +1,8 @@
|
||||
from odoo import api, fields, models, _
|
||||
import re
|
||||
from pypinyin import pinyin, Style
|
||||
from datetime import date
|
||||
|
||||
|
||||
|
||||
class HrPayrollStructure(models.Model):
|
||||
@@ -25,6 +27,7 @@ class HrPayrollStructure(models.Model):
|
||||
position_subsidy = fields.Monetary(string="岗位补贴", currency_field="currency_id")
|
||||
integrated_subsidy = fields.Monetary(string="综合补贴", currency_field="currency_id")
|
||||
advance_performance_bonuses = fields.Monetary(string="预发绩效奖金", currency_field="currency_id")
|
||||
renk_log_ids = fields.One2many("rank.log.line", "structure_id", string="职级日志明细行")
|
||||
|
||||
@api.model
|
||||
def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True):
|
||||
@@ -105,6 +108,19 @@ class HrPayrollStructure(models.Model):
|
||||
"view_mode": "form",
|
||||
}
|
||||
|
||||
def write(self, vals):
|
||||
result = super(HrPayrollStructure, self).write(vals)
|
||||
field_mapping = {
|
||||
'base_salary': '基本工资',
|
||||
'rank_salary': '职级工资',
|
||||
'communication_subsidy': '通讯补贴',
|
||||
'position_salary': '岗位工资'
|
||||
}
|
||||
for field, name in field_mapping.items():
|
||||
if field in vals:
|
||||
self._handle_salary_rule(name, self[field])
|
||||
return result
|
||||
|
||||
def action_yuthon_payroll_wizard(self):
|
||||
return {
|
||||
"type": "ir.actions.act_window",
|
||||
@@ -184,3 +200,72 @@ class HrPayrollStructure(models.Model):
|
||||
for rule in payroll.rule_ids:
|
||||
if rule.name == '工会会费':
|
||||
rule.write({'category_id': category_id.id})
|
||||
|
||||
def rank_log_wizard(self):
|
||||
return {
|
||||
"type": "ir.actions.act_window",
|
||||
"name": "职级日志",
|
||||
"res_model": "rank.log.wizard",
|
||||
"view_mode": "form",
|
||||
"target": "new",
|
||||
}
|
||||
|
||||
def update_rank(self):
|
||||
payroll_ids = self.env["hr.payroll.structure"].browse(
|
||||
self._context.get('active_ids', self._context.get('active_id')))
|
||||
for payroll in payroll_ids:
|
||||
log_data = {
|
||||
'structure_id': payroll.id,
|
||||
'base_salary': payroll.base_salary,
|
||||
'rank_salary': payroll.rank_salary,
|
||||
'communication_subsidy': payroll.communication_subsidy,
|
||||
'position_salary': payroll.position_salary,
|
||||
'advance_performance_bonuses': payroll.advance_performance_bonuses,
|
||||
'effective_date': payroll.create_time,
|
||||
'lapse_date': payroll.end_time,
|
||||
'is_enable': payroll.is_enable
|
||||
}
|
||||
self.env['rank.log.line'].create(log_data)
|
||||
|
||||
def empty_the_log(self):
|
||||
payroll_ids = self.env["hr.payroll.structure"].browse(
|
||||
self._context.get('active_ids', self._context.get('active_id')))
|
||||
for payroll in payroll_ids:
|
||||
payroll.renk_log_ids.unlink()
|
||||
|
||||
def rank_log_time(self):
|
||||
"""定时任务:根据日志记录的生效时间更新主模型字段值"""
|
||||
today = date.today()
|
||||
for structure in self.search([]):
|
||||
# 获取该职级下所有有效的日志记录
|
||||
valid_logs = structure.renk_log_ids.filtered(
|
||||
lambda log: log.is_enable and
|
||||
log.effective_date and
|
||||
log.effective_date <= today and
|
||||
(not log.lapse_date or log.lapse_date >= today)
|
||||
).sorted(key=lambda l: l.effective_date, reverse=True)
|
||||
if valid_logs:
|
||||
latest_log = valid_logs[0]
|
||||
structure.write({
|
||||
'base_salary': latest_log.base_salary,
|
||||
'rank_salary': latest_log.rank_salary,
|
||||
'communication_subsidy': latest_log.communication_subsidy,
|
||||
'position_salary': latest_log.position_salary,
|
||||
'advance_performance_bonuses': latest_log.advance_performance_bonuses,
|
||||
})
|
||||
|
||||
class RankLogLine(models.Model):
|
||||
_name = 'rank.log.line'
|
||||
_description = '职级日志'
|
||||
|
||||
structure_id = fields.Many2one('hr.payroll.structure', string='关联职级')
|
||||
base_salary = fields.Float(string="基本工资")
|
||||
rank_salary = fields.Float(string="职级工资")
|
||||
communication_subsidy = fields.Float(string="通讯补贴")
|
||||
position_salary = fields.Float(string="岗位工资")
|
||||
advance_performance_bonuses = fields.Float(string="预发绩效奖金")
|
||||
effective_date = fields.Date(string="生效日期")
|
||||
lapse_date = fields.Date(string="失效日期")
|
||||
is_enable = fields.Boolean(string="启用")
|
||||
|
||||
|
||||
|
||||
@@ -31,4 +31,6 @@ 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
|
||||
access_initialize_payroll_wizard,access_initialize_payroll_wizard,model_initialize_payroll_wizard,base.group_user,1,1,1,1
|
||||
access_rank_log_line,access_rank_log_line,model_rank_log_line,base.group_user,1,1,1,1
|
||||
access_rank_log_wizard,access_rank_log_wizard,model_rank_log_wizard,base.group_user,1,1,1,1
|
||||
|
@@ -76,6 +76,22 @@
|
||||
<xpath expr="//field[@name='partner_id']" position="after">
|
||||
<field name="company_id"/>
|
||||
</xpath>
|
||||
<xpath expr="//page[@name='other_input']" position="after">
|
||||
<page string="职级日志">
|
||||
<field name="renk_log_ids">
|
||||
<tree editable="bottom">
|
||||
<field name="base_salary"/>
|
||||
<field name="rank_salary"/>
|
||||
<field name="communication_subsidy"/>
|
||||
<field name="position_salary"/>
|
||||
<field name="advance_performance_bonuses"/>
|
||||
<field name="effective_date"/>
|
||||
<field name="lapse_date"/>
|
||||
<field name="is_enable" optional="hide"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
<record id="hr_payroll_structure_search" model="ir.ui.view">
|
||||
@@ -125,6 +141,13 @@
|
||||
<field name="binding_model_id" ref="hr_payroll.model_hr_payroll_structure"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">action = model.action_select_delete_wizard()</field>
|
||||
</record>
|
||||
<record id="all_rank_log_wizard" model="ir.actions.server">
|
||||
<field name="name">职级日志导入</field>
|
||||
<field name="model_id" ref="hr_payroll.model_hr_payroll_structure"/>
|
||||
<field name="binding_model_id" ref="hr_payroll.model_hr_payroll_structure"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">action = model.rank_log_wizard()</field>
|
||||
</record>
|
||||
<record id="select_delete_structure" model="ir.actions.server">
|
||||
<field name="name">删除工资项</field>
|
||||
@@ -133,11 +156,18 @@
|
||||
<field name="state">code</field>
|
||||
<field name="code">action = model.delete_structure()</field>
|
||||
</record>
|
||||
<record id="select_update_lc" model="ir.actions.server">
|
||||
<field name="name">一次性</field>
|
||||
<record id="select_update_rank_log" model="ir.actions.server">
|
||||
<field name="name">更新日志</field>
|
||||
<field name="model_id" ref="hr_payroll.model_hr_payroll_structure"/>
|
||||
<field name="binding_model_id" ref="hr_payroll.model_hr_payroll_structure"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">action = model.update_payroll_items()</field>
|
||||
<field name="code">action = model.update_rank()</field>
|
||||
</record>
|
||||
<record id="select_empty_the_log" model="ir.actions.server">
|
||||
<field name="name">清空职级日志</field>
|
||||
<field name="model_id" ref="hr_payroll.model_hr_payroll_structure"/>
|
||||
<field name="binding_model_id" ref="hr_payroll.model_hr_payroll_structure"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">action = model.empty_the_log()</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -10,4 +10,5 @@ from . import payroll_retired_wizard
|
||||
from . import salary_print_wizard
|
||||
from . import salary_year_wizard
|
||||
from . import payslip_send_wizard
|
||||
from . import initialize_payroll_wizard
|
||||
from . import initialize_payroll_wizard
|
||||
from . import rank_log_wizard
|
||||
@@ -0,0 +1,44 @@
|
||||
# -*- 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 RankLogWizard(models.Model):
|
||||
_name = 'rank.log.wizard'
|
||||
_description = '职级日志导入弹窗'
|
||||
|
||||
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)
|
||||
self.payroll_rank_log(row)
|
||||
|
||||
def payroll_rank_log(self, row):
|
||||
structure_id = self.env['hr.payroll.structure'].search([('name', '=', row[1].value)])
|
||||
base_salary = row[2].value
|
||||
rank_salary = row[3].value
|
||||
advance_performance_bonuses = row[4].value
|
||||
communication_subsidy = row[5].value
|
||||
position_salary = row[6].value
|
||||
log_data = {
|
||||
'structure_id': structure_id.id,
|
||||
'base_salary': float(base_salary) if base_salary else 0.0,
|
||||
'rank_salary': float(rank_salary) if rank_salary else 0.0,
|
||||
'advance_performance_bonuses': float(advance_performance_bonuses) if advance_performance_bonuses else 0.0,
|
||||
'communication_subsidy': float(communication_subsidy) if communication_subsidy else 0.0,
|
||||
'position_salary': float(position_salary) if position_salary else 0.0,
|
||||
'effective_date': fields.Date.today(),
|
||||
'is_enable': True
|
||||
}
|
||||
self.env['rank.log.line'].create(log_data)
|
||||
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<record id="labor_template_downloads_rank_log_action" model="ir.actions.act_url">
|
||||
<field name="name">职级日志模板</field>
|
||||
<field name="target">self</field>
|
||||
<field name="url">.</field>
|
||||
</record>
|
||||
<record id="rank_log_wizard_form" model="ir.ui.view">
|
||||
<field name="name">审批意见弹窗</field>
|
||||
<field name="model">rank.log.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<sheet>
|
||||
<header>
|
||||
<button name="%(labor_template_downloads_tian_he_action)d" string="模板下载" type="action"
|
||||
class="btn btn-primary"/>
|
||||
</header>
|
||||
<group>
|
||||
<group>
|
||||
<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>
|
||||
Reference in New Issue
Block a user