Browse Source

[ADD] Initial Commit

pull/124/head
Ajmalcybrosys 6 years ago
parent
commit
10cd29b85e
  1. 36
      hr_zk_attendance/README.rst
  2. 22
      hr_zk_attendance/__init__.py
  3. 45
      hr_zk_attendance/__manifest__.py
  4. 15
      hr_zk_attendance/data/download_data.xml
  5. 6
      hr_zk_attendance/doc/RELEASE_NOTES.md
  6. 25
      hr_zk_attendance/models/__init__.py
  7. 106
      hr_zk_attendance/models/machine_analysis.py
  8. 280
      hr_zk_attendance/models/zk_machine.py
  9. 119
      hr_zk_attendance/models/zkattendance.py
  10. 64
      hr_zk_attendance/models/zkconnect.py
  11. 71
      hr_zk_attendance/models/zkconst.py
  12. 82
      hr_zk_attendance/models/zkdevice.py
  13. 56
      hr_zk_attendance/models/zkextendfmt.py
  14. 62
      hr_zk_attendance/models/zkextendoplog.py
  15. 44
      hr_zk_attendance/models/zkface.py
  16. 156
      hr_zk_attendance/models/zklib.py
  17. 23
      hr_zk_attendance/models/zkos.py
  18. 23
      hr_zk_attendance/models/zkpin.py
  19. 43
      hr_zk_attendance/models/zkplatform.py
  20. 23
      hr_zk_attendance/models/zkserialnumber.py
  21. 23
      hr_zk_attendance/models/zkssr.py
  22. 50
      hr_zk_attendance/models/zktime.py
  23. 140
      hr_zk_attendance/models/zkuser.py
  24. 23
      hr_zk_attendance/models/zkversion.py
  25. 23
      hr_zk_attendance/models/zkworkcode.py
  26. 4
      hr_zk_attendance/security/ir.model.access.csv
  27. BIN
      hr_zk_attendance/static/description/banner.gif
  28. BIN
      hr_zk_attendance/static/description/cybro_logo.png
  29. BIN
      hr_zk_attendance/static/description/hr_zk_attendance_cybrosys_1.png
  30. BIN
      hr_zk_attendance/static/description/hr_zk_attendance_cybrosys_2.png
  31. BIN
      hr_zk_attendance/static/description/hr_zk_attendance_cybrosys_3.png
  32. BIN
      hr_zk_attendance/static/description/hr_zk_attendance_cybrosys_4.png
  33. BIN
      hr_zk_attendance/static/description/hr_zk_attendance_cybrosys_5.png
  34. BIN
      hr_zk_attendance/static/description/hr_zk_attendance_cybrosys_6.png
  35. BIN
      hr_zk_attendance/static/description/icon.png
  36. 412
      hr_zk_attendance/static/description/index.html
  37. 71
      hr_zk_attendance/views/zk_machine_attendance_view.xml
  38. 69
      hr_zk_attendance/views/zk_machine_view.xml
  39. 38
      medical_lab_management/README.rst
  40. 22
      medical_lab_management/__init__.py
  41. 55
      medical_lab_management/__manifest__.py
  42. 19
      medical_lab_management/models/__init__.py
  43. 24
      medical_lab_management/models/account_invoice.py
  44. 179
      medical_lab_management/models/lab_appointment.py
  45. 65
      medical_lab_management/models/lab_patient.py
  46. 120
      medical_lab_management/models/lab_request.py
  47. 23
      medical_lab_management/models/lab_test_content_type.py
  48. 32
      medical_lab_management/models/lab_test_type.py
  49. 21
      medical_lab_management/models/physician_speciality.py
  50. 20
      medical_lab_management/models/res_partner.py
  51. 18
      medical_lab_management/models/testing_unit.py
  52. 60
      medical_lab_management/report/lab_patient_card.xml
  53. 54
      medical_lab_management/report/lab_test_report.xml
  54. 23
      medical_lab_management/report/report.xml
  55. 19
      medical_lab_management/security/ir.model.access.csv
  56. 20
      medical_lab_management/security/lab_users.xml
  57. BIN
      medical_lab_management/static/description/app.png
  58. BIN
      medical_lab_management/static/description/banner.jpg
  59. BIN
      medical_lab_management/static/description/card.png
  60. BIN
      medical_lab_management/static/description/content.png
  61. BIN
      medical_lab_management/static/description/cybro_logo.png
  62. BIN
      medical_lab_management/static/description/icon.png
  63. 446
      medical_lab_management/static/description/index.html
  64. BIN
      medical_lab_management/static/description/invoice.png
  65. BIN
      medical_lab_management/static/description/lab-management-cybrosys-1.png
  66. BIN
      medical_lab_management/static/description/lab-management-cybrosys-10.png
  67. BIN
      medical_lab_management/static/description/lab-management-cybrosys-11.png
  68. BIN
      medical_lab_management/static/description/lab-management-cybrosys-12.png
  69. BIN
      medical_lab_management/static/description/lab-management-cybrosys-13.png
  70. BIN
      medical_lab_management/static/description/lab-management-cybrosys-2.png
  71. BIN
      medical_lab_management/static/description/lab-management-cybrosys-3.png
  72. BIN
      medical_lab_management/static/description/lab-management-cybrosys-4.png
  73. BIN
      medical_lab_management/static/description/lab-management-cybrosys-5.png
  74. BIN
      medical_lab_management/static/description/lab-management-cybrosys-6.png
  75. BIN
      medical_lab_management/static/description/lab-management-cybrosys-7.png
  76. BIN
      medical_lab_management/static/description/lab-management-cybrosys-8.png
  77. BIN
      medical_lab_management/static/description/lab-management-cybrosys-9.png
  78. BIN
      medical_lab_management/static/description/mail.png
  79. BIN
      medical_lab_management/static/description/patient.png
  80. BIN
      medical_lab_management/static/description/phy.png
  81. BIN
      medical_lab_management/static/description/request1.png
  82. BIN
      medical_lab_management/static/description/request2.png
  83. BIN
      medical_lab_management/static/description/result.png
  84. BIN
      medical_lab_management/static/description/test.png
  85. BIN
      medical_lab_management/static/description/today.png
  86. BIN
      medical_lab_management/static/description/unit.png
  87. BIN
      medical_lab_management/static/description/user.png
  88. 30
      medical_lab_management/views/account_invoice.xml
  89. 234
      medical_lab_management/views/lab_appointment.xml
  90. 160
      medical_lab_management/views/lab_patient_view.xml
  91. 121
      medical_lab_management/views/lab_request.xml
  92. 73
      medical_lab_management/views/lab_test_content_type.xml
  93. 103
      medical_lab_management/views/lab_test_type.xml
  94. 27
      medical_lab_management/views/physician_details.xml
  95. 18
      medical_lab_management/views/physician_specialty.xml
  96. 22
      medical_lab_management/views/res_partner.xml
  97. 72
      medical_lab_management/views/test_unit_view.xml
  98. 32
      product_return_pos/README.md
  99. 1
      product_return_pos/__init__.py
  100. 41
      product_return_pos/__manifest__.py

