@@ -9,4 +9,5 @@ class YuthonHrEmployee(models.Model):
|
||||
_inherit = "hr.employee"
|
||||
|
||||
user_role_id = fields.Many2one('soong.user.role', string="主角色", store=True)
|
||||
user_role_ids = fields.Many2many('soong.user.role', string="辅助角色", store=True)
|
||||
user_role_ids = fields.Many2many('soong.user.role', string="辅助角色", store=True)
|
||||
department_ids = fields.Many2many('hr.department', string="辅助部门", store=True)
|
||||
@@ -151,21 +151,29 @@ class SoongWorkflowMixin(models.AbstractModel):
|
||||
else:
|
||||
if btn_rec.name == '转交':
|
||||
# 如果有下一个节点,发消息通知。
|
||||
state_list = ['拟办' if i.node_name == 'start' else i.node_name for i in btn_rec.workflow_id.node_ids]
|
||||
state_list = ['拟办' if i.node_name == 'start' else i.node_name for i in
|
||||
btn_rec.workflow_id.node_ids]
|
||||
# 当前节点状态
|
||||
self_state = state_list.index('拟办' if self.state == 'start' else self.state)
|
||||
# 下一个节点
|
||||
next_state = btn_rec.workflow_id.node_ids[self_state + 1].button_ids[1]
|
||||
next_state = btn_rec.workflow_id.node_ids[self_state + 1].button_ids[0]
|
||||
# 不自动匹配
|
||||
employee_user_role_ids = self.env['hr.employee'].search([('user_role_id', '=', next_state.users_role_id.id)])
|
||||
employee_user_role_ids = self.env['hr.employee'].search(
|
||||
['|', ('user_role_id', '=', next_state.users_role_id.id),
|
||||
('user_role_ids', 'in', next_state.users_role_id.id)])
|
||||
# 自动匹配
|
||||
employee_user_role_id = self.env['hr.employee'].search([('user_role_id', '=', next_state.users_role_id.id),
|
||||
('department_id', '=', self.department_id.id)])
|
||||
employee_user_role_id = self.env['hr.employee'].search(
|
||||
[('user_role_id', '=', next_state.users_role_id.id), '|',
|
||||
('department_id', '=', self.department_id.id),
|
||||
('department_ids', 'in', self.department_id.id)])
|
||||
employee_ids = employee_user_role_ids if not next_state.is_automatic else employee_user_role_id
|
||||
url = 'https://oa.thtzjt.com/mail/view?model={}&res_id={}'.format(self._name, self.id)
|
||||
for employee in employee_ids:
|
||||
self.sudo().env["wecom.apps"].sync_send_message_textcard(category='oa', user_id=employee.wecom_userid,
|
||||
title=self.name, description="您有新的审批单{}请及时处理".format(self.name),
|
||||
self.sudo().env["wecom.apps"].sync_send_message_textcard(category='oa',
|
||||
user_id=employee.wecom_userid,
|
||||
title=self.name,
|
||||
description="您有新的审批单{}请及时处理".format(
|
||||
self.name),
|
||||
url=url, btntxt="详情")
|
||||
return btn_rec.with_context(cx).run()
|
||||
|
||||
@@ -197,7 +205,8 @@ class SoongWorkflowMixin(models.AbstractModel):
|
||||
"default_res_model": self._name,
|
||||
"default_log_ids": logs.ids,
|
||||
"default_node_btn_id": btn_rec.id,
|
||||
"default_node_link_len": '转交2' if len(btn_rec.node_id.out_link_ids) > 1 and btn_rec.name == '转交' else '',
|
||||
"default_node_link_len": '转交2' if len(
|
||||
btn_rec.node_id.out_link_ids) > 1 and btn_rec.name == '转交' else '',
|
||||
},
|
||||
}
|
||||
# 下一个节点
|
||||
@@ -211,10 +220,15 @@ class SoongWorkflowMixin(models.AbstractModel):
|
||||
'record_id': self.id,
|
||||
})
|
||||
# 不自动匹配
|
||||
employee_user_role_ids = self.env['hr.employee'].search([('user_role_id', '=', next_state.users_role_id.id)])
|
||||
employee_user_role_ids = self.env['hr.employee'].search(
|
||||
['|', ('user_role_id', '=', next_state.users_role_id.id),
|
||||
('user_role_ids', 'in', next_state.users_role_id.id)])
|
||||
# 自动匹配
|
||||
employee_user_role_id = self.env['hr.employee'].search([('user_role_id', '=', next_state.users_role_id.id),
|
||||
('department_id', '=', self.department_id.id)])
|
||||
employee_user_role_id = self.env['hr.employee'].search(
|
||||
[('user_role_id', '=', next_state.users_role_id.id), '|',
|
||||
('department_id', '=', self.department_id.id),
|
||||
('department_ids', 'in', self.department_id.id)])
|
||||
|
||||
employee_ids = employee_user_role_ids.ids if not next_state.is_automatic else employee_user_role_id.ids
|
||||
if not employee_ids:
|
||||
state = btn_rec.workflow_id.node_ids[self_state + 1]
|
||||
@@ -236,23 +250,25 @@ class SoongWorkflowMixin(models.AbstractModel):
|
||||
"default_is_automatic": next_state.is_automatic,
|
||||
"default_employee_ids": employee_ids,
|
||||
"default_node_btn_id": btn_rec.id,
|
||||
"default_node_link_len": '转交2' if len(btn_rec.node_id.out_link_ids) > 1 and btn_rec.name == '转交' else '',
|
||||
"default_node_link_len": '转交2' if len(
|
||||
btn_rec.node_id.out_link_ids) > 1 and btn_rec.name == '转交' else '',
|
||||
},
|
||||
}
|
||||
|
||||
@api.constrains("state")
|
||||
def _update_wkf_records(self):
|
||||
for rec in self:
|
||||
record_obj = self.env["soong.workflow.record"].search([("res_model", "=", rec._name), ("res_id", "=", rec.id)])
|
||||
record_obj = self.env["soong.workflow.record"].search(
|
||||
[("res_model", "=", rec._name), ("res_id", "=", rec.id)])
|
||||
current_user_id = self.env.user.id
|
||||
if not record_obj:
|
||||
record_obj = self.env["soong.workflow.record"].create({
|
||||
"res_model": rec._name,
|
||||
"res_id": rec.id,
|
||||
"workflow_id": rec.workflow_id.id,
|
||||
"node_id": rec.node_id.id,
|
||||
"users_ids": [(4, current_user_id)],
|
||||
})
|
||||
"res_model": rec._name,
|
||||
"res_id": rec.id,
|
||||
"workflow_id": rec.workflow_id.id,
|
||||
"node_id": rec.node_id.id,
|
||||
"users_ids": [(4, current_user_id)],
|
||||
})
|
||||
record_obj.update({"workflow_id": rec.workflow_id.id,
|
||||
"node_id": rec.node_id.id,
|
||||
"users_ids": [(4, current_user_id)],
|
||||
@@ -322,17 +338,18 @@ class SoongWorkflowMixin(models.AbstractModel):
|
||||
state_list.append('end')
|
||||
else:
|
||||
state_list.append(state.name)
|
||||
self_node_id = record.workflow_id.node_ids.search([('name', '=', self.state), ('workflow_id', '=', record.workflow_id.id)])
|
||||
self_node_id = record.workflow_id.node_ids.search(
|
||||
[('name', '=', self.state), ('workflow_id', '=', record.workflow_id.id)])
|
||||
transmitted = self_node_id.button_ids.search([('name', '=', '转交'), ('node_id', '=', self_node_id.id)])[0]
|
||||
if transmitted.btn_hide:
|
||||
if transmitted.review_type == 'user_role':
|
||||
user_ids_list = employee_id.search(['|', ('user_role_id', '=', transmitted.users_role_id.id),
|
||||
('user_role_ids', 'in', [transmitted.users_role_id.id])]).ids
|
||||
('user_role_ids', 'in', [transmitted.users_role_id.id])]).ids
|
||||
if self.env.user.employee_id.id in user_ids_list:
|
||||
raise UserError('当前节点不允许收回')
|
||||
else:
|
||||
state_index = state_list.index(self.state)
|
||||
self.write({'state': state_list[state_index-1]})
|
||||
self.write({'state': state_list[state_index - 1]})
|
||||
else:
|
||||
raise UserError('请配置节点角色')
|
||||
else:
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
<field name="user_role_id"/>
|
||||
<field name="user_role_ids" widget="many2many_tags"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='department_id']" position="after">
|
||||
<field name="department_ids" widget="many2many_tags"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_employee_inherit_tree_soong" model="ir.ui.view">
|
||||
|
||||
@@ -38,7 +38,7 @@ class SoongWorkflowCommentWizard(models.TransientModel):
|
||||
'custom_id', 'employee_id',
|
||||
string="督办人员", store=True)
|
||||
|
||||
is_automatic = fields.Boolean('是否自动识别')
|
||||
is_automatic = fields.Boolean('是否自动匹配')
|
||||
|
||||
@api.onchange('record_id')
|
||||
def _onchange_record_id(self):
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<!-- 转交人员 -->
|
||||
<field name="trans_link_id" invisible="not node_link_len" string="转交节点"/>
|
||||
<field name="comment_note_id"/>
|
||||
<field name="employee_ids" widget="many2many_tags" string="人员范围" invisible="is_automatic"/>
|
||||
<field name="employee_ids" widget="many2many_tags" string="人员范围"/>
|
||||
</group>
|
||||
<group string="流程选择" invisible="node_btn_name != '分发'">
|
||||
<field name="comment_note_id"/>
|
||||
|
||||
@@ -62,11 +62,11 @@ class HolidaysRequestBatch(models.Model):
|
||||
leave_by_hour = fields.Boolean(string='按小时请假', default=True)
|
||||
leave_unit = fields.Selection(string='时长单位', selection=[('day', '天'), ('hour', '小时')])
|
||||
|
||||
@api.constrains('leave_line_ids')
|
||||
def _check_leave_line_ids(self):
|
||||
for rec in self:
|
||||
if rec.leave_line_ids.filtered(lambda line: line.leave_duration <= 0):
|
||||
raise ValidationError('请假天数不能小于0')
|
||||
# @api.constrains('leave_line_ids')
|
||||
# def _check_leave_line_ids(self):
|
||||
# for rec in self:
|
||||
# if rec.leave_line_ids.filtered(lambda line: line.leave_duration <= 0):
|
||||
# raise ValidationError('请假天数不能小于0')
|
||||
|
||||
@api.onchange('leave_by_hour')
|
||||
def _onchange_leave_by_hour(self):
|
||||
|
||||
@@ -55,16 +55,9 @@ class HrLeaveAllocation(models.Model):
|
||||
# {员工社保时间: 员工列表}
|
||||
emp_dict = {}
|
||||
# 员工根据社保时间创建字典
|
||||
for e in employees:
|
||||
if '年' in e.social_insurance_time:
|
||||
month_year = int(e.social_insurance_time[0]) * 12
|
||||
else:
|
||||
month_year = 0
|
||||
if '月' in e.social_insurance_time:
|
||||
month = int(e.social_insurance_time[-3])
|
||||
else:
|
||||
month = 0
|
||||
key = month_year + month
|
||||
for e in employees.search([('compute_month', '!=', 0)]):
|
||||
# [XSK] TODO 使用实际字段 -2024/11/15 17:00
|
||||
key = e.compute_month
|
||||
if emp_dict.get(key):
|
||||
emp_dict[key].append(e)
|
||||
else:
|
||||
@@ -80,8 +73,7 @@ class HrLeaveAllocation(models.Model):
|
||||
if level.added_value_type == 'hour':
|
||||
level_month = level.added_value // (30 * 24)
|
||||
for emp_int, emp_list in emp_dict.items():
|
||||
if emp_int >= level_month:
|
||||
# [XSK] TODO(2024/11/15):
|
||||
if emp_int != 0 and emp_int >= level_month:
|
||||
# 应计方案内时间支持天月年,不支持小时
|
||||
# 在请求类型中应该只支持小时
|
||||
info_list = [{**item, 'number_of_days': level.start_count} for item in allocation._prepare_holiday_values(emp_list)]
|
||||
@@ -90,8 +82,5 @@ class HrLeaveAllocation(models.Model):
|
||||
else:
|
||||
super()._action_validate_create_childs()
|
||||
if allocation_vals:
|
||||
self.env['hr.leave.allocation'].with_context(
|
||||
mail_notify_force_send=False,
|
||||
mail_activity_automation_skip=True
|
||||
).create(allocation_vals)
|
||||
self.env['hr.leave.allocation'].with_context(mail_notify_force_send=False, mail_activity_automation_skip=True).create(allocation_vals)
|
||||
self.linked_request_ids.filtered(lambda c: c.state != 'validate').action_validate()
|
||||
|
||||
@@ -65,9 +65,10 @@ class YuthonHrEmployee(models.Model):
|
||||
open_start_time = fields.Date(string="参加工作时间")
|
||||
social_insurance_date = fields.Date(string="缴纳社保日期")
|
||||
social_insurance_time = fields.Char(string="社保时长", compute='_compute_social_insurance_time', store=True)
|
||||
compute_month = fields.Integer(string="社保时长假期")
|
||||
open_start_time_today = fields.Date(string="工作至今")
|
||||
interrupt_work_month = fields.Integer(string="中断工作月数")
|
||||
cumulative_work_month = fields.Integer(string="累计工作月数", compute='_compute_cumulative_work_month', store=True)
|
||||
cumulative_work_month = fields.Integer(string="累计工作月数", compute='_compute_social_insurance_info', store=True)
|
||||
cumulative_work_years = fields.Char(string="累计工作年限", compute='_compute_cumulative_work_years', store=True)
|
||||
# 教育
|
||||
high_degree = fields.Char(string="最高学历")
|
||||
@@ -164,33 +165,25 @@ class YuthonHrEmployee(models.Model):
|
||||
else:
|
||||
record.company_old = None
|
||||
|
||||
@api.depends('social_insurance_date')
|
||||
def _compute_cumulative_work_month(self):
|
||||
@api.depends('social_insurance_date', 'interrupt_work_month')
|
||||
def _compute_social_insurance_info(self):
|
||||
for record in self:
|
||||
if record.social_insurance_time :
|
||||
cumulative_months = 0
|
||||
if record.social_insurance_date:
|
||||
today = datetime.now().date()
|
||||
if record.social_insurance_date:
|
||||
delta = relativedelta(today, record.social_insurance_date)
|
||||
record.cumulative_work_month = delta.years * 12 + delta.months
|
||||
else:
|
||||
record.cumulative_work_month = 0
|
||||
|
||||
@api.depends('cumulative_work_month', 'interrupt_work_month')
|
||||
def _compute_social_insurance_time(self):
|
||||
for record in self:
|
||||
record.social_insurance_time = record.cumulative_work_month - record.interrupt_work_month
|
||||
total_months = int(record.social_insurance_time)
|
||||
delta = relativedelta(today, record.social_insurance_date)
|
||||
cumulative_months = delta.years * 12 + delta.months
|
||||
record.cumulative_work_month = cumulative_months
|
||||
total_months = cumulative_months - record.interrupt_work_month
|
||||
record.compute_month = total_months
|
||||
if total_months <= 0:
|
||||
record.social_insurance_time = "0个月"
|
||||
years = total_months // 12
|
||||
months = total_months % 12
|
||||
if years > 0:
|
||||
result_str = f"{years}年"
|
||||
if months > 0:
|
||||
result_str += f"{months}个月"
|
||||
social_insurance_time_str = "0个月"
|
||||
else:
|
||||
result_str = f"{months}个月"
|
||||
record.social_insurance_time = result_str
|
||||
years = total_months // 12
|
||||
months = total_months % 12
|
||||
social_insurance_time_str = f"{years}年{months}个月" if years > 0 and months > 0 else (
|
||||
f"{years}年" if years > 0 else f"{months}个月")
|
||||
record.social_insurance_time = social_insurance_time_str
|
||||
|
||||
@api.depends('cumulative_work_month')
|
||||
def _compute_cumulative_work_years(self):
|
||||
|
||||
@@ -115,6 +115,7 @@
|
||||
<field name="open_start_time"/>
|
||||
<field name="open_start_time_today"/>
|
||||
<field name="social_insurance_date"/>
|
||||
<field name="compute_month" invisible="1"/>
|
||||
<field name="social_insurance_time"/>
|
||||
<field name="interrupt_work_month"/>
|
||||
<field name="cumulative_work_month"/>
|
||||
|
||||
@@ -16,7 +16,7 @@ class YuthonNotice(models.Model):
|
||||
department_id = fields.Many2one(related='users_id.employee_id.department_id', string="部门")
|
||||
yuthon_company = fields.Selection(related='users_id.employee_id.yuthon_company', string="公司")
|
||||
notice_type_id = fields.Many2one('yuthon.notice.type', string="类型")
|
||||
create_date = fields.Date(string="发布日期")
|
||||
create_date = fields.Date(string="发布日期", default=fields.Date.today())
|
||||
start_date = fields.Date(string="生效日期", default=fields.Date.today())
|
||||
end_date = fields.Date(string="终止日期")
|
||||
sequence = fields.Integer(string="顺序", default=1, compute='_compute_sequence')
|
||||
@@ -81,7 +81,7 @@ class YuthonNotice(models.Model):
|
||||
'state': 'no',
|
||||
})
|
||||
self.sudo().env["wecom.apps"].sync_send_message_textcard(category='notice', user_id=we_id,
|
||||
title="通知公告", description=self.name,
|
||||
title="通知公告", description=self.name+self.users_id.name,
|
||||
url=str, btntxt="详细信息")
|
||||
# partner_ids = self.sudo().env['res.users'].search([('id', 'in', employee_users_list)]).mapped('partner_id').ids
|
||||
# self.sudo().with_context(lang=self.env.lang)._message_auto_subscribe_notify(partner_ids, 'yuthon_notice.message_yuthon_confirm_users_data')
|
||||
|
||||
@@ -33,15 +33,19 @@
|
||||
<button name="notice_publish" string="发布" type="object" class="btn-primary"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<group col="2">
|
||||
<group col="4">
|
||||
<group>
|
||||
<field name="notice_type_id" required="1"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="users_id" required="1"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="yuthon_company" string="发布公司"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="department_id" string="发布部门" invisible="1"/>
|
||||
<field name="create_date"/>
|
||||
<field name="users_id" required="1"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="is_notice_roger" invisible="1"/>
|
||||
|
||||
@@ -43,7 +43,7 @@ class YuthonWillTask(models.Model):
|
||||
raise UserError("请同步{}的企业微信".format(employee_id.name))
|
||||
url = "https://oa.thtzjt.com/mail/view?model={}&res_id={}".format(self._name, self.id)
|
||||
self.sudo().env["wecom.apps"].sync_send_message_textcard(category='task', user_id=employee_id.wecom_userid,
|
||||
title="待办事项提醒", description="请注意你的待办事项" + self.task_content,
|
||||
title="待办事项提醒", description=self.task_content,
|
||||
url=url, btntxt="详细信息")
|
||||
|
||||
def button_add_comment(self):
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<field name='name'>yuthon.will.task.tree</field>
|
||||
<field name='model'>yuthon.will.task</field>
|
||||
<field name='arch' type='xml'>
|
||||
<tree string='待办任务' editable="bottom"
|
||||
<tree string='日程' editable="bottom"
|
||||
decoration-danger="priority == 'very_urgent'"
|
||||
decoration-info="priority == 'urgent'"
|
||||
decoration-success="priority == 'important'">
|
||||
@@ -25,7 +25,7 @@
|
||||
<field name='name'>yuthon.will.task.search</field>
|
||||
<field name='model'>yuthon.will.task</field>
|
||||
<field name='arch' type='xml'>
|
||||
<search string='待办任务'>
|
||||
<search string='日程'>
|
||||
<field name="task_content"/>
|
||||
<filter name="next_seven_days" string="周内事项" domain="[('start_time', '>=', context_today()),
|
||||
('start_time', '<=', context_today() + relativedelta(days=7))]"/>
|
||||
@@ -38,7 +38,7 @@
|
||||
<field name="name">yuthon.will.task.form</field>
|
||||
<field name="model">yuthon.will.task</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="待办任务">
|
||||
<form string="日程">
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
@@ -64,7 +64,7 @@
|
||||
<field name="model">yuthon.will.task</field>
|
||||
<field name="priority" eval="2"/>
|
||||
<field name="arch" type="xml">
|
||||
<calendar string="待办事项"
|
||||
<calendar string="日程"
|
||||
date_start="start_time"
|
||||
date_stop="end_time"
|
||||
event_open_popup="true"
|
||||
@@ -78,17 +78,17 @@
|
||||
</field>
|
||||
</record>
|
||||
<record id='view_yuthon_will_task_action' model='ir.actions.act_window'>
|
||||
<field name='name'>待办任务</field>
|
||||
<field name='name'>日程</field>
|
||||
<field name='res_model'>yuthon.will.task</field>
|
||||
<field name='view_mode'>tree,calendar</field>
|
||||
<field name="context">{'search_default_next_seven_days': 1}</field>
|
||||
</record>
|
||||
<menuitem id='menu_yuthon_will_task'
|
||||
name='待办'
|
||||
name='日程'
|
||||
web_icon="yuthon_will_task,static/description/icon.png"
|
||||
sequence='1'/>
|
||||
<menuitem id='menu_yuthon_will_task_root'
|
||||
name='待办任务'
|
||||
name='日程任务'
|
||||
parent='menu_yuthon_will_task'
|
||||
action='view_yuthon_will_task_action'
|
||||
sequence='1'/>
|
||||
@@ -97,7 +97,7 @@
|
||||
parent="menu_yuthon_will_task"
|
||||
sequence="1"/>
|
||||
<menuitem id="task_type_setting_menu"
|
||||
name="任务类型设置"
|
||||
name="任务类型"
|
||||
parent="task_type_menu"
|
||||
action="view_task_type_setting_action"
|
||||
sequence="5"/>
|
||||
|
||||
@@ -82,16 +82,25 @@
|
||||
parent="menu_hr_attendance_duty_summary_menu_board"
|
||||
action="yuthon_hr_attendance.yuthon_duty_summary_wizard_action"
|
||||
sequence="5"/>
|
||||
<menuitem id="menu_adjustments_approval_board"
|
||||
name="值班调休申请"
|
||||
parent="menu_hr_attendance_duty_summary_menu_board"
|
||||
sequence="7"
|
||||
action="yuthon_hr_attendance.view_yuthon_adjustments_approval_action"/>
|
||||
<menuitem id="menu_yuthon_duty_setting_board"
|
||||
<menuitem id="menu_yuthon_duty_shows_board"
|
||||
name="值班说明"
|
||||
parent="menu_hr_attendance_duty_summary_menu_board"
|
||||
sequence="9"
|
||||
sequence="7"
|
||||
action="yuthon_hr_attendance.action_yuthon_duty_setting"/>
|
||||
<menuitem id="menu_hr_attendance_duty_summary_flow_board"
|
||||
name="流程"
|
||||
parent="menu_hr_attendance_duty_summary_menu_board"
|
||||
sequence="9"/>
|
||||
<menuitem id="menu_adjustments_approval_board"
|
||||
name="值班调休申请"
|
||||
parent="menu_hr_attendance_duty_summary_flow_board"
|
||||
sequence="1"
|
||||
action="yuthon_hr_attendance.view_yuthon_adjustments_approval_action"/>
|
||||
<menuitem id="menu_yuthon_abnormal_approval_board"
|
||||
name="值班异常申请"
|
||||
parent="menu_hr_attendance_duty_summary_flow_board"
|
||||
sequence="3"
|
||||
action="yuthon_hr_attendance.view_yuthon_abnormal_approval_action"/>
|
||||
<!-- 计划相关 -->
|
||||
<menuitem id="menu_hr_attendance_approval_request_board"
|
||||
name="流程"
|
||||
|
||||
Reference in New Issue
Block a user