You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

208 lines
9.9 KiB

# -*- coding: utf-8 -*-
###################################################################################
#
# Cybrosys Technologies Pvt. Ltd.
# Copyright (C) 2020-TODAY Cybrosys Technologies(<http://www.cybrosys.com>).
# Author: cybrosys(<https://www.cybrosys.com>)
#
# This program is free software: you can modify
# it under the terms of the GNU Affero General Public License (AGPL) as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
###################################################################################
import pytz
import sys
import datetime
import logging
import binascii
from . import zklib
from .zkconst import *
from struct import unpack
from odoo import api, fields, models
from odoo import _
from odoo.exceptions import UserError, ValidationError
_logger = logging.getLogger(__name__)
try:
from zk import ZK, const
except ImportError:
_logger.error("Please Install pyzk library.")
_logger = logging.getLogger(__name__)
class HrAttendance(models.Model):
_inherit = 'hr.attendance'
device_id = fields.Char(string='Biometric Device ID')
class ZkMachine(models.Model):
_name = 'zk.machine'
name = fields.Char(string='Machine IP', required=True)
port_no = fields.Integer(string='Port No', required=True)
address_id = fields.Many2one('res.partner', string='Working Address')
company_id = fields.Many2one('res.company', string='Company', default=lambda self: self.env.user.company_id.id)
def device_connect(self, zk):
try:
conn = zk.connect()
return conn
except:
return False
def clear_attendance(self):
for info in self:
try:
machine_ip = info.name
zk_port = info.port_no
timeout = 30
try:
zk = ZK(machine_ip, port=zk_port, timeout=timeout, password=0, force_udp=False, ommit_ping=False)
except NameError:
raise UserError(_("Please install it with 'pip3 install pyzk'."))
conn = self.device_connect(zk)
if conn:
conn.enable_device()
clear_data = zk.get_attendance()
if clear_data:
# conn.clear_attendance()
self._cr.execute("""delete from zk_machine_attendance""")
conn.disconnect()
raise UserError(_('Attendance Records Deleted.'))
else:
raise UserError(_('Unable to clear Attendance log. Are you sure attendance log is not empty.'))
else:
raise UserError(
_('Unable to connect to Attendance Device. Please use Test Connection button to verify.'))
except:
raise ValidationError(
'Unable to clear Attendance log. Are you sure attendance device is connected & record is not empty.')
def getSizeUser(self, zk):
"""Checks a returned packet to see if it returned CMD_PREPARE_DATA,
indicating that data packets are to be sent
Returns the amount of bytes that are going to be sent"""
command = unpack('HHHH', zk.data_recv[:8])[0]
if command == CMD_PREPARE_DATA:
size = unpack('I', zk.data_recv[8:12])[0]
print("size", size)
return size
else:
return False
def zkgetuser(self, zk):
"""Start a connection with the time clock"""
try:
users = zk.get_users()
print(users)
return users
except:
return False
@api.model
def cron_download(self):
machines = self.env['zk.machine'].search([])
for machine in machines :
machine.download_attendance()
def download_attendance(self):
_logger.info("++++++++++++Cron Executed++++++++++++++++++++++")
zk_attendance = self.env['zk.machine.attendance']
att_obj = self.env['hr.attendance']
for info in self:
machine_ip = info.name
zk_port = info.port_no
timeout = 15
try:
zk = ZK(machine_ip, port=zk_port, timeout=timeout, password=0, force_udp=False, ommit_ping=False)
except NameError:
raise UserError(_("Pyzk module not Found. Please install it with 'pip3 install pyzk'."))
conn = self.device_connect(zk)
if conn:
# conn.disable_device() #Device Cannot be used during this time.
try:
user = conn.get_users()
except:
user = False
try:
attendance = conn.get_attendance()
except:
attendance = False
if attendance:
for each in attendance:
atten_time = each.timestamp
atten_time = datetime.strptime(atten_time.strftime('%Y-%m-%d %H:%M:%S'), '%Y-%m-%d %H:%M:%S')
local_tz = pytz.timezone(
self.env.user.partner_id.tz or 'GMT')
local_dt = local_tz.localize(atten_time, is_dst=None)
utc_dt = local_dt.astimezone(pytz.utc)
utc_dt = utc_dt.strftime("%Y-%m-%d %H:%M:%S")
atten_time = datetime.strptime(
utc_dt, "%Y-%m-%d %H:%M:%S")
atten_time = fields.Datetime.to_string(atten_time)
if user:
for uid in user:
if uid.user_id == each.user_id:
get_user_id = self.env['hr.employee'].search(
[('device_id', '=', each.user_id)])
if get_user_id:
duplicate_atten_ids = zk_attendance.search(
[('device_id', '=', each.user_id), ('punching_time', '=', atten_time)])
if duplicate_atten_ids:
continue
else:
zk_attendance.create({'employee_id': get_user_id.id,
'device_id': each.user_id,
'attendance_type': str(each.status),
'punch_type': str(each.punch),
'punching_time': atten_time,
'address_id': info.address_id.id})
att_var = att_obj.search([('employee_id', '=', get_user_id.id),
('check_out', '=', False)])
print('ddfcd', str(each.status))
if each.punch == 0: #check-in
if not att_var:
att_obj.create({'employee_id': get_user_id.id,
'check_in': atten_time})
if each.punch == 1: #check-out
if len(att_var) == 1:
att_var.write({'check_out': atten_time})
else:
att_var1 = att_obj.search([('employee_id', '=', get_user_id.id)])
if att_var1:
att_var1[-1].write({'check_out': atten_time})
else:
print('ddfcd', str(each.status))
print('user', uid.name)
employee = self.env['hr.employee'].create(
{'device_id': each.user_id, 'name': uid.name})
zk_attendance.create({'employee_id': employee.id,
'device_id': each.user_id,
'attendance_type': str(each.status),
'punch_type': str(each.punch),
'punching_time': atten_time,
'address_id': info.address_id.id})
att_obj.create({'employee_id': employee.id,
'check_in': atten_time})
else:
pass
# zk.enableDevice()
conn.disconnect
return True
else:
raise UserError(_('Unable to get the attendance log, please try again later.'))
else:
raise UserError(_('Unable to connect, please check the parameters and network connections.'))