@@ -25,7 +25,7 @@ class YuthonOvertimeLine(models.Model):
|
||||
carry_forward_quantity = fields.Float(string="结转时长")
|
||||
carry_forward_date = fields.Date(string="结转日期")
|
||||
archive_state = fields.Selection([('to_do', '待归档'), ('done', '已归档')], default='to_do', string='状态')
|
||||
remaining_quantity = fields.Float(string="剩余数")
|
||||
remaining_quantity = fields.Float(string="剩余数", compute='_compute_vacation_sum', store=True)
|
||||
|
||||
@api.depends('workday', 'public_holidays', 'carry_forward_quantity')
|
||||
def _compute_vacation_sum(self):
|
||||
|
||||
@@ -15,6 +15,20 @@
|
||||
<field name="numbercall">-1</field>
|
||||
<field eval="False" name="doall"/>
|
||||
</record>
|
||||
<record forcecreate="True" id="yuthon_medical_manage_data" model="ir.cron">
|
||||
<field name="name">定时任务:发放体检费</field>
|
||||
<field name="model_id" ref="model_yuthon_medical_manage"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">model.medical_manage()</field>
|
||||
<field eval="True" name="active"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="interval_number">1</field>
|
||||
<field name="interval_type">year</field>
|
||||
<field name="nextcall"
|
||||
eval="(DateTime.now() + relativedelta(day=1)).strftime('%Y-%m-%d 00:00:00')"/>
|
||||
<field name="numbercall">-1</field>
|
||||
<field eval="False" name="doall"/>
|
||||
</record>
|
||||
<record forcecreate="True" id="late_arrivals_are_allowed" model="ir.cron">
|
||||
<field name="name">定时任务:重置物管允许迟到次数</field>
|
||||
<field name="model_id" ref="model_hr_employee"/>
|
||||
|
||||
@@ -11,25 +11,49 @@ class YuthonMedicalManage(models.Model):
|
||||
employee_id = fields.Many2one('hr.employee', string="员工姓名")
|
||||
year = fields.Char(string="年份")
|
||||
current_year_remaining = fields.Float(string="本年剩余", compute="_compute_current_year_remaining")
|
||||
last_year_quota = fields.Float(string="上年额度")
|
||||
last_year_balance = fields.Float(string="上年结余")
|
||||
last_year_used = fields.Float(string="上年使用")
|
||||
last_year_remaining = fields.Float(string="上年剩余")
|
||||
prev_last_year_quota = fields.Float(string="前年额度")
|
||||
prev_last_year_balance = fields.Float(string="前年结余")
|
||||
prev_last_year_used = fields.Float(string="前年使用")
|
||||
last_year_quota = fields.Float(string="去年额度")
|
||||
last_year_used = fields.Float(string="去年使用", compute="_compute_last_year_used")
|
||||
last_year_remaining = fields.Float(string="去年剩余")
|
||||
prev_last_year_remaining = fields.Float(string="前年剩余")
|
||||
this_year_usage = fields.Float(string='本年使用')
|
||||
this_year_usage = fields.Float(string='本年使用', compute="_compute_this_year_usage")
|
||||
this_year_quota = fields.Float(string='本年额度')
|
||||
medical_line_ids = fields.One2many('yuthon.medical.line', 'medical_manage_id', string="体检费明细")
|
||||
company_id = fields.Many2one(related="employee_id.company_id", string="公司", default=lambda self: self.env.company)
|
||||
|
||||
@api.depends('this_year_quota', 'this_year_usage', 'last_year_balance')
|
||||
@api.depends('this_year_quota', 'this_year_usage', 'last_year_remaining')
|
||||
def _compute_current_year_remaining(self):
|
||||
for record in self:
|
||||
record.current_year_remaining = record.this_year_quota + record.last_year_balance - record.this_year_usage
|
||||
record.current_year_remaining = record.this_year_quota + record.last_year_remaining - record.this_year_usage
|
||||
|
||||
def _calculate_medical_quota(self, employee, current_date):
|
||||
@api.depends('employee_id', 'year')
|
||||
def _compute_last_year_used(self):
|
||||
if not self:
|
||||
return
|
||||
for record in self:
|
||||
line_domain = ([
|
||||
('employee_id', '=', record.employee_id.id),
|
||||
('enable', '=', True),
|
||||
('medical_date', '>=', f"{str(int(record.year)-1)}-01-01"),
|
||||
('medical_date', '<=', f"{str(int(record.year)-1)}-12-31")
|
||||
])
|
||||
all_lines = self.env['yuthon.medical.line'].search(line_domain)
|
||||
record.last_year_used = sum(all_lines.mapped('medical_fee'))
|
||||
|
||||
@api.depends('employee_id', 'year')
|
||||
def _compute_this_year_usage(self):
|
||||
if not self:
|
||||
return
|
||||
for record in self:
|
||||
line_domain = ([
|
||||
('employee_id', '=', record.employee_id.id),
|
||||
('enable', '=', True),
|
||||
('medical_date', '>=', f"{record.year}-01-01"),
|
||||
('medical_date', '<=', f"{record.year}-12-31")
|
||||
])
|
||||
all_lines = self.env['yuthon.medical.line'].search(line_domain)
|
||||
record.this_year_usage = sum(all_lines.mapped('medical_fee'))
|
||||
|
||||
def _calculate_medical_quota(self, employee, year):
|
||||
current_date = fields.Date.today()
|
||||
valid_rules = self.env['yuthon.medical.rule'].search([
|
||||
('start_date', '<=', current_date),
|
||||
'|', ('end_date', '>=', current_date), ('end_date', '=', False)
|
||||
@@ -43,42 +67,39 @@ class YuthonMedicalManage(models.Model):
|
||||
increment_times = exceed_age_years // rule.increase_interval_years
|
||||
base_quota += rule.increment_amount * increment_times
|
||||
|
||||
if rule.cap > 0:
|
||||
base_quota = min(base_quota, rule.cap)
|
||||
|
||||
# 女性婚姻状态补助
|
||||
final_quota = base_quota
|
||||
if employee.gender == 'female':
|
||||
if employee.user_sex == 'girl':
|
||||
if employee.marital == 'single':
|
||||
final_quota += rule.allowance_unmarried_women
|
||||
elif employee.marital == 'married':
|
||||
final_quota += rule.allowance_married_women
|
||||
|
||||
entry_date = fields.Date.from_string(employee.entry_date)
|
||||
current_year = current_date.year
|
||||
entry_year = entry_date.year
|
||||
|
||||
# 判断是否为当年入职
|
||||
if entry_year == current_year:
|
||||
if entry_year == year:
|
||||
entry_month = entry_date.month
|
||||
ratio = (12 - entry_month + 1) / 12
|
||||
final_quota = final_quota * ratio
|
||||
final_quota = max(final_quota, 0.0)
|
||||
|
||||
if rule.cap > 0:
|
||||
final_quota = min(base_quota, rule.cap)
|
||||
|
||||
return final_quota
|
||||
|
||||
def medical_manage(self):
|
||||
current_date = fields.Date.today()
|
||||
current_year = str(current_date.year)
|
||||
last_year = str(int(current_year) - 1)
|
||||
prev_last_year = str(int(current_year) - 2)
|
||||
open_contracts = self.env['hr.contract'].search([
|
||||
('state', '=', 'open'),
|
||||
last_year_medical_recs = self.env['yuthon.medical.manage'].search([
|
||||
('year', '=', last_year),
|
||||
('company_id.name', '=', '集团本部')
|
||||
])
|
||||
open_employees = open_contracts.mapped('employee_id')
|
||||
|
||||
open_employees = last_year_medical_recs.mapped('employee_id')
|
||||
for employee in open_employees:
|
||||
# 查找/创建该员工的本年体检费记录
|
||||
medical_manage_rec = self.env['yuthon.medical.manage'].search([
|
||||
('employee_id', '=', employee.id),
|
||||
('year', '=', current_year)
|
||||
@@ -93,8 +114,9 @@ class YuthonMedicalManage(models.Model):
|
||||
else:
|
||||
continue
|
||||
|
||||
this_year_quota = self._calculate_medical_quota(employee, current_date)
|
||||
medical_manage_rec.write({'this_year_quota': this_year_quota})
|
||||
this_year_quota = self._calculate_medical_quota(employee, current_year)
|
||||
medical_manage_rec.write({'this_year_quota': this_year_quota,
|
||||
})
|
||||
|
||||
# 回填上年数据
|
||||
last_year_rec = self.env['yuthon.medical.manage'].search([
|
||||
@@ -104,33 +126,23 @@ class YuthonMedicalManage(models.Model):
|
||||
if last_year_rec:
|
||||
medical_manage_rec.write({
|
||||
'last_year_quota': last_year_rec.this_year_quota,
|
||||
'last_year_used': last_year_rec.this_year_usage,
|
||||
'last_year_remaining': last_year_rec.current_year_remaining,
|
||||
'last_year_balance': last_year_rec.current_year_remaining,
|
||||
})
|
||||
|
||||
# 回填前年数据
|
||||
prev_last_year_rec = self.env['yuthon.medical.manage'].search([
|
||||
('employee_id', '=', employee.id),
|
||||
('year', '=', prev_last_year)
|
||||
], limit=1)
|
||||
if prev_last_year_rec:
|
||||
medical_manage_rec.write({
|
||||
'prev_last_year_quota': prev_last_year_rec.this_year_quota,
|
||||
'prev_last_year_used': prev_last_year_rec.this_year_usage,
|
||||
'prev_last_year_remaining': prev_last_year_rec.current_year_remaining,
|
||||
'prev_last_year_balance': prev_last_year_rec.current_year_remaining,
|
||||
})
|
||||
|
||||
# 回填前年数据
|
||||
prev_last_year_vals = {
|
||||
'prev_last_year_remaining': last_year_rec.last_year_remaining,
|
||||
}
|
||||
medical_manage_rec.write(prev_last_year_vals)
|
||||
|
||||
def button_details(self):
|
||||
form_id = self.env.ref('yuthon_hr_employee.view_yuthon_medical_manage_form').id
|
||||
tree_id = self.env.ref('yuthon_hr_employee.yuthon_medical_line_tree').id
|
||||
return {
|
||||
"type": "ir.actions.act_window",
|
||||
"name": "修正申请",
|
||||
"res_model": "yuthon.medical.manage",
|
||||
"views": [[form_id, "form"]],
|
||||
"res_id": self.id,
|
||||
"name": "查看详情",
|
||||
"res_model": "yuthon.medical.line",
|
||||
"views": [[tree_id, "tree"]],
|
||||
"domain": [('employee_id', '=', self.employee_id.id)],
|
||||
}
|
||||
|
||||
def property_reimbursement_form(self):
|
||||
@@ -151,16 +163,30 @@ class YuthonMedicalManage(models.Model):
|
||||
'target': 'new',
|
||||
}
|
||||
|
||||
def update_year(self):
|
||||
def update_initial_value(self):
|
||||
medical_ids = self.env["yuthon.medical.manage"].browse(
|
||||
self._context.get('active_ids', self._context.get('active_id')))
|
||||
for rec in medical_ids:
|
||||
rec.year = 2025
|
||||
current_year = str(rec.year)
|
||||
last_year = str(int(current_year) - 1)
|
||||
prev_last_year = str(int(current_year) - 2)
|
||||
last_year_quota = self._calculate_medical_quota(rec.employee_id, last_year)
|
||||
prev_last_year_quota = self._calculate_medical_quota(rec.employee_id, prev_last_year)
|
||||
this_year_quota = self._calculate_medical_quota(rec.employee_id, current_year)
|
||||
rec.write({
|
||||
'this_year_quota': this_year_quota,
|
||||
'last_year_quota': last_year_quota,
|
||||
'prev_last_year_quota': prev_last_year_quota,
|
||||
})
|
||||
|
||||
|
||||
|
||||
class YuthonMedicalLine(models.Model):
|
||||
_name = 'yuthon.medical.line'
|
||||
_description = '体检费明细'
|
||||
|
||||
medical_manage_id = fields.Many2one('yuthon.medical.manage', string="关联体检费管理")
|
||||
medical_date = fields.Date(string="体检日期")
|
||||
medical_fee = fields.Float(string="费用")
|
||||
employee_id = fields.Many2one('hr.employee', string="姓名")
|
||||
medical_date = fields.Date(string="报销日期")
|
||||
medical_fee = fields.Float(string="金额")
|
||||
enable = fields.Boolean(string="启用", default=True)
|
||||
|
||||
|
||||
@@ -11,64 +11,27 @@
|
||||
<field name="employee_id" widget="ztree_select" options="{'no_create': True}"/>
|
||||
<field name="year" column_invisible="1"/>
|
||||
<field name="company_id" required="1" optional="show"/>
|
||||
<field name="this_year_usage"/>
|
||||
<field name="current_year_remaining" options='{ "fg_color": "blue"}'/>
|
||||
<field name="this_year_quota"/>
|
||||
<field name="current_year_remaining"/>
|
||||
<field name="this_year_usage" options='{ "fg_color": "red"}'/>
|
||||
<field name="last_year_remaining" options='{ "fg_color": "blue"}'/>
|
||||
<field name="last_year_quota"/>
|
||||
<field name="last_year_balance"/>
|
||||
<field name="last_year_used"/>
|
||||
<field name="last_year_remaining"/>
|
||||
<field name="prev_last_year_quota"/>
|
||||
<field name="prev_last_year_balance"/>
|
||||
<field name="prev_last_year_used"/>
|
||||
<field name="prev_last_year_remaining"/>
|
||||
<field name="last_year_used" options='{ "fg_color": "red"}'/>
|
||||
<field name="prev_last_year_remaining" options='{ "fg_color": "blue"}'/>
|
||||
<button name="button_details" string="查看详情" type="object" class="oe_highlight"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_yuthon_medical_manage_form" model="ir.ui.view">
|
||||
<field name="name">yuthon.medical.manage.form</field>
|
||||
<field name="model">yuthon.medical.manage</field>
|
||||
<record id="yuthon_medical_line_tree" model="ir.ui.view">
|
||||
<field name="name">体检报销费</field>
|
||||
<field name="model">yuthon.medical.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="体检费管理" create="0">
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<label for="employee_id" widget="ztree_select" options="{'no_create': True}"/>
|
||||
<h1>
|
||||
<field name="employee_id" widget="ztree_select" options="{'no_create': True}"/>
|
||||
</h1>
|
||||
</div>
|
||||
<group>
|
||||
<field name="current_year_remaining"/>
|
||||
</group>
|
||||
<group col="2">
|
||||
<group>
|
||||
<field name="last_year_quota"/>
|
||||
<field name="last_year_quota"/>
|
||||
<field name="last_year_balance"/>
|
||||
<field name="last_year_used"/>
|
||||
<field name="last_year_remaining"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="prev_last_year_quota"/>
|
||||
<field name="prev_last_year_balance"/>
|
||||
<field name="prev_last_year_used"/>
|
||||
<field name="prev_last_year_remaining"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="体检费">
|
||||
<field name="medical_line_ids">
|
||||
<tree editable="bottom">
|
||||
<field name="medical_manage_id" column_invisible="1"/>
|
||||
<field name="medical_date"/>
|
||||
<field name="medical_fee"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
<tree editable="bottom">
|
||||
<field name="medical_date"/>
|
||||
<field name="employee_id"/>
|
||||
<field name="medical_fee"/>
|
||||
<field name="enable"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_yuthon_medical_manage_search" model="ir.ui.view">
|
||||
@@ -99,5 +62,10 @@
|
||||
<field name="state">code</field>
|
||||
<field name="code">action = model.medical_manage_wizard()</field>
|
||||
</record>
|
||||
<record id="yuthon_medical_line_action" model="ir.actions.act_window">
|
||||
<field name="name">体检报销费</field>
|
||||
<field name="res_model">yuthon.medical.line</field>
|
||||
<field name="view_mode">tree</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
||||
|
||||
@@ -175,7 +175,7 @@ class YuthonWillTask(models.Model):
|
||||
data_user_ids = '参与人: ' + ', '.join(will_id.employee_ids.mapped('name')) + '\n'
|
||||
data_employee_id = ('司机:' + ', '.join(will_id.employee_ids2.mapped('name')) + '\n') if will_id.employee_ids2 else ''
|
||||
data_nota = ('备注:' + will_id.remarks) if will_id.remarks else ('') + '\n'
|
||||
data = data_date + data_name + data_user_ids + data_nota + data_employee_id
|
||||
data = data_date + data_name + data_user_ids + data_employee_id + data_nota
|
||||
# url = f'https://phone.thtzjt.com/phone/Schedule/{will_id.id}/{employee_id.id}'
|
||||
self.sudo().env["wecom.apps"].sync_send_message_textcard(category='task', user_id=employee_id.wecom_userid, title="日程事项提醒", description=data,
|
||||
url=url, btntxt="详细信息")
|
||||
|
||||
@@ -530,6 +530,11 @@
|
||||
parent="hr_menu_root_board"
|
||||
action="yuthon_hr_employee.view_yuthon_medical_rule_action"
|
||||
sequence="15"/>
|
||||
<menuitem id="yuthon_medical_line_menu_root_board"
|
||||
name="体检报销费"
|
||||
parent="hr_menu_root_board"
|
||||
action="yuthon_hr_employee.yuthon_medical_line_action"
|
||||
sequence="15"/>
|
||||
<!-- <menuitem id="hr_set_process_menu_root_board"-->
|
||||
<!-- name="流程"-->
|
||||
<!-- parent="hr_menu_root_board"-->
|
||||
|
||||
Reference in New Issue
Block a user