Merge pull request !12787 from 李鹏宇/dev_wang
This commit is contained in:
李鹏宇
2026-09-07 11:21:17 +00:00
committed by Gitee
4 changed files with 67 additions and 37 deletions
+1
View File
@@ -20,6 +20,7 @@
'views/attendance_iot_views.xml',
'views/attendance_iot_log_views.xml',
# 'views/inherit_hr_employee_views.xml',
'views/inherit_hr_employee_tree_views.xml',
'wizard/attendance_iot_manager_wizard_views.xml',
'views/iot_message.xml'
],
+12 -14
View File
@@ -53,15 +53,13 @@ class HrEmployee(models.Model):
return res
def _get_attendance_iot_copy_action(self, sync_to_all=False):
# 打开「拷贝考勤机记录」弹窗的公共方法
# sync_to_all=True 时弹窗默认带出本公司全部考勤机(同步到全部设备)
self.ensure_one()
# 源考勤机:取该员工已绑定的第一台考勤机
source_iot = self.attendance_iot_ids[:1].attendance_iot_id
# 员工还没绑定任何考勤机时无法拷贝,直接提示
if not source_iot:
raise exceptions.UserError('该员工还没有绑定任何考勤机,无法拷贝!')
# 返回弹窗动作,context 带上源考勤机、员工、是否同步全部设备
# 打开「拷贝考勤机记录」弹窗(供员工列表按钮调用,支持多选员工)
# sync_to_all=True 时弹窗默认带出选中员工公司的全部考勤机
# 取选中员工的 id 列表(列表可勾选多条)
employee_ids = self.ids
# 源公司:取第一个选中员工的公司
company = self[:1].company_id
# 返回弹窗动作,context 带上员工、公司、是否同步全部设备
return {
'type': 'ir.actions.act_window',
'name': '拷贝考勤机记录',
@@ -70,11 +68,11 @@ class HrEmployee(models.Model):
'view_id': self.env.ref('attendance_iot.attendance_iot_import_user_wizard_form').id,
'target': 'new',
'context': {
# 源考勤机:弹窗里显示为「当前被拷贝考勤机」
'default_source_attendance_iot_id': source_iot.id,
# 被拷贝的员工:点同步时按该员工创建考勤机用户记录
'default_source_employee_id': self.id,
# 是否默认带出本公司全部考勤机
# 选中要同步的员工 id 列表
'default_employee_ids': employee_ids,
# 选中员工所在公司(决定带出哪家公司的考勤机)
'default_company_id': company.id,
# 是否默认带出公司全部考勤机
'default_sync_to_all': sync_to_all,
},
}
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- 员工列表顶部加考勤机拷贝按钮 -->
<record id="view_employee_tree_inherit_attendance_iot" model="ir.ui.view">
<field name="name">hr.employee.tree.attendance.iot.buttons</field>
<field name="model">hr.employee</field>
<field name="inherit_id" ref="hr.view_employee_tree"/>
<field name="arch" type="xml">
<xpath expr="//tree" position="inside">
<header>
<!-- 批量拷贝:弹窗由用户手动勾选要同步的考勤机 -->
<button name="action_attendance_iot_batch_copy" string="批量拷贝" type="object" class="btn-primary" display="always"/>
<!-- 同步到全部设备:弹窗默认带出公司全部考勤机 -->
<button name="action_attendance_iot_sync_all" string="同步到全部设备" type="object" class="btn-primary" display="always"/>
</header>
</xpath>
</field>
</record>
</odoo>
@@ -13,42 +13,54 @@ class AttendanceIotImportUserWizard(models.TransientModel):
def default_get(self, fields_list):
# 先调用父类获取各字段的默认值字典
res = super(AttendanceIotImportUserWizard, self).default_get(fields_list)
# 从上下文中取出列表页勾选的考勤机用户记录 id 列表
active_ids = self.env.context.get('active_ids')
# 按 id 批量取出被勾选的考勤机用户记录
records = self.env['attendance.iot.user'].browse(active_ids)
# 取第一条记录,作为被拷贝的源考勤机
source_iot = records[0].attendance_iot_id
# 查出源考勤机所属公司的全部考勤机,作为同步目标默认带出(不排除源设备)
company_iots = self.env['attendance.iot'].search(
[('company_id', '=', source_iot.company_id.id)])
res.update({
'current_attendance_iot_id': source_iot.id,
'attendance_iot_ids': [(6, 0, company_iots.ids)],
})
# 入口一:员工列表按钮进入,context 带了选中的员工 id 列表
employee_ids = self.env.context.get('default_employee_ids')
if employee_ids:
# 源公司:第一个选中员工的公司
company = self.env['hr.employee'].browse(employee_ids[0]).company_id
# 「同步到全部设备」时默认带出该公司全部考勤机
if self.env.context.get('default_sync_to_all'):
company_iots = self.env['attendance.iot'].search(
[('company_id', '=', company.id)])
res['attendance_iot_ids'] = [(6, 0, company_iots.ids)]
else:
# 入口二:考勤机用户列表勾选进入,取第一条记录的源考勤机
active_ids = self.env.context.get('active_ids')
records = self.env['attendance.iot.user'].browse(active_ids)
# 取第一条记录,作为被拷贝的源考勤机
source_iot = records[0].attendance_iot_id
# 查出源考勤机所属公司的全部考勤机,作为同步目标默认带出(不排除源设备)
company_iots = self.env['attendance.iot'].search(
[('company_id', '=', source_iot.company_id.id)])
res.update({
'current_attendance_iot_id': source_iot.id,
'attendance_iot_ids': [(6, 0, company_iots.ids)],
})
return res
def action_import(self):
# 获取用户, employee_id
# 根据 attendance_iot_user.employ_id 批量给每个考勤机创建信息
# 完成
ids = self.env.context.get('active_ids')
records = self.env['attendance.iot.user'].browse(ids)
# 入口一:员工列表按钮进入,context 带了选中的员工 id 列表
employee_ids = self.env.context.get('default_employee_ids')
if employee_ids:
# 按员工处理(browse 自动去重)
employees = self.env['hr.employee'].browse(employee_ids)
else:
# 入口二:考勤机用户列表勾选进入,取勾选记录对应的员工
employees = self.env['attendance.iot.user'].browse(
self.env.context.get('active_ids')).mapped('employee_id')
values = []
for attendance_iot_id in self.attendance_iot_ids:
for record in records:
for employee in employees:
# 去重,已经有的记录不再更新,
iot_user = self.env['attendance.iot.user'].search(
[('attendance_iot_id','=', attendance_iot_id.id), ('employee_id', '=', record.employee_id.id)])
[('attendance_iot_id','=', attendance_iot_id.id), ('employee_id', '=', employee.id)])
if iot_user:
if not self.is_force_update:
continue
iot_user.with_context(iot_sync=True).unlink()
values.append({
'attendance_iot_id': attendance_iot_id.id,
'employee_id': record.employee_id.id
'employee_id': employee.id
})
self.env['attendance.iot.user'].sudo().create(values)