Files
gzth/attendance_iot/models/attendance_iot_user.py
T
2026-06-03 10:58:05 +08:00

145 lines
6.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import json
import urllib
import base64
from odoo import api, fields, models, tools
import logging
_logger = logging.getLogger(__name__)
class AttendanceIotUser(models.Model):
_name = 'attendance.iot.user'
attendance_iot_id = fields.Many2one('attendance.iot', string="设备号")
attendance_address = fields.Char(related='attendance_iot_id.attendance_address', string="设备地址")
employee_id = fields.Many2one('hr.employee', string="员工")
company_id = fields.Many2one(related='employee_id.company_id', string="公司")
id_valid = fields.Date(string="有效日期")
# 从 employee_id 获取.
image_1920 = fields.Image(related='employee_id.avatar_image', string="一寸照")
department_id = fields.Many2one('hr.department', related='employee_id.department_id', string="部门", store=True)
mobile_phone = fields.Char(related='employee_id.mobile_phone', string="电话")
iot_user_id = fields.Char(string='设备上用户的编码')
_sql_constraints = [('unique','UNIQUE(attendance_iot_id,employee_id)','一台设备不允许上传相同的员工信息')]
# def unlink(self):
# if not self._context.get('iot_sync'):
# # 下发删除信息
# iot_id = self[0].attendance_iot_id.name
# # 如果是主动下发的客户,则使用 employee_id.id 作为用户的编码
# self.env['iot.message'].create([{
# 'name': '删除用户',
# 'topic': f'iot/device/{iot_id}',
# 'device_sn': iot_id,
# 'message_data': json.dumps({
# 'cmd': 'delMultiUser',
# 'user_ids': [x.iot_user_id if x.iot_user_id else f'bd{x.employee_id.mobile_phone}' for x in self]
# }, ensure_ascii=False)
# }])
# return super(AttendanceIotUser, self).unlink()
@api.model_create_multi
def create(self, value_list):
res = super(AttendanceIotUser, self).create(value_list)
# 来自设备的同步,不要再写回设备
if self._context.get('iot_sync'):
return res
for r in res:
emp = r.employee_id
add_value = {
'cmd': 'addUser',
'user_id': f'{emp.mobile_phone}',
'name': emp.name,
'phone': emp.mobile_phone or '',
'id_card': emp.identification_id or '',
'effect_time': emp.entry_date.strftime('%Y-%m-%d') if emp.entry_date else '',
'id_valid': r.id_valid.strftime('%Y-%m-%d') if r.id_valid else '',
}
# face_template 单独放最后
if emp.compress_image:
raw = emp.compress_image
try:
b64 = raw.decode('ascii')
except UnicodeDecodeError:
b64 = base64.b64encode(raw).decode('ascii')
face_template = urllib.parse.quote(
f"data:image/jpeg;base64,{b64}", encoding='utf-8')
add_value['face_template'] = face_template
_logger.info(f"addUser 携带 face_template,base64长度: {len(b64)}")
else:
_logger.warning(f"addUser 未携带 face_template,compress_image 为空")
self.env['iot.message'].create([{
'name': '增加用户',
'topic': f'iot/device/{r.attendance_iot_id.name}',
'device_sn': r.attendance_iot_id.name,
'message_data': json.dumps(add_value, ensure_ascii=False)
}])
return res
def action_update_iot_info(self):
if self._context.get('iot_sync'):
return
for record in self:
emp = record.employee_id
# 下发信息 - 完整传参
update_value = {
'cmd': 'editUser',
'edit_mode': 1,
'user_id': f'{emp.mobile_phone}',
'name': emp.name,
'phone': emp.mobile_phone or '',
'id_card': emp.identification_id or '',
'effect_time': emp.entry_date.strftime('%Y-%m-%d') if emp.entry_date else '',
'id_valid': record.id_valid.strftime('%Y-%m-%d') if record.id_valid else '',
}
# face_template 单独放最后
if emp.compress_image:
raw = emp.compress_image
try:
b64 = raw.decode('ascii')
except UnicodeDecodeError:
b64 = base64.b64encode(raw).decode('ascii')
face_template = urllib.parse.quote(
f"data:image/jpeg;base64,{b64}", encoding='utf-8')
update_value['face_template'] = face_template
_logger.info(f"editUser 携带 face_template,base64长度: {len(b64)}")
else:
_logger.warning(f"editUser 未携带 face_template,compress_image 为空")
_logger.info(f"action_update_iot_info--{update_value}")
self.env['iot.message'].create([{
'name': '修改用户信息',
'topic': f'iot/device/{record.attendance_iot_id.name}',
'device_sn': record.attendance_iot_id.name,
'message_data': json.dumps(update_value, ensure_ascii=False)
}])
def action_batch_sync_to_all_devices(self):
"""
批量同步:将勾选员工的人脸数据,推送到该员工关联的全部设备
"""
if self._context.get('iot_sync'):
return
for record in self:
employee = record.employee_id
# 找到该员工在所有设备上的绑定记录
all_bindings = self.search([('employee_id', '=', employee.id)])
if all_bindings:
# action_update_iot_info 内部会跳过 iot_sync 上下文
all_bindings.with_context(iot_sync=False).action_update_iot_info()
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': '同步完成',
'message': f'已向 {len(self)} 名员工关联的全部设备推送同步指令',
'sticky': False,
'type': 'success',
}
}