36
hr_zk_attendance/README.rst

@ -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

22
hr_zk_attendance/__init__.py

@ -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

45
hr_zk_attendance/__manifest__.py

@ -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,
}

15
hr_zk_attendance/data/download_data.xml

@ -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>

6
hr_zk_attendance/doc/RELEASE_NOTES.md

@ -0,0 +1,6 @@
## Module <hr_zk_attendance>
#### 24.04.2019
#### Version 12.0.1.0.0
##### ADD
- Initial commit

25
hr_zk_attendance/models/__init__.py

@ -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

106
hr_zk_attendance/models/machine_analysis.py

@ -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)

280
hr_zk_attendance/models/zk_machine.py

@ -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.'))

119
hr_zk_attendance/models/zkattendance.py

@ -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

64
hr_zk_attendance/models/zkconnect.py

@ -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 )

71
hr_zk_attendance/models/zkconst.py

@ -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

82
hr_zk_attendance/models/zkdevice.py

@ -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

56
hr_zk_attendance/models/zkextendfmt.py

@ -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:]

62
hr_zk_attendance/models/zkextendoplog.py

@ -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:]

44
hr_zk_attendance/models/zkface.py

@ -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

156
hr_zk_attendance/models/zklib.py

@ -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)

23
hr_zk_attendance/models/zkos.py

