@ -0,0 +1,36 @@ |
|||
Biometric Device Integration v12 |
|||
================================ |
|||
This Cybrosys's module integrates Odoo attendance with biometric device attendance. |
|||
|
|||
Features |
|||
======== |
|||
* Integrates biometric device(Face+Thumb) with HR attendance. |
|||
* Managing attendance automatically |
|||
* Keeps zk machine history in Odoo |
|||
* Option to configure multiple zk devices |
|||
* Option to clear all zk history from both device and Odoo |
|||
|
|||
Technical Notes |
|||
=============== |
|||
Used Libraries: |
|||
|
|||
*This integration is only applicable for the the device ZKteco model 'uFace 202' & 'iFace990' |
|||
* zklib |
|||
you can install zklib library using "sudo pip install zklib" |
|||
|
|||
Compatible Devices |
|||
|
|||
*ZKteco model 'uFace 202' |
|||
*ZKteco model 'iFace990' |
|||
|
|||
Author |
|||
======= |
|||
* Cybrosys Techno Solutions <https://www.cybrosys.com> |
|||
|
|||
Credits |
|||
======= |
|||
Developer: Niyas Raphy @ Cybrosys, odoo@cybrosys.com V11 |
|||
Developer: Jesni Banu @ cybrosys, odoo@cybrosys.com V10 |
|||
Developer: Basith @ Cybrosys, odoo@cybrosys.com V12 |
|||
Developer: Mostafa Shokiel , mostafa.shokiel@gmail.com |
|||
|
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2018-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/>. |
|||
# |
|||
################################################################################### |
|||
from . import models |
@ -0,0 +1,45 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2018-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/>. |
|||
# |
|||
################################################################################### |
|||
{ |
|||
'name': 'Biometric Device Integration', |
|||
'version': '12.0.1.0.0', |
|||
'summary': """Integrating Biometric Device With HR Attendance (Face + Thumb)""", |
|||
'description': 'This module integrates Odoo with the biometric device(Model: ZKteco uFace 202)', |
|||
'category': 'Generic Modules/Human Resources', |
|||
'author': 'Cybrosys Techno Solutions, Mostafa Shokiel', |
|||
'company': 'Cybrosys Techno Solutions', |
|||
'website': "https://www.cybrosys.com", |
|||
'depends': ['base_setup', 'hr_attendance'], |
|||
'data': [ |
|||
'security/ir.model.access.csv', |
|||
'views/zk_machine_view.xml', |
|||
'views/zk_machine_attendance_view.xml', |
|||
'data/download_data.xml' |
|||
|
|||
], |
|||
'images': ['static/description/banner.gif'], |
|||
'license': 'AGPL-3', |
|||
'demo': [], |
|||
'installable': True, |
|||
'auto_install': False, |
|||
'application': False, |
|||
} |
@ -0,0 +1,15 @@ |
|||
<?xml version="1.0"?> |
|||
<odoo noupdate="1"> |
|||
<record forcecreate="True" id="cron_download_data" model="ir.cron"> |
|||
<field name="name">Download Data</field> |
|||
<field eval="True" name="active" /> |
|||
<field name="user_id" ref="base.user_root" /> |
|||
<field name="interval_number">10</field> |
|||
<field name="interval_type">minutes</field> |
|||
<field name="numbercall">-1</field> |
|||
|
|||
<field name="model_id" ref="hr_zk_attendance.model_zk_machine" /> |
|||
<field name="state">code</field> |
|||
<field name="code">model.cron_download()</field> |
|||
</record> |
|||
</odoo> |
@ -0,0 +1,6 @@ |
|||
## Module <hr_zk_attendance> |
|||
|
|||
#### 24.04.2019 |
|||
#### Version 12.0.1.0.0 |
|||
##### ADD |
|||
- Initial commit |
@ -0,0 +1,25 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2018-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/>. |
|||
# |
|||
################################################################################### |
|||
from . import zk_machine |
|||
from . import machine_analysis |
|||
from . import zklib |
|||
|
@ -0,0 +1,106 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2018-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/>. |
|||
# |
|||
################################################################################### |
|||
from odoo import tools |
|||
from odoo import models, fields, api, _ |
|||
|
|||
|
|||
class HrEmployee(models.Model): |
|||
_inherit = 'hr.employee' |
|||
|
|||
device_id = fields.Char(string='Biometric Device ID') |
|||
|
|||
|
|||
class ZkMachine(models.Model): |
|||
_name = 'zk.machine.attendance' |
|||
_inherit = 'hr.attendance' |
|||
|
|||
@api.constrains('check_in', 'check_out', 'employee_id') |
|||
def _check_validity(self): |
|||
"""overriding the __check_validity function for employee attendance.""" |
|||
pass |
|||
|
|||
device_id = fields.Char(string='Biometric Device ID') |
|||
punch_type = fields.Selection([('0', 'Check In'), |
|||
('1', 'Check Out'), |
|||
('2', 'Break Out'), |
|||
('3', 'Break In'), |
|||
('4', 'Overtime In'), |
|||
('5', 'Overtime Out')], |
|||
string='Punching Type') |
|||
|
|||
attendance_type = fields.Selection([('1', 'Finger'), |
|||
('15', 'Face'), |
|||
('2','Type_2'), |
|||
('3','Password'), |
|||
('4','Card')], string='Category') |
|||
punching_time = fields.Datetime(string='Punching Time') |
|||
address_id = fields.Many2one('res.partner', string='Working Address') |
|||
|
|||
|
|||
class ReportZkDevice(models.Model): |
|||
_name = 'zk.report.daily.attendance' |
|||
_auto = False |
|||
_order = 'punching_day desc' |
|||
|
|||
name = fields.Many2one('hr.employee', string='Employee') |
|||
punching_day = fields.Datetime(string='Date') |
|||
address_id = fields.Many2one('res.partner', string='Working Address') |
|||
attendance_type = fields.Selection([('1', 'Finger'), |
|||
('15', 'Face'), |
|||
('2','Type_2'), |
|||
('3','Password'), |
|||
('4','Card')], |
|||
string='Category') |
|||
punch_type = fields.Selection([('0', 'Check In'), |
|||
('1', 'Check Out'), |
|||
('2', 'Break Out'), |
|||
('3', 'Break In'), |
|||
('4', 'Overtime In'), |
|||
('5', 'Overtime Out')], string='Punching Type') |
|||
punching_time = fields.Datetime(string='Punching Time') |
|||
|
|||
def init(self): |
|||
tools.drop_view_if_exists(self._cr, 'zk_report_daily_attendance') |
|||
query = """ |
|||
create or replace view zk_report_daily_attendance as ( |
|||
select |
|||
min(z.id) as id, |
|||
z.employee_id as name, |
|||
z.write_date as punching_day, |
|||
z.address_id as address_id, |
|||
z.attendance_type as attendance_type, |
|||
z.punching_time as punching_time, |
|||
z.punch_type as punch_type |
|||
from zk_machine_attendance z |
|||
join hr_employee e on (z.employee_id=e.id) |
|||
GROUP BY |
|||
z.employee_id, |
|||
z.write_date, |
|||
z.address_id, |
|||
z.attendance_type, |
|||
z.punch_type, |
|||
z.punching_time |
|||
) |
|||
""" |
|||
self._cr.execute(query) |
|||
|
|||
|
@ -0,0 +1,280 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2018-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__) |
|||
|
|||
|
|||
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) |
|||
|
|||
@api.multi |
|||
def device_connect(self, zk): |
|||
command = CMD_CONNECT |
|||
command_string = '' |
|||
chksum = 0 |
|||
session_id = 0 |
|||
reply_id = -1 + USHRT_MAX |
|||
buf = zk.createHeader(command, chksum, session_id, |
|||
reply_id, command_string) |
|||
zk.zkclient.sendto(buf, zk.address) |
|||
try: |
|||
zk.data_recv, addr = zk.zkclient.recvfrom(1024) |
|||
zk.session_id = unpack('HHHH', zk.data_recv[:8])[2] |
|||
command = unpack('HHHH', zk.data_recv[:8])[0] |
|||
if command == 2005: |
|||
conn = True |
|||
else: |
|||
conn = False |
|||
except: |
|||
conn = False |
|||
return conn |
|||
|
|||
@api.multi |
|||
def clear_attendance(self): |
|||
for info in self: |
|||
try: |
|||
machine_ip = info.name |
|||
port = info.port_no |
|||
zk = zklib.ZKLib(machine_ip, port) |
|||
conn = self.device_connect(zk) |
|||
if conn: |
|||
zk.enableDevice() |
|||
clear_data = zk.getAttendance() |
|||
if clear_data: |
|||
zk.clearAttendance() |
|||
self._cr.execute("""delete from zk_machine_attendance""") |
|||
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.')) |
|||
except: |
|||
raise ValidationError('Warning !!! Machine is not connected') |
|||
|
|||
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] |
|||
return size |
|||
else: |
|||
return False |
|||
|
|||
def zkgetuser(self, zk): |
|||
"""Start a connection with the time clock""" |
|||
command = CMD_USERTEMP_RRQ |
|||
command_string = '\x05' |
|||
chksum = 0 |
|||
session_id = zk.session_id |
|||
reply_id = unpack('HHHH', zk.data_recv[:8])[3] |
|||
|
|||
buf = zk.createHeader(command, chksum, session_id, reply_id, command_string) |
|||
zk.zkclient.sendto(buf, zk.address) |
|||
try: |
|||
zk.data_recv, addr = zk.zkclient.recvfrom(1024) |
|||
|
|||
if self.getSizeUser(zk): |
|||
bytes = self.getSizeUser(zk) |
|||
|
|||
while bytes > 0: |
|||
data_recv, addr = zk.zkclient.recvfrom(1032) |
|||
zk.userdata.append(data_recv) |
|||
bytes -= 1024 |
|||
|
|||
zk.session_id = unpack('HHHH', zk.data_recv[:8])[2] |
|||
data_recv = zk.zkclient.recvfrom(8) |
|||
|
|||
users = {} |
|||
if len(zk.userdata) > 0: |
|||
userdata = zk.userdata[0] |
|||
userdata = userdata[11:] |
|||
while len(userdata) > 72: |
|||
uid, role, password, name, userid = unpack('2s2s8s28sx31s', userdata.ljust(72)[:72]) |
|||
uid = int(binascii.hexlify(uid), 16) |
|||
# Clean up some messy characters from the user name |
|||
password = password.split(b'\x00', 1)[0] |
|||
password = str(password.strip(b'\x00|\x01\x10x|\x000').decode('utf-8')) |
|||
# uid = uid.split('\x00', 1)[0] |
|||
userid = str(userid.strip(b'\x00|\x01\x10x|\x000|\x9aC').decode('utf-8')) |
|||
name = name.split(b'\x00', 1)[0].decode('utf-8') |
|||
if name.strip() == "": |
|||
name = uid |
|||
users[uid] = (userid, name, int(binascii.hexlify(role), 16), password) |
|||
userdata = userdata[72:] |
|||
return users |
|||
except: |
|||
return False |
|||
|
|||
@api.model |
|||
def cron_download(self): |
|||
machines = self.env['zk.machine'].search([]) |
|||
for machine in machines : |
|||
machine.download_attendance() |
|||
|
|||
@api.multi |
|||
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 |
|||
port = info.port_no |
|||
zk = zklib.ZKLib(machine_ip, port) |
|||
conn = self.device_connect(zk) |
|||
if conn: |
|||
zk.enableDevice() |
|||
user = self.zkgetuser(zk) |
|||
command = CMD_ATTLOG_RRQ |
|||
command_string = '' |
|||
chksum = 0 |
|||
session_id = zk.session_id |
|||
reply_id = unpack('HHHH', zk.data_recv[:8])[3] |
|||
buf = zk.createHeader(command, chksum, session_id, |
|||
reply_id, command_string) |
|||
zk.zkclient.sendto(buf, zk.address) |
|||
try: |
|||
zk.data_recv, addr = zk.zkclient.recvfrom(1024) |
|||
command = unpack('HHHH', zk.data_recv[:8])[0] |
|||
if command == CMD_PREPARE_DATA: |
|||
size = unpack('I', zk.data_recv[8:12])[0] |
|||
zk_size = size |
|||
else: |
|||
zk_size = False |
|||
if zk_size: |
|||
bytes = zk_size |
|||
while bytes > 0: |
|||
data_recv, addr = zk.zkclient.recvfrom(1032) |
|||
zk.attendancedata.append(data_recv) |
|||
bytes -= 1024 |
|||
zk.session_id = unpack('HHHH', zk.data_recv[:8])[2] |
|||
data_recv = zk.zkclient.recvfrom(8) |
|||
attendance = [] |
|||
if len(zk.attendancedata) > 0: |
|||
# The first 4 bytes don't seem to be related to the user |
|||
for x in range(len(zk.attendancedata)): |
|||
if x > 0: |
|||
zk.attendancedata[x] = zk.attendancedata[x][8:] |
|||
attendancedata = b''.join(zk.attendancedata) |
|||
attendancedata = attendancedata[14:] |
|||
while len(attendancedata) > 0: |
|||
uid, state, timestamp, space = unpack('24s1s4s11s', attendancedata.ljust(40)[:40]) |
|||
pls = unpack('c', attendancedata[29:30]) |
|||
uid = uid.split(b'\x00', 1)[0].decode('utf-8') |
|||
tmp = '' |
|||
for i in reversed(range(int(len(binascii.hexlify(timestamp)) / 2))): |
|||
tmp += binascii.hexlify(timestamp).decode('utf-8')[i * 2:(i * 2) + 2] |
|||
attendance.append((uid, int(binascii.hexlify(state), 16), |
|||
decode_time(int(tmp, 16)), unpack('HHHH', space[:8])[0])) |
|||
|
|||
attendancedata = attendancedata[40:] |
|||
except Exception as e: |
|||
_logger.info("++++++++++++Exception++++++++++++++++++++++", e) |
|||
attendance = False |
|||
if attendance: |
|||
for each in attendance: |
|||
atten_time = each[2] |
|||
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 user[uid][0] == str(each[0]): |
|||
get_user_id = self.env['hr.employee'].search( |
|||
[('device_id', '=', str(each[0]))]) |
|||
if get_user_id: |
|||
duplicate_atten_ids = zk_attendance.search( |
|||
[('device_id', '=', str(each[0])), ('punching_time', '=', atten_time)]) |
|||
if duplicate_atten_ids: |
|||
continue |
|||
else: |
|||
zk_attendance.create({'employee_id': get_user_id.id, |
|||
'device_id': each[0], |
|||
'attendance_type': str(each[1]), |
|||
'punch_type': str(each[3]), |
|||
'punching_time': atten_time, |
|||
'address_id': info.address_id.id}) |
|||
att_var = att_obj.search([('employee_id', '=', get_user_id.id), |
|||
('check_out', '=', False)]) |
|||
if each[3] == 0: #check-in |
|||
if not att_var: |
|||
att_obj.create({'employee_id': get_user_id.id, |
|||
'check_in': atten_time}) |
|||
if each[3] == 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: |
|||
employee = self.env['hr.employee'].create( |
|||
{'device_id': str(each[0]), 'name': user[uid][1]}) |
|||
zk_attendance.create({'employee_id': employee.id, |
|||
'device_id': each[0], |
|||
'attendance_type': str(each[1]), |
|||
'punch_type': str(each[3]), |
|||
'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() |
|||
zk.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.')) |
@ -0,0 +1,119 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2018-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 binascii |
|||
from struct import pack, unpack |
|||
from .zkconst import * |
|||
|
|||
|
|||
def getSizeAttendance(self): |
|||
"""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', self.data_recv[:8])[0] |
|||
if command == CMD_PREPARE_DATA: |
|||
size = unpack('I', self.data_recv[8:12])[0] |
|||
return size |
|||
else: |
|||
return False |
|||
|
|||
|
|||
def reverseHex(hexstr): |
|||
tmp = '' |
|||
for i in reversed( xrange( int(len(hexstr)/2) ) ): |
|||
tmp += hexstr[i*2:(i*2)+2] |
|||
|
|||
return tmp |
|||
|
|||
def zkgetattendance(self): |
|||
"""Start a connection with the time clock""" |
|||
command = CMD_ATTLOG_RRQ |
|||
command_string = '' |
|||
chksum = 0 |
|||
session_id = self.session_id |
|||
reply_id = unpack('HHHH', self.data_recv[:8])[3] |
|||
|
|||
buf = self.createHeader(command, chksum, session_id, |
|||
reply_id, command_string) |
|||
self.zkclient.sendto(buf, self.address) |
|||
#print buf.encode("hex") |
|||
try: |
|||
self.data_recv, addr = self.zkclient.recvfrom(1024) |
|||
|
|||
if getSizeAttendance(self): |
|||
bytes = getSizeAttendance(self) |
|||
while bytes > 0: |
|||
data_recv, addr = self.zkclient.recvfrom(1032) |
|||
self.attendancedata.append(data_recv) |
|||
bytes -= 1024 |
|||
|
|||
self.session_id = unpack('HHHH', self.data_recv[:8])[2] |
|||
data_recv = self.zkclient.recvfrom(8) |
|||
|
|||
attendance = [] |
|||
if len(self.attendancedata) > 0: |
|||
# The first 4 bytes don't seem to be related to the user |
|||
for x in xrange(len(self.attendancedata)): |
|||
if x > 0: |
|||
self.attendancedata[x] = self.attendancedata[x][8:] |
|||
|
|||
attendancedata = b''.join( self.attendancedata ) |
|||
|
|||
attendancedata = attendancedata[14:] |
|||
|
|||
while len(attendancedata) > 40: |
|||
|
|||
uid, state, timestamp, space = unpack( '24s1s4s11s', attendancedata.ljust(40)[:40] ) |
|||
|
|||
|
|||
# Clean up some messy characters from the user name |
|||
#uid = unicode(uid.strip('\x00|\x01\x10x'), errors='ignore') |
|||
uid = uid.split(b'\x00', 1)[0].decode('utf-8') |
|||
#print "%s, %s, %s" % (uid, state, decode_time( int( reverseHex( timestamp.encode('hex') ), 16 ) ) ) |
|||
|
|||
attendance.append( ( uid, int( binascii.hexlify(state), 16 ), decode_time( int( reverseHex( binascii.hexlify(timestamp).decode('utf-8')), 16 ) ) ) ) |
|||
|
|||
attendancedata = attendancedata[40:] |
|||
|
|||
return attendance |
|||
except: |
|||
return False |
|||
|
|||
|
|||
def zkclearattendance(self): |
|||
"""Start a connection with the time clock""" |
|||
command = CMD_CLEAR_ATTLOG |
|||
command_string = '' |
|||
chksum = 0 |
|||
session_id = self.session_id |
|||
reply_id = unpack('HHHH', self.data_recv[:8])[3] |
|||
|
|||
buf = self.createHeader(command, chksum, session_id, |
|||
reply_id, command_string) |
|||
self.zkclient.sendto(buf, self.address) |
|||
#print buf.encode("hex") |
|||
try: |
|||
self.data_recv, addr = self.zkclient.recvfrom(1024) |
|||
self.session_id = unpack('HHHH', self.data_recv[:8])[2] |
|||
return self.data_recv[8:] |
|||
except: |
|||
return False |
@ -0,0 +1,64 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2018-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/>. |
|||
# |
|||
################################################################################### |
|||
from struct import pack, unpack |
|||
from .zkconst import * |
|||
|
|||
|
|||
def zkconnect(self): |
|||
"""Start a connection with the time clock""" |
|||
command = CMD_CONNECT |
|||
command_string = '' |
|||
chksum = 0 |
|||
session_id = 0 |
|||
reply_id = -1 + USHRT_MAX |
|||
|
|||
buf = self.createHeader(command, chksum, session_id, |
|||
reply_id, command_string) |
|||
|
|||
self.zkclient.sendto(buf, self.address) |
|||
|
|||
try: |
|||
self.data_recv, addr = self.zkclient.recvfrom(1024) |
|||
self.session_id = unpack('HHHH', self.data_recv[:8])[2] |
|||
|
|||
return self.checkValid( self.data_recv ) |
|||
except: |
|||
return False |
|||
|
|||
|
|||
def zkdisconnect(self): |
|||
"""Disconnect from the clock""" |
|||
command = CMD_EXIT |
|||
command_string = '' |
|||
chksum = 0 |
|||
session_id = self.session_id |
|||
|
|||
reply_id = unpack('HHHH', self.data_recv[:8])[3] |
|||
|
|||
buf = self.createHeader(command, chksum, session_id, |
|||
reply_id, command_string) |
|||
|
|||
self.zkclient.sendto(buf, self.address) |
|||
|
|||
self.data_recv, addr = self.zkclient.recvfrom(1024) |
|||
return self.checkValid( self.data_recv ) |
|||
|
@ -0,0 +1,71 @@ |
|||
from datetime import datetime, date |
|||
|
|||
USHRT_MAX = 65535 |
|||
|
|||
|
|||
CMD_CONNECT = 1000 |
|||
CMD_EXIT = 1001 |
|||
CMD_ENABLEDEVICE = 1002 |
|||
CMD_DISABLEDEVICE = 1003 |
|||
|
|||
CMD_ACK_OK = 2000 |
|||
CMD_ACK_ERROR = 2001 |
|||
CMD_ACK_DATA = 2002 |
|||
|
|||
CMD_PREPARE_DATA = 1500 |
|||
CMD_DATA = 1501 |
|||
|
|||
CMD_USERTEMP_RRQ = 9 |
|||
CMD_ATTLOG_RRQ = 13 |
|||
CMD_CLEAR_DATA = 14 |
|||
CMD_CLEAR_ATTLOG = 15 |
|||
|
|||
CMD_WRITE_LCD = 66 |
|||
|
|||
CMD_GET_TIME = 201 |
|||
CMD_SET_TIME = 202 |
|||
|
|||
CMD_VERSION = 1100 |
|||
CMD_DEVICE = 11 |
|||
|
|||
CMD_CLEAR_ADMIN = 20 |
|||
CMD_SET_USER = 8 |
|||
|
|||
LEVEL_USER = 0 |
|||
LEVEL_ADMIN = 14 |
|||
|
|||
def encode_time(t): |
|||
"""Encode a timestamp send at the timeclock |
|||
|
|||
copied from zkemsdk.c - EncodeTime""" |
|||
d = ( (t.year % 100) * 12 * 31 + ((t.month - 1) * 31) + t.day - 1) *\ |
|||
(24 * 60 * 60) + (t.hour * 60 + t.minute) * 60 + t.second |
|||
|
|||
return d |
|||
|
|||
|
|||
def decode_time(t): |
|||
"""Decode a timestamp retrieved from the timeclock |
|||
|
|||
copied from zkemsdk.c - DecodeTime""" |
|||
second = t % 60 |
|||
t = t / 60 |
|||
|
|||
minute = t % 60 |
|||
t = t / 60 |
|||
|
|||
hour = t % 24 |
|||
t = t / 24 |
|||
|
|||
day = t % 31+1 |
|||
t = t / 31 |
|||
|
|||
month = t % 12+1 |
|||
t = t / 12 |
|||
|
|||
year = t + 2000 |
|||
|
|||
d = datetime(int(year), int(month), int(day), int(hour), int(minute), int(second)) |
|||
|
|||
return d |
|||
|
@ -0,0 +1,82 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2018-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/>. |
|||
# |
|||
################################################################################### |
|||
from struct import pack, unpack |
|||
from .zkconst import * |
|||
|
|||
|
|||
def zkdevicename(self): |
|||
"""Start a connection with the time clock""" |
|||
command = CMD_DEVICE |
|||
command_string = '~DeviceName' |
|||
chksum = 0 |
|||
session_id = self.session_id |
|||
reply_id = unpack('HHHH', self.data_recv[:8])[3] |
|||
|
|||
buf = self.createHeader(command, chksum, session_id, |
|||
reply_id, command_string) |
|||
self.zkclient.sendto(buf, self.address) |
|||
#print buf.encode("hex") |
|||
try: |
|||
self.data_recv, addr = self.zkclient.recvfrom(1024) |
|||
self.session_id = unpack('HHHH', self.data_recv[:8])[2] |
|||
return self.data_recv[8:] |
|||
except: |
|||
return False |
|||
|
|||
|
|||
def zkenabledevice(self): |
|||
"""Start a connection with the time clock""" |
|||
command = CMD_ENABLEDEVICE |
|||
command_string = '' |
|||
chksum = 0 |
|||
session_id = self.session_id |
|||
reply_id = unpack('HHHH', self.data_recv[:8])[3] |
|||
|
|||
buf = self.createHeader(command, chksum, session_id, |
|||
reply_id, command_string) |
|||
self.zkclient.sendto(buf, self.address) |
|||
#print buf.encode("hex") |
|||
try: |
|||
self.data_recv, addr = self.zkclient.recvfrom(1024) |
|||
self.session_id = unpack('HHHH', self.data_recv[:8])[2] |
|||
return self.data_recv[8:] |
|||
except: |
|||
return False |
|||
|
|||
def zkdisabledevice(self): |
|||
"""Start a connection with the time clock""" |
|||
command = CMD_DISABLEDEVICE |
|||
command_string = '\x00\x00' |
|||
chksum = 0 |
|||
session_id = self.session_id |
|||
reply_id = unpack('HHHH', self.data_recv[:8])[3] |
|||
|
|||
buf = self.createHeader(command, chksum, session_id, |
|||
reply_id, command_string) |
|||
self.zkclient.sendto(buf, self.address) |
|||
#print buf.encode("hex") |
|||
try: |
|||
self.data_recv, addr = self.zkclient.recvfrom(1024) |
|||
self.session_id = unpack('HHHH', self.data_recv[:8])[2] |
|||
return self.data_recv[8:] |
|||
except: |
|||
return False |
@ -0,0 +1,56 @@ |
|||
def zkextendfmt(self): |
|||
try: |
|||
test = self.exttrynumber |
|||
except: |
|||
self.exttrynumber = 1 |
|||
|
|||
data_seq=[ self.data_recv.encode("hex")[4:6], self.data_recv.encode("hex")[6:8] ] |
|||
#print data_seq |
|||
if self.exttrynumber == 1: |
|||
plus1 = 0 |
|||
plus2 = 0 |
|||
else: |
|||
plus1 = -1 |
|||
plus2 = +1 |
|||
|
|||
|
|||
desc = ": +"+hex( int('99', 16)+plus1 ).lstrip('0x')+", +"+hex(int('b1', 16)+plus2).lstrip("0x") |
|||
self.data_seq1 = hex( int( data_seq[0], 16 ) + int( '99', 16 ) + plus1 ).lstrip("0x") |
|||
self.data_seq2 = hex( int( data_seq[1], 16 ) + int( 'b1', 16 ) + plus2 ).lstrip("0x") |
|||
|
|||
if len(self.data_seq1) >= 3: |
|||
#self.data_seq2 = hex( int( self.data_seq2, 16 ) + int( self.data_seq1[:1], 16) ).lstrip("0x") |
|||
self.data_seq1 = self.data_seq1[-2:] |
|||
|
|||
if len(self.data_seq2) >= 3: |
|||
#self.data_seq1 = hex( int( self.data_seq1, 16 ) + int( self.data_seq2[:1], 16) ).lstrip("0x") |
|||
self.data_seq2 = self.data_seq2[-2:] |
|||
|
|||
|
|||
if len(self.data_seq1) <= 1: |
|||
self.data_seq1 = "0"+self.data_seq1 |
|||
|
|||
if len(self.data_seq2) <= 1: |
|||
self.data_seq2 = "0"+self.data_seq2 |
|||
|
|||
|
|||
counter = hex( self.counter ).lstrip("0x") |
|||
if len(counter): |
|||
counter = "0" + counter |
|||
#print self.data_seq1+" "+self.data_seq2+desc |
|||
data = "0b00"+self.data_seq1+self.data_seq2+self.id_com+counter+"007e457874656e64466d7400" |
|||
self.zkclient.sendto(data.decode("hex"), self.address) |
|||
#print data |
|||
try: |
|||
self.data_recv, addr = self.zkclient.recvfrom(1024) |
|||
except: |
|||
if self.exttrynumber == 1: |
|||
self.exttrynumber = 2 |
|||
tmp = zkextendfmt(self) |
|||
if len(tmp) < 1: |
|||
self.exttrynumber = 1 |
|||
|
|||
self.id_com = self.data_recv.encode("hex")[8:12] |
|||
self.counter = self.counter+1 |
|||
#print self.data_recv.encode("hex") |
|||
return self.data_recv[8:] |
@ -0,0 +1,62 @@ |
|||
def zkextendoplog(self, index=0): |
|||
try: |
|||
test = self.extlogtrynumber |
|||
except: |
|||
self.extlogtrynumber = 1 |
|||
|
|||
data_seq = [ self.data_recv.encode("hex")[4:6], self.data_recv.encode("hex")[6:8] ] |
|||
#print data_seq |
|||
|
|||
if index==0: |
|||
self.data_seq1 = hex( int( data_seq[0], 16 ) + int( '104', 16 ) ).lstrip("0x") |
|||
self.data_seq2 = hex( int( data_seq[1], 16 ) + int( '19', 16 ) ).lstrip("0x") |
|||
desc = ": +104, +19" |
|||
header="0b00" |
|||
elif index==1: |
|||
self.data_seq1 = hex( abs( int( data_seq[0], 16 ) - int( '2c', 16 ) ) ).lstrip("0x") |
|||
self.data_seq2 = hex( abs( int( data_seq[1], 16 ) - int( '2', 16 ) ) ).lstrip("0x") |
|||
desc = ": -2c, -2" |
|||
header="d107" |
|||
elif index>=2: |
|||
self.data_seq1 = hex( abs( int( data_seq[0], 16 ) - int( '2c', 16 ) ) ).lstrip("0x") |
|||
self.data_seq2 = hex( abs( int( data_seq[1], 16 ) - int( '2', 16 ) ) ).lstrip("0x") |
|||
desc = ": -2c, -2" |
|||
header="ffff" |
|||
|
|||
|
|||
#print self.data_seq1+" "+self.data_seq2 |
|||
if len(self.data_seq1) >= 3: |
|||
self.data_seq2 = hex( int( self.data_seq2, 16 ) + int( self.data_seq1[:1], 16) ).lstrip("0x") |
|||
self.data_seq1 = self.data_seq1[-2:] |
|||
|
|||
if len(self.data_seq2) >= 3: |
|||
self.data_seq1 = hex( int( self.data_seq1, 16 ) + int( self.data_seq2[:1], 16) ).lstrip("0x") |
|||
self.data_seq2 = self.data_seq2[-2:] |
|||
|
|||
if len(self.data_seq1) <= 1: |
|||
self.data_seq1 = "0"+self.data_seq1 |
|||
|
|||
if len(self.data_seq2) <= 1: |
|||
self.data_seq2 = "0"+self.data_seq2 |
|||
|
|||
|
|||
counter = hex( self.counter ).lstrip("0x") |
|||
if len(counter): |
|||
counter = "0" + counter |
|||
|
|||
#print self.data_seq1+" "+self.data_seq2+desc |
|||
data = header+self.data_seq1+self.data_seq2+self.id_com+counter+"00457874656e644f504c6f6700" |
|||
self.zkclient.sendto(data.decode("hex"), self.address) |
|||
#print data |
|||
try: |
|||
self.data_recv, addr = self.zkclient.recvfrom(1024) |
|||
except: |
|||
bingung=1 |
|||
if self.extlogtrynumber == 1: |
|||
self.extlogtrynumber = 2 |
|||
zkextendoplog(self) |
|||
|
|||
self.id_com = self.data_recv.encode("hex")[8:12] |
|||
self.counter = self.counter+1 |
|||
#print self.data_recv.encode("hex") |
|||
return self.data_recv[8:] |
@ -0,0 +1,44 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2018-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/>. |
|||
# |
|||
################################################################################### |
|||
from struct import pack, unpack |
|||
from .zkconst import * |
|||
|
|||
|
|||
def zkfaceon(self): |
|||
"""Start a connection with the time clock""" |
|||
command = CMD_DEVICE |
|||
command_string = 'FaceFunOn' |
|||
chksum = 0 |
|||
session_id = self.session_id |
|||
reply_id = unpack('HHHH', self.data_recv[:8])[3] |
|||
|
|||
buf = self.createHeader(command, chksum, session_id, |
|||
reply_id, command_string) |
|||
self.zkclient.sendto(buf, self.address) |
|||
#print buf.encode("hex") |
|||
try: |
|||
self.data_recv, addr = self.zkclient.recvfrom(1024) |
|||
self.session_id = unpack('HHHH', self.data_recv[:8])[2] |
|||
return self.data_recv[8:] |
|||
except: |
|||
return False |
|||
|
@ -0,0 +1,156 @@ |
|||
from socket import * |
|||
from .zkconnect import * |
|||
from .zkversion import * |
|||
from .zkos import * |
|||
from .zkextendfmt import * |
|||
from .zkextendoplog import * |
|||
from .zkplatform import * |
|||
from .zkworkcode import * |
|||
from .zkssr import * |
|||
from .zkpin import * |
|||
from .zkface import * |
|||
from .zkserialnumber import * |
|||
from .zkdevice import * |
|||
from .zkuser import * |
|||
from .zkattendance import * |
|||
from .zktime import * |
|||
|
|||
class ZKLib: |
|||
|
|||
def __init__(self, ip, port): |
|||
self.address = (ip, port) |
|||
self.zkclient = socket(AF_INET, SOCK_DGRAM) |
|||
self.zkclient.settimeout(3) |
|||
self.session_id = 0 |
|||
self.userdata = [] |
|||
self.attendancedata = [] |
|||
|
|||
|
|||
def createChkSum(self, p): |
|||
"""This function calculates the chksum of the packet to be sent to the |
|||
time clock |
|||
|
|||
Copied from zkemsdk.c""" |
|||
l = len(p) |
|||
chksum = 0 |
|||
while l > 1: |
|||
chksum += unpack('H', pack('BB', p[0], p[1]))[0] |
|||
|
|||
p = p[2:] |
|||
if chksum > USHRT_MAX: |
|||
chksum -= USHRT_MAX |
|||
l -= 2 |
|||
|
|||
|
|||
if l: |
|||
chksum = chksum + p[-1] |
|||
|
|||
while chksum > USHRT_MAX: |
|||
chksum -= USHRT_MAX |
|||
|
|||
chksum = ~chksum |
|||
|
|||
while chksum < 0: |
|||
chksum += USHRT_MAX |
|||
|
|||
return pack('H', chksum) |
|||
|
|||
|
|||
def createHeader(self, command, chksum, session_id, reply_id, |
|||
command_string): |
|||
"""This function puts a the parts that make up a packet together and |
|||
packs them into a byte string""" |
|||
buf = pack('HHHH', command, chksum, session_id, reply_id) + command_string.encode(encoding='utf_8', errors='strict') |
|||
|
|||
buf = unpack('8B'+'%sB' % len(command_string), buf) |
|||
|
|||
chksum = unpack('H', self.createChkSum(buf))[0] |
|||
#print unpack('H', self.createChkSum(buf)) |
|||
reply_id += 1 |
|||
if reply_id >= USHRT_MAX: |
|||
reply_id -= USHRT_MAX |
|||
|
|||
buf = pack('HHHH', command, chksum, session_id, reply_id) |
|||
return buf + command_string.encode(encoding='utf_8', errors='strict') |
|||
|
|||
|
|||
def checkValid(self, reply): |
|||
"""Checks a returned packet to see if it returned CMD_ACK_OK, |
|||
indicating success""" |
|||
command = unpack('HHHH', reply[:8])[0] |
|||
if command == CMD_ACK_OK: |
|||
return True |
|||
else: |
|||
return False |
|||
|
|||
def connect(self): |
|||
return zkconnect(self) |
|||
|
|||
def disconnect(self): |
|||
return zkdisconnect(self) |
|||
|
|||
def version(self): |
|||
return zkversion(self) |
|||
|
|||
def osversion(self): |
|||
return zkos(self) |
|||
|
|||
def extendFormat(self): |
|||
return zkextendfmt(self) |
|||
|
|||
def extendOPLog(self, index=0): |
|||
return zkextendoplog(self, index) |
|||
|
|||
def platform(self): |
|||
return zkplatform(self) |
|||
|
|||
def fmVersion(self): |
|||
return zkplatformVersion(self) |
|||
|
|||
def workCode(self): |
|||
return zkworkcode(self) |
|||
|
|||
def ssr(self): |
|||
return zkssr(self) |
|||
|
|||
def pinWidth(self): |
|||
return zkpinwidth(self) |
|||
|
|||
def faceFunctionOn(self): |
|||
return zkfaceon(self) |
|||
|
|||
def serialNumber(self): |
|||
return zkserialnumber(self) |
|||
|
|||
def deviceName(self): |
|||
return zkdevicename(self) |
|||
|
|||
def disableDevice(self): |
|||
return zkdisabledevice(self) |
|||
|
|||
def enableDevice(self): |
|||
return zkenabledevice(self) |
|||
|
|||
def getUser(self): |
|||
return zkgetuser(self) |
|||
|
|||
def setUser(self, uid, userid, name, password, role): |
|||
return zksetuser(self, uid, userid, name, password, role) |
|||
|
|||
def clearUser(self): |
|||
return zkclearuser(self) |
|||
|
|||
def clearAdmin(self): |
|||
return zkclearadmin(self) |
|||
|
|||
def getAttendance(self): |
|||
return zkgetattendance(self) |
|||
|
|||
def clearAttendance(self): |
|||
return zkclearattendance(self) |
|||
|
|||
def setTime(self, t): |
|||
return zksettime(self, t) |
|||
|
|||
def getTime(self): |
|||
return zkgettime(self) |
@ -0,0 +1,23 @@ |
|||
from struct import pack, unpack |
|||
from .zkconst import * |
|||
|
|||
|
|||
def zkos(self): |
|||
"""Start a connection with the time clock""" |
|||
command = CMD_DEVICE |
|||
command_string = '~OS' |
|||
chksum = 0 |
|||
session_id = self.session_id |
|||
|
|||
reply_id = unpack('HHHH', self.data_recv[:8])[3] |
|||
|
|||
buf = self.createHeader(command, chksum, session_id, |
|||
reply_id, command_string) |
|||
self.zkclient.sendto(buf, self.address) |
|||
|
|||
try: |
|||
self.data_recv, addr = self.zkclient.recvfrom(1024) |
|||
self.session_id = unpack('HHHH', self.data_recv[:8])[2] |
|||
return self.data_recv[8:] |
|||
except: |
|||
return False |
@ -0,0 +1,23 @@ |
|||
from struct import pack, unpack |
|||
from .zkconst import * |
|||
|
|||
|
|||
def zkpinwidth(self): |
|||
"""Start a connection with the time clock""" |
|||
command = CMD_DEVICE |
|||
command_string = '~PIN2Width' |
|||
chksum = 0 |
|||
session_id = self.session_id |
|||
reply_id = unpack('HHHH', self.data_recv[:8])[3] |
|||
|
|||
buf = self.createHeader(command, chksum, session_id, |
|||
reply_id, command_string) |
|||
self.zkclient.sendto(buf, self.address) |
|||
#print buf.encode("hex") |
|||
try: |
|||
self.data_recv, addr = self.zkclient.recvfrom(1024) |
|||
self.session_id = unpack('HHHH', self.data_recv[:8])[2] |
|||
return self.data_recv[8:] |
|||
except: |
|||
return False |
|||
|
@ -0,0 +1,43 @@ |
|||
from struct import pack, unpack |
|||
from .zkconst import * |
|||
|
|||
|
|||
def zkplatform(self): |
|||
"""Start a connection with the time clock""" |
|||
command = CMD_DEVICE |
|||
command_string = '~Platform' |
|||
chksum = 0 |
|||
session_id = self.session_id |
|||
reply_id = unpack('HHHH', self.data_recv[:8])[3] |
|||
|
|||
buf = self.createHeader(command, chksum, session_id, |
|||
reply_id, command_string) |
|||
self.zkclient.sendto(buf, self.address) |
|||
#print buf.encode("hex") |
|||
try: |
|||
self.data_recv, addr = self.zkclient.recvfrom(1024) |
|||
self.session_id = unpack('HHHH', self.data_recv[:8])[2] |
|||
return self.data_recv[8:] |
|||
except: |
|||
return False |
|||
|
|||
|
|||
def zkplatformVersion(self): |
|||
"""Start a connection with the time clock""" |
|||
command = CMD_DEVICE |
|||
command_string = '~ZKFPVersion' |
|||
chksum = 0 |
|||
session_id = self.session_id |
|||
reply_id = unpack('HHHH', self.data_recv[:8])[3] |
|||
|
|||
buf = self.createHeader(command, chksum, session_id, |
|||
reply_id, command_string) |
|||
self.zkclient.sendto(buf, self.address) |
|||
#print buf.encode("hex") |
|||
try: |
|||
self.data_recv, addr = self.zkclient.recvfrom(1024) |
|||
self.session_id = unpack('HHHH', self.data_recv[:8])[2] |
|||
return self.data_recv[8:] |
|||
except: |
|||
return False |
|||
|
@ -0,0 +1,23 @@ |
|||
from struct import pack, unpack |
|||
from .zkconst import * |
|||
|
|||
|
|||
def zkserialnumber(self): |
|||
"""Start a connection with the time clock""" |
|||
command = CMD_DEVICE |
|||
command_string = '~SerialNumber' |
|||
chksum = 0 |
|||
session_id = self.session_id |
|||
reply_id = unpack('HHHH', self.data_recv[:8])[3] |
|||
|
|||
buf = self.createHeader(command, chksum, session_id, |
|||
reply_id, command_string) |
|||
self.zkclient.sendto(buf, self.address) |
|||
#print buf.encode("hex") |
|||
try: |
|||
self.data_recv, addr = self.zkclient.recvfrom(1024) |
|||
self.session_id = unpack('HHHH', self.data_recv[:8])[2] |
|||
return self.data_recv[8:] |
|||
except: |
|||
return False |
|||
|
@ -0,0 +1,23 @@ |
|||
from struct import pack, unpack |
|||
from .zkconst import * |
|||
|
|||
|
|||
def zkssr(self): |
|||
"""Start a connection with the time clock""" |
|||
command = CMD_DEVICE |
|||
command_string = '~SSR' |
|||
chksum = 0 |
|||
session_id = self.session_id |
|||
reply_id = unpack('HHHH', self.data_recv[:8])[3] |
|||
|
|||
buf = self.createHeader(command, chksum, session_id, |
|||
reply_id, command_string) |
|||
self.zkclient.sendto(buf, self.address) |
|||
#print buf.encode("hex") |
|||
try: |
|||
self.data_recv, addr = self.zkclient.recvfrom(1024) |
|||
self.session_id = unpack('HHHH', self.data_recv[:8])[2] |
|||
return self.data_recv[8:] |
|||
except: |
|||
return False |
|||
|
@ -0,0 +1,50 @@ |
|||
from struct import pack, unpack |
|||
from .zkconst import * |
|||
|
|||
|
|||
def reverseHex(hexstr): |
|||
tmp = '' |
|||
for i in reversed( xrange( len(hexstr)/2 ) ): |
|||
tmp += hexstr[i*2:(i*2)+2] |
|||
|
|||
return tmp |
|||
|
|||
|
|||
def zksettime(self, t): |
|||
"""Start a connection with the time clock""" |
|||
command = CMD_SET_TIME |
|||
command_string = pack('I',encode_time(t)) |
|||
chksum = 0 |
|||
session_id = self.session_id |
|||
reply_id = unpack('HHHH', self.data_recv[:8])[3] |
|||
|
|||
buf = self.createHeader(command, chksum, session_id, |
|||
reply_id, command_string) |
|||
self.zkclient.sendto(buf, self.address) |
|||
#print buf.encode("hex") |
|||
try: |
|||
self.data_recv, addr = self.zkclient.recvfrom(1024) |
|||
self.session_id = unpack('HHHH', self.data_recv[:8])[2] |
|||
return self.data_recv[8:] |
|||
except: |
|||
return False |
|||
|
|||
|
|||
def zkgettime(self): |
|||
"""Start a connection with the time clock""" |
|||
command = CMD_GET_TIME |
|||
command_string = '' |
|||
chksum = 0 |
|||
session_id = self.session_id |
|||
reply_id = unpack('HHHH', self.data_recv[:8])[3] |
|||
|
|||
buf = self.createHeader(command, chksum, session_id, |
|||
reply_id, command_string) |
|||
self.zkclient.sendto(buf, self.address) |
|||
#print buf.encode("hex") |
|||
try: |
|||
self.data_recv, addr = self.zkclient.recvfrom(1024) |
|||
self.session_id = unpack('HHHH', self.data_recv[:8])[2] |
|||
return decode_time( int( reverseHex( self.data_recv[8:].encode("hex") ), 16 ) ) |
|||
except: |
|||
return False |
@ -0,0 +1,140 @@ |
|||
from struct import pack, unpack |
|||
from .zkconst import * |
|||
|
|||
|
|||
def getSizeUser(self): |
|||
"""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', self.data_recv[:8])[0] |
|||
if command == CMD_PREPARE_DATA: |
|||
size = unpack('I', self.data_recv[8:12])[0] |
|||
return size |
|||
else: |
|||
return False |
|||
|
|||
|
|||
def zksetuser(self, uid, userid, name, password, role): |
|||
"""Start a connection with the time clock""" |
|||
command = CMD_SET_USER |
|||
command_string = pack('sxs8s28ss7sx8s16s', chr( uid ), chr(role), password, name, chr(1), '', userid, '' ) |
|||
chksum = 0 |
|||
session_id = self.session_id |
|||
reply_id = unpack('HHHH', self.data_recv[:8])[3] |
|||
|
|||
buf = self.createHeader(command, chksum, session_id, |
|||
reply_id, command_string) |
|||
self.zkclient.sendto(buf, self.address) |
|||
#print buf.encode("hex") |
|||
try: |
|||
self.data_recv, addr = self.zkclient.recvfrom(1024) |
|||
self.session_id = unpack('HHHH', self.data_recv[:8])[2] |
|||
return self.data_recv[8:] |
|||
except: |
|||
return False |
|||
|
|||
|
|||
def zkgetuser(self): |
|||
"""Start a connection with the time clock""" |
|||
command = CMD_USERTEMP_RRQ |
|||
command_string = '\x05' |
|||
chksum = 0 |
|||
session_id = self.session_id |
|||
reply_id = unpack('HHHH', self.data_recv[:8])[3] |
|||
|
|||
buf = self.createHeader(command, chksum, session_id, |
|||
reply_id, command_string) |
|||
self.zkclient.sendto(buf, self.address) |
|||
#print buf.encode("hex") |
|||
try: |
|||
self.data_recv, addr = self.zkclient.recvfrom(1024) |
|||
|
|||
|
|||
if getSizeUser(self): |
|||
bytes = getSizeUser(self) |
|||
|
|||
while bytes > 0: |
|||
data_recv, addr = self.zkclient.recvfrom(1032) |
|||
self.userdata.append(data_recv) |
|||
bytes -= 1024 |
|||
|
|||
self.session_id = unpack('HHHH', self.data_recv[:8])[2] |
|||
data_recv = self.zkclient.recvfrom(8) |
|||
|
|||
users = {} |
|||
if len(self.userdata) > 0: |
|||
# The first 4 bytes don't seem to be related to the user |
|||
for x in xrange(len(self.userdata)): |
|||
if x > 0: |
|||
self.userdata[x] = self.userdata[x][8:] |
|||
|
|||
userdata = ''.join( self.userdata ) |
|||
|
|||
userdata = userdata[11:] |
|||
|
|||
while len(userdata) > 72: |
|||
|
|||
uid, role, password, name, userid = unpack( '2s2s8s28sx31s', userdata.ljust(72)[:72] ) |
|||
|
|||
uid = int( uid.encode("hex"), 16) |
|||
# Clean up some messy characters from the user name |
|||
password = password.split('\x00', 1)[0] |
|||
password = unicode(password.strip('\x00|\x01\x10x'), errors='ignore') |
|||
|
|||
#uid = uid.split('\x00', 1)[0] |
|||
userid = unicode(userid.strip('\x00|\x01\x10x'), errors='ignore') |
|||
|
|||
name = name.split('\x00', 1)[0] |
|||
|
|||
if name.strip() == "": |
|||
name = uid |
|||
|
|||
users[uid] = (userid, name, int( role.encode("hex"), 16 ), password) |
|||
|
|||
#print("%d, %s, %s, %s, %s" % (uid, userid, name, int( role.encode("hex"), 16 ), password)) |
|||
userdata = userdata[72:] |
|||
|
|||
return users |
|||
except: |
|||
return False |
|||
|
|||
|
|||
def zkclearuser(self): |
|||
"""Start a connection with the time clock""" |
|||
command = CMD_CLEAR_DATA |
|||
command_string = '' |
|||
chksum = 0 |
|||
session_id = self.session_id |
|||
reply_id = unpack('HHHH', self.data_recv[:8])[3] |
|||
|
|||
buf = self.createHeader(command, chksum, session_id, |
|||
reply_id, command_string) |
|||
self.zkclient.sendto(buf, self.address) |
|||
#print buf.encode("hex") |
|||
try: |
|||
self.data_recv, addr = self.zkclient.recvfrom(1024) |
|||
self.session_id = unpack('HHHH', self.data_recv[:8])[2] |
|||
return self.data_recv[8:] |
|||
except: |
|||
return False |
|||
|
|||
|
|||
def zkclearadmin(self): |
|||
"""Start a connection with the time clock""" |
|||
command = CMD_CLEAR_ADMIN |
|||
command_string = '' |
|||
chksum = 0 |
|||
session_id = self.session_id |
|||
reply_id = unpack('HHHH', self.data_recv[:8])[3] |
|||
|
|||
buf = self.createHeader(command, chksum, session_id, |
|||
reply_id, command_string) |
|||
self.zkclient.sendto(buf, self.address) |
|||
#print buf.encode("hex") |
|||
try: |
|||
self.data_recv, addr = self.zkclient.recvfrom(1024) |
|||
self.session_id = unpack('HHHH', self.data_recv[:8])[2] |
|||
return self.data_recv[8:] |
|||
except: |
|||
return False |
@ -0,0 +1,23 @@ |
|||
from struct import pack, unpack |
|||
from .zkconst import * |
|||
|
|||
|
|||
def zkversion(self): |
|||
"""Start a connection with the time clock""" |
|||
command = CMD_VERSION |
|||
command_string = '' |
|||
chksum = 0 |
|||
session_id = self.session_id |
|||
reply_id = unpack('HHHH', self.data_recv[:8])[3] |
|||
|
|||
buf = self.createHeader(command, chksum, session_id, |
|||
reply_id, command_string) |
|||
self.zkclient.sendto(buf, self.address) |
|||
#print buf.encode("hex") |
|||
try: |
|||
self.data_recv, addr = self.zkclient.recvfrom(1024) |
|||
self.session_id = unpack('HHHH', self.data_recv[:8])[2] |
|||
return self.data_recv[8:] |
|||
except: |
|||
return False |
|||
|
@ -0,0 +1,23 @@ |
|||
from struct import pack, unpack |
|||
from .zkconst import * |
|||
|
|||
|
|||
def zkworkcode(self): |
|||
"""Start a connection with the time clock""" |
|||
command = CMD_DEVICE |
|||
command_string = 'WorkCode' |
|||
chksum = 0 |
|||
session_id = self.session_id |
|||
reply_id = unpack('HHHH', self.data_recv[:8])[3] |
|||
|
|||
buf = self.createHeader(command, chksum, session_id, |
|||
reply_id, command_string) |
|||
self.zkclient.sendto(buf, self.address) |
|||
#print buf.encode("hex") |
|||
try: |
|||
self.data_recv, addr = self.zkclient.recvfrom(1024) |
|||
self.session_id = unpack('HHHH', self.data_recv[:8])[2] |
|||
return self.data_recv[8:] |
|||
except: |
|||
return False |
|||
|
|
After Width: | Height: | Size: 537 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 123 KiB |
After Width: | Height: | Size: 132 KiB |
After Width: | Height: | Size: 128 KiB |
After Width: | Height: | Size: 166 KiB |
After Width: | Height: | Size: 234 KiB |
After Width: | Height: | Size: 161 KiB |
After Width: | Height: | Size: 13 KiB |
@ -0,0 +1,412 @@ |
|||
<section class="oe_container" style="background-image:url(https://www.cybrosys.com/images/odoo-index-header-banner.png);background-repeat:no-repeat;background-size:100%;padding: 4% 0% 2% 15%;background-position-y: -107px;"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h2 class="oe_slogan" style="font-size: 35px;color: #fff;font-weight: 900;text-transform: uppercase;text-align: left;margin: 0;margin-bottom: 16px;"> |
|||
HR Biometric Device Integration |
|||
</h2> |
|||
<h3 class="oe_slogan" style="font-size: 25px;color: #fff;font-weight: 600;text-align: left;opacity: 1;margin: 0 !important;"> |
|||
This Module Integrates Biometric Device With HR Attendance |
|||
</h3> |
|||
<h5 class="oe_slogan" style="text-align: left;background: #fff;width: 293px;padding: 10px;color: #080808 !important;opacity: 1 !important;font-weight: 600;font-size: 20px;"> |
|||
<a style="color: #080808 !important;" href="https://www.cybrosys.com" target="_blank">Cybrosys Technologies</a> |
|||
</h5> |
|||
<a style="color: #080808 !important;" href="https://www.cybrosys.com" target="_blank"> |
|||
<div style="width: 215px;margin-left: 57%;text-align: center;background: #ffffff;height: 215px;border-radius: 100%;display: flex;justify-content: center;align-items: center;box-shadow: 0 0 12px 4px #00000059;"> |
|||
<img src="https://www.cybrosys.com/images/cybro-logo-oca.png" alt="cybrosys technologies" style="width: 180px;"/> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</section> |
|||
<section class="oe_container" style="padding: 1% 0% 3% 15%;"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h2 class="oe_slogan" style="text-align: left;font-size: 28px;font-weight: 600;margin: 0px !important;"> |
|||
Overview |
|||
</h2> |
|||
<h3 class="oe_slogan" style="text-align: left;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 24px;"> |
|||
Automation is an implementation factor for a successful ERP. Using this module, HR attendance can be automated via integrating Thumb / Face detection device with Odoo. |
|||
One can configure a user both from thumbing device or Odoo employee form. |
|||
</h3> |
|||
</div> |
|||
</section> |
|||
<section class="oe_container" style="background-image:url(https://www.cybrosys.com/images/odoo-index-banner.png); background-repeat:no-repeat; background-size:cover;padding: 10% 0% 25% 15%;"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h2 class="oe_slogan" style="text-align: left;font-size: 28px;font-weight: 600;margin: 0px !important;"> |
|||
Features |
|||
</h2> |
|||
<h3 class="oe_slogan" style="text-align: left;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 18px;"> |
|||
<img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Integrates biometric device(Face+Thumb) with HR attendance. |
|||
|
|||
</h3> |
|||
<h3 class="oe_slogan" style="text-align: left;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 18px;"> |
|||
<img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Option to keep the device attendance log in Odoo. |
|||
</h3> |
|||
<h3 class="oe_slogan" style="text-align: left;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 18px;"> |
|||
<img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Option to clear the device attendance log from both device and Odoo. |
|||
|
|||
</h3> |
|||
<h3 class="oe_slogan" style="text-align: left;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 18px;"> |
|||
<img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Automating HR attendance. |
|||
</h3> |
|||
<h3 class="oe_slogan" style="text-align: left;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 18px;"> |
|||
<img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Option to configure multiple devices. |
|||
|
|||
</h3> |
|||
<h3 class="oe_slogan" style="text-align: left;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 18px;"> |
|||
<img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
This module will support with ZKteco model 'uFace 202', ZKteco model 'iFace990' |
|||
</h3> |
|||
</div> |
|||
</section> |
|||
<section class="oe_container" style="padding: 3% 0% 0% 15%;"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h2 class="oe_slogan" style="text-align: left;font-size: 28px;font-weight: 600;margin: 0px !important;"> |
|||
Biometric Device Configuration |
|||
</h2> |
|||
<h3 class="oe_slogan" style="text-align: left;padding: 5% 0% 0% 0%;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 24px;"> |
|||
<div> |
|||
<img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Here you can configure your all devices with it's IP address and port number. |
|||
</div> |
|||
</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
<img src="hr_zk_attendance_cybrosys_1.png" alt="" style="width: 95%;"/> |
|||
</div> |
|||
<h2 class="oe_slogan" style="text-align: left;font-size: 28px;font-weight: 600;margin: 0px !important;"> |
|||
Download/Clear Device Attendance Log |
|||
</h2> |
|||
<h3 class="oe_slogan" style="text-align: left;padding: 5% 0% 0% 0%;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 24px;"> |
|||
<div> |
|||
<img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
After configuration, you can download your device attendance log into Odoo through |
|||
'Download' button.If the device is connected, then the Odoo will download all device |
|||
attendance log. |
|||
Otherwise, the Odoo will display you a warning message as follow. |
|||
</div> |
|||
</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
<img src="hr_zk_attendance_cybrosys_2.png" alt="" style="width: 95%;"/> |
|||
</div> |
|||
<h3 class="oe_slogan" style="text-align: left;padding: 5% 0% 0% 0%;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 24px;"> |
|||
<div><img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
You can also clear all attendance log from both Odoo and device via 'Clear' button. |
|||
If the device is not connected it will display you a warning message as follow. |
|||
</div> |
|||
</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
<img src="hr_zk_attendance_cybrosys_3.png" alt="" style="width: 95%;"/> |
|||
</div> |
|||
<h2 class="oe_slogan" style="text-align: left;font-size: 28px;font-weight: 600;margin: 0px !important;"> |
|||
Biometric Device Attendance Log |
|||
</h2> |
|||
<h3 class="oe_slogan" style="text-align: left;padding: 5% 0% 0% 0%;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 24px;"> |
|||
<div> |
|||
<img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Here you can see all device attendance log |
|||
</div> |
|||
</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
<img src="hr_zk_attendance_cybrosys_4.png" alt="" style="width: 95%;"/> |
|||
</div> |
|||
<h2 class="oe_slogan" style="text-align: left;font-size: 28px;font-weight: 600;margin: 0px !important;"> |
|||
HR Attendance |
|||
</h2> |
|||
<h3 class="oe_slogan" style="text-align: left;padding: 5% 0% 0% 0%;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 24px;"> |
|||
<div><img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Here, Odoo automatically generates HR attendance log while downloading the device attendance. |
|||
</div> |
|||
</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
<img src="hr_zk_attendance_cybrosys_5.png" alt="" style="width: 95%;"/> |
|||
</div> |
|||
<h2 class="oe_slogan" style="text-align: left;font-size: 28px;font-weight: 600;margin: 0px !important;"> |
|||
Employee Configuration |
|||
</h2> |
|||
<h3 class="oe_slogan" style="text-align: left;padding: 5% 0% 0% 0%;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 24px;"> |
|||
<img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
You can update existing employees with the 'Device Id' which are the id in the biometric device. |
|||
If there is no match with the biometric device id then system will automatically create corresponding employee. |
|||
</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
<img src="hr_zk_attendance_cybrosys_6.png" alt="" style="width: 95%;"/> |
|||
</div> |
|||
<h3 class="oe_slogan" style="text-align: left;padding: 5% 0% 0% 0%;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 24px;"> |
|||
<img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Note:- This integration is only applicable for the device ZKteco model 'uFace 202'<br/> |
|||
Please install zklib library (sudo pip install zklib) |
|||
</h3> |
|||
</div> |
|||
</section> |
|||
<section class="oe_container" style="padding: 7px 0% 0% 3%;"> |
|||
<div class="oe_row oe_spaced"> |
|||
<a style="color: #080808 !important;" href="https://apps.odoo.com/apps/modules/browse?search=cybrosys" target="_blank"><img src="https://www.cybrosys.com/images/view-more-apps.jpg" alt="cybrosys technologies" style="width: 100%;margin-bottom: 50px;"/></a> |
|||
</div> |
|||
</section> |
|||
<section class="oe_container" style="padding: 1% 0% 0% 3%;"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h2 class="oe_slogan" style="text-align: left;font-size: 28px;font-weight: 600;margin: 0px !important;"> |
|||
Our Services |
|||
</h2> |
|||
<div style="display:flex;padding-top: 20px;justify-content: space-between;"> |
|||
<div style="flex-basis: 18%;"> |
|||
|
|||
<div style="width:75px;height:75px;background:#fff; border-radius:100%;margin: auto;"> |
|||
<a href="https://www.cybrosys.com/odoo-customization-and-installation/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/odoo-customization.png" style="width: 100%;border-radius: 100%;"/> |
|||
</a> |
|||
</div> |
|||
<h3 class="oe_slogan" style="font-weight: 800;text-align: center;font-size: 14px;width: 100%;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;"> |
|||
<a href="https://www.cybrosys.com/odoo-customization-and-installation/" target="_blank"> |
|||
Odoo Customization |
|||
</a> |
|||
</h3> |
|||
|
|||
</div> |
|||
<div style="flex-basis: 18%;"> |
|||
|
|||
<div style="width:75px;height:75px;background:#fff; border-radius:100%;margin: auto;"> |
|||
<a href="https://www.cybrosys.com/odoo-erp-implementation/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/odoo-erp-implementation.png" style="width: 100%;border-radius: 100%;"/> |
|||
</a> |
|||
</div> |
|||
<h3 class="oe_slogan" style="font-weight: 800;text-align: center;font-size: 14px;width: 100%;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;"> |
|||
<a href="https://www.cybrosys.com/odoo-erp-implementation/" target="_blank"> |
|||
Odoo Implementation </a> |
|||
</h3> |
|||
|
|||
</div> |
|||
<div style="flex-basis: 18%;"> |
|||
|
|||
<div style="width:75px;height:75px;background:#fff; border-radius:100%;margin: auto;"> |
|||
<a href="https://www.cybrosys.com/odoo-erp-integration/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/odoo-erp-integration.png" style="width: 100%;border-radius: 100%;"/> |
|||
</a> |
|||
</div> |
|||
<h3 class="oe_slogan" style="font-weight: 800;text-align: center;font-size: 14px;width: 100%;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;"> |
|||
<a href="https://www.cybrosys.com/odoo-erp-integration/" target="_blank"> |
|||
Odoo Integration |
|||
</a> |
|||
</h3> |
|||
|
|||
</div> |
|||
<div style="flex-basis: 18%;"> |
|||
|
|||
<div style="width:75px;height:75px;background:#fff; border-radius:100%;margin: auto;"> |
|||
<a href="https://www.cybrosys.com/odoo-erp-support/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/odoo-erp-support.png" style="width: 100%;border-radius: 100%;"/> |
|||
</a> |
|||
</div> |
|||
<h3 class="oe_slogan" style="font-weight: 800;text-align: center;font-size: 14px;width: 100%;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;"> |
|||
<a href="https://www.cybrosys.com/odoo-erp-support/" target="_blank"> |
|||
Odoo Support</a> |
|||
</h3> |
|||
|
|||
</div> |
|||
<div style="flex-basis: 18%;"> |
|||
|
|||
<div style="width:75px;height:75px;background:#fff; border-radius:100%;margin: auto;"> |
|||
<a href="https://www.cybrosys.com/hire-odoo-developer/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/hire-odoo-developer.png" style="width: 100%;border-radius: 100%;"/> |
|||
</a> |
|||
</div> |
|||
<h3 class="oe_slogan" style="font-weight: 800;text-align: center;font-size: 14px;width: 100%;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;"> |
|||
<a href="https://www.cybrosys.com/hire-odoo-developer/" target="_blank"> |
|||
Hire Odoo Developers</a> |
|||
</h3> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
<section class="oe_container" style="padding: 1% 0% 0% 3%;"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h2 class="oe_slogan" style="text-align: left;font-size: 28px;font-weight: 600;margin: 0px !important;"> |
|||
Our Industries |
|||
</h2> |
|||
<div style="display:flex;justify-content: space-between;flex-wrap:wrap;"> |
|||
<div style="flex-basis: 32%;padding-top: 20px;"> |
|||
|
|||
<div style="width:30%; float:left;"> |
|||
<div style="width:75px;height:75px;background:#CE2D48; border-radius:100%;float: left;text-align: left;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/best-trading-erp/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/odoo-index-industry-1.png" alt="Odoo Industry" style=" border-radius: 100%;width:100%;"/> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div style="width:70%;float:left;"> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 14px;font-weight:800;width: auto;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 4px;margin-left: 16px;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/best-trading-erp/" target="_blank"> |
|||
Trading |
|||
</a> |
|||
</h3> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 13px;width: auto;margin: 0;margin-top:5px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 5px;margin-left: 16px;"> |
|||
Easily procure and sell your products. |
|||
</h3> |
|||
</div> |
|||
|
|||
</div> |
|||
<div style="flex-basis: 32%;padding-top: 20px;"> |
|||
|
|||
<div style="width:30%; float:left;"> |
|||
<div style="width:75px;height:75px;background:#CE2D48; border-radius:100%;float: left;text-align: left;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/manufacturing-erp-software/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/odoo-index-industry-2.png" alt="Odoo Industry" style=" border-radius: 100%;width:100%;"/> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div style="width:70%;float:left;"> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 14px;font-weight:800;width: auto;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 4px;margin-left: 16px;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/manufacturing-erp-software/" target="_blank"> |
|||
Manufacturing</a> |
|||
</h3> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 13px;width: auto;margin: 0;margin-top:5px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 5px;margin-left: 16px;"> |
|||
Plan, track and schedule your operations. |
|||
</h3> |
|||
</div> |
|||
|
|||
</div> |
|||
<div style="flex-basis: 32%;padding-top: 20px;"> |
|||
|
|||
<div style="width:30%; float:left;"> |
|||
<div style="width:75px;height:75px;background:#CE2D48; border-radius:100%;float: left;text-align: left;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/restaurant-management/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/odoo-index-industry-3.png" alt="Odoo Industry" style=" border-radius: 100%;width:100%;"/> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div style="width:70%;float:left;"> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 14px;font-weight:800;width: auto;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 4px;margin-left: 16px;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/restaurant-management/" target="_blank"> |
|||
Restaurant</a> |
|||
</h3> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 13px;width: auto;margin: 0;margin-top:5px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 5px;margin-left: 16px;"> |
|||
Run your bar or restaurant methodical. |
|||
</h3> |
|||
</div> |
|||
|
|||
</div> |
|||
<div style="flex-basis: 32%;padding-top: 20px;"> |
|||
|
|||
<div style="width:30%; float:left;"> |
|||
<div style="width:75px;height:75px;background:#CE2D48; border-radius:100%;float: left;text-align: left;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/pos/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/odoo-index-industry-4.png" alt="Odoo Industry" style=" border-radius: 100%;width:100%;"/> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div style="width:70%;float:left;"> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 14px;font-weight:800;width: auto;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 4px;margin-left: 16px;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/pos/" target="_blank"> |
|||
POS</a> |
|||
</h3> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 13px;width: auto;margin: 0;margin-top:5px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 5px;margin-left: 16px;"> |
|||
Easy configuring and convivial selling. |
|||
</h3> |
|||
</div> |
|||
|
|||
</div> |
|||
<div style="flex-basis: 32%;padding-top: 20px;"> |
|||
|
|||
<div style="width:30%; float:left;"> |
|||
<div style="width:75px;height:75px;background:#CE2D48; border-radius:100%;float: left;text-align: left;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/ecommerce-website/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/odoo-index-industry-5.png" alt="Odoo Industry" style=" border-radius: 100%;width:100%;"/> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div style="width:70%;float:left;"> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 14px;font-weight:800;width: auto;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 0px;margin-left: 16px;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/ecommerce-website/" target="_blank"> |
|||
E-commerce & Website</a> |
|||
</h3> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 13px;width: auto;margin: 0;margin-top:5px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 5px;margin-left: 16px;"> |
|||
Mobile friendly, awe-inspiring product pages. |
|||
</h3> |
|||
</div> |
|||
</div> |
|||
<div style="flex-basis: 32%;padding-top: 20px;"> |
|||
|
|||
<div style="width:30%; float:left;"> |
|||
<div style="width:75px;height:75px;background:#CE2D48; border-radius:100%;float: left;text-align: left;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/hotel-management-erp/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/odoo-index-industry-6.png" alt="Odoo Industry" style=" border-radius: 100%;width:100%;"/> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div style="width:70%;float:left;"> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 14px;font-weight:800;width: auto;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 4px;margin-left: 16px;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/hotel-management-erp/" target="_blank"> |
|||
Hotel Management</a> |
|||
</h3> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 13px;width: auto;margin: 0;margin-top:5px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 5px;margin-left: 16px;"> |
|||
An all-inclusive hotel management application. |
|||
</h3> |
|||
</div> |
|||
</div> |
|||
<div style="flex-basis: 32%;padding-top: 20px;"> |
|||
|
|||
<div style="width:30%; float:left;"> |
|||
<div style="width:75px;height:75px;background:#CE2D48; border-radius:100%;float: left;text-align: left;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/education-erp-software/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/odoo-index-industry-7.png" alt="Odoo Industry" style=" border-radius: 100%;width:100%;"/> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div style="width:70%;float:left;"> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 14px;font-weight:800;width: auto;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 4px;margin-left: 16px;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/education-erp-software/" target="_blank"> |
|||
Education</a> |
|||
</h3> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 13px;width: auto;margin: 0;margin-top:5px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 5px;margin-left: 16px;"> |
|||
A Collaborative platform for educational management. |
|||
</h3> |
|||
</div> |
|||
</div> |
|||
<div style="flex-basis: 32%;padding-top: 20px;"> |
|||
|
|||
<div style="width:30%; float:left;"> |
|||
<div style="width:75px;height:75px;background:#CE2D48; border-radius:100%;float: left;text-align: left;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/service-management/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/odoo-index-industry-8.png" alt="Odoo Industry" style=" border-radius: 100%;width:100%;"/> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div style="width:70%;float:left;"> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 14px;font-weight:800;width: auto;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 4px;margin-left: 16px;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/service-management/" target="_blank"> |
|||
Service Management</a> |
|||
</h3> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 13px;width: auto;margin: 0;margin-top:5px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 5px;margin-left: 16px;"> |
|||
Keep track of services and invoice accordingly. |
|||
</h3> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
<section class="oe_container" style="background-image:url(https://www.cybrosys.com/images/odoo-index-footer-bg.png); background-repeat:no-repeat; background-size:100%;padding: 13% 0% 6% 0%;"> |
|||
<div class="oe_slogan" style="margin-top:10px !important;margin-bottom: 0px;"> |
|||
<div> |
|||
<a style="color: #5c5c5c !important;border-radius: 0;background: none;border: none;background: #fff;box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62, 57, 107, 0.05);border-radius: 30px;font-size: 12px;padding: 9px 26px;margin-right: 9px;width: 200px;text-transform: capitalize;" class="btn btn-primary btn-lg mt8" style="color: #FFFFFF !important;border-radius: 0;" href="mailto:odoo@cybrosys.com"><i class="fa fa-envelope"></i> Email us </a> |
|||
<a style="color: #5c5c5c !important;border-radius: 0;background: none;border: none;background: #fff;box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62, 57, 107, 0.05);border-radius: 30px;font-size: 12px;padding: 9px 26px;margin-right: 9px;width: 200px;text-transform: capitalize;" class="btn btn-primary btn-lg mt8" style="color: #FFFFFF !important;border-radius: 0;" href="https://www.cybrosys.com/contact/"><i class="fa fa-phone"></i> Contact Us </a> |
|||
<a style="color: #5c5c5c !important;border-radius: 0;background: none;border: none;background: #fff;box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62, 57, 107, 0.05);border-radius: 30px;font-size: 12px;padding: 9px 26px;margin-right: 9px;width: 200px;text-transform: capitalize;" class="btn btn-primary btn-lg mt8" style="color: #FFFFFF !important;border-radius: 0;" href="https://www.cybrosys.com/contact/"><i class="fa fa-check-square"></i> Request Customization </a> |
|||
</div> |
|||
<br> |
|||
<img src="https://www.cybrosys.com/images/logo.png" style="width: 190px; margin-bottom: 25px;margin-top: 30px;" class="center-block"> |
|||
<div> |
|||
<a href="https://twitter.com/cybrosys" target="_blank"><i class="fa fa-2x fa-twitter" style="color:white;background: #00a0d1;width:35px;height: 35px;padding-top: 7px;font-size: 21px;margin-right: 6px;border-radius: 100%;"></i></a></td> |
|||
<a href="https://www.linkedin.com/company/cybrosys-technologies-pvt-ltd" target="_blank"><i class="fa fa-2x fa-linkedin" style="color:white;background: #31a3d6;width:35px;padding-left: 3px;height: 35px;padding-top: 7px;font-size: 21px;margin-right: 6px;border-radius: 100%;"></i></a></td> |
|||
<a href="https://www.facebook.com/cybrosystechnologies" target="_blank"><i class="fa fa-2x fa-facebook" style="color:white;background: #3b5998;width:35px; ;height: 35px;padding-top: 7px;font-size: 21px;margin-right: 6px;border-radius: 100%;"></i></a></td> |
|||
<a href="https://plus.google.com/106641282743045431892/about" target="_blank"><i class="fa fa-2x fa-google-plus" style="color:white;background: #c53c2c;width:35px;padding-left: 3px;height: 35px;padding-top: 7px;font-size: 21px;margin-right: 6px;border-radius: 100%;"></i></a></td> |
|||
<a href="https://in.pinterest.com/cybrosys" target="_blank"><i class="fa fa-2x fa-pinterest" style="color:white;background: #ac0f18;width:35px;padding-left: 3px;height: 35px;padding-top: 7px;font-size: 21px;margin-right: 6px;border-radius: 100%;"></i></a></td> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
|
|||
|
|||
|
|||
|
@ -0,0 +1,71 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- Customize Attendance Report --> |
|||
<record id="inherited_view_attendance_tree" model="ir.ui.view"> |
|||
<field name="name">inherited_hr.attendance.tree</field> |
|||
<field name="model">hr.attendance</field> |
|||
<field name="inherit_id" ref="hr_attendance.view_attendance_tree"/> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Employee attendances"> |
|||
<field name="worked_hours" type="measure"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="inherited_hr_attendance_view_filter" model="ir.ui.view"> |
|||
<field name="name">inherited_hr_attendance_view_filter</field> |
|||
<field name="model">hr.attendance</field> |
|||
<field name="inherit_id" ref="hr_attendance.hr_attendance_view_filter"/> |
|||
<field name="arch" type="xml"> |
|||
<search string="Hr Attendance Search"> |
|||
<group expand="0" string="Group By"> |
|||
<separator/> |
|||
<filter name="date" string="Date" context="{'group_by':'check_in:day'}"/> |
|||
|
|||
</group> |
|||
</search> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="view_zk_report_daily_attendance_search" model="ir.ui.view"> |
|||
<field name="name">zk.report.daily.attendance.search</field> |
|||
<field name="model">zk.report.daily.attendance</field> |
|||
<field name="arch" type="xml" > |
|||
<search string="Hr Attendance Search"> |
|||
<filter icon="terp-stock_align_left_24" string="My Attendance" name="my_attendance" domain="[('name.user_id.id', '=', uid)]" /> |
|||
<filter name="today" string="Today" domain="[('punching_time', '>=', datetime.datetime.now().replace(hour=0, minute=0, second=0)),('punching_time', '<=', datetime.datetime.now().replace(hour=23, minute=59, second=59))]" /> |
|||
<filter string="Current Month" name="month" domain="[('punching_time', '>=', datetime.datetime.now().strftime('%Y-%m-01'))]" /> |
|||
<separator/> |
|||
|
|||
<field name="name" string="Name"/> |
|||
</search> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="view_zk_report_daily_attendance_tree" model="ir.ui.view"> |
|||
<field name="name">zk.report.daily.attendance.tree</field> |
|||
<field name="model">zk.report.daily.attendance</field> |
|||
<field name="arch" type="xml" > |
|||
<tree string="Attendance" create="false" delete="false" colors="green:punch_type in ('0');red:punch_type in ('1');"> |
|||
<field name="punching_day"/> |
|||
<field name="name"/> |
|||
<field name="punch_type"/> |
|||
<field name="attendance_type"/> |
|||
<field name="punching_time"/> |
|||
<field name="address_id"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="action_zk_report_daily_attendance" model="ir.actions.act_window"> |
|||
<field name="name">Attendance Analysis</field> |
|||
<field name="res_model">zk.report.daily.attendance</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">tree</field> |
|||
<field name="context">{'search_default_my_attendance':1}</field> |
|||
<field name="search_view_id" ref="view_zk_report_daily_attendance_search" /> |
|||
</record> |
|||
|
|||
<menuitem id="menu_zk_attendance_view" name="Attendance log" action="action_zk_report_daily_attendance" parent="zk_machine_menu" |
|||
sequence="2" groups="hr_attendance.group_hr_attendance_user"/> |
|||
</odoo> |
@ -0,0 +1,69 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<record id="view_zk_machine_form" model="ir.ui.view"> |
|||
<field name="name">zk.machine.form</field> |
|||
<field name="model">zk.machine</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="Biometric Device"> |
|||
<header> |
|||
<button name="clear_attendance" type="object" string="Clear Data" class="oe_highlight" |
|||
icon="fa-remove " confirm="Are you sure you want to do this?"/> |
|||
<button name="download_attendance" type="object" string="Download Data" class="oe_highlight" |
|||
icon="fa-download " confirm="Are you sure you want to do this?" /> |
|||
</header> |
|||
<sheet> |
|||
<div class="oe_title"> |
|||
<label for="name" /> |
|||
<h1> |
|||
<field name="name" placeholder="Machine IP"/> |
|||
</h1> |
|||
</div> |
|||
<group> |
|||
<group> |
|||
<field name="port_no"/> |
|||
<field name="address_id"/> |
|||
</group> |
|||
<group> |
|||
<field name="company_id" groups="base.group_multi_company"/> |
|||
</group> |
|||
</group> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="view_zk_machine_tree" model="ir.ui.view"> |
|||
<field name="name">zk.machine.tree</field> |
|||
<field name="model">zk.machine</field> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Biometric Machine"> |
|||
<field name="name"/> |
|||
<field name="port_no"/> |
|||
<field name="address_id"/> |
|||
<field name="company_id" groups="base.group_multi_company"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="zk_machine_action" model="ir.actions.act_window"> |
|||
<field name="name">Attendances</field> |
|||
<field name="res_model">zk.machine</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">tree,form</field> |
|||
</record> |
|||
|
|||
<record id="hr_employee_inherit_form_view" model="ir.ui.view"> |
|||
<field name="name">hr.employee.form</field> |
|||
<field name="model">hr.employee</field> |
|||
<field name="inherit_id" ref="hr.view_employee_form"/> |
|||
<field name="arch" type="xml"> |
|||
<field name="user_id" position="after"> |
|||
<field name="device_id"/> |
|||
</field> |
|||
</field> |
|||
</record> |
|||
|
|||
<menuitem id="zk_machine_menu" parent="hr_attendance.menu_hr_attendance_root" sequence="50" name="Biometric Manager" /> |
|||
<menuitem id="zk_machine_sub_menu" parent="zk_machine_menu" name="Device Configuration" action="zk_machine_action" sequence="1"/> |
|||
</odoo> |
|||
|
@ -0,0 +1,38 @@ |
|||
========================== |
|||
Medical Lab Management v12 |
|||
========================== |
|||
|
|||
Helps You To Manage Medical Lab Operations. |
|||
|
|||
Installation |
|||
============ |
|||
|
|||
Just install the module from apps list. |
|||
|
|||
Configuration |
|||
============= |
|||
#1.Create test units for lab test. |
|||
#2.Create test contents for lab test. |
|||
#3.Create lab test, add the contents and their units and normal range for the contents. |
|||
#4.Create patients. |
|||
#5.When a particular patient comes first create the patient and from the |
|||
super button in the patient name called 'Lab Appointments' create the appointment for the patient. |
|||
#6.When we confirm the appointment an email will be sent to the patient with the appointment Details. |
|||
#7.When we click on 'Request LAb' button lab test request will be created. |
|||
#8.Select the particular lab request and add the result when we complete the test. |
|||
#9.The request tree view will show green color if the test state is in Sample collection or Test in progress. |
|||
#10.The request tree view will show grey color if the test is cancelled ,it show blue color if the request is in draft stage and |
|||
it show black color if the test is completed. |
|||
#11.When the test request are completed the Appointment state will be in 'Test Result' state . |
|||
#12.Create invoice for the lab test. |
|||
#13.There is two type of users 'Lab technician' and 'lab User'. Lab technician have the right to create,delete,read lab test unit,test content,lab test |
|||
while the lab user have only read permission on these records. The other rights are same to both the user. |
|||
|
|||
Credits |
|||
======= |
|||
Anusha P P @ cybrosys |
|||
Niyas Raphy @ cybrosys |
|||
|
|||
Author |
|||
======= |
|||
Cybrosys Techno Solutions www.cybrosys.com |
@ -0,0 +1,22 @@ |
|||
################################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Author: Anusha P P(<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 <https://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################### |
|||
|
|||
from . import models |
@ -0,0 +1,55 @@ |
|||
################################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Author: Anusha P P(<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 <https://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################### |
|||
|
|||
{ |
|||
'name': "Medical Lab Management", |
|||
'version': '12.0.1.0.0', |
|||
'summary': """Manage Medical Lab Operations.""", |
|||
'description': """Manage Medical Lab General Operations.""", |
|||
'author': "Cybrosys Techno Solutions", |
|||
'maintainer': 'Cybrosys Techno Solutions', |
|||
'company': "Cybrosys Techno Solutions", |
|||
'website': "https://www.cybrosys.com", |
|||
'category': 'Industries', |
|||
'depends': ['base', 'mail', 'account'], |
|||
'data': [ |
|||
'security/lab_users.xml', |
|||
'security/ir.model.access.csv', |
|||
'views/res_partner.xml', |
|||
'views/lab_patient_view.xml', |
|||
'views/test_unit_view.xml', |
|||
'views/lab_test_type.xml', |
|||
'views/lab_test_content_type.xml', |
|||
'views/physician_specialty.xml', |
|||
'views/physician_details.xml', |
|||
'views/lab_request.xml', |
|||
'views/lab_appointment.xml', |
|||
'views/account_invoice.xml', |
|||
'report/report.xml', |
|||
'report/lab_test_report.xml', |
|||
'report/lab_patient_card.xml', |
|||
], |
|||
'images': ['static/description/banner.jpg'], |
|||
'license': 'AGPL-3', |
|||
'installable': True, |
|||
'auto_install': False, |
|||
'application': True, |
|||
} |
@ -0,0 +1,19 @@ |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2019-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Maintainer: Cybrosys Technologies (<https://www.cybrosys.com>) |
|||
# |
|||
############################################################################## |
|||
|
|||
from . import physician_speciality |
|||
from . import res_partner |
|||
from . import lab_patient |
|||
from . import testing_unit |
|||
from . import lab_test_type |
|||
from . import lab_test_content_type |
|||
from . import lab_appointment |
|||
from . import lab_request |
|||
from . import account_invoice |
|||
|
|||
|
@ -0,0 +1,24 @@ |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Maintainer: Cybrosys Technologies (<https://www.cybrosys.com>) |
|||
# |
|||
############################################################################# |
|||
|
|||
from odoo import models, fields, api |
|||
|
|||
|
|||
class LabRequestInvoices(models.Model): |
|||
_inherit = 'account.invoice' |
|||
|
|||
is_lab_invoice = fields.Boolean(string="Is Lab Invoice") |
|||
lab_request = fields.Many2one('lab.appointment', string="Lab Appointment", help="Source Document") |
|||
|
|||
@api.multi |
|||
def action_invoice_paid(self): |
|||
res = super(LabRequestInvoices, self).action_invoice_paid() |
|||
lab_app_obj = self.env['lab.appointment'].search([('id', '=', self.lab_request.id)]) |
|||
for obj in lab_app_obj: |
|||
obj.write({'state': 'invoiced'}) |
|||
return res |
@ -0,0 +1,179 @@ |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2019-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Maintainer: Cybrosys Technologies (<https://www.cybrosys.com>) |
|||
# |
|||
############################################################################## |
|||
|
|||
import datetime |
|||
from odoo.exceptions import UserError |
|||
from odoo import fields, models, api, _ |
|||
|
|||
|
|||
class Appointment(models.Model): |
|||
_name = 'lab.appointment' |
|||
_inherit = ['mail.thread'] |
|||
_rec_name = 'name' |
|||
_description = "Appointment" |
|||
_order = 'appointment_date' |
|||
|
|||
user_id = fields.Many2one('res.users', 'Responsible', readonly=True) |
|||
patient_id = fields.Many2one('lab.patient', string='Patient', required=True, select=True, |
|||
help='Patient Name') |
|||
name = fields.Char(string='Appointment ID', readonly=True, default=lambda self: _('New')) |
|||
date = fields.Datetime(string='Requested Date', default=lambda s: fields.Datetime.now(), |
|||
help="This is the date in which patient appointment is noted") |
|||
appointment_date = fields.Datetime(string='Appointment Date', default=lambda s: fields.Datetime.now(), |
|||
help="This is the appointment date") |
|||
physician_id = fields.Many2one('res.partner', string='Referred By', select=True) |
|||
comment = fields.Text(string='Comments') |
|||
appointment_lines = fields.One2many('lab.appointment.lines', 'test_line_appointment', string="Test Request") |
|||
|
|||
request_count = fields.Integer(compute="_compute_state", string='# of Requests', copy=False, default=0) |
|||
inv_count = fields.Integer(compute="_compute_state", string='# of Invoices', copy=False, default=0) |
|||
state = fields.Selection([ |
|||
('draft', 'Draft'), |
|||
('confirm', 'Confirmed'), |
|||
('request_lab', 'Lab Requested'), |
|||
('completed', 'Test Result'), |
|||
('to_invoice', 'To Invoice'), |
|||
('invoiced', 'Done'), |
|||
('cancel', 'Cancelled'), |
|||
], string='Status', readonly=True, copy=False, index=True, track_visibility='onchange', default='draft', |
|||
) |
|||
|
|||
priority = fields.Selection([ |
|||
('0', 'Low'), |
|||
('1', 'Normal'), |
|||
('2', 'High') |
|||
], size=1) |
|||
|
|||
_defaults = { |
|||
'priority': '0', |
|||
} |
|||
|
|||
@api.model |
|||
def create(self, vals): |
|||
if vals: |
|||
vals['name'] = self.env['ir.sequence'].next_by_code('lab.appointment') or _('New') |
|||
result = super(Appointment, self).create(vals) |
|||
return result |
|||
|
|||
@api.multi |
|||
def _compute_state(self): |
|||
for obj in self: |
|||
obj.request_count = self.env['lab.request'].search_count([('app_id', '=', obj.id)]) |
|||
obj.inv_count = self.env['account.invoice'].search_count([('lab_request', '=', obj.id)]) |
|||
|
|||
@api.multi |
|||
def create_invoice(self): |
|||
invoice_obj = self.env["account.invoice"] |
|||
invoice_line_obj = self.env["account.invoice.line"] |
|||
for lab in self: |
|||
lab.write({'state': 'to_invoice'}) |
|||
if lab.patient_id: |
|||
curr_invoice = { |
|||
'partner_id': lab.patient_id.patient.id, |
|||
'account_id': lab.patient_id.patient.property_account_receivable_id.id, |
|||
'state': 'draft', |
|||
'type': 'out_invoice', |
|||
'date_invoice': datetime.datetime.now(), |
|||
'origin': "Lab Test# : " + lab.name, |
|||
'target': 'new', |
|||
'lab_request': lab.id, |
|||
'is_lab_invoice': True |
|||
} |
|||
|
|||
inv_ids = invoice_obj.create(curr_invoice) |
|||
inv_id = inv_ids.id |
|||
|
|||
if inv_ids: |
|||
journal = self.env['account.journal'].search([('type', '=', 'sale')], limit=1) |
|||
prd_account_id = journal.default_credit_account_id.id |
|||
if lab.appointment_lines: |
|||
for line in lab.appointment_lines: |
|||
curr_invoice_line = { |
|||
'name': line.lab_test.lab_test, |
|||
'price_unit': line.cost or 0, |
|||
'quantity': 1.0, |
|||
'account_id': prd_account_id, |
|||
'invoice_id': inv_id, |
|||
} |
|||
invoice_line_obj.create(curr_invoice_line) |
|||
|
|||
# self.write({'state': 'invoiced'}) |
|||
view_id = self.env.ref('account.invoice_form').id |
|||
return { |
|||
'view_type': 'form', |
|||
'view_mode': 'form', |
|||
'res_model': 'account.invoice', |
|||
'view_id': view_id, |
|||
'type': 'ir.actions.act_window', |
|||
'name': _('Lab Invoices'), |
|||
'res_id': inv_id |
|||
} |
|||
|
|||
@api.multi |
|||
def action_request(self): |
|||
if self.appointment_lines: |
|||
for line in self.appointment_lines: |
|||
data = self.env['lab.test'].search([('lab_test', '=', line.lab_test.lab_test)]) |
|||
self.env['lab.request'].create({'lab_request_id': self.name, |
|||
'app_id': self.id, |
|||
'lab_requestor': self.patient_id.id, |
|||
'lab_requesting_date': self.appointment_date, |
|||
'test_request': line.lab_test.id, |
|||
'request_line': [(6, 0, [x.id for x in data.test_lines])], |
|||
}) |
|||
self.state = 'request_lab' |
|||
else: |
|||
raise UserError(_('Please Select Lab Test.')) |
|||
|
|||
@api.multi |
|||
def confirm_appointment(self): |
|||
|
|||
message_body = "Dear " + self.patient_id.patient.name + "," + "<br>Your Appointment Has been Confirmed " \ |
|||
+ "<br>Appointment ID : " + self.name + "<br>Date : " + self.appointment_date + \ |
|||
'<br><br>Thank you' |
|||
|
|||
template_obj = self.env['mail.mail'] |
|||
template_data = { |
|||
'subject': 'Appointment Confirmation', |
|||
'body_html': message_body, |
|||
'email_from': self.env.user.company_id.email, |
|||
'email_to': self.patient_id.email |
|||
} |
|||
template_id = template_obj.create(template_data) |
|||
template_obj.send(template_id) |
|||
self.write({'state': 'confirm'}) |
|||
|
|||
@api.multi |
|||
def cancel_appointment(self): |
|||
return self.write({'state': 'cancel'}) |
|||
|
|||
|
|||
class LabAppointmentLines(models.Model): |
|||
_name = 'lab.appointment.lines' |
|||
|
|||
lab_test = fields.Many2one('lab.test', string="Test") |
|||
cost = fields.Char(string="Cost") |
|||
requesting_date = fields.Date(string="Date") |
|||
test_line_appointment = fields.Many2one('lab.appointment', string="Appointment") |
|||
|
|||
@api.onchange('lab_test') |
|||
def cost_update(self): |
|||
if self.lab_test: |
|||
self.cost = self.lab_test.test_cost |
|||
|
|||
|
|||
class LabPatientInherit(models.Model): |
|||
_inherit = 'lab.patient' |
|||
|
|||
app_count = fields.Integer(compute="_compute_state", string='# of Appointments', copy=False, default=0) |
|||
|
|||
@api.multi |
|||
def _compute_state(self): |
|||
for obj in self: |
|||
obj.app_count = self.env['lab.appointment'].search_count([('patient_id', '=', obj.id)]) |
|||
|
@ -0,0 +1,65 @@ |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2019-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Maintainer: Cybrosys Technologies (<https://www.cybrosys.com>) |
|||
# |
|||
############################################################################## |
|||
|
|||
from dateutil.relativedelta import relativedelta |
|||
from odoo import models, fields, api, _ |
|||
|
|||
|
|||
class LabPatient(models.Model): |
|||
_name = 'lab.patient' |
|||
_rec_name = 'patient' |
|||
_description = 'Patient' |
|||
|
|||
patient = fields.Many2one('res.partner', string='Partner', required=True) |
|||
patient_image = fields.Binary(string='Photo') |
|||
patient_id = fields.Char(string='Patient ID', readonly=True) |
|||
name = fields.Char(string='Patient ID', default=lambda self: _('New')) |
|||
title = fields.Selection([ |
|||
('ms', 'Miss'), |
|||
('mister', 'Mister'), |
|||
('mrs', 'Mrs'), |
|||
], string='Title', default='mister', required=True) |
|||
emergency_contact = fields.Many2one( |
|||
'res.partner', string='Emergency Contact') |
|||
gender = fields.Selection( |
|||
[('m', 'Male'), ('f', 'Female'), |
|||
('ot', 'Other')], 'Gender', required=True) |
|||
dob = fields.Date(string='Date Of Birth', required=True) |
|||
age = fields.Char(string='Age', compute='compute_age') |
|||
blood_group = fields.Selection( |
|||
[('A+', 'A+ve'), ('B+', 'B+ve'), ('O+', 'O+ve'), ('AB+', 'AB+ve'), |
|||
('A-', 'A-ve'), ('B-', 'B-ve'), ('O-', 'O-ve'), ('AB-', 'AB-ve')], |
|||
'Blood Group') |
|||
visa_info = fields.Char(string='Visa Info', size=64) |
|||
id_proof_number = fields.Char(string='ID Proof Number') |
|||
note = fields.Text(string='Note') |
|||
date = fields.Datetime(string='Date Requested', default=lambda s: fields.Datetime.now(), invisible=True) |
|||
phone = fields.Char(string="Phone", required=True) |
|||
email = fields.Char(string="Email", required=True) |
|||
|
|||
@api.multi |
|||
def compute_age(self): |
|||
for data in self: |
|||
if data.dob: |
|||
dob = fields.Datetime.from_string(data.dob) |
|||
date = fields.Datetime.from_string(data.date) |
|||
delta = relativedelta(date, dob) |
|||
data.age = str(delta.years) + ' years' |
|||
|
|||
@api.model |
|||
def create(self, vals): |
|||
sequence = self.env['ir.sequence'].next_by_code('lab.patient') |
|||
vals['name'] = sequence or _('New') |
|||
result = super(LabPatient, self).create(vals) |
|||
return result |
|||
|
|||
@api.onchange('patient') |
|||
def detail_get(self): |
|||
self.phone = self.patient.phone |
|||
self.email = self.patient.email |
|||
|
@ -0,0 +1,120 @@ |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2019-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Maintainer: Cybrosys Technologies (<https://www.cybrosys.com>) |
|||
# |
|||
############################################################################## |
|||
|
|||
import datetime |
|||
from odoo import models, fields, api, _ |
|||
from odoo.exceptions import ValidationError |
|||
|
|||
|
|||
class LabRequest(models.Model): |
|||
_name = 'lab.request' |
|||
_inherit = ['mail.thread'] |
|||
_rec_name = 'lab_request_id' |
|||
_description = 'Lab Request' |
|||
|
|||
name = fields.Char(string='Lab Test', size=16, readonly=True, required=True, help="Lab result ID", default=lambda *a: '#') |
|||
lab_request_id = fields.Char(string='Appointment ID', help="Lab appointment ID") |
|||
app_id = fields.Many2one('lab.appointment', string='Appointment') |
|||
lab_requestor = fields.Many2one('lab.patient', string='Patient', required=True, select=True, |
|||
help='Patient Name') |
|||
test_request = fields.Many2one('lab.test', string='Test') |
|||
lab_requesting_date = fields.Datetime(string='Requested Date') |
|||
comment = fields.Text('Comment') |
|||
request_line = fields.One2many('lab.test.attribute', 'test_request_reverse', string="Test Lines") |
|||
state = fields.Selection([ |
|||
('draft', 'Draft'), |
|||
('sample_collection', 'Sample Collected'), |
|||
('test_in_progress', 'Test In Progress'), |
|||
('completed', 'Completed'), |
|||
('cancel', 'Cancelled'), |
|||
|
|||
], string='Status', readonly=True, copy=False, index=True, track_visibility='onchange', default='draft') |
|||
|
|||
@api.model |
|||
def create(self, vals): |
|||
sequence = self.env['ir.sequence'].next_by_code('lab.request') |
|||
vals['name'] = sequence or '/' |
|||
return super(LabRequest, self).create(vals) |
|||
|
|||
@api.multi |
|||
def set_to_sample_collection(self): |
|||
return self.write({'state': 'sample_collection'}) |
|||
|
|||
@api.multi |
|||
def set_to_test_in_progress(self): |
|||
return self.write({'state': 'test_in_progress'}) |
|||
|
|||
@api.multi |
|||
def cancel_lab_test(self): |
|||
return self.write({'state': 'cancel'}) |
|||
|
|||
@api.multi |
|||
def set_to_test_completed(self): |
|||
if not self.request_line: |
|||
raise ValidationError(_("No Result Lines Entered !")) |
|||
req_obj = self.env['lab.request'].search_count([('app_id', '=', self.app_id.id), |
|||
('id', '!=', self.id)]) |
|||
req_obj_count = self.env['lab.request'].search_count([('app_id', '=', self.app_id.id), |
|||
('id', '!=', self.id), |
|||
('state', '=', 'completed')]) |
|||
if req_obj == req_obj_count: |
|||
app_obj = self.env['lab.appointment'].search([('id', '=', self.app_id.id)]) |
|||
app_obj.write({'state': 'completed'}) |
|||
return self.write({'state': 'completed'}) |
|||
|
|||
@api.multi |
|||
def print_lab_test(self): |
|||
return self.env.ref('medical_lab_management.print_lab_test').report_action(self) |
|||
|
|||
@api.multi |
|||
def lab_invoice_create(self): |
|||
invoice_obj = self.env["account.invoice"] |
|||
invoice_line_obj = self.env["account.invoice.line"] |
|||
for lab in self: |
|||
if lab.lab_requestor: |
|||
curr_invoice = { |
|||
'partner_id': lab.lab_requestor.patient.id, |
|||
'account_id': lab.lab_requestor.patient.property_account_receivable_id.id, |
|||
'state': 'draft', |
|||
'type': 'out_invoice', |
|||
'date_invoice': datetime.datetime.now(), |
|||
'origin': "Lab Test# : " + lab.name, |
|||
'target': 'new', |
|||
'lab_request': lab.id, |
|||
'is_lab_invoice': True |
|||
} |
|||
|
|||
inv_ids = invoice_obj.create(curr_invoice) |
|||
inv_id = inv_ids.id |
|||
|
|||
if inv_ids: |
|||
journal = self.env['account.journal'].search([('type', '=', 'sale')], limit=1) |
|||
prd_account_id = journal.default_credit_account_id.id |
|||
if lab.test_request: |
|||
curr_invoice_line = { |
|||
'name': "Charge for lab test", |
|||
'price_unit': lab.test_request.test_cost or 0, |
|||
'quantity': 1.0, |
|||
'account_id': prd_account_id, |
|||
'invoice_id': inv_id, |
|||
} |
|||
|
|||
invoice_line_obj.create(curr_invoice_line) |
|||
|
|||
self.write({'state': 'invoiced'}) |
|||
form_view_ref = self.env.ref('account.invoice_form', False) |
|||
tree_view_ref = self.env.ref('account.invoice_tree', False) |
|||
|
|||
return { |
|||
'domain': "[('id', '=', " + str(inv_id) + ")]", |
|||
'name': 'Lab Invoices', |
|||
'view_mode': 'form', |
|||
'res_model': 'account.invoice', |
|||
'type': 'ir.actions.act_window', |
|||
'views': [(tree_view_ref.id, 'tree'), (form_view_ref.id, 'form')], |
|||
} |
@ -0,0 +1,23 @@ |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2019-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Maintainer: Cybrosys Technologies (<https://www.cybrosys.com>) |
|||
# |
|||
############################################################################## |
|||
|
|||
from odoo import models, fields |
|||
|
|||
|
|||
class LabTestContentType(models.Model): |
|||
_name = 'lab.test.content_type' |
|||
_rec_name = 'content_type_name' |
|||
_description = "Content" |
|||
|
|||
content_type_name = fields.Char(string="Name", required=True, help="Content type name") |
|||
content_type_code = fields.Char(string="Code") |
|||
parent_test = fields.Many2one('lab.test', string="Test Category") |
|||
|
|||
|
|||
|
|||
|
@ -0,0 +1,32 @@ |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2019-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Maintainer: Cybrosys Technologies (<https://www.cybrosys.com>) |
|||
# |
|||
############################################################################## |
|||
|
|||
from odoo import models, fields |
|||
|
|||
|
|||
class LabTestType(models.Model): |
|||
_name = 'lab.test' |
|||
_description = "Lab Test" |
|||
_rec_name = 'lab_test' |
|||
_inherit = ['mail.thread'] |
|||
|
|||
lab_test = fields.Char(string="Test Name", required=True, help="Name of lab test ") |
|||
lab_test_code = fields.Char(string="Test Code", required=True) |
|||
test_lines = fields.One2many('lab.test.attribute', 'test_line_reverse', string="Attribute") |
|||
test_cost = fields.Integer(string="Cost", required=True) |
|||
|
|||
|
|||
class LabTestAttribute(models.Model): |
|||
_name = 'lab.test.attribute' |
|||
|
|||
test_content = fields.Many2one('lab.test.content_type', string="Content") |
|||
result = fields.Char(string="Result") |
|||
unit = fields.Many2one('test.unit', string="Unit") |
|||
interval = fields.Char(string="Reference Intervals") |
|||
test_line_reverse = fields.Many2one('lab.test', string="Attribute") |
|||
test_request_reverse = fields.Many2one('lab.request', string="Request") |
@ -0,0 +1,21 @@ |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2019-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Maintainer: Cybrosys Technologies (<https://www.cybrosys.com>) |
|||
# |
|||
############################################################################## |
|||
|
|||
from odoo import models, fields |
|||
|
|||
|
|||
class PhysicianSpeciality(models.Model): |
|||
_name = 'physician.speciality' |
|||
_description = 'Medical Specialty' |
|||
|
|||
code = fields.Char(string='ID') |
|||
name = fields.Char(string='Specialty', help='Name of the specialty', required=True) |
|||
|
|||
_sql_constraints = [ |
|||
('name_uniq', 'UNIQUE(name)', 'Name must be unique!'), |
|||
] |
@ -0,0 +1,20 @@ |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2019-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Maintainer: Cybrosys Technologies (<https://www.cybrosys.com>) |
|||
# |
|||
############################################################################## |
|||
|
|||
from odoo import models, fields |
|||
|
|||
|
|||
class ResPartnerPatient(models.Model): |
|||
_inherit = 'res.partner' |
|||
|
|||
is_patient = fields.Boolean(string='Is Patient') |
|||
is_physician = fields.Boolean(string='Is Physician') |
|||
speciality = fields.Many2one('physician.speciality', string='Speciality') |
|||
hospital = fields.Many2one('res.partner', string='Hospital') |
|||
|
|||
|
@ -0,0 +1,18 @@ |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2019-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Maintainer: Cybrosys Technologies (<https://www.cybrosys.com>) |
|||
# |
|||
############################################################################## |
|||
|
|||
from odoo import models, fields |
|||
|
|||
|
|||
class TestingUnit(models.Model): |
|||
_name = 'test.unit' |
|||
_rec_name = 'code' |
|||
_description = "Test Unit" |
|||
|
|||
unit = fields.Char(string="Unit", required=True) |
|||
code = fields.Char(string="code", required=True) |
@ -0,0 +1,60 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<data> |
|||
<template id="report_patient_label"> |
|||
<t t-call="web.html_container"> |
|||
<t t-foreach="docs" t-as="o"> |
|||
<div class="page"> |
|||
<div class="oe_structure"/> |
|||
<div class="row"> |
|||
<div class="col-xs-2" style="margin:auto;"> |
|||
</div> |
|||
<center> |
|||
<div class="col-xs-8" style="margin:auto"> |
|||
<table class="table table-condensed" style="border: 3px solid black !important;"> |
|||
<tr> |
|||
<td width="40%"> |
|||
<p style="text-align:center;padding-top:10px;"> |
|||
<img t-if="not o.patient_image" t-att-src="'/web/static/src/img/placeholder.png'" height="120" border="1" width="120"/> |
|||
<img t-if="o.patient_image" t-att-src="'data:image/png;base64,%s' %o.patient_image" height="120" border="1" width="120"/> |
|||
</p> |
|||
<p style="text-align:center;"> |
|||
<strong><span t-field="o.patient.name"/></strong> |
|||
</p> |
|||
</td> |
|||
<td width="60%"> |
|||
<table> |
|||
<tr> |
|||
<td> |
|||
<p style="text-align:right;padding-top:30px;"><strong>Patient ID : </strong></p> |
|||
<p style="text-align:right;"><strong>Sex : </strong></p> |
|||
<p style="text-align:right;"><strong>Age : </strong></p> |
|||
</td> |
|||
<td> |
|||
<p style="text-align:left;padding-top:30px;padding-left:10px;" t-field="o.name"/> |
|||
<t t-if="o.gender=='m'"> |
|||
<p style="text-align:left;padding-left:10px;">Male</p> |
|||
</t> |
|||
<t t-if="o.gender=='ot'"> |
|||
<p style="text-align:left;padding-left:10px;">Other</p> |
|||
</t> |
|||
<t t-if="o.gender=='f'"> |
|||
<p style="text-align:left;padding-left:10px;">Female</p> |
|||
</t> |
|||
<p style="text-align:left;padding-left:10px;" t-field="o.age"/> |
|||
</td> |
|||
</tr> |
|||
</table> |
|||
</td> |
|||
</tr> |
|||
</table> |
|||
</div> |
|||
</center> |
|||
</div> |
|||
</div> |
|||
<p style="page-break-after:always"></p> |
|||
</t> |
|||
</t> |
|||
</template> |
|||
</data> |
|||
</odoo> |
@ -0,0 +1,54 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
<template id="report_patient_labtest"> |
|||
<t t-foreach="docs" t-as="o"> |
|||
<t t-call="web.external_layout"> |
|||
<div class="page"> |
|||
<t t-if="o and 'company_id' in o"> |
|||
<t t-set="company" t-value="o.company_id"> </t> |
|||
</t> |
|||
<t t-if="not o or not 'company_id' in o"> |
|||
<t t-set="company" t-value="res_company"> </t> |
|||
</t> |
|||
<h3 style="text-decoration:underline;text-align:center;"><b>Lab Test Report</b></h3> |
|||
<br/> |
|||
<br/> |
|||
<table width="99%" style="margin-left:50px;margin-top:5px;border: None solid black;"> |
|||
<tr> |
|||
<td style="width:50px;height:25px" ><span>Patient: </span><span t-att-style="style" t-esc="o.lab_requestor.patient.name"/></td> |
|||
<td style="width:50px;height:25px" ><span>Test : </span><span t-att-style="style" t-esc="o.test_request.lab_test"/></td> |
|||
<td style="width:50px;height:25px" ><span>Date: </span><span t-att-style="style" t-esc="o.lab_requesting_date"/></td> |
|||
</tr> |
|||
</table> |
|||
<br/> |
|||
<br/> |
|||
<br/> |
|||
<br/> |
|||
<table width="99%" style="border:1px solid black;padding-left:1.16cm;"> |
|||
<thead> |
|||
<th style="border:1px solid black;text-align:center;" width="13%" class="td4">Content</th> |
|||
<th style="border:1px solid black;text-align:center;" width="13%" class="td4">Unit</th> |
|||
<th style="border:1px solid black;text-align:center;" width="13%" class="td4">Normal Range</th> |
|||
<th style="border:1px solid black;text-align:center;" width="13%" class="td4">Result</th> |
|||
</thead> |
|||
<tbody> |
|||
<t t-foreach="o.request_line" t-as="l"> |
|||
<tr style="border:1px solid black"> |
|||
<td style="border:1px solid black;text-align:center;"><span t-esc="l.test_content.content_type_name" style="font-size:16px;"/></td> |
|||
<td style="border:1px solid black;text-align:center;"><span t-esc="l.unit.code" style="font-size:16px;"/></td> |
|||
<td style="border:1px solid black;text-align:center;"><span t-esc="l.interval" style="font-size:16px;"/></td> |
|||
<td style="border:1px solid black;text-align:center;"><span t-esc="l.result" style="font-size:16px;"/></td> |
|||
</tr> |
|||
</t> |
|||
</tbody> |
|||
</table> |
|||
<br/> |
|||
<br/> |
|||
</div> |
|||
<p style="page-break-after:always"></p> |
|||
</t> |
|||
</t> |
|||
</template> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1,23 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<data> |
|||
<report |
|||
string="Lab Test Result" |
|||
id="print_lab_test" |
|||
model="lab.request" |
|||
report_type="qweb-pdf" |
|||
name="medical_lab_management.report_patient_labtest" |
|||
file="medical_lab_management.report_patient_labtest" |
|||
/> |
|||
|
|||
<report |
|||
string="Patient Card" |
|||
id="action_report_patient_label" |
|||
model="lab.patient" |
|||
report_type="qweb-pdf" |
|||
name="medical_lab_management.report_patient_label" |
|||
file="medical_lab_management.report_patient_label" |
|||
|
|||
/> |
|||
</data> |
|||
</odoo> |
|
@ -0,0 +1,20 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<record model="ir.module.category" id="module_category_lab_management"> |
|||
<field name="name">Lab Management</field> |
|||
</record> |
|||
|
|||
<record id="group_lab_management_user" model="res.groups"> |
|||
<field name="name">Lab User</field> |
|||
<field name="category_id" ref="module_category_lab_management"/> |
|||
<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/> |
|||
</record> |
|||
|
|||
<record id="group_lab_management_technician" model="res.groups"> |
|||
<field name="name">Lab Manager</field> |
|||
<field name="category_id" ref="module_category_lab_management"/> |
|||
<field name="implied_ids" eval="[(4, ref('group_lab_management_user'))]"/> |
|||
<field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/> |
|||
</record> |
|||
|
|||
</odoo> |
After Width: | Height: | Size: 80 KiB |
After Width: | Height: | Size: 99 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 32 KiB |
@ -0,0 +1,446 @@ |
|||
<section class="oe_container" style="background-image:url(https://www.cybrosys.com/images/odoo-index-header-banner.png);background-repeat:no-repeat;background-size:100%;padding: 4% 0% 2% 15%;background-position-y: -107px;"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h2 class="oe_slogan" style="font-size: 35px;color: #fff;font-weight: 900;text-transform: uppercase;text-align: left;margin: 0;margin-bottom: 16px;"> |
|||
Medical Lab Management |
|||
</h2> |
|||
<h3 class="oe_slogan" style="font-size: 25px;color: #fff;font-weight: 600;text-align: left;opacity: 1;margin: 0 !important;"> |
|||
Manage Lab Activities |
|||
</h3> |
|||
<h5 class="oe_slogan" style="text-align: left;background: #fff;width: 293px;padding: 10px;color: #080808 !important;opacity: 1 !important;font-weight: 600;font-size: 20px;"> |
|||
<a style="color: #080808 !important;" href="https://www.cybrosys.com" target="_blank">Cybrosys Technologies</a> |
|||
</h5> |
|||
<a style="color: #080808 !important;" href="https://www.cybrosys.com" target="_blank"> |
|||
<div style="width: 215px;margin-left: 57%;text-align: center;background: #ffffff;height: 215px;border-radius: 100%;display: flex;justify-content: center;align-items: center;box-shadow: 0 0 12px 4px #00000059;"> |
|||
<img src="https://www.cybrosys.com/images/cybro-logo-oca.png" alt="cybrosys technologies" style="width: 180px;"/> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</section> |
|||
<section class="oe_container" style="padding: 1% 0% 3% 15%;"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h2 class="oe_slogan" style="text-align: left;font-size: 28px;font-weight: 600;margin: 0px !important;"> |
|||
Overview |
|||
</h2> |
|||
<h3 class="oe_slogan" style="text-align: left;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 24px;"> |
|||
This app helps the user to systematically perform the activities of a Medical Laboratory. |
|||
The app simplifies the activities like Patient Management, Appointment Management, Test Requests Management, Lab Results Management, and so on. |
|||
</h3> |
|||
</div> |
|||
</section> |
|||
<section class="oe_container" style="background-image:url(https://www.cybrosys.com/images/odoo-index-banner.png); background-repeat:no-repeat; background-size:cover;padding: 10% 0% 25% 15%;"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h2 class="oe_slogan" style="text-align: left;font-size: 28px;font-weight: 600;margin: 0px !important;"> |
|||
Features |
|||
</h2> |
|||
<h3 class="oe_slogan" style="text-align: left;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 18px;"> |
|||
<img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Manage Patients |
|||
</h3> |
|||
<h3 class="oe_slogan" style="text-align: left;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 18px;"> |
|||
<img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Issue Patient Card |
|||
</h3> |
|||
<h3 class="oe_slogan" style="text-align: left;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 18px;"> |
|||
<img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Manage Referrals of Patients |
|||
</h3> |
|||
<h3 class="oe_slogan" style="text-align: left;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 18px;"> |
|||
<img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Manage Appointments |
|||
</h3> |
|||
<h3 class="oe_slogan" style="text-align: left;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 18px;"> |
|||
<img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Mail Notification For Appointments |
|||
</h3> |
|||
<h3 class="oe_slogan" style="text-align: left;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 18px;"> |
|||
<img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Manage Lab Requests |
|||
</h3> |
|||
<h3 class="oe_slogan" style="text-align: left;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 18px;"> |
|||
<img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Print Lab Test Result Of Patient |
|||
</h3> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container" style="padding: 3% 0% 0% 15%;"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h2 class="oe_slogan" style="text-align: left;font-size: 28px;font-weight: 600;margin: 0px !important;"> |
|||
Screenshots |
|||
</h2> |
|||
<h3 class="oe_slogan" style="text-align: left;padding: 5% 0% 0% 0%;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 24px;"> |
|||
<div> |
|||
<img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Create patients. |
|||
</div> |
|||
</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
<img src="lab-management-cybrosys-1.png" alt="" style="width: 95%;"/> |
|||
</div> |
|||
<h3 class="oe_slogan" style="text-align: left;padding: 5% 0% 0% 0%;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 24px;"> |
|||
<div> |
|||
<img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Go to Laboratory -> Patient -> Print -> Patient Card. |
|||
</div> |
|||
</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
<img src="lab-management-cybrosys-2.png" alt="" style="width: 95%;"/> |
|||
</div> |
|||
<h3 class="oe_slogan" style="text-align: left;padding: 5% 0% 0% 0%;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 24px;"> |
|||
<div><img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Go to Laboratory -> Appointments->Create Appointments. |
|||
</div> |
|||
</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
<img src="lab-management-cybrosys-3.png" alt="" style="width: 95%;"/> |
|||
</div> |
|||
<h3 class="oe_slogan" style="text-align: left;padding: 5% 0% 0% 0%;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 24px;"> |
|||
<div><img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
When we confirm the appointment the appointment details will be sent through E-Mail. |
|||
</div> |
|||
</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
<img src="lab-management-cybrosys-4.png" alt="" style="width: 95%;"/> |
|||
</div> |
|||
<h3 class="oe_slogan" style="text-align: left;padding: 5% 0% 0% 0%;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 24px;"> |
|||
<div><img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Lab Request |
|||
</div> |
|||
</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
<img src="lab-management-cybrosys-5.png" alt="" style="width: 95%;"/> |
|||
</div> |
|||
<h3 class="oe_slogan" style="text-align: left;padding: 5% 0% 0% 0%;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 24px;"> |
|||
<div><img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Lab Test Result |
|||
</div> |
|||
</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
<img src="lab-management-cybrosys-6.png" alt="" style="width: 95%;"/> |
|||
</div> |
|||
<h3 class="oe_slogan" style="text-align: left;padding: 5% 0% 0% 0%;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 24px;"> |
|||
<div><img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Create invoice for lab test. |
|||
</div> |
|||
</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
<img src="lab-management-cybrosys-7.png" alt="" style="width: 95%;"/> |
|||
</div> |
|||
<h3 class="oe_slogan" style="text-align: left;padding: 5% 0% 0% 0%;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 24px;"> |
|||
<div><img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
You can see today's appointments here. |
|||
</div> |
|||
</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
<img src="lab-management-cybrosys-8.png" alt="" style="width: 95%;"/> |
|||
</div> |
|||
<h3 class="oe_slogan" style="text-align: left;padding: 5% 0% 0% 0%;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 24px;"> |
|||
<div><img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Go to Laboratory -> Configuration -> Lab test. |
|||
</div> |
|||
</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
<img src="lab-management-cybrosys-9.png" alt="" style="width: 95%;"/> |
|||
</div> |
|||
<h3 class="oe_slogan" style="text-align: left;padding: 5% 0% 0% 0%;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 24px;"> |
|||
<div><img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Go to Laboratory -> Configuration -> Test Contents. |
|||
</div> |
|||
</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
<img src="lab-management-cybrosys-10.png" alt="" style="width: 95%;"/> |
|||
</div> |
|||
<h3 class="oe_slogan" style="text-align: left;padding: 5% 0% 0% 0%;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 24px;"> |
|||
<div><img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
Go to Laboratory -> Configuration -> Testing Unit. |
|||
</div> |
|||
</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
<img src="lab-management-cybrosys-11.png" alt="" style="width: 95%;"/> |
|||
</div> |
|||
<h3 class="oe_slogan" style="text-align: left;padding: 5% 0% 0% 0%;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 24px;"> |
|||
<div><img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
We can add referral physician details. |
|||
</div> |
|||
</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
<img src="lab-management-cybrosys-12.png" alt="" style="width: 95%;"/> |
|||
</div> |
|||
<h3 class="oe_slogan" style="text-align: left;padding: 5% 0% 0% 0%;font-size: 16px;width: 90%;margin: 0;margin-top: 14px;color: #000 !important;opacity: 1 !important;line-height: 24px;"> |
|||
<div><img src="https://www.cybrosys.com/images/ico-tick.png"> |
|||
There are two type <users class=""></users> |
|||
</div> |
|||
</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
<img src="lab-management-cybrosys-13.png" alt="" style="width: 95%;"/> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
<section class="oe_container" style="padding: 7px 0% 0% 3%;"> |
|||
<div class="oe_row oe_spaced"> |
|||
<a style="color: #080808 !important;" href="https://apps.odoo.com/apps/modules/browse?search=cybrosys" target="_blank"><img src="https://www.cybrosys.com/images/view-more-apps.jpg" alt="cybrosys technologies" style="width: 100%;margin-bottom: 50px;"/></a> |
|||
</div> |
|||
</section> |
|||
<section class="oe_container" style="padding: 1% 0% 0% 3%;"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h2 class="oe_slogan" style="text-align: left;font-size: 28px;font-weight: 600;margin: 0px !important;"> |
|||
Our Services |
|||
</h2> |
|||
<div style="display:flex;padding-top: 20px;justify-content: space-between;"> |
|||
<div style="flex-basis: 18%;"> |
|||
|
|||
<div style="width:75px;height:75px;background:#fff; border-radius:100%;margin: auto;"> |
|||
<a href="https://www.cybrosys.com/odoo-customization-and-installation/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/odoo-customization.png" style="width: 100%;border-radius: 100%;"/> |
|||
</a> |
|||
</div> |
|||
<h3 class="oe_slogan" style="font-weight: 800;text-align: center;font-size: 14px;width: 100%;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;"> |
|||
<a href="https://www.cybrosys.com/odoo-customization-and-installation/" target="_blank"> |
|||
Odoo Customization |
|||
</a> |
|||
</h3> |
|||
|
|||
</div> |
|||
<div style="flex-basis: 18%;"> |
|||
|
|||
<div style="width:75px;height:75px;background:#fff; border-radius:100%;margin: auto;"> |
|||
<a href="https://www.cybrosys.com/odoo-erp-implementation/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/odoo-erp-implementation.png" style="width: 100%;border-radius: 100%;"/> |
|||
</a> |
|||
</div> |
|||
<h3 class="oe_slogan" style="font-weight: 800;text-align: center;font-size: 14px;width: 100%;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;"> |
|||
<a href="https://www.cybrosys.com/odoo-erp-implementation/" target="_blank"> |
|||
Odoo Implementation </a> |
|||
</h3> |
|||
|
|||
</div> |
|||
<div style="flex-basis: 18%;"> |
|||
|
|||
<div style="width:75px;height:75px;background:#fff; border-radius:100%;margin: auto;"> |
|||
<a href="https://www.cybrosys.com/odoo-erp-integration/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/odoo-erp-integration.png" style="width: 100%;border-radius: 100%;"/> |
|||
</a> |
|||
</div> |
|||
<h3 class="oe_slogan" style="font-weight: 800;text-align: center;font-size: 14px;width: 100%;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;"> |
|||
<a href="https://www.cybrosys.com/odoo-erp-integration/" target="_blank"> |
|||
Odoo Integration |
|||
</a> |
|||
</h3> |
|||
|
|||
</div> |
|||
<div style="flex-basis: 18%;"> |
|||
|
|||
<div style="width:75px;height:75px;background:#fff; border-radius:100%;margin: auto;"> |
|||
<a href="https://www.cybrosys.com/odoo-erp-support/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/odoo-erp-support.png" style="width: 100%;border-radius: 100%;"/> |
|||
</a> |
|||
</div> |
|||
<h3 class="oe_slogan" style="font-weight: 800;text-align: center;font-size: 14px;width: 100%;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;"> |
|||
<a href="https://www.cybrosys.com/odoo-erp-support/" target="_blank"> |
|||
Odoo Support</a> |
|||
</h3> |
|||
|
|||
</div> |
|||
<div style="flex-basis: 18%;"> |
|||
|
|||
<div style="width:75px;height:75px;background:#fff; border-radius:100%;margin: auto;"> |
|||
<a href="https://www.cybrosys.com/hire-odoo-developer/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/hire-odoo-developer.png" style="width: 100%;border-radius: 100%;"/> |
|||
</a> |
|||
</div> |
|||
<h3 class="oe_slogan" style="font-weight: 800;text-align: center;font-size: 14px;width: 100%;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;"> |
|||
<a href="https://www.cybrosys.com/hire-odoo-developer/" target="_blank"> |
|||
Hire Odoo Developers</a> |
|||
</h3> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
<section class="oe_container" style="padding: 1% 0% 0% 3%;"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h2 class="oe_slogan" style="text-align: left;font-size: 28px;font-weight: 600;margin: 0px !important;"> |
|||
Our Industries |
|||
</h2> |
|||
<div style="display:flex;justify-content: space-between;flex-wrap:wrap;"> |
|||
<div style="flex-basis: 32%;padding-top: 20px;"> |
|||
|
|||
<div style="width:30%; float:left;"> |
|||
<div style="width:75px;height:75px;background:#CE2D48; border-radius:100%;float: left;text-align: left;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/best-trading-erp/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/odoo-index-industry-1.png" alt="Odoo Industry" style=" border-radius: 100%;width:100%;"/> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div style="width:70%;float:left;"> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 14px;font-weight:800;width: auto;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 4px;margin-left: 16px;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/best-trading-erp/" target="_blank"> |
|||
Trading |
|||
</a> |
|||
</h3> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 13px;width: auto;margin: 0;margin-top:5px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 5px;margin-left: 16px;"> |
|||
Easily procure and sell your products. |
|||
</h3> |
|||
</div> |
|||
|
|||
</div> |
|||
<div style="flex-basis: 32%;padding-top: 20px;"> |
|||
|
|||
<div style="width:30%; float:left;"> |
|||
<div style="width:75px;height:75px;background:#CE2D48; border-radius:100%;float: left;text-align: left;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/manufacturing-erp-software/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/odoo-index-industry-2.png" alt="Odoo Industry" style=" border-radius: 100%;width:100%;"/> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div style="width:70%;float:left;"> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 14px;font-weight:800;width: auto;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 4px;margin-left: 16px;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/manufacturing-erp-software/" target="_blank"> |
|||
Manufacturing</a> |
|||
</h3> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 13px;width: auto;margin: 0;margin-top:5px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 5px;margin-left: 16px;"> |
|||
Plan, track and schedule your operations. |
|||
</h3> |
|||
</div> |
|||
|
|||
</div> |
|||
<div style="flex-basis: 32%;padding-top: 20px;"> |
|||
|
|||
<div style="width:30%; float:left;"> |
|||
<div style="width:75px;height:75px;background:#CE2D48; border-radius:100%;float: left;text-align: left;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/restaurant-management/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/odoo-index-industry-3.png" alt="Odoo Industry" style=" border-radius: 100%;width:100%;"/> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div style="width:70%;float:left;"> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 14px;font-weight:800;width: auto;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 4px;margin-left: 16px;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/restaurant-management/" target="_blank"> |
|||
Restaurant</a> |
|||
</h3> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 13px;width: auto;margin: 0;margin-top:5px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 5px;margin-left: 16px;"> |
|||
Run your bar or restaurant methodical. |
|||
</h3> |
|||
</div> |
|||
|
|||
</div> |
|||
<div style="flex-basis: 32%;padding-top: 20px;"> |
|||
|
|||
<div style="width:30%; float:left;"> |
|||
<div style="width:75px;height:75px;background:#CE2D48; border-radius:100%;float: left;text-align: left;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/pos/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/odoo-index-industry-4.png" alt="Odoo Industry" style=" border-radius: 100%;width:100%;"/> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div style="width:70%;float:left;"> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 14px;font-weight:800;width: auto;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 4px;margin-left: 16px;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/pos/" target="_blank"> |
|||
POS</a> |
|||
</h3> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 13px;width: auto;margin: 0;margin-top:5px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 5px;margin-left: 16px;"> |
|||
Easy configuring and convivial selling. |
|||
</h3> |
|||
</div> |
|||
|
|||
</div> |
|||
<div style="flex-basis: 32%;padding-top: 20px;"> |
|||
|
|||
<div style="width:30%; float:left;"> |
|||
<div style="width:75px;height:75px;background:#CE2D48; border-radius:100%;float: left;text-align: left;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/ecommerce-website/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/odoo-index-industry-5.png" alt="Odoo Industry" style=" border-radius: 100%;width:100%;"/> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div style="width:70%;float:left;"> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 14px;font-weight:800;width: auto;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 0px;margin-left: 16px;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/ecommerce-website/" target="_blank"> |
|||
E-commerce & Website</a> |
|||
</h3> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 13px;width: auto;margin: 0;margin-top:5px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 5px;margin-left: 16px;"> |
|||
Mobile friendly, awe-inspiring product pages. |
|||
</h3> |
|||
</div> |
|||
</div> |
|||
<div style="flex-basis: 32%;padding-top: 20px;"> |
|||
|
|||
<div style="width:30%; float:left;"> |
|||
<div style="width:75px;height:75px;background:#CE2D48; border-radius:100%;float: left;text-align: left;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/hotel-management-erp/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/odoo-index-industry-6.png" alt="Odoo Industry" style=" border-radius: 100%;width:100%;"/> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div style="width:70%;float:left;"> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 14px;font-weight:800;width: auto;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 4px;margin-left: 16px;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/hotel-management-erp/" target="_blank"> |
|||
Hotel Management</a> |
|||
</h3> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 13px;width: auto;margin: 0;margin-top:5px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 5px;margin-left: 16px;"> |
|||
An all-inclusive hotel management application. |
|||
</h3> |
|||
</div> |
|||
</div> |
|||
<div style="flex-basis: 32%;padding-top: 20px;"> |
|||
|
|||
<div style="width:30%; float:left;"> |
|||
<div style="width:75px;height:75px;background:#CE2D48; border-radius:100%;float: left;text-align: left;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/education-erp-software/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/odoo-index-industry-7.png" alt="Odoo Industry" style=" border-radius: 100%;width:100%;"/> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div style="width:70%;float:left;"> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 14px;font-weight:800;width: auto;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 4px;margin-left: 16px;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/education-erp-software/" target="_blank"> |
|||
Education</a> |
|||
</h3> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 13px;width: auto;margin: 0;margin-top:5px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 5px;margin-left: 16px;"> |
|||
A Collaborative platform for educational management. |
|||
</h3> |
|||
</div> |
|||
</div> |
|||
<div style="flex-basis: 32%;padding-top: 20px;"> |
|||
|
|||
<div style="width:30%; float:left;"> |
|||
<div style="width:75px;height:75px;background:#CE2D48; border-radius:100%;float: left;text-align: left;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/service-management/" target="_blank"> |
|||
<img src="https://www.cybrosys.com/images/odoo-index-industry-8.png" alt="Odoo Industry" style=" border-radius: 100%;width:100%;"/> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div style="width:70%;float:left;"> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 14px;font-weight:800;width: auto;margin: 0;margin-top: 14px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 4px;margin-left: 16px;"> |
|||
<a href="https://www.cybrosys.com/odoo/industries/service-management/" target="_blank"> |
|||
Service Management</a> |
|||
</h3> |
|||
<h3 class="oe_slogan" style=" text-align: left;font-size: 13px;width: auto;margin: 0;margin-top:5px;color: #000 !important;margin-top: 5px;opacity: 1 !important;line-height: 17px;float: left;margin-top: 5px;margin-left: 16px;"> |
|||
Keep track of services and invoice accordingly. |
|||
</h3> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
<section class="oe_container" style="background-image:url(https://www.cybrosys.com/images/odoo-index-footer-bg.png); background-repeat:no-repeat; background-size:100%;padding: 13% 0% 6% 0%;"> |
|||
<div class="oe_slogan" style="margin-top:10px !important;margin-bottom: 0px;"> |
|||
<div> |
|||
<a style="color: #5c5c5c !important;border-radius: 0;background: none;border: none;background: #fff;box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62, 57, 107, 0.05);border-radius: 30px;font-size: 12px;padding: 9px 26px;margin-right: 9px;width: 200px;text-transform: capitalize;" class="btn btn-primary btn-lg mt8" style="color: #FFFFFF !important;border-radius: 0;" href="mailto:odoo@cybrosys.com"><i class="fa fa-envelope"></i> Email us </a> |
|||
<a style="color: #5c5c5c !important;border-radius: 0;background: none;border: none;background: #fff;box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62, 57, 107, 0.05);border-radius: 30px;font-size: 12px;padding: 9px 26px;margin-right: 9px;width: 200px;text-transform: capitalize;" class="btn btn-primary btn-lg mt8" style="color: #FFFFFF !important;border-radius: 0;" href="https://www.cybrosys.com/contact/"><i class="fa fa-phone"></i> Contact Us </a> |
|||
<a style="color: #5c5c5c !important;border-radius: 0;background: none;border: none;background: #fff;box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62, 57, 107, 0.05);border-radius: 30px;font-size: 12px;padding: 9px 26px;margin-right: 9px;width: 200px;text-transform: capitalize;" class="btn btn-primary btn-lg mt8" style="color: #FFFFFF !important;border-radius: 0;" href="https://www.cybrosys.com/contact/"><i class="fa fa-check-square"></i> Request Customization </a> |
|||
</div> |
|||
<br> |
|||
<img src="https://www.cybrosys.com/images/logo.png" style="width: 190px; margin-bottom: 25px;margin-top: 30px;" class="center-block"> |
|||
<div> |
|||
<a href="https://twitter.com/cybrosys" target="_blank"><i class="fa fa-2x fa-twitter" style="color:white;background: #00a0d1;width:35px;height: 35px;padding-top: 7px;font-size: 21px;margin-right: 6px;border-radius: 100%;"></i></a></td> |
|||
<a href="https://www.linkedin.com/company/cybrosys-technologies-pvt-ltd" target="_blank"><i class="fa fa-2x fa-linkedin" style="color:white;background: #31a3d6;width:35px;padding-left: 3px;height: 35px;padding-top: 7px;font-size: 21px;margin-right: 6px;border-radius: 100%;"></i></a></td> |
|||
<a href="https://www.facebook.com/cybrosystechnologies" target="_blank"><i class="fa fa-2x fa-facebook" style="color:white;background: #3b5998;width:35px; ;height: 35px;padding-top: 7px;font-size: 21px;margin-right: 6px;border-radius: 100%;"></i></a></td> |
|||
<a href="https://plus.google.com/106641282743045431892/about" target="_blank"><i class="fa fa-2x fa-google-plus" style="color:white;background: #c53c2c;width:35px;padding-left: 3px;height: 35px;padding-top: 7px;font-size: 21px;margin-right: 6px;border-radius: 100%;"></i></a></td> |
|||
<a href="https://in.pinterest.com/cybrosys" target="_blank"><i class="fa fa-2x fa-pinterest" style="color:white;background: #ac0f18;width:35px;padding-left: 3px;height: 35px;padding-top: 7px;font-size: 21px;margin-right: 6px;border-radius: 100%;"></i></a></td> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
|
|||
|
After Width: | Height: | Size: 79 KiB |
After Width: | Height: | Size: 112 KiB |
After Width: | Height: | Size: 67 KiB |
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 111 KiB |
After Width: | Height: | Size: 108 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 114 KiB |
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 103 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 116 KiB |
After Width: | Height: | Size: 62 KiB |
After Width: | Height: | Size: 103 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 83 KiB |
After Width: | Height: | Size: 80 KiB |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 78 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 66 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 54 KiB |
After Width: | Height: | Size: 78 KiB |
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<data> |
|||
<record id="lab_invoice_cust_invoice_view" model="ir.ui.view"> |
|||
<field name="name">account.invoice.cust.invoice_form</field> |
|||
<field name="model">account.invoice</field> |
|||
<field name="inherit_id" ref="account.invoice_form"/> |
|||
<field name="arch" type="xml"> |
|||
<xpath expr="//field[@name='date_invoice']" position="after"> |
|||
<field name="is_lab_invoice" invisible="1"/> |
|||
<field name="lab_request" /> |
|||
</xpath> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="lab_invoice_cust_invoice_filter_view" model="ir.ui.view"> |
|||
<field name="name">account.invoice.cust.invoice_filter_form</field> |
|||
<field name="model">account.invoice</field> |
|||
<field name="inherit_id" ref="account.view_account_invoice_filter"/> |
|||
<field name="arch" type="xml"> |
|||
<xpath expr="//field[@name='user_id']" position="after"> |
|||
<field name="lab_request"/> |
|||
</xpath> |
|||
<xpath expr="//group/filter[@name='status']" position="after"> |
|||
<filter string="Appointment" name="appointment" domain="[]" context="{'group_by':'lab_request'}"/> |
|||
</xpath> |
|||
</field> |
|||
</record> |
|||
</data> |
|||
</odoo> |
@ -0,0 +1,234 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<odoo> |
|||
<data> |
|||
<record model="ir.actions.act_window" id="lab_invoice_action"> |
|||
<field name="name">Invoices</field> |
|||
<field name="res_model">account.invoice</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">tree,form,kanban,calendar,graph,pivot</field> |
|||
<field name="view_id" ref="account.invoice_tree"/> |
|||
<field name="domain">[('is_lab_invoice','=',True)]</field> |
|||
<field name="search_view_id" ref="account.view_account_invoice_filter"/> |
|||
<field name="help" type="html"> |
|||
<p class="oe_view_nocontent_create"> |
|||
Create Invoices. |
|||
</p> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="lab_invoice_action_view_tree" model="ir.actions.act_window.view"> |
|||
<field name="sequence">1</field> |
|||
<field name="view_mode">tree</field> |
|||
<field name="act_window_id" ref="medical_lab_management.lab_invoice_action"/> |
|||
</record> |
|||
|
|||
<record id="lab_invoice_view_form" model="ir.actions.act_window.view"> |
|||
<field name="sequence">2</field> |
|||
<field name="view_mode">form</field> |
|||
<field name="view_id" ref="account.invoice_form"/> |
|||
<field name="act_window_id" ref="medical_lab_management.lab_invoice_action"/> |
|||
</record> |
|||
|
|||
<record model="ir.ui.view" id="kanban_view_lab_appointment"> |
|||
<field name="name">Appointment Kanban</field> |
|||
<field name="model">lab.appointment</field> |
|||
<field name="arch" type="xml"> |
|||
<kanban> |
|||
<templates> |
|||
<t t-name="kanban-box"> |
|||
<div class="oe_kanban_global_click"> |
|||
<div class="oe_kanban_details"> |
|||
<strong> |
|||
<ul> |
|||
<li>Name :<field name="patient_id"/></li> |
|||
<li>Lab Request ID :<field name="name"/></li> |
|||
<li>Appointment Date :<field name="appointment_date"/></li> |
|||
</ul> |
|||
</strong> |
|||
</div> |
|||
</div> |
|||
</t> |
|||
</templates> |
|||
</kanban> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="view_lab_appointment_tree" model="ir.ui.view"> |
|||
<field name="name">lab.appointment.tree</field> |
|||
<field name="model">lab.appointment</field> |
|||
<field name="priority" eval="8" /> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Appointments" colors="blue:state in ('sample_collection','test_in_progress');black:state == 'draft';gray:state in ('invoiced','cancelled');green:state == 'completed'"> |
|||
<field name="patient_id" /> |
|||
<field name="name" /> |
|||
<field name="state" /> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="view_lab_appointment_form" model="ir.ui.view"> |
|||
<field name="name">lab.appointment.form</field> |
|||
<field name="model">lab.appointment</field> |
|||
<field name="priority" eval="8" /> |
|||
<field name="arch" type="xml"> |
|||
<form string="Appointment"> |
|||
<header> |
|||
<button name="confirm_appointment" states="draft" string="Confirm" type="object" class="oe_highlight" /> |
|||
<button name="action_request" states="confirm" string="Request Lab" type="object" class="oe_highlight" /> |
|||
<button name="create_invoice" states="completed" string="Create Invoice" type="object" class="oe_highlight"/> |
|||
<button name="cancel_appointment" states="draft,confirm" string="Cancelled" type="object"/> |
|||
<field name="state" widget="statusbar" statusbar_visible="draft,confirm,request_lab,completed,to_invoice,invoiced" |
|||
/> |
|||
</header> |
|||
<sheet> |
|||
<div class="oe_button_box" name="button_box"> |
|||
<button name="%(act_open_lab_request_view)d" |
|||
type="action" |
|||
class="oe_stat_button" |
|||
icon="fa-building-o" |
|||
context = "{'search_default_app_id': [active_id]}" |
|||
attrs="{'invisible': [('request_count', '=', 0)]}"> |
|||
<field name="request_count" widget="statinfo" string="Lab Requests"/> |
|||
</button> |
|||
<button name="%(lab_invoice_action)d" |
|||
type="action" |
|||
class="oe_stat_button" |
|||
icon="fa-pencil-square-o" |
|||
context = "{'search_default_lab_request': [active_id]}" |
|||
attrs="{'invisible': [('inv_count', '=', 0)]}"> |
|||
<field name="inv_count" widget="statinfo" string="Lab Invoice"/> |
|||
</button> |
|||
</div> |
|||
<group> |
|||
<group col="4" colspan="4"> |
|||
<field name="patient_id" /> |
|||
<field name="priority" widget="priority"/> |
|||
<field name="name" /> |
|||
<field name="date" /> |
|||
<field name="appointment_date" /> |
|||
<field name="physician_id" domain="[('is_physician','=',True)]" context="{'search_default_is_physician':1, 'default_is_physician':1}"/> |
|||
</group> |
|||
</group> |
|||
<notebook colspan="4"> |
|||
<page string="Lab Requests"> |
|||
<field name="appointment_lines"> |
|||
<tree string="Lab Request" editable="bottom"> |
|||
<field name="lab_test"/> |
|||
<field name="cost"/> |
|||
</tree> |
|||
</field> |
|||
</page> |
|||
<page name="Note" |
|||
string="Note"> |
|||
<field name="comment"/> |
|||
</page> |
|||
</notebook> |
|||
</sheet> |
|||
<div class="oe_chatter"> |
|||
<field name="message_follower_ids" widget="mail_followers"/> |
|||
<field name="message_ids" widget="mail_thread"/> |
|||
</div> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="view_lab_appointment_search" model="ir.ui.view"> |
|||
<field name="name">lab.appointment.search</field> |
|||
<field name="model">lab.appointment</field> |
|||
<field name="priority" eval="8" /> |
|||
<field name="arch" type="xml"> |
|||
<search string="Appointment"> |
|||
<field name="patient_id" /> |
|||
<field name="date" /> |
|||
<field name="name" /> |
|||
<field name="physician_id" /> |
|||
<newline /> |
|||
<group expand="0" string="Group By..."> |
|||
<filter name="patient_id" string="Patient" |
|||
domain="[]" context="{'group_by':'patient_id'}" /> |
|||
<filter name="date" string="Date" |
|||
domain="[]" context="{'group_by':'date'}" /> |
|||
<filter name="appointment_date" string="Appointment date" |
|||
domain="[]" context="{'group_by':'appointment_date'}" /> |
|||
<filter name="physician_id" string="Physician" |
|||
domain="[]" context="{'group_by':'physician_id'}" /> |
|||
</group> |
|||
</search> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.actions.act_window" id="act_open_lab_appointment_view"> |
|||
<field name="name">Appointments</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">lab.appointment</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">tree,form,kanban</field> |
|||
<field name="search_view_id" ref="view_lab_appointment_search" /> |
|||
<field name="domain">[]</field> |
|||
<field name="context">{}</field> |
|||
<field name="help" type="html"> |
|||
<p class="oe_view_nocontent_create"> |
|||
Create Appointments. |
|||
</p> |
|||
</field> |
|||
</record> |
|||
|
|||
|
|||
<record model="ir.actions.act_window" id="act_open_lab_appointment_view_2"> |
|||
<field name="name">Appointments</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">lab.appointment</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">tree,form</field> |
|||
<field name="search_view_id" ref="view_lab_appointment_search" /> |
|||
<field name="domain">[('appointment_date', '>=',((datetime.date.today()- datetime.timedelta(days=0)).strftime('%Y-%m-%d 00:00:00'))), |
|||
('appointment_date', '<=',((datetime.date.today()- datetime.timedelta(days=0)).strftime('%Y-%m-%d 23:59:59')))] |
|||
</field> |
|||
<field name="context">{}</field> |
|||
<field name="help" type="html"> |
|||
<p class="oe_view_nocontent_create"> |
|||
Create Appointments. |
|||
</p> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.sequence" id="seq_lab_appointment"> |
|||
<field name="name">Appointment </field> |
|||
<field name="code">lab.appointment</field> |
|||
<field name="prefix">ID</field> |
|||
<field name="padding">3</field> |
|||
<field name="company_id" eval="False" /> |
|||
</record> |
|||
|
|||
|
|||
|
|||
<menuitem id="menu_lab_appointment" name="Appointments" sequence="11" |
|||
parent="menu_root_lab" groups="group_lab_management_user,group_lab_management_technician"/> |
|||
<menuitem id="menu_lab_appointment_child" name="Appointments" sequence="10" |
|||
parent="menu_lab_appointment" action="act_open_lab_appointment_view" |
|||
groups="group_lab_management_user,group_lab_management_technician"/> |
|||
<menuitem id="menu_lab_appointment_child_2" name=" Today's Appointments" sequence="11" |
|||
groups="group_lab_management_user,group_lab_management_technician" |
|||
parent="menu_lab_appointment" action="act_open_lab_appointment_view_2"/> |
|||
|
|||
<record id="view_lab_patient_form_inherit" model="ir.ui.view"> |
|||
<field name="name">lab.patient.form</field> |
|||
<field name="model">lab.patient</field> |
|||
<field name="inherit_id" ref="medical_lab_management.view_lab_patient_form" /> |
|||
<field name="arch" type="xml"> |
|||
<data> |
|||
<xpath expr="//div[@name='button_box']" position="inside"> |
|||
<button name="%(act_open_lab_appointment_view)d" |
|||
type="action" |
|||
class="oe_stat_button" |
|||
icon="fa-building-o" |
|||
context = "{'search_default_patient_id': [active_id], 'default_patient_id':[active_id]}" > |
|||
<field name="app_count" widget="statinfo" string="Appointments"/> |
|||
|
|||
</button> |
|||
</xpath> |
|||
</data> |
|||
</field> |
|||
</record> |
|||
</data> |
|||
</odoo> |
@ -0,0 +1,160 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<odoo> |
|||
<data> |
|||
<menuitem id="menu_root_lab" name="Laboratory" sequence="40" |
|||
groups="group_lab_management_user,group_lab_management_technician"/> |
|||
<record model="ir.ui.view" id="kanban_view_patient"> |
|||
<field name="name">Patient Kanban</field> |
|||
<field name="model">lab.patient</field> |
|||
<field name="arch" type="xml"> |
|||
<kanban> |
|||
<field name='id'/> |
|||
<templates> |
|||
<t t-name="kanban-box"> |
|||
<div class="oe_kanban_global_click"> |
|||
<div class="o_kanban_image"> |
|||
<img t-att-src="kanban_image('lab.patient', 'patient_image', record.id.value)"/> |
|||
</div> |
|||
<div class="oe_kanban_details"> |
|||
<strong> |
|||
<ul> |
|||
<li>Name :<field name="patient"/></li> |
|||
<li>Patient ID :<field name="name"/></li> |
|||
</ul> |
|||
</strong> |
|||
</div> |
|||
</div> |
|||
</t> |
|||
</templates> |
|||
</kanban> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="view_lab_patient_tree" model="ir.ui.view"> |
|||
<field name="name">lab.patient.tree</field> |
|||
<field name="model">lab.patient</field> |
|||
<field name="priority" eval="8" /> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Patient"> |
|||
<field name="title" /> |
|||
<field name="patient" /> |
|||
<field name="name" /> |
|||
<field name="phone"/> |
|||
<field name="email"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="view_lab_patient_form" model="ir.ui.view"> |
|||
<field name="name">lab.patient.form</field> |
|||
<field name="model">lab.patient</field> |
|||
<field name="priority" eval="8" /> |
|||
<field name="arch" type="xml"> |
|||
<form string="Patient"> |
|||
<sheet> |
|||
<div class="oe_button_box" name="button_box"> |
|||
</div> |
|||
<field name="patient_image" widget="image" class="oe_avatar"/> |
|||
<div name="title_name" class="oe_title"> |
|||
<h3> |
|||
<field name="title" |
|||
style="width: 30%%" /> |
|||
</h3> |
|||
<h1> |
|||
<table> |
|||
<tr> |
|||
<td> |
|||
<field name="patient" |
|||
required="1" |
|||
placeholder="FullName" |
|||
style="padding-right:10px" |
|||
domain="[('is_patient','=',True)]" context="{'search_default_is_patient':1, 'default_is_patient':1, 'default_customer':1}" |
|||
/> |
|||
</td> |
|||
</tr> |
|||
</table> |
|||
</h1> |
|||
</div> |
|||
<group> |
|||
<group> |
|||
<field name="name" /> |
|||
<field name="gender" /> |
|||
<field name="dob" /> |
|||
<field name="age"/> |
|||
<field name="phone"/> |
|||
</group> |
|||
<group> |
|||
<field name="visa_info"/> |
|||
<field name="id_proof_number"/> |
|||
<field name="date" invisible="1"/> |
|||
<field name="blood_group"/> |
|||
<field name="email"/> |
|||
</group> |
|||
</group> |
|||
<notebook> |
|||
<page string="Note"> |
|||
<group> |
|||
<field name="note"/> |
|||
</group> |
|||
</page> |
|||
</notebook> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="view_lab_patient_search" model="ir.ui.view"> |
|||
<field name="name">lab.patient.search</field> |
|||
<field name="model">lab.patient</field> |
|||
<field name="priority" eval="8" /> |
|||
<field name="arch" type="xml"> |
|||
<search string="Patient"> |
|||
<field name="patient" /> |
|||
<field name="blood_group" /> |
|||
<field name="name" /> |
|||
<newline /> |
|||
<group expand="0" string="Group By..."> |
|||
<filter name="blood_group" string="Blood Group" |
|||
domain="[]" context="{'group_by':'blood_group'}" /> |
|||
<filter name="name" string="Patient ID" |
|||
domain="[]" context="{'group_by':'name'}" /> |
|||
<filter name="patient" string="Patient" |
|||
domain="[]" context="{'group_by':'patient'}" /> |
|||
</group> |
|||
</search> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.actions.act_window" id="act_open_lab_patient_view"> |
|||
<field name="name">Patients</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">lab.patient</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">kanban,tree,form</field> |
|||
<field name="search_view_id" ref="view_lab_patient_search" /> |
|||
<field name="domain">[]</field> |
|||
<field name="context">{}</field> |
|||
<field name="help" type="html"> |
|||
<p class="oe_view_nocontent_create"> |
|||
Create Patients. |
|||
</p> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.sequence" id="seq_lab_patient"> |
|||
<field name="name">Patient</field> |
|||
<field name="code">lab.patient</field> |
|||
<field name="prefix">PID</field> |
|||
<field name="padding">3</field> |
|||
<field name="company_id" eval="False" /> |
|||
</record> |
|||
|
|||
<menuitem id="menu_lab_patient" name="Patient" sequence="10" |
|||
parent="menu_root_lab" groups="group_lab_management_user,group_lab_management_technician"/> |
|||
<menuitem id="menu_lab_patient_child" name="Patient" sequence="10" |
|||
parent="menu_lab_patient" action="act_open_lab_patient_view" |
|||
groups="group_lab_management_user,group_lab_management_technician"/> |
|||
|
|||
|
|||
</data> |
|||
</odoo> |
@ -0,0 +1,121 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<odoo> |
|||
<data> |
|||
<record id="view_lab_request_tree" model="ir.ui.view"> |
|||
<field name="name">lab.request.tree</field> |
|||
<field name="model">lab.request</field> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Lab Request" colors="green:state in ('sample_collection','test_in_progress');black:state == 'completed';gray:state == 'cancelled';blue:state == 'draft'"> |
|||
<field name="name" /> |
|||
<field name="lab_requestor" /> |
|||
<field name="lab_request_id" /> |
|||
<field name="test_request" /> |
|||
<field name="state" /> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
<record id="view_lab_reques_form" model="ir.ui.view"> |
|||
<field name="name">lab.request.form</field> |
|||
<field name="model">lab.request</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="Lab Request"> |
|||
<header> |
|||
<button name="set_to_sample_collection" states="draft" string="Sample Collection" type="object" class="oe_highlight"/> |
|||
<button name="set_to_test_in_progress" states="sample_collection" string="Test In Progress" type="object" class="oe_highlight"/> |
|||
<button name="set_to_test_completed" states="test_in_progress" string="Complete Test" type="object" class="oe_highlight"/> |
|||
<button name="print_lab_test" states="completed,invoiced" string="Print Lab Test" type="object" class="oe_highlight"/> |
|||
<button name="cancel_lab_test" states="draft" string="Cancel" type="object"/> |
|||
<field name="state" widget="statusbar" statusbar_visible="draft,sample_collection,test_in_progress,completed" statusbar_colors='{"Completed":"blue","Test In Progress":"red","Invoiced":"grey"}'/> |
|||
</header> |
|||
<sheet> |
|||
<div class="oe_left" style="width: 500px;"> |
|||
<div class="oe_title" style="width: 390px;"> |
|||
<label class="oe_edit_only" for="name"/> |
|||
<h1><field name="name" class="oe_inline"/></h1> |
|||
</div> |
|||
</div> |
|||
<group> |
|||
<group col="4" colspan="4"> |
|||
<field name="lab_requestor" attrs="{'readonly': [('state', '!=', 'draft')]}"/> |
|||
<field name="lab_request_id"/> |
|||
<field name="lab_requesting_date" /> |
|||
<field name="test_request"/> |
|||
<field name="app_id" invisible="1"/> |
|||
</group> |
|||
</group> |
|||
<notebook colspan="4"> |
|||
<page string="Test lines"> |
|||
<field name="request_line"> |
|||
<tree string="Test lines" editable="bottom"> |
|||
<field name="test_content" /> |
|||
<field name="unit"/> |
|||
<field name="interval"/> |
|||
<field name="result"/> |
|||
</tree> |
|||
</field> |
|||
</page> |
|||
<page name="Note" |
|||
string="Note"> |
|||
<field name="comment"/> |
|||
</page> |
|||
</notebook> |
|||
</sheet> |
|||
<div class="oe_chatter"> |
|||
<field name="message_follower_ids" widget="mail_followers" groups="base.group_user"/> |
|||
<field name="message_ids" widget="mail_thread"/> |
|||
</div> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
<record id="view_lab_requester_search" model="ir.ui.view"> |
|||
<field name="name">lab.request.search</field> |
|||
<field name="model">lab.request</field> |
|||
<field name="priority" eval="8" /> |
|||
<field name="arch" type="xml"> |
|||
<search string="Lab Request"> |
|||
<field name="lab_requestor" /> |
|||
<field name="lab_request_id" /> |
|||
<field name="app_id" /> |
|||
<newline /> |
|||
<group expand="0" string="Group By..."> |
|||
<filter name="lab_requestor" string="Patient" |
|||
domain="[]" context="{'group_by':'lab_requestor'}" /> |
|||
<filter name="lab_request_id" string="Date" |
|||
domain="[]" context="{'group_by':'lab_request_id'}" /> |
|||
</group> |
|||
</search> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.actions.act_window" id="act_open_lab_request_view"> |
|||
<field name="name">Lab Request</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">lab.request</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">tree,form</field> |
|||
<field name="search_view_id" ref="view_lab_requester_search" /> |
|||
<field name="domain">[]</field> |
|||
<field name="context">{}</field> |
|||
<field name="help" type="html"> |
|||
<p class="oe_view_nocontent_create"> |
|||
Create Lab request. |
|||
</p> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.sequence" id="seq_lab_request"> |
|||
<field name="name">Lab Request</field> |
|||
<field name="code">lab.request</field> |
|||
<field name="prefix">LR</field> |
|||
<field name="padding">3</field> |
|||
<field name="company_id" eval="False" /> |
|||
</record> |
|||
|
|||
<menuitem id="menu_lab_request" name="Lab Request" sequence="12" |
|||
parent="menu_root_lab" |
|||
groups="group_lab_management_user,group_lab_management_technician"/> |
|||
<menuitem id="menu_lab_request_child" name="Lab Request" sequence="10" |
|||
parent="menu_lab_request" action="act_open_lab_request_view" |
|||
groups="group_lab_management_user,group_lab_management_technician"/> |
|||
</data> |
|||
</odoo> |
@ -0,0 +1,73 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<odoo> |
|||
<data> |
|||
<record id="view_lab_content_tree" model="ir.ui.view"> |
|||
<field name="name">lab.test.content_type.tree</field> |
|||
<field name="model">lab.test.content_type</field> |
|||
<field name="priority" eval="8" /> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Contents"> |
|||
<field name="content_type_name" /> |
|||
<field name="content_type_code" /> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="view_lab_content_form" model="ir.ui.view"> |
|||
<field name="name">lab.test.content_type.form</field> |
|||
<field name="model">lab.test.content_type</field> |
|||
<field name="priority" eval="8" /> |
|||
<field name="arch" type="xml"> |
|||
<form string="Contents"> |
|||
<sheet> |
|||
<group> |
|||
<group col="4" colspan="4"> |
|||
<field name="content_type_name" /> |
|||
<field name="content_type_code" /> |
|||
</group> |
|||
</group> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="view_lab_content_search" model="ir.ui.view"> |
|||
<field name="name">lab.test.content_type.search</field> |
|||
<field name="model">lab.test.content_type</field> |
|||
<field name="priority" eval="8" /> |
|||
<field name="arch" type="xml"> |
|||
<search string="Test Content"> |
|||
<field name="content_type_name" /> |
|||
<field name="content_type_code" /> |
|||
<newline /> |
|||
<group expand="0" string="Group By..."> |
|||
<filter name="content_type_name" string="Content" |
|||
domain="[]" context="{'group_by':'content_type_name'}" /> |
|||
<filter name="content_type_code" string="Content Code" |
|||
domain="[]" context="{'group_by':'content_type_code'}" /> |
|||
</group> |
|||
</search> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.actions.act_window" id="act_open_lab_content_view"> |
|||
<field name="name">Test Contents</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">lab.test.content_type</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">tree,form</field> |
|||
<field name="domain">[]</field> |
|||
<field name="search_view_id" ref="view_lab_content_search" /> |
|||
<field name="context">{}</field> |
|||
<field name="help" type="html"> |
|||
<p class="oe_view_nocontent_create"> |
|||
Create Test Contents. |
|||
</p> |
|||
</field> |
|||
</record> |
|||
|
|||
<menuitem id="menu_lab_content" name="Test Content" sequence="10" |
|||
parent="configuration_id" action="act_open_lab_content_view" |
|||
groups="group_lab_management_user,group_lab_management_technician"/> |
|||
</data> |
|||
</odoo> |
@ -0,0 +1,103 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<odoo> |
|||
<data> |
|||
<record id="view_lab_test_tree" model="ir.ui.view"> |
|||
<field name="name">lab.test.tree</field> |
|||
<field name="model">lab.test</field> |
|||
<field name="priority" eval="8" /> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Lab Test"> |
|||
<field name="lab_test" /> |
|||
<field name="lab_test_code" /> |
|||
<field name="test_cost" /> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="view_lab_test_form" model="ir.ui.view"> |
|||
<field name="name">lab.test.form</field> |
|||
<field name="model">lab.test</field> |
|||
<field name="priority" eval="8" /> |
|||
<field name="arch" type="xml"> |
|||
<form string="Lab Test"> |
|||
<sheet> |
|||
<group> |
|||
<group col="4" colspan="4"> |
|||
<field name="lab_test" /> |
|||
<field name="lab_test_code"/> |
|||
<field name="test_cost" /> |
|||
</group> |
|||
</group> |
|||
<notebook> |
|||
<page string="Lab Test Type" style="overflow-x:scroll;"> |
|||
<group> |
|||
<field name="test_lines" nolabel="1"> |
|||
<tree string="Lab Test Type" editable="bottom"> |
|||
<field name="test_content" /> |
|||
<field name="unit"/> |
|||
<field name="interval"/> |
|||
</tree> |
|||
</field> |
|||
</group> |
|||
</page> |
|||
</notebook> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="view_lab_test_search" model="ir.ui.view"> |
|||
<field name="name">lab.test.search</field> |
|||
<field name="model">lab.test</field> |
|||
<field name="priority" eval="8" /> |
|||
<field name="arch" type="xml"> |
|||
<search string="Lab Test"> |
|||
<field name="lab_test" /> |
|||
<newline /> |
|||
<group expand="0" string="Group By..."> |
|||
<filter name="lab_test" string="Test" |
|||
domain="[]" context="{'group_by':'lab_test'}" /> |
|||
</group> |
|||
</search> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.actions.act_window" id="act_open_lab_test_view"> |
|||
<field name="name">Lab Test</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">lab.test</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">tree,form</field> |
|||
<field name="search_view_id" ref="view_lab_test_search" /> |
|||
<field name="domain">[]</field> |
|||
<field name="context">{}</field> |
|||
<field name="help" type="html"> |
|||
<p class="oe_view_nocontent_create"> |
|||
Create Lab Tests. |
|||
</p> |
|||
</field> |
|||
</record> |
|||
|
|||
<menuitem id="menu_lab_test" name="Lab Test" sequence="1" |
|||
parent="configuration_id" action="act_open_lab_test_view" |
|||
groups="group_lab_management_user,group_lab_management_technician"/> |
|||
|
|||
<record id="view_lab_test_attribute_form" model="ir.ui.view"> |
|||
<field name="name">lab.test.attribute.form</field> |
|||
<field name="model">lab.test.attribute</field> |
|||
<field name="priority" eval="8" /> |
|||
<field name="arch" type="xml"> |
|||
<form string="Lab Test Type Attribute"> |
|||
<group> |
|||
<group col="4" colspan="4"> |
|||
<field name="test_content" /> |
|||
<field name="result"/> |
|||
<field name="unit" /> |
|||
<field name="interval"/> |
|||
</group> |
|||
</group> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
</data> |
|||
</odoo> |
@ -0,0 +1,27 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<data> |
|||
<record model="ir.actions.act_window" id="action_physician"> |
|||
<field name="name">Physician</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">res.partner</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">tree,form</field> |
|||
<field name="domain">[('is_physician','=',1)]</field> |
|||
<field name="context">{'default_customer':0, 'default_supplier':0 , 'default_is_physician':1}</field> |
|||
<field name="filter" eval="True"/> |
|||
<field name="help" type="html"> |
|||
<p class="oe_view_nocontent_create"> |
|||
Click to add physician. |
|||
</p> |
|||
</field> |
|||
</record> |
|||
|
|||
<menuitem id="menu_physician" name="Referrals From" sequence="18" |
|||
parent="menu_root_lab" |
|||
groups="group_lab_management_user,group_lab_management_technician"/> |
|||
<menuitem id="menu_physician_child" name="Physician" sequence="1" |
|||
parent="menu_physician" action="action_physician" |
|||
groups="group_lab_management_user,group_lab_management_technician"/> |
|||
</data> |
|||
</odoo> |
@ -0,0 +1,18 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<data> |
|||
<record id="physician_speciality_view_form" model="ir.ui.view"> |
|||
<field name="name">physician.speciality.form</field> |
|||
<field name="model">physician.speciality</field> |
|||
<field name="priority" eval="8" /> |
|||
<field name="arch" type="xml"> |
|||
<form string="Specialty"> |
|||
<group> |
|||
<field name="code" /> |
|||
<field name="name" /> |
|||
</group> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
</data> |
|||
</odoo> |
@ -0,0 +1,22 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<odoo> |
|||
<data> |
|||
<record id="view_res_partner_inherit" model="ir.ui.view"> |
|||
<field name="name">res.partner.form</field> |
|||
<field name="model">res.partner</field> |
|||
<field name="inherit_id" ref="base.view_partner_form"/> |
|||
<field name="arch" type="xml"> |
|||
<notebook position="inside"> |
|||
<page string="Lab" groups="base.group_user"> |
|||
<group> |
|||
<field name="is_patient"/> |
|||
<field name="is_physician"/> |
|||
<field name="speciality" attrs="{'invisible': [('is_physician', '=', False)]}"/> |
|||
<field name="hospital" attrs="{'invisible': [('is_physician', '=', False)]}"/> |
|||
</group> |
|||
</page> |
|||
</notebook> |
|||
</field> |
|||
</record> |
|||
</data> |
|||
</odoo> |
@ -0,0 +1,72 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<odoo> |
|||
<data> |
|||
<record id="view_test_unit_tree" model="ir.ui.view"> |
|||
<field name="name">test.unit.tree</field> |
|||
<field name="model">test.unit</field> |
|||
<field name="priority" eval="8" /> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Test Unit"> |
|||
<field name="unit" /> |
|||
<field name="code" /> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
<record id="view_test_unit_form" model="ir.ui.view"> |
|||
<field name="name">test.unit.form</field> |
|||
<field name="model">test.unit</field> |
|||
<field name="priority" eval="8" /> |
|||
<field name="arch" type="xml"> |
|||
<form string="Test Unit"> |
|||
<sheet> |
|||
<group> |
|||
<group> |
|||
<field name="unit" /> |
|||
</group> |
|||
<group> |
|||
<field name="code" /> |
|||
</group> |
|||
</group> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
<record id="view_test_unit_search" model="ir.ui.view"> |
|||
<field name="name">test.unit.search</field> |
|||
<field name="model">test.unit</field> |
|||
<field name="priority" eval="8" /> |
|||
<field name="arch" type="xml"> |
|||
<search string="Testing Unit"> |
|||
<field name="unit" /> |
|||
<group expand="0" string="Group By..."> |
|||
<filter name="unit" string="Blood Group"></filter> |
|||
</group> |
|||
</search> |
|||
</field> |
|||
</record> |
|||
<record model="ir.actions.act_window" id="act_open_test_unit_view"> |
|||
<field name="name">Testing Units</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">test.unit</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">tree,form</field> |
|||
<field name="search_view_id" ref="view_test_unit_search" /> |
|||
<field name="domain">[]</field> |
|||
<field name="context">{}</field> |
|||
<field name="help" type="html"> |
|||
<p class="oe_view_nocontent_create"> |
|||
Create Testing Units. |
|||
</p> |
|||
</field> |
|||
</record> |
|||
<menuitem id="configuration_id" |
|||
name="Configuration" |
|||
parent="menu_root_lab" |
|||
sequence="100"/> |
|||
<menuitem name="Testing Unit" |
|||
id="test_unit_conf" |
|||
parent="configuration_id" |
|||
action="act_open_test_unit_view" |
|||
sequence="20" /> |
|||
</data> |
|||
</odoo> |
@ -0,0 +1,32 @@ |
|||
Product Return In POS |
|||
===================== |
|||
POS Order Return. |
|||
|
|||
Installation |
|||
============ |
|||
- www.odoo.com/documentation/12.0/setup/install.html |
|||
- Install our custom addon |
|||
|
|||
License |
|||
======= |
|||
GNU AFFERO GENERAL PUBLIC LICENSE, Version 3 (AGPLv3) |
|||
(http://www.gnu.org/licenses/agpl.html) |
|||
|
|||
Bug Tracker |
|||
=========== |
|||
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. |
|||
|
|||
Credits |
|||
======= |
|||
* Cybrosys Techno Solutions <https://www.cybrosys.com> |
|||
|
|||
|
|||
Developer: Anusha P P - odoo@cybrosys.com |
|||
|
|||
Maintainer |
|||
---------- |
|||
|
|||
This module is maintained by Cybrosys Technologies. |
|||
|
|||
For support and more information, please visit https://www.cybrosys.com. |
|||
|
@ -0,0 +1 @@ |
|||
from . import models |
@ -0,0 +1,41 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2017-TODAY Cybrosys Technologies(<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 <https://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################### |
|||
{ |
|||
'name': 'Product Return In POS', |
|||
'version': '12.0.0.1.0', |
|||
'category': 'Point of Sale', |
|||
'summary': 'POS Order Return', |
|||
'author': 'Cybrosys Techno Solutions', |
|||
'company': 'Cybrosys Techno Solutions', |
|||
'maintainer': 'Cybrosys Techno Solutions', |
|||
'images': ['static/description/banner.jpg'], |
|||
'website': 'https://www.cybrosys.com', |
|||
'depends': ['point_of_sale'], |
|||
'data': [ |
|||
'views/return.xml', |
|||
'views/pos_template.xml', |
|||
], |
|||
'qweb': ['static/src/xml/*.xml'], |
|||
'license': 'AGPL-3', |
|||
'installable': True, |
|||
'auto_install': False, |
|||
'application': False, |
|||
|
|||
} |