@ -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

23
hr_zk_attendance/models/zkpin.py

@ -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

43
hr_zk_attendance/models/zkplatform.py

@ -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

23
hr_zk_attendance/models/zkserialnumber.py

@ -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

23
hr_zk_attendance/models/zkssr.py

@ -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

50
hr_zk_attendance/models/zktime.py

@ -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

140
hr_zk_attendance/models/zkuser.py

@ -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

23
hr_zk_attendance/models/zkversion.py

@ -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

23
hr_zk_attendance/models/zkworkcode.py

@ -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

4
hr_zk_attendance/security/ir.model.access.csv

@ -0,0 +1,4 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_hr_zk_machine_user,zk.machine.hr_biometric_machine,model_zk_machine,hr_attendance.group_hr_attendance_user,1,1,1,1
access_hr_zk_machine_user1,zk.machine.hr_biometric_machine1,model_zk_machine_attendance,hr_attendance.group_hr_attendance_user,1,1,1,1
access_hr_zk_machine_user2,zk.machine.hr_biometric_machine2,model_zk_report_daily_attendance,hr_attendance.group_hr_attendance_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_hr_zk_machine_user zk.machine.hr_biometric_machine model_zk_machine hr_attendance.group_hr_attendance_user 1 1 1 1
3 access_hr_zk_machine_user1 zk.machine.hr_biometric_machine1 model_zk_machine_attendance hr_attendance.group_hr_attendance_user 1 1 1 1
4 access_hr_zk_machine_user2 zk.machine.hr_biometric_machine2 model_zk_report_daily_attendance hr_attendance.group_hr_attendance_user 1 1 1 1

BIN
hr_zk_attendance/static/description/banner.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 KiB

BIN
hr_zk_attendance/static/description/cybro_logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
hr_zk_attendance/static/description/hr_zk_attendance_cybrosys_1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

BIN
hr_zk_attendance/static/description/hr_zk_attendance_cybrosys_2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

BIN
hr_zk_attendance/static/description/hr_zk_attendance_cybrosys_3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

BIN
hr_zk_attendance/static/description/hr_zk_attendance_cybrosys_4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

BIN
hr_zk_attendance/static/description/hr_zk_attendance_cybrosys_5.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

BIN
hr_zk_attendance/static/description/hr_zk_attendance_cybrosys_6.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

BIN
hr_zk_attendance/static/description/icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

412
hr_zk_attendance/static/description/index.html

@ -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>

71
hr_zk_attendance/views/zk_machine_attendance_view.xml

@ -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', '&gt;=', datetime.datetime.now().replace(hour=0, minute=0, second=0)),('punching_time', '&lt;=', datetime.datetime.now().replace(hour=23, minute=59, second=59))]" />
<filter string="Current Month" name="month" domain="[('punching_time', '&gt;=', 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>

69
hr_zk_attendance/views/zk_machine_view.xml

@ -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>

38
medical_lab_management/README.rst

@ -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

22
medical_lab_management/__init__.py

@ -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

55
medical_lab_management/__manifest__.py

@ -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,
}

19
medical_lab_management/models/__init__.py

@ -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

24
medical_lab_management/models/account_invoice.py

@ -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

179
medical_lab_management/models/lab_appointment.py

@ -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)])

65
medical_lab_management/models/lab_patient.py

@ -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

120
medical_lab_management/models/lab_request.py

@ -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')],
}

23
medical_lab_management/models/lab_test_content_type.py

@ -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")

32
medical_lab_management/models/lab_test_type.py

@ -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")

21
medical_lab_management/models/physician_speciality.py

@ -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!'),
]

20
medical_lab_management/models/res_partner.py

@ -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')

18
medical_lab_management/models/testing_unit.py

@ -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)

60
medical_lab_management/report/lab_patient_card.xml

@ -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>

54
medical_lab_management/report/lab_test_report.xml

@ -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>

23
medical_lab_management/report/report.xml

@ -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>

19
medical_lab_management/security/ir.model.access.csv

@ -0,0 +1,19 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_lab_request_user,lab.request,model_lab_request,group_lab_management_user,1,1,1,1
access_lab_patient_user,lab.patient,model_lab_patient,group_lab_management_user,1,1,1,1
access_lab_appointment_user,lab.appointment,model_lab_appointment,group_lab_management_user,1,1,1,1
access_test_unit_user,test.unit,model_test_unit,group_lab_management_user,1,0,0,0
access_lab_physician_user,physician.speciality,model_physician_speciality,group_lab_management_user,1,1,1,1
access_lab_test_user,lab.test,model_lab_test,group_lab_management_user,1,0,0,0
access_lab_appointment_line_user,lab.appointment.lines,model_lab_appointment_lines,group_lab_management_user,1,1,1,1
access_lab_test_content_type_user,lab.test.content_type,model_lab_test_content_type,group_lab_management_user,1,0,0,0
access_lab_test_attribute_user,lab.test.attribute,model_lab_test_attribute,group_lab_management_user,1,1,1,1
access_lab_request_technician,lab.request,model_lab_request,group_lab_management_technician,1,1,1,1
access_lab_patient_technician,lab.patient,model_lab_patient,group_lab_management_technician,1,1,1,1
access_lab_appointment_technician,lab.appointment,model_lab_appointment,group_lab_management_technician,1,1,1,1
access_test_unit_technician,test.unit,model_test_unit,group_lab_management_technician,1,1,1,1
access_lab_physician_technician,physician.speciality,model_physician_speciality,group_lab_management_technician,1,0,0,0
access_lab_test_technician,lab.test,model_lab_test,group_lab_management_technician,1,1,1,1
access_lab_test_content_type_technician,lab.test.content_type,model_lab_test_content_type,group_lab_management_technician,1,1,1,1
access_lab_appointment_line_technician,lab.appointment.lines,model_lab_appointment_lines,group_lab_management_technician,1,1,1,1
access_lab_test_attribute_technician,lab.test.attribute,model_lab_test_attribute,group_lab_management_technician,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_lab_request_user lab.request model_lab_request group_lab_management_user 1 1 1 1
3 access_lab_patient_user lab.patient model_lab_patient group_lab_management_user 1 1 1 1
4 access_lab_appointment_user lab.appointment model_lab_appointment group_lab_management_user 1 1 1 1
5 access_test_unit_user test.unit model_test_unit group_lab_management_user 1 0 0 0
6 access_lab_physician_user physician.speciality model_physician_speciality group_lab_management_user 1 1 1 1
7 access_lab_test_user lab.test model_lab_test group_lab_management_user 1 0 0 0
8 access_lab_appointment_line_user lab.appointment.lines model_lab_appointment_lines group_lab_management_user 1 1 1 1
9 access_lab_test_content_type_user lab.test.content_type model_lab_test_content_type group_lab_management_user 1 0 0 0
10 access_lab_test_attribute_user lab.test.attribute model_lab_test_attribute group_lab_management_user 1 1 1 1
11 access_lab_request_technician lab.request model_lab_request group_lab_management_technician 1 1 1 1
12 access_lab_patient_technician lab.patient model_lab_patient group_lab_management_technician 1 1 1 1
13 access_lab_appointment_technician lab.appointment model_lab_appointment group_lab_management_technician 1 1 1 1
14 access_test_unit_technician test.unit model_test_unit group_lab_management_technician 1 1 1 1
15 access_lab_physician_technician physician.speciality model_physician_speciality group_lab_management_technician 1 0 0 0
16 access_lab_test_technician lab.test model_lab_test group_lab_management_technician 1 1 1 1
17 access_lab_test_content_type_technician lab.test.content_type model_lab_test_content_type group_lab_management_technician 1 1 1 1
18 access_lab_appointment_line_technician lab.appointment.lines model_lab_appointment_lines group_lab_management_technician 1 1 1 1
19 access_lab_test_attribute_technician lab.test.attribute model_lab_test_attribute group_lab_management_technician 1 1 1 1

20
medical_lab_management/security/lab_users.xml

@ -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>

BIN
medical_lab_management/static/description/app.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

BIN
medical_lab_management/static/description/banner.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

BIN
medical_lab_management/static/description/card.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
medical_lab_management/static/description/content.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

BIN
medical_lab_management/static/description/cybro_logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
medical_lab_management/static/description/icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

446
medical_lab_management/static/description/index.html

@ -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>

BIN
medical_lab_management/static/description/invoice.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

BIN
medical_lab_management/static/description/lab-management-cybrosys-1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

BIN
medical_lab_management/static/description/lab-management-cybrosys-10.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

BIN
medical_lab_management/static/description/lab-management-cybrosys-11.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

BIN
medical_lab_management/static/description/lab-management-cybrosys-12.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

BIN
medical_lab_management/static/description/lab-management-cybrosys-13.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

BIN
medical_lab_management/static/description/lab-management-cybrosys-2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
medical_lab_management/static/description/lab-management-cybrosys-3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

BIN
medical_lab_management/static/description/lab-management-cybrosys-4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
medical_lab_management/static/description/lab-management-cybrosys-5.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

BIN
medical_lab_management/static/description/lab-management-cybrosys-6.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
medical_lab_management/static/description/lab-management-cybrosys-7.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

BIN
medical_lab_management/static/description/lab-management-cybrosys-8.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
medical_lab_management/static/description/lab-management-cybrosys-9.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

BIN
medical_lab_management/static/description/mail.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
medical_lab_management/static/description/patient.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

BIN
medical_lab_management/static/description/phy.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

BIN
medical_lab_management/static/description/request1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

BIN
medical_lab_management/static/description/request2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

BIN
medical_lab_management/static/description/result.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
medical_lab_management/static/description/test.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

BIN
medical_lab_management/static/description/today.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

BIN
medical_lab_management/static/description/unit.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
medical_lab_management/static/description/user.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

30
medical_lab_management/views/account_invoice.xml

@ -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>

234
medical_lab_management/views/lab_appointment.xml

@ -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', '&gt;=',((datetime.date.today()- datetime.timedelta(days=0)).strftime('%Y-%m-%d 00:00:00'))),
('appointment_date', '&lt;=',((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>

160
medical_lab_management/views/lab_patient_view.xml

@ -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>

121
medical_lab_management/views/lab_request.xml

@ -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>

73
medical_lab_management/views/lab_test_content_type.xml

@ -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>

103
medical_lab_management/views/lab_test_type.xml

@ -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>

27
medical_lab_management/views/physician_details.xml

@ -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>

18
medical_lab_management/views/physician_specialty.xml

@ -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>

22
medical_lab_management/views/res_partner.xml

@ -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>

72
medical_lab_management/views/test_unit_view.xml

@ -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>

32
product_return_pos/README.md

@ -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.

1
product_return_pos/__init__.py

@ -0,0 +1 @@
from . import models

41
product_return_pos/__manifest__.py

@ -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,
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save