@ -0,0 +1,47 @@ |
|||||
|
.. image:: https://img.shields.io/badge/license-AGPL--3-blue.svg |
||||
|
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html |
||||
|
:alt: License: AGPL-3 |
||||
|
|
||||
|
Hospital Management Odoo 17 |
||||
|
=========================== |
||||
|
This Module helps to manage day to day activities of a hospital. |
||||
|
|
||||
|
Configuration |
||||
|
============= |
||||
|
Install python-barcode (pip install python-barcode) |
||||
|
|
||||
|
License |
||||
|
------- |
||||
|
Affero General Public License, Version 3 (AGPL v3). |
||||
|
(https://www.gnu.org/licenses/lgpl-3.0-standalone.html) |
||||
|
|
||||
|
Company |
||||
|
------- |
||||
|
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ |
||||
|
|
||||
|
Credits |
||||
|
------- |
||||
|
* Developer:(V17) Subina, |
||||
|
Contact: odoo@cybrosys.com |
||||
|
|
||||
|
Contacts |
||||
|
-------- |
||||
|
* Mail Contact : odoo@cybrosys.com |
||||
|
* Website : https://cybrosys.com |
||||
|
|
||||
|
Bug Tracker |
||||
|
----------- |
||||
|
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. |
||||
|
|
||||
|
Maintainer |
||||
|
========== |
||||
|
.. image:: https://cybrosys.com/images/logo.png |
||||
|
:target: https://cybrosys.com |
||||
|
|
||||
|
This module is maintained by Cybrosys Technologies. |
||||
|
|
||||
|
For support and more information, please visit `Our Website <https://cybrosys.com/>`__ |
||||
|
|
||||
|
Further information |
||||
|
=================== |
||||
|
HTML Description: `<static/description/index.html>`__ |
@ -0,0 +1,23 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from . import controllers |
||||
|
from . import models |
@ -0,0 +1,112 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
{ |
||||
|
"name": "Hospital Management Odoo 17", |
||||
|
"version": "17.0.1.0.0", |
||||
|
"category": "Industries", |
||||
|
"summary": """This Module Helps to Manage Patients Records, Doctors Details, |
||||
|
Lab Management , Employee Management etc.""", |
||||
|
"description": """The hospital management module can be used to handle |
||||
|
the day-to-day activities of the hospital. Managing patient scheduling, |
||||
|
making patient ID cards, creating patient lab test results, and adding |
||||
|
doctors, patients, prescriptions, vaccines, etc. are all made easier |
||||
|
with the help of this module. This app offers a different dashboards for |
||||
|
different users.""", |
||||
|
"author": "Cybrosys Techno Solutions", |
||||
|
"company": "Cybrosys Techno Solutions", |
||||
|
"maintainer": "Cybrosys Techno Solutions", |
||||
|
"website": "https://www.cybrosys.com", |
||||
|
"depends": ["website", "hr", "stock", "sale_management"], |
||||
|
"data": [ |
||||
|
"security/base_hospital_management_groups.xml", |
||||
|
"security/doctor_allocation_security.xml", |
||||
|
"security/doctor_slot_security.xml", |
||||
|
"security/patient_lab_test_security.xml", |
||||
|
"security/ir.model.access.csv", |
||||
|
"data/ir_sequence_data.xml", |
||||
|
"data/ir_cron_data.xml", |
||||
|
"data/website_data.xml", |
||||
|
"views/menu_views.xml", |
||||
|
"views/inpatient_surgery_views.xml", |
||||
|
"views/hospital_bed_views.xml", |
||||
|
"views/blood_bank_views.xml", |
||||
|
"views/contra_indication_views.xml", |
||||
|
"views/booking_success_templates.xml", |
||||
|
"views/hospital_building_views.xml", |
||||
|
"views/hospital_degree_views.xml", |
||||
|
"views/doctor_allocation_views.xml", |
||||
|
"views/hr_employee_views.xml", |
||||
|
"views/hospital_inpatient_views.xml", |
||||
|
"views/hospital_insurance_views.xml", |
||||
|
"views/hospital_laboratory_views.xml", |
||||
|
"views/patient_lab_test_views.xml", |
||||
|
"views/lab_test_views.xml", |
||||
|
"views/lab_test_result_views.xml", |
||||
|
"views/medicine_brand_views.xml", |
||||
|
"views/menu_views.xml", |
||||
|
"views/hospital_outpatient_views.xml", |
||||
|
"views/res_partner_views.xml", |
||||
|
"views/patient_portal_templates.xml", |
||||
|
"views/hospital_vaccination_views.xml", |
||||
|
"views/product_template_views.xml", |
||||
|
"views/room_facility_views.xml", |
||||
|
"views/patient_card_templates.xml", |
||||
|
"views/booking_success_templates.xml", |
||||
|
"views/doctor_specialization_views.xml", |
||||
|
"views/hospital_pharmacy_views.xml", |
||||
|
"views/hospital_ward_views.xml", |
||||
|
"views/patient_booking_templates.xml", |
||||
|
"views/patient_room_views.xml", |
||||
|
"views/lab_test_line_views.xml", |
||||
|
"report/res_partner_reports.xml", |
||||
|
"report/lab_test_line_reports.xml", |
||||
|
], |
||||
|
"demo": ["demo/hr_job_demo.xml"], |
||||
|
"assets": { |
||||
|
"web.assets_frontend": [ |
||||
|
"base_hospital_management/static/src/js/prescription.js", |
||||
|
"base_hospital_management/static/src/js/website_page.js", |
||||
|
], |
||||
|
"web.assets_backend": [ |
||||
|
"base_hospital_management/static/src/css/doctor_dashboard.css", |
||||
|
"base_hospital_management/static/src/css/reception_dashboard.css", |
||||
|
"base_hospital_management/static/src/css/lab_dashboard.css", |
||||
|
"base_hospital_management/static/src/css/pharmacy_dashboard.css", |
||||
|
"base_hospital_management/static/src/xml/lab_dashboard_templates.xml", |
||||
|
"base_hospital_management/static/src/xml/doctor_dashboard_templates.xml", |
||||
|
"base_hospital_management/static/src/js/lab_dashboard.js", |
||||
|
"base_hospital_management/static/src/js/doctor_dashboard.js", |
||||
|
"base_hospital_management/static/src/xml/pharmacy_orderlines.xml", |
||||
|
"base_hospital_management/static/src/js/pharmacy_orderlines.js", |
||||
|
"base_hospital_management/static/src/xml/pharmacy_dashboard_templates.xml", |
||||
|
"base_hospital_management/static/src/js/pharmacy_dashboard.js", |
||||
|
"base_hospital_management/static/src/xml/reception_dashboard_templates.xml", |
||||
|
"base_hospital_management/static/src/js/reception_dashboard.js", |
||||
|
], |
||||
|
}, |
||||
|
"external_dependencies": {"python": ["python-barcode"]}, |
||||
|
"images": ["static/description/banner.jpg"], |
||||
|
"license": "AGPL-3", |
||||
|
"installable": True, |
||||
|
"auto_install": False, |
||||
|
"application": True, |
||||
|
} |
@ -0,0 +1,24 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from . import patient_booking |
||||
|
from . import portal |
||||
|
from . import view_portal |
@ -0,0 +1,78 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import fields, http |
||||
|
from odoo.http import request |
||||
|
|
||||
|
|
||||
|
class PatientBooking(http.Controller): |
||||
|
"""Class for patient booking""" |
||||
|
|
||||
|
@http.route('/patient_booking', type='http', auth="public", website=True) |
||||
|
def patient_booking(self): |
||||
|
"""Function for patient booking from website.""" |
||||
|
if request.env.user._is_public(): |
||||
|
return request.redirect('/web/login') |
||||
|
values = { |
||||
|
'user': request.env.user.name, |
||||
|
'date': fields.date.today() |
||||
|
} |
||||
|
return request.render( |
||||
|
"base_hospital_management.patient_booking_form", values) |
||||
|
|
||||
|
@http.route('/patient_booking/success', type='http', |
||||
|
website=True, csrf=False) |
||||
|
def patient_booking_submit(self, **kw): |
||||
|
"""Function for submitting the patient booking""" |
||||
|
if request.env.user.partner_id.patient_seq in ['New', 'User', |
||||
|
'Employee']: |
||||
|
request.env.user.partner_id.sudo().write( |
||||
|
{'patient_seq': request.env['ir.sequence'].sudo().next_by_code( |
||||
|
'patient.sequence')}) or 'New' |
||||
|
op = request.env['hospital.outpatient'].sudo().create({ |
||||
|
'patient_id': request.env.user.partner_id.id, |
||||
|
'doctor_id': int(kw.get("doctor-name")), |
||||
|
'op_date': kw.get("date"), |
||||
|
'reason': kw.get("reason") |
||||
|
}) |
||||
|
op.sudo().action_confirm() |
||||
|
return request.redirect('/my/home') |
||||
|
|
||||
|
@http.route('/patient_booking/get_doctors', type='json', auth="public", |
||||
|
website=True) |
||||
|
def update_doctors(self, **kw): |
||||
|
"""Method for fetching doctor allocation for the selected date""" |
||||
|
domain = [('date', '=', kw.get('selected_date'))] |
||||
|
departments = [] |
||||
|
doctors = [] |
||||
|
if kw.get('department'): |
||||
|
domain.append( |
||||
|
('doctor_id.department_id.id', '=', kw.get('department'))) |
||||
|
allocation = request.env['doctor.allocation'].sudo().search(domain) |
||||
|
for rec in allocation: |
||||
|
if request.env.user.partner_id not in rec.mapped( |
||||
|
'op_ids.patient_id'): |
||||
|
doctors.append({'id': rec.id, 'name': rec.name}) |
||||
|
if ({'id': rec.department_id.id, 'name': rec.department_id.name} |
||||
|
not in departments): |
||||
|
departments.append({'id': rec.department_id.id, |
||||
|
'name': rec.department_id.name}) |
||||
|
return {'doctors': doctors, 'departments': departments} |
@ -0,0 +1,44 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo.http import request |
||||
|
from odoo.addons.portal.controllers.portal import CustomerPortal |
||||
|
|
||||
|
|
||||
|
class WebsiteCustomerPortal(CustomerPortal): |
||||
|
"""Class for inheriting _prepare_home_portal_values function """ |
||||
|
|
||||
|
def _prepare_home_portal_values(self, counters): |
||||
|
"""Function for updating the counts of vaccinations, lab tests and op |
||||
|
of portal user""" |
||||
|
values = super()._prepare_home_portal_values(counters) |
||||
|
if 'vaccination_count' in counters: |
||||
|
values['vaccination_count'] = request.env[ |
||||
|
'hospital.vaccination'].sudo(). \ |
||||
|
search_count([('patient_id.user_ids', '=', request.uid)]) |
||||
|
if 'lab_test_count' in counters: |
||||
|
values['lab_test_count'] = request.env['patient.lab.test'].sudo(). \ |
||||
|
search_count([('patient_id.user_ids', '=', request.uid)]) |
||||
|
if 'op_count' in counters: |
||||
|
values['op_count'] = request.env[ |
||||
|
'hospital.outpatient'].sudo().search_count( |
||||
|
[('patient_id.user_ids', '=', request.uid)]) |
||||
|
return values |
@ -0,0 +1,129 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import http |
||||
|
from odoo.http import request |
||||
|
|
||||
|
|
||||
|
class ViewPortal(http.Controller): |
||||
|
"""Class holding portal view methods""" |
||||
|
|
||||
|
@http.route('/my/vaccinations', type='http', auth="public", website=True) |
||||
|
def portal_my_vaccine(self, **kw): |
||||
|
"""Function for rendering vaccination details of portal user""" |
||||
|
v_list = [] |
||||
|
for rec in request.env['hospital.vaccination'].sudo().search( |
||||
|
[('patient_id.user_ids.id', '=', request.uid)]): |
||||
|
request.env.cr.execute( |
||||
|
f"""SELECT id FROM ir_attachment WHERE res_id = {rec.id} |
||||
|
and res_model='hospital.vaccination' """) |
||||
|
attachment_id = False |
||||
|
attachment = request.env.cr.dictfetchall() |
||||
|
if attachment: |
||||
|
attachment_id = attachment[0]['id'] |
||||
|
data = { |
||||
|
'id': rec.id, |
||||
|
'name': rec.name, |
||||
|
'vaccine_date': rec.vaccine_date, |
||||
|
'dose': rec.dose, |
||||
|
'vaccine_product_id': rec.vaccine_product_id.name, |
||||
|
'vaccine_price': rec.vaccine_price, |
||||
|
'attachment_id': attachment_id |
||||
|
} |
||||
|
v_list.append(data) |
||||
|
values = { |
||||
|
'vaccinations': v_list, |
||||
|
'page_name': 'vaccination' |
||||
|
} |
||||
|
return request.render("base_hospital_management.portal_my_vaccines", |
||||
|
values) |
||||
|
|
||||
|
@http.route(['/my/tests'], type='http', auth="public", website=True) |
||||
|
def portal_my_tests(self, **kw): |
||||
|
"""Function for rendering tests of portal user""" |
||||
|
tests_list = [] |
||||
|
for rec in request.env['patient.lab.test'].sudo().search( |
||||
|
[('patient_id.user_ids', '=', request.uid)]): |
||||
|
request.env['account.move'].sudo().search( |
||||
|
[('ref', '=', rec.test_id.name) |
||||
|
], limit=1) |
||||
|
data = { |
||||
|
'id': rec.id, |
||||
|
'name': rec.test_id.name, |
||||
|
'date': rec.date |
||||
|
} |
||||
|
tests_list.append(data) |
||||
|
values = { |
||||
|
'tests': tests_list, |
||||
|
'page_name': 'lab_test' |
||||
|
} |
||||
|
return request.render("base_hospital_management.portal_my_tests", |
||||
|
values) |
||||
|
|
||||
|
@http.route('/my/tests/<int:test_id>', type="http", auth="public", |
||||
|
website=True) |
||||
|
def tests_view(self, test_id): |
||||
|
"""Function for rendering test results of portal user""" |
||||
|
result_list = [] |
||||
|
all_test = request.env['patient.lab.test'].sudo().browse(test_id) |
||||
|
test_result_ids = request.env['lab.test.result'].sudo().search( |
||||
|
[('id', 'in', all_test.result_ids.ids)]) |
||||
|
for rec in test_result_ids: |
||||
|
query = f"""SELECT id FROM ir_attachment WHERE res_id = {rec.id} |
||||
|
and res_model='lab.test.result' """ |
||||
|
request.env.cr.execute(query) |
||||
|
attachment_id = False |
||||
|
attachment = request.env.cr.dictfetchall() |
||||
|
if attachment: |
||||
|
attachment_id = attachment[0]['id'] |
||||
|
result_list.append({ |
||||
|
'id': rec.id, |
||||
|
'name': rec.test_id.name, |
||||
|
'result': rec.result, |
||||
|
'price': rec.price, |
||||
|
'attachment_id': attachment_id, |
||||
|
}) |
||||
|
values = { |
||||
|
'all_test_id': all_test.id, |
||||
|
'results': result_list, |
||||
|
'page_name': 'test_results' |
||||
|
} |
||||
|
return request.render( |
||||
|
"base_hospital_management.portal_my_tests_results", values) |
||||
|
|
||||
|
@http.route('/my/op', type='http', auth="public", |
||||
|
website=True) |
||||
|
def portal_my_op(self, **kw): |
||||
|
"""Function for rendering prescriptions of portal user""" |
||||
|
op = request.env['hospital.outpatient'].sudo().search_read( |
||||
|
[('patient_id.user_ids.id', '=', request.uid)], |
||||
|
['op_reference', 'op_date', 'doctor_id', 'slot', |
||||
|
'prescription_ids']) |
||||
|
for record in op: |
||||
|
hours = int(record['slot']) |
||||
|
minutes = int((record['slot'] - hours) * 60) |
||||
|
record['slot'] = '{:02d}:{:02d}'.format(hours, minutes) |
||||
|
values = { |
||||
|
'op': op, |
||||
|
'page_name': 'op' |
||||
|
} |
||||
|
return request.render( |
||||
|
"base_hospital_management.portal_my_op", values) |
@ -0,0 +1,15 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
<data noupdate="1"> |
||||
|
<!-- Scheduled action for checking blood bank availability--> |
||||
|
<record id="ir_cron_scheduler_blood_availability" model="ir.cron"> |
||||
|
<field name="name">Blood Bank Availability</field> |
||||
|
<field name="model_id" ref="model_blood_bank"/> |
||||
|
<field name="state">code</field> |
||||
|
<field name="code">model.action_change_availability()</field> |
||||
|
<field name="interval_number">3</field> |
||||
|
<field name="interval_type">months</field> |
||||
|
<field name="numbercall">-1</field> |
||||
|
</record> |
||||
|
</data> |
||||
|
</odoo> |
@ -0,0 +1,74 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
<data noupdate="1"> |
||||
|
<!-- Blood Bank sequence--> |
||||
|
<record id="blood_bank_sequence" model="ir.sequence"> |
||||
|
<field name="name">Blood Bank Sequence</field> |
||||
|
<field name="code">blood.bank</field> |
||||
|
<field name="prefix">BB/</field> |
||||
|
<field name="padding">3</field> |
||||
|
<field name="number_next">1</field> |
||||
|
<field name="number_increment">1</field> |
||||
|
</record> |
||||
|
<!-- Building sequence generator--> |
||||
|
<record id="building_sequence" model="ir.sequence"> |
||||
|
<field name="name">Building Sequence</field> |
||||
|
<field name="code">building.sequence</field> |
||||
|
<field name="prefix">BC/</field> |
||||
|
<field name="padding">3</field> |
||||
|
<field name="number_next">1</field> |
||||
|
<field name="number_increment">1</field> |
||||
|
</record> |
||||
|
<!-- Inpatient sequence generator--> |
||||
|
<record id="inpatient_sequence" model="ir.sequence"> |
||||
|
<field name="name">Inpatient sequence</field> |
||||
|
<field name="code">hospital.inpatient</field> |
||||
|
<field name="prefix">IN/PAT</field> |
||||
|
<field name="padding">3</field> |
||||
|
<field name="number_next">1</field> |
||||
|
<field name="number_increment">1</field> |
||||
|
</record> |
||||
|
<!-- Lab test sequence generator--> |
||||
|
<record id="seq_lab_test_line" model="ir.sequence"> |
||||
|
<field name="name">Lab Test Sequence</field> |
||||
|
<field name="code">lab.test.sequence</field> |
||||
|
<field name="prefix">LB/TS/</field> |
||||
|
<field name="padding">3</field> |
||||
|
<field name="number_next">1</field> |
||||
|
<field name="number_increment">1</field> |
||||
|
</record> |
||||
|
<!-- Lab test draft sequence--> |
||||
|
<record id="seq_hospital_draft_lab_test" model="ir.sequence"> |
||||
|
<field name="name">Lab Test Draft Sequence</field> |
||||
|
<field name="code">lab_tests.draft.sequence</field> |
||||
|
<field name="prefix">LB/DR/</field> |
||||
|
<field name="padding">3</field> |
||||
|
<field name="number_next">1</field> |
||||
|
<field name="number_increment">1</field> |
||||
|
</record> |
||||
|
<!-- Lab sequence generator--> |
||||
|
<record id="lab_sequence" model="ir.sequence"> |
||||
|
<field name="name">Laboratory Sequence</field> |
||||
|
<field name="code">laboratory.sequence</field> |
||||
|
<field name="prefix">LAB</field> |
||||
|
<field name="padding">3</field> |
||||
|
</record> |
||||
|
<!-- Patient sequence generator--> |
||||
|
<record id="patient_sequence" model="ir.sequence"> |
||||
|
<field name="name">Patient sequence</field> |
||||
|
<field name="code">patient.sequence</field> |
||||
|
<field name="prefix">PAT</field> |
||||
|
<field name="padding">3</field> |
||||
|
<field name="number_next">1</field> |
||||
|
<field name="number_increment">1</field> |
||||
|
</record> |
||||
|
<!-- Vaccination sequence generator--> |
||||
|
<record id="vaccination_sequence" |
||||
|
model="ir.sequence"> |
||||
|
<field name="name">Vaccination Sequence</field> |
||||
|
<field name="code">vaccination.sequence</field> |
||||
|
<field name="prefix">VAC</field> |
||||
|
<field name="padding">3</field> |
||||
|
</record> |
||||
|
</data> |
||||
|
</odoo> |
@ -0,0 +1,12 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
<data noupdate="1"> |
||||
|
<!-- Booking menu in Website--> |
||||
|
<record id="website_menu_patient_booking" model="website.menu"> |
||||
|
<field name="name">Booking</field> |
||||
|
<field name="url">/patient_booking</field> |
||||
|
<field name="parent_id" ref="website.main_menu"/> |
||||
|
<field name="sequence" type="int">50</field> |
||||
|
</record> |
||||
|
</data> |
||||
|
</odoo> |
@ -0,0 +1,24 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
<data noupdate="1"> |
||||
|
<!-- Adding job positions to demo data --> |
||||
|
<record id="job_position_doctor" model="hr.job"> |
||||
|
<field name="name">Doctor</field> |
||||
|
</record> |
||||
|
<record id="job_position_nurse" model="hr.job"> |
||||
|
<field name="name">Nurse</field> |
||||
|
</record> |
||||
|
<record id="job_position_receptionist" model="hr.job"> |
||||
|
<field name="name">Receptionist</field> |
||||
|
</record> |
||||
|
<record id="job_position_pharmacist" model="hr.job"> |
||||
|
<field name="name">Pharmacist</field> |
||||
|
</record> |
||||
|
<record id="job_position_staff" model="hr.job"> |
||||
|
<field name="name">Staff</field> |
||||
|
</record> |
||||
|
<record id="job_position_lab_technician" model="hr.job"> |
||||
|
<field name="name">Lab Technician</field> |
||||
|
</record> |
||||
|
</data> |
||||
|
</odoo> |
@ -0,0 +1,7 @@ |
|||||
|
## Module <base_hospital_management> |
||||
|
|
||||
|
#### 03.06.2024 |
||||
|
#### Version 17.0.1.0.0 |
||||
|
#### ADD |
||||
|
|
||||
|
- Initial commit for Hospital Management Odoo 17 |
@ -0,0 +1,58 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from . import account_payment_register |
||||
|
from . import blood_bank |
||||
|
from . import blood_donation |
||||
|
from . import contra_indication |
||||
|
from . import doctor_allocation |
||||
|
from . import doctor_round |
||||
|
from . import doctor_slot |
||||
|
from . import doctor_specialization |
||||
|
from . import hospital_bed |
||||
|
from . import hospital_building |
||||
|
from . import hospital_degree |
||||
|
from . import hospital_family |
||||
|
from . import hospital_inpatient |
||||
|
from . import hospital_insurance |
||||
|
from . import hospital_laboratory |
||||
|
from . import hospital_outpatient |
||||
|
from . import hospital_pharmacy |
||||
|
from . import hospital_vaccination |
||||
|
from . import hospital_ward |
||||
|
from . import hr_employee |
||||
|
from . import inpatient_payment |
||||
|
from . import inpatient_surgery |
||||
|
from . import ir_attachment |
||||
|
from . import lab_medicine_line |
||||
|
from . import lab_test |
||||
|
from . import lab_test_line |
||||
|
from . import lab_test_result |
||||
|
from . import medicine_brand |
||||
|
from . import nursing_plan |
||||
|
from . import patient_lab_test |
||||
|
from . import patient_room |
||||
|
from . import pharmacy_medicine |
||||
|
from . import prescription_line |
||||
|
from . import product_template |
||||
|
from . import res_partner |
||||
|
from . import res_users |
||||
|
from . import room_facility |
@ -0,0 +1,42 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import api, models |
||||
|
|
||||
|
|
||||
|
class AccountPaymentRegister(models.TransientModel): |
||||
|
""" |
||||
|
Adding inpatient field to invoicing model. |
||||
|
""" |
||||
|
_inherit = "account.payment.register" |
||||
|
|
||||
|
@api.model |
||||
|
def create(self, vals_list): |
||||
|
"""Create records to inpatient payment""" |
||||
|
self.env['inpatient.payment'].sudo().create({ |
||||
|
'name': vals_list['communication'], |
||||
|
'subtotal': vals_list['amount'], |
||||
|
'inpatient_id': self.env['hospital.inpatient'].sudo().search([( |
||||
|
'patient_id', '=', vals_list['partner_id'])], |
||||
|
order='create_date desc', limit=1).id, |
||||
|
'date': vals_list['payment_date'] |
||||
|
}) |
||||
|
return super().create(vals_list) |
@ -0,0 +1,101 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class BloodBank(models.Model): |
||||
|
"""Class holding Blood bank details""" |
||||
|
_name = 'blood.bank' |
||||
|
_description = "Blood Bank" |
||||
|
|
||||
|
partner_id = fields.Many2one('res.partner', |
||||
|
string='Donor Name', |
||||
|
domain=[('patient_seq', 'not in', |
||||
|
['New', 'Employee', 'User'])], |
||||
|
help='Name of the blood donor', |
||||
|
required=True) |
||||
|
name = fields.Char(string='Sequence', |
||||
|
help='Sequence number indicating the blood bank', |
||||
|
index=True, |
||||
|
default=lambda self: 'New') |
||||
|
date = fields.Date(string='Date', help='Blood donating date', |
||||
|
default=fields.Date.today()) |
||||
|
blood_type = fields.Selection([('a_positive', 'A+'), |
||||
|
('a_negative', 'A-'), |
||||
|
('b_positive', 'B+'), ('b_negative', 'B-'), |
||||
|
('o_positive', 'O+'), ('o_negative', '0-'), |
||||
|
('ab_positive', 'AB+'), |
||||
|
('ab_negative', 'AB-')], |
||||
|
string='Blood Group', |
||||
|
help='Choose your blood group', required=True, |
||||
|
group_expand='_group_expand_states') |
||||
|
blood_donation_ids = fields.One2many('blood.donation', |
||||
|
'blood_bank_id', |
||||
|
string='Contra Indications', |
||||
|
help='Lists all the ' |
||||
|
'contraindications') |
||||
|
state = fields.Selection([('avail', 'Available'), |
||||
|
('not', 'Unavailable')], |
||||
|
string='State', help='State of the blood donation', |
||||
|
readonly=True, default="avail") |
||||
|
assigned_patient_id = fields.Many2one('res.partner', |
||||
|
string='Receiver', |
||||
|
domain=[('patient_seq', 'not in', |
||||
|
['New', 'Employee', |
||||
|
'User'])], |
||||
|
help='Choose the patient to whom ' |
||||
|
'blood is donating') |
||||
|
|
||||
|
@api.model |
||||
|
def create(self, vals): |
||||
|
"""Function for creating blood sequence number""" |
||||
|
if vals.get('name', 'New') == 'New': |
||||
|
vals['name'] = self.env['ir.sequence'].next_by_code( |
||||
|
'blood.bank') or 'New' |
||||
|
return super().create(vals) |
||||
|
|
||||
|
@api.onchange('partner_id') |
||||
|
def _onchange_partner_id(self): |
||||
|
"""Function for listing all contra indications""" |
||||
|
self.blood_donation_ids = False |
||||
|
self.sudo().write({ |
||||
|
'blood_donation_ids': [(0, 0, { |
||||
|
'questions': rec.blood_donation_question}) |
||||
|
for rec in |
||||
|
self.env['contra.indication'].sudo().search( |
||||
|
[])]}) |
||||
|
|
||||
|
def _group_expand_states(self, states, domain, order): |
||||
|
"""Method for expanding all blood groups in kanban view""" |
||||
|
return [key for key, val in type(self).blood_type.selection] |
||||
|
|
||||
|
def action_blood_available(self): |
||||
|
"""Change the state to unavailable""" |
||||
|
self.sudo().write({ |
||||
|
'state': 'not' |
||||
|
}) |
||||
|
|
||||
|
def action_change_availability(self): |
||||
|
"""Cron action for changing the state of the record""" |
||||
|
for rec in self.sudo().search([]): |
||||
|
if rec.date <= fields.Date.subtract(fields.Date.today(), months=1): |
||||
|
rec.state = 'avail' |
@ -0,0 +1,38 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class BloodDonation(models.Model): |
||||
|
"""Class holding blood donation details""" |
||||
|
_name = 'blood.donation' |
||||
|
_description = 'Blood Donation' |
||||
|
_rec_name = 'questions' |
||||
|
|
||||
|
questions = fields.Text(string='Contra Indications', |
||||
|
help='Contraindications of the blood donor') |
||||
|
is_true = fields.Boolean(string='Is True', |
||||
|
help='True for contraindications') |
||||
|
blood_bank_id = fields.Many2one('blood.bank', |
||||
|
string='Blood Bank', |
||||
|
help='Blood bank corresponding to the ' |
||||
|
'donor') |
@ -0,0 +1,33 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class ContraIndication(models.Model): |
||||
|
"""Class holding the contra indications""" |
||||
|
_name = 'contra.indication' |
||||
|
_description = 'Contra Indication' |
||||
|
_rec_name = 'blood_donation_question' |
||||
|
|
||||
|
blood_donation_question = fields.Text(string='Contra Indications', |
||||
|
help='Contra indications of the ' |
||||
|
'blood donor') |
@ -0,0 +1,220 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import api, fields, models |
||||
|
from odoo.exceptions import ValidationError |
||||
|
|
||||
|
|
||||
|
class DoctorAllocation(models.Model): |
||||
|
"""Class holding doctor allocations""" |
||||
|
_name = 'doctor.allocation' |
||||
|
_description = 'Doctor Allocation' |
||||
|
|
||||
|
doctor_id = fields.Many2one('hr.employee', string="Doctor", |
||||
|
help='Name of the doctor', |
||||
|
domain=[('job_id.name', '=', 'Doctor')]) |
||||
|
name = fields.Char(string="Name", readonly=True, default='New', |
||||
|
help='Name of the allocation') |
||||
|
department_id = fields.Many2one(string='Department', |
||||
|
help='Department of the doctor', |
||||
|
related='doctor_id.department_id') |
||||
|
op_ids = fields.One2many('hospital.outpatient', |
||||
|
'doctor_id', |
||||
|
string='Booking', |
||||
|
help='Patient booking belongs to this ' |
||||
|
'allocation') |
||||
|
company_id = fields.Many2one('res.company', string='Company', |
||||
|
default=lambda self: self.env.company.id, |
||||
|
help='Indicates the company') |
||||
|
is_doctor = fields.Boolean(string='Is Doctor', help='True for doctors.') |
||||
|
date = fields.Date(string='Date', |
||||
|
help='Indicate the allocated date for a doctor', |
||||
|
default=fields.Date.today()) |
||||
|
work_to = fields.Float(string='Work To', required=True, |
||||
|
help='Allocation time ending time in 24 hrs format') |
||||
|
work_from = fields.Float(string='Work From', required=True, |
||||
|
help='Allocation time starting time in 24 hrs ' |
||||
|
'format') |
||||
|
time_avg = fields.Float(string='Duration', help="Average Consultation time " |
||||
|
"per Patient in minutes", |
||||
|
readonly=False, |
||||
|
related='doctor_id.time_avg') |
||||
|
patient_type = fields.Selection([('inpatient', 'Inpatient'), |
||||
|
('outpatient', 'Outpatient')], |
||||
|
string='Patient Type', |
||||
|
help='Indicates the type of patient') |
||||
|
patient_limit = fields.Integer(string='Limit Patient', |
||||
|
help='Maximum number of patients allowed ' |
||||
|
'per allocation', store=True, |
||||
|
compute='_compute_patient_limit', ) |
||||
|
patient_count = fields.Integer(string='Patient Count', |
||||
|
help='Number of patient under ' |
||||
|
'this allocation', |
||||
|
compute='_compute_patient_count') |
||||
|
slot_remaining = fields.Integer(string='Slots Remaining', |
||||
|
help='Number of slots remaining in this' |
||||
|
' allocation', store=True, |
||||
|
compute='_compute_slot_remaining') |
||||
|
latest_slot = fields.Float(string='Available Slot', |
||||
|
help='Indicates the latest available slot') |
||||
|
state = fields.Selection( |
||||
|
[('draft', 'Draft'), ('confirm', 'Confirmed'), |
||||
|
('cancel', 'Cancelled')], |
||||
|
default='draft', string='State', help='State of Doctor allocation') |
||||
|
|
||||
|
@api.model |
||||
|
def create(self, vals): |
||||
|
"""Method for creating name""" |
||||
|
work_from_hr = int(vals['work_from']) |
||||
|
work_from_min = int((vals['work_from'] - work_from_hr) * 60) |
||||
|
work_from = "{:02d}:{:02d}".format(work_from_hr, work_from_min) |
||||
|
work_to_hr = int(vals['work_to']) |
||||
|
work_to_min = int((vals['work_to'] - work_to_hr) * 60) |
||||
|
work_to = "{:02d}:{:02d}".format(work_to_hr, work_to_min) |
||||
|
doctor_group = self.env.ref( |
||||
|
'base_hospital_management.base_hospital_management_group_doctor') |
||||
|
if doctor_group in self.env.user.groups_id: |
||||
|
default_doctor_id = self.env['hr.employee'].sudo().search( |
||||
|
[('user_id', '=', self.env.user.id)], limit=1) |
||||
|
if default_doctor_id: |
||||
|
vals[ |
||||
|
'name'] = (default_doctor_id.name + ': ' + work_from + '-' |
||||
|
+ work_to) |
||||
|
else: |
||||
|
vals['name'] = self.env['hr.employee'].sudo().browse( |
||||
|
vals['doctor_id']).name + ': ' + work_from + '-' + work_to |
||||
|
return super().create(vals) |
||||
|
|
||||
|
@api.onchange('work_from', 'work_to') |
||||
|
def _onchange_work_from(self): |
||||
|
"""Method for calculating name""" |
||||
|
if self.work_from and self.work_to: |
||||
|
work_from_hr = int(self.work_from) |
||||
|
work_from_min = int((self.work_from - work_from_hr) * 60) |
||||
|
work_from = "{:02d}:{:02d}".format(work_from_hr, work_from_min) |
||||
|
work_to_hr = int(self.work_to) |
||||
|
work_to_min = int((self.work_to - work_to_hr) * 60) |
||||
|
work_to = "{:02d}:{:02d}".format(work_to_hr, work_to_min) |
||||
|
self.name = str(self.doctor_id.name) + ': ' + work_from + '-' + work_to |
||||
|
|
||||
|
@api.model |
||||
|
def default_get(self, doctor_id): |
||||
|
"""Method for making doctor field readonly and applying default value |
||||
|
for doctor login""" |
||||
|
res = super().default_get(doctor_id) |
||||
|
doctor_group = self.env.ref( |
||||
|
'base_hospital_management.base_hospital_management_group_doctor') |
||||
|
if doctor_group in self.env.user.groups_id: |
||||
|
default_doctor_id = self.env['hr.employee'].sudo().search( |
||||
|
[('user_id', '=', self.env.user.id)], limit=1) |
||||
|
if default_doctor_id: |
||||
|
res['doctor_id'] = default_doctor_id.id |
||||
|
res['is_doctor'] = True |
||||
|
self.is_doctor = True |
||||
|
else: |
||||
|
self.is_doctor = False |
||||
|
res['is_doctor'] = False |
||||
|
return res |
||||
|
|
||||
|
@api.constrains('work_from', 'work_to', 'date') |
||||
|
def _check_overlap(self): |
||||
|
"""Method for checking overlapping""" |
||||
|
for allocation in self: |
||||
|
if allocation.work_from >= allocation.work_to: |
||||
|
raise ValidationError("Work From must be less than Work To.") |
||||
|
overlapping_allocations = self.sudo().search([ |
||||
|
('id', '!=', allocation.id), |
||||
|
('date', '=', allocation.date), |
||||
|
('doctor_id', '=', allocation.doctor_id.id), |
||||
|
'|', |
||||
|
'&', ('work_from', '<=', allocation.work_from), |
||||
|
('work_to', '>=', allocation.work_from), |
||||
|
'&', ('work_from', '<=', allocation.work_to), |
||||
|
('work_to', '>=', allocation.work_to) |
||||
|
]) |
||||
|
if overlapping_allocations: |
||||
|
raise ValidationError( |
||||
|
"Overlap detected with another doctor allocation on the " |
||||
|
"same date.") |
||||
|
|
||||
|
@api.depends('work_from', 'work_to', 'time_avg') |
||||
|
def _compute_patient_limit(self): |
||||
|
"""Method for computing patient limit""" |
||||
|
for record in self: |
||||
|
if (record.work_from and record.work_to and record.time_avg |
||||
|
and record.time_avg > 0): |
||||
|
patient_slots = int( |
||||
|
(record.work_to - record.work_from) / record.time_avg) |
||||
|
if patient_slots <= 0: |
||||
|
raise ValidationError( |
||||
|
"Work From must be less than Work To.") |
||||
|
else: |
||||
|
record.patient_limit = patient_slots |
||||
|
else: |
||||
|
record.patient_limit = 10 |
||||
|
|
||||
|
@api.depends('op_ids') |
||||
|
def _compute_patient_count(self): |
||||
|
"""Method for computing patient count""" |
||||
|
for rec in self: |
||||
|
rec.patient_count = len(rec.op_ids) |
||||
|
|
||||
|
@api.depends('op_ids', 'patient_count', 'patient_limit') |
||||
|
def _compute_slot_remaining(self): |
||||
|
"""Method for computing slot remaining""" |
||||
|
for rec in self: |
||||
|
rec.slot_remaining = rec.patient_limit - rec.patient_count |
||||
|
|
||||
|
def action_get_patient_booking(self): |
||||
|
"""Returns form view of bed""" |
||||
|
return { |
||||
|
'name': "Patient Booking", |
||||
|
'type': 'ir.actions.act_window', |
||||
|
'view_mode': 'tree,form', |
||||
|
'res_model': 'hospital.outpatient', |
||||
|
'domain': [('id', 'in', self.op_ids.ids)], |
||||
|
'context': {'create': False} |
||||
|
} |
||||
|
|
||||
|
def action_confirm_allocation(self): |
||||
|
"""Confirmation of allocation""" |
||||
|
self.state = 'confirm' |
||||
|
|
||||
|
def action_cancel_allocation(self): |
||||
|
"""Method for cancelling a allocation""" |
||||
|
self.state = 'cancel' |
||||
|
|
||||
|
@api.model |
||||
|
def get_allocation_lines(self): |
||||
|
"""Returns allocated hour details to display on the dashboard""" |
||||
|
data_list = [] |
||||
|
allocated_hour = self.sudo().search([ |
||||
|
('doctor_id.user_id', '=', self.env.user.id) |
||||
|
]) |
||||
|
for rec in allocated_hour: |
||||
|
data_list.append({ |
||||
|
'date': rec.date, |
||||
|
'name': rec.name, |
||||
|
'patient_type': rec.patient_type, |
||||
|
'patient_limit': rec.patient_limit, |
||||
|
'patient_count': rec.patient_count |
||||
|
}) |
||||
|
return data_list |
@ -0,0 +1,39 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class DoctorRound(models.Model): |
||||
|
"""Class holding doctor round details""" |
||||
|
_name = 'doctor.round' |
||||
|
_description = "Doctor Rounds" |
||||
|
|
||||
|
admission_id = fields.Many2one('hospital.inpatient', |
||||
|
string='Patient', |
||||
|
help='Choose the patient') |
||||
|
doctor_id = fields.Many2one('hr.employee', |
||||
|
domain=[('job_id.name', '=', 'Doctor')], |
||||
|
string='Doctor', help='Choose your doctor') |
||||
|
date = fields.Datetime(string='Visit Time', help='Choose the visit time ' |
||||
|
'of doctor') |
||||
|
status = fields.Char(string='Status', help='Status of doctor rounds') |
||||
|
notes = fields.Text(string='Note', help='Notes regarding the rounds') |
@ -0,0 +1,128 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class DoctorSlot(models.Model): |
||||
|
"""Model for handling a doctor's slot for surgery""" |
||||
|
_name = 'doctor.slot' |
||||
|
_description = "Doctor Slot" |
||||
|
_inherit = ["mail.thread", "mail.activity.mixin"] |
||||
|
|
||||
|
doctor_id = fields.Many2one('hr.employee', string="Doctor", |
||||
|
help='Doctors name', |
||||
|
domain=[('job_id.name', '=', 'Doctor')]) |
||||
|
date_start = fields.Datetime(default=fields.Date.today(), string='Date', |
||||
|
help='Date of surgery') |
||||
|
patient_id = fields.Many2one('res.partner', |
||||
|
domain=[('patient_seq', 'not in', |
||||
|
['New', 'Employee', 'User'])], |
||||
|
string='Patient', help='Name of the patient') |
||||
|
name = fields.Char(string='Surgery', help='Name of surgery') |
||||
|
state = fields.Selection([('confirmed', 'Confirmed'), |
||||
|
('cancel', 'Cancel'), |
||||
|
('done', 'Done'), |
||||
|
('draft', 'Draft')], default='draft', |
||||
|
string='State', help='State of the slot') |
||||
|
time = fields.Float(string='Time', help='Time of surgery') |
||||
|
hours_to_take = fields.Float(string='Duration', |
||||
|
help='Time duration for the surgery') |
||||
|
company_id = fields.Many2one('res.company', string='Company', |
||||
|
default=lambda self: self.env.company.id) |
||||
|
|
||||
|
def hospital_inpatient_confirm(self): |
||||
|
"""Inpatient confirmation from Doctor's dashboard""" |
||||
|
data_list = [] |
||||
|
for rec in self.env['doctor.slot'].sudo().search( |
||||
|
[('doctor_id.user_id', '=', self.env.user.id), |
||||
|
('state', '=', 'confirmed')]): |
||||
|
data_list.append({ |
||||
|
'id': rec.id, |
||||
|
'planned_date': rec.date_start, |
||||
|
'patient_id': rec.patient_id.name, |
||||
|
'name': rec.name, |
||||
|
'state': rec.state |
||||
|
}) |
||||
|
return data_list |
||||
|
|
||||
|
def hospital_inpatient_cancel(self): |
||||
|
"""Inpatients cancellation from Doctor's dashboard""" |
||||
|
data_list = [] |
||||
|
for rec in self.env['doctor.slot'].sudo().search( |
||||
|
[('doctor_id.user_id', '=', self.env.user.id), |
||||
|
('state', '=', 'cancel')]): |
||||
|
data_list.append({ |
||||
|
'id': rec.id, |
||||
|
'planned_date': rec.date_start, |
||||
|
'patient_id': rec.patient_id.name, |
||||
|
'name': rec.name, |
||||
|
'state': rec.state |
||||
|
}) |
||||
|
return data_list |
||||
|
|
||||
|
def hospital_inpatient_done(self): |
||||
|
"""Inpatient done function from doctor's dashboard""" |
||||
|
data_list = [] |
||||
|
for rec in self.env['doctor.slot'].sudo().search( |
||||
|
[('doctor_id.user_id', '=', self.env.user.id), |
||||
|
('state', '=', 'done')]): |
||||
|
data_list.append({ |
||||
|
'id': rec.id, |
||||
|
'planned_date': rec.date_start, |
||||
|
'patient_id': rec.patient_id.name, |
||||
|
'name': rec.name, |
||||
|
'state': rec.state |
||||
|
}) |
||||
|
return data_list |
||||
|
|
||||
|
def action_get_doctor_slot(self): |
||||
|
"""Function for returning doctor's slot to doctor's dashboard""" |
||||
|
data_list = [] |
||||
|
for rec in self.sudo().search( |
||||
|
[('doctor_id.user_id', '=', self.env.user.id), |
||||
|
('state', '=', 'draft')]): |
||||
|
data_list.append({ |
||||
|
'id': rec.id, |
||||
|
'planned_date': rec.date_start, |
||||
|
'patient_id': rec.patient_id.patient_seq, |
||||
|
'name': rec.name, |
||||
|
'state': rec.state |
||||
|
}) |
||||
|
return data_list |
||||
|
|
||||
|
def action_confirm(self): |
||||
|
"""Function for confirming a slot""" |
||||
|
self.sudo().write({ |
||||
|
'state': 'confirmed' |
||||
|
}) |
||||
|
|
||||
|
def action_cancel(self): |
||||
|
"""Function for cancelling a slot""" |
||||
|
self.sudo().write({ |
||||
|
'state': 'cancel' |
||||
|
}) |
||||
|
|
||||
|
def action_done(self): |
||||
|
"""Function for change the state to done""" |
||||
|
self.sudo().write({ |
||||
|
'state': 'done' |
||||
|
}) |
@ -0,0 +1,32 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class DoctorSpecialization(models.Model): |
||||
|
"""Class holding doctor's specializations""" |
||||
|
_name = 'doctor.specialization' |
||||
|
_description = 'Doctor Specialization' |
||||
|
_rec_name = 'specialization' |
||||
|
|
||||
|
specialization = fields.Char(string="Specialization", |
||||
|
help='Specify the name of specialization') |
@ -0,0 +1,59 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class HospitalBed(models.Model): |
||||
|
"""Class holding hospital bed details""" |
||||
|
_name = 'hospital.bed' |
||||
|
_description = 'Beds' |
||||
|
|
||||
|
_sql_constraints = [('unique_room', 'unique (name)', |
||||
|
'Bed number should be unique!')] |
||||
|
name = fields.Char(string="Bed Number", help='Indicates the unique ' |
||||
|
'number for a bed', |
||||
|
required=True) |
||||
|
bed_type = fields.Selection([('gatch', 'Gatch Bed'), |
||||
|
('electric', 'Electric'), |
||||
|
('stretcher', 'Stretcher'), |
||||
|
('low', 'Low Bed'), |
||||
|
('air', 'Low Air Loss'), |
||||
|
('circo', 'Circo Electric'), |
||||
|
('clinitron', 'Clinitron'), |
||||
|
], string="Type", help='Type of bed') |
||||
|
note = fields.Text(string="Notes", help='Notes regarding bed') |
||||
|
ward_id = fields.Many2one('hospital.ward', string="Ward", |
||||
|
help='Indicates the ward to which the bed' |
||||
|
' belongs to') |
||||
|
room_id = fields.Many2one('patient.room', string="Room", |
||||
|
help='Indicates the room to which the bed' |
||||
|
' belongs to') |
||||
|
currency_id = fields.Many2one('res.currency', string='Currency', |
||||
|
help='Currency in which bed rent calculates', |
||||
|
default=lambda self: |
||||
|
self.env.user.company_id.currency_id.id, |
||||
|
required=True) |
||||
|
bed_rent = fields.Monetary(string='Rent', help="The charge for the bed") |
||||
|
state = fields.Selection([('avail', 'Available'), ('not', 'Unavailable')], |
||||
|
string='State', readonly=True, |
||||
|
help='State of the bed', |
||||
|
default="avail") |
@ -0,0 +1,87 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class HospitalBuilding(models.Model): |
||||
|
"""Class containing field and functions related to hospital building""" |
||||
|
_name = 'hospital.building' |
||||
|
_description = 'Buildings' |
||||
|
|
||||
|
notes = fields.Text(string='Notes', help='Notes regarding the building') |
||||
|
name = fields.Char(string='Block Code', |
||||
|
help='Code for uniquely identifying a block', |
||||
|
copy=False, readonly=True, index=True, |
||||
|
default=lambda self: 'New') |
||||
|
phone = fields.Char(string='Phone', |
||||
|
help='Phone number for contact the building') |
||||
|
mobile = fields.Char(string='Mobile', |
||||
|
help='Mobile number for contact the building') |
||||
|
email = fields.Char(string='Email', help='Email of the building') |
||||
|
room_count = fields.Integer(string="Rooms", |
||||
|
help='Number of rooms in the building', |
||||
|
compute="_compute_room_count") |
||||
|
ward_count = fields.Integer(string="Wards", |
||||
|
help='Number of wards in the building', |
||||
|
compute="_compute_ward_count") |
||||
|
|
||||
|
@api.model |
||||
|
def create(self, vals): |
||||
|
"""Create building sequence""" |
||||
|
if vals.get('name', 'New') == 'New': |
||||
|
vals['name'] = self.env['ir.sequence'].next_by_code( |
||||
|
'building.sequence') or 'New' |
||||
|
return super().create(vals) |
||||
|
|
||||
|
def _compute_room_count(self): |
||||
|
"""Calculates room_count in a building""" |
||||
|
for rec in self: |
||||
|
rec.room_count = self.env['patient.room'].sudo().search_count([( |
||||
|
'building_id', '=', rec.id)]) |
||||
|
|
||||
|
def _compute_ward_count(self): |
||||
|
"""Counting wards in the building""" |
||||
|
for rec in self: |
||||
|
rec.ward_count = self.env['hospital.ward'].sudo().search_count([( |
||||
|
'building_id', '=', rec.id)]) |
||||
|
|
||||
|
def get_room_count(self): |
||||
|
"""Smart button action for viewing all rooms in a building""" |
||||
|
return { |
||||
|
'name': 'Room', |
||||
|
'domain': [('building_id', '=', self.id)], |
||||
|
'type': 'ir.actions.act_window', |
||||
|
'res_model': 'patient.room', |
||||
|
'view_mode': 'tree,form', |
||||
|
'context': {'create': False}, |
||||
|
} |
||||
|
|
||||
|
def get_ward_count(self): |
||||
|
"""Smart button action for viewing all wards in a building""" |
||||
|
return { |
||||
|
'name': 'Wards', |
||||
|
'domain': [('building_id', '=', self.id)], |
||||
|
'type': 'ir.actions.act_window', |
||||
|
'res_model': 'hospital.ward', |
||||
|
'view_mode': 'tree,form', |
||||
|
'context': {'create': False}, |
||||
|
} |
@ -0,0 +1,30 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class HospitalDegree(models.Model): |
||||
|
"""Class holding degree details of Doctor""" |
||||
|
_name = 'hospital.degree' |
||||
|
_description = 'Degree' |
||||
|
|
||||
|
name = fields.Char(string="Degree", help='Degree of the staff') |
@ -0,0 +1,39 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class HospitalFamily(models.Model): |
||||
|
"""Class holding hospital family details""" |
||||
|
_name = 'hospital.family' |
||||
|
_description = 'Hospital Family' |
||||
|
|
||||
|
name = fields.Char(string="Name", help='Name of family member') |
||||
|
relation = fields.Char(string="Relation", help='Relation with the patient') |
||||
|
age = fields.Integer(string="Age", help='Age of family member') |
||||
|
deceased = fields.Selection([('yes', 'Yes'), ('no', 'NO')], |
||||
|
string="Diseased", help='Specify whether the ' |
||||
|
'family member is ' |
||||
|
'alive or not') |
||||
|
family_id = fields.Many2one('res.partner', |
||||
|
string="Family ID", help='Choose the family ' |
||||
|
'member') |
@ -0,0 +1,484 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
import datetime |
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class HospitalInpatient(models.Model): |
||||
|
"""Class holding inpatient details""" |
||||
|
_name = 'hospital.inpatient' |
||||
|
_description = 'Inpatient' |
||||
|
_inherit = ['mail.thread.cc', 'mail.activity.mixin'] |
||||
|
|
||||
|
patient_id = fields.Many2one('res.partner', string="Patient", |
||||
|
domain=[('patient_seq', 'not in', |
||||
|
['New', 'Employee', 'User'])], |
||||
|
required=True, help='Choose the patient') |
||||
|
name = fields.Char(string="Sequence Number", store=True, |
||||
|
copy=False, readonly=True, index=True, |
||||
|
help='Sequence number of inpatient for uniquely ' |
||||
|
'identifying', |
||||
|
default=lambda self: 'New') |
||||
|
reason = fields.Text( |
||||
|
string="Reason For Admission", |
||||
|
help="Current reason for hospitalization of the patient") |
||||
|
bed_id = fields.Many2one('hospital.bed', string='Bed', |
||||
|
help='Choose the bed') |
||||
|
room_id = fields.Many2one('patient.room', string='Room', |
||||
|
help='Choose the room to which patient admitted' |
||||
|
' to') |
||||
|
building_id = fields.Many2one( |
||||
|
'hospital.building', related='room_id.building_id', |
||||
|
string="Block", help='Name of the block') |
||||
|
room_building_id = fields.Many2one( |
||||
|
'hospital.building', related='room_id.building_id', |
||||
|
string="Room Building", |
||||
|
help='Name of the building to which room belongs to') |
||||
|
ward_id = fields.Many2one('hospital.ward', |
||||
|
related='bed_id.ward_id', |
||||
|
string='Ward', |
||||
|
help='Ward to which the bed belongs to') |
||||
|
type_admission = fields.Selection([('emergency', |
||||
|
'Emergency Admission'), |
||||
|
('routine', 'Routine Admission')], |
||||
|
string="Admission Type", |
||||
|
help='The type of admission', |
||||
|
required=True) |
||||
|
attending_doctor_id = fields.Many2one('hr.employee', |
||||
|
string="Attending Doctor", |
||||
|
required=True, |
||||
|
help='Name of attending doctor', |
||||
|
domain=[ |
||||
|
('job_id.name', '=', 'Doctor')]) |
||||
|
operating_doctor_id = fields.Many2one('hr.employee', |
||||
|
string="Operating Doctor", |
||||
|
help='Name of operating doctor', |
||||
|
domain=[ |
||||
|
('job_id.name', '=', 'Doctor')]) |
||||
|
hosp_date = fields.Date(string="Admission Date", |
||||
|
help='Date of hospitalisation', |
||||
|
default=fields.Date.today()) |
||||
|
discharge_date = fields.Date(string="Discharge Date", |
||||
|
help='Date of discharge', copy=False) |
||||
|
condition = fields.Text( |
||||
|
string="Condition Before Hospitalization", |
||||
|
help="The condition of the patient before he/she is admitted to" |
||||
|
" the hospital") |
||||
|
nursing_plan_ids = fields.One2many('nursing.plan', |
||||
|
'admission_id', |
||||
|
string='Nursing Plan', |
||||
|
help='Nursing plan of the inpatient') |
||||
|
active = fields.Boolean(string='Active', default=True, |
||||
|
help='True for active inpatients') |
||||
|
doctor_round_ids = fields.One2many('doctor.round', |
||||
|
'admission_id', |
||||
|
string='Doctor Rounds', |
||||
|
help='Doctor rounds of the patient') |
||||
|
discharge_plan = fields.Text(string="Discharge Plan", |
||||
|
help='Discharge plan of the inpatient') |
||||
|
notes = fields.Text(string="Notes", help='Notes regarding the inpatient') |
||||
|
bed_rent = fields.Monetary(string='Rent Per Day', related='bed_id.bed_rent', |
||||
|
help='Rent for the bed') |
||||
|
currency_id = fields.Many2one('res.currency', string='Currency', |
||||
|
help='Currency in which rent is calculating', |
||||
|
default=lambda self: self.env.user.company_id |
||||
|
.currency_id.id) |
||||
|
state = fields.Selection([('draft', 'Draft'), |
||||
|
('reserve', 'Reserved'), |
||||
|
('admit', 'Admitted'), ('invoice', 'Invoiced'), |
||||
|
('dis', 'Discharge')], |
||||
|
string='State', readonly=True, |
||||
|
help='State of inpatient', |
||||
|
default="draft") |
||||
|
bed_rent_amount = fields.Monetary(string="Total Bed Rent", |
||||
|
help='Total rent ' |
||||
|
'for stayed ' |
||||
|
'days', |
||||
|
compute='_compute_bed_rent_amount', |
||||
|
copy=False) |
||||
|
invoice_id = fields.Many2one('account.move', string='Invoice', |
||||
|
help='Invoice id of the inpatient', copy=False) |
||||
|
admit_days = fields.Integer(string='Days', |
||||
|
help='Number of days the inpatient admitted', |
||||
|
compute='_compute_admit_days', |
||||
|
copy=False) |
||||
|
bed_type = fields.Selection([('gatch', 'Gatch Bed'), |
||||
|
('electric', 'Electric'), |
||||
|
('stretcher', 'Stretcher'), |
||||
|
('low', 'Low Bed'), |
||||
|
('air', 'Low Air Loss'), |
||||
|
('circo', 'Circo Electric'), |
||||
|
('clinitron', 'Clinitron'), |
||||
|
], string="Bed Type", |
||||
|
help='Indicates the type of bed') |
||||
|
is_ward = fields.Selection([('ward', 'Ward'), ('room', 'Room')], |
||||
|
string='Room/Ward', |
||||
|
help='Choose where the patient is admitted to') |
||||
|
payment_ids = fields.One2many('inpatient.payment', |
||||
|
'inpatient_id', |
||||
|
string='Payment Details', |
||||
|
help='Payment details of the patient') |
||||
|
is_invoice = fields.Boolean(string='Is Invoice', |
||||
|
help='View invoice button will be visible if ' |
||||
|
'this field is true') |
||||
|
prescription_ids = fields.One2many('prescription.line', |
||||
|
'inpatient_id', |
||||
|
string='Prescription', |
||||
|
help='Medical prescriptions of patient') |
||||
|
enable_outpatient = fields.Boolean(string='Prescription History', |
||||
|
help='If checked, the prescription ' |
||||
|
'history of the patient will be ' |
||||
|
'added') |
||||
|
lab_test_ids = fields.One2many('patient.lab.test', |
||||
|
'inpatient_id', |
||||
|
string='Lab Test', |
||||
|
help='Lab tests of the inpatient') |
||||
|
test_count = fields.Integer(string='Test Created', |
||||
|
help='Number of tests of the inpatient', |
||||
|
compute='_compute_test_count') |
||||
|
test_ids = fields.One2many('patient.lab.test', |
||||
|
'inpatient_id', string='Test Line', |
||||
|
help='Details of the lab test') |
||||
|
surgery_ids = fields.One2many('inpatient.surgery', |
||||
|
'inpatient_id', |
||||
|
string='Surgery/Operation', |
||||
|
help='Surgery details of the patient') |
||||
|
room_rent = fields.Monetary(string='Rent per day', help='Rent for the room', |
||||
|
related='room_id.rent') |
||||
|
room_rent_amount = fields.Monetary(string="Total Room Rent", |
||||
|
compute='_compute_room_rent_amount', |
||||
|
help='Total rent for the room', |
||||
|
copy=False) |
||||
|
|
||||
|
@api.model |
||||
|
def create(self, vals): |
||||
|
"""Sequence number generation""" |
||||
|
if vals.get('name', 'New') == 'New': |
||||
|
vals['name'] = self.env['ir.sequence'].next_by_code( |
||||
|
'hospital.inpatient') or 'New' |
||||
|
return super().create(vals) |
||||
|
|
||||
|
@api.depends('test_ids') |
||||
|
def _compute_test_count(self): |
||||
|
"""Method for computing test count""" |
||||
|
self.test_count = self.env['lab.test.line'].sudo().search_count( |
||||
|
[('id', 'in', self.test_ids.ids)]) |
||||
|
|
||||
|
def _compute_admit_days(self): |
||||
|
"""Method for computing admit days""" |
||||
|
if self.hosp_date: |
||||
|
if self.discharge_date: |
||||
|
self.admit_days = (self.discharge_date - self.hosp_date + |
||||
|
datetime.timedelta(days=1)).days |
||||
|
else: |
||||
|
self.admit_days = (fields.date.today() - self.hosp_date + |
||||
|
datetime.timedelta(days=1)).days |
||||
|
|
||||
|
@api.depends('hosp_date', 'discharge_date', |
||||
|
'admit_days', 'room_id') |
||||
|
def _compute_room_rent_amount(self): |
||||
|
"""Method for computing room rent amount""" |
||||
|
if self.hosp_date: |
||||
|
if self.discharge_date: |
||||
|
self.admit_days = (self.discharge_date - self.hosp_date + |
||||
|
datetime.timedelta(days=1)).days |
||||
|
self.room_rent_amount = self.room_id.rent * self.admit_days |
||||
|
else: |
||||
|
self.admit_days = (fields.date.today() - self.hosp_date + |
||||
|
datetime.timedelta(days=1)).days |
||||
|
self.room_rent_amount = self.room_id.rent * self.admit_days |
||||
|
self.room_rent_amount = self.room_id.rent * self.admit_days |
||||
|
|
||||
|
@api.depends('hosp_date', 'discharge_date', 'room_rent_amount', |
||||
|
'admit_days') |
||||
|
def _compute_bed_rent_amount(self): |
||||
|
"""Method for computing bed rent amount""" |
||||
|
if self.hosp_date: |
||||
|
if self.discharge_date: |
||||
|
self.admit_days = (self.discharge_date - self.hosp_date + |
||||
|
datetime.timedelta(days=1)).days |
||||
|
self.bed_rent_amount = self.bed_id.bed_rent * self.admit_days |
||||
|
else: |
||||
|
self.admit_days = (fields.date.today() - self.hosp_date + |
||||
|
datetime.timedelta(days=1)).days |
||||
|
self.bed_rent_amount = self.bed_id.bed_rent * self.admit_days |
||||
|
else: |
||||
|
self.bed_rent_amount = self.bed_id.bed_rent |
||||
|
|
||||
|
@api.onchange('enable_outpatient') |
||||
|
def _onchange_enable_outpatient(self): |
||||
|
"""Method for adding prescription lines of patient""" |
||||
|
self.prescription_ids = False |
||||
|
if self.enable_outpatient: |
||||
|
outpatient_id = self.env['hospital.outpatient'].sudo().search( |
||||
|
[('patient_id', '=', self.patient_id.id)]) |
||||
|
self.sudo().write({ |
||||
|
'prescription_ids': [(0, 0, { |
||||
|
'medicine_id': rec.medicine_id.id, |
||||
|
'quantity': rec.quantity, |
||||
|
'no_intakes': rec.no_intakes, |
||||
|
'note': rec.note, |
||||
|
'time': rec.time, |
||||
|
}) for rec in outpatient_id.prescription_ids] |
||||
|
}) |
||||
|
|
||||
|
@api.onchange('bed_type') |
||||
|
def _onchange_bed_type(self): |
||||
|
"""Method for filtering beds according to the bed type""" |
||||
|
return {'domain': { |
||||
|
'bed_id': [ |
||||
|
('bed_type', '=', self.bed_type), |
||||
|
('state', '=', 'avail') |
||||
|
], 'room_id': [ |
||||
|
('bed_type', '=', self.bed_type), |
||||
|
('state', '=', 'avail') |
||||
|
]}} |
||||
|
|
||||
|
def action_view_invoice(self): |
||||
|
"""Method for viewing Invoice""" |
||||
|
self.ensure_one() |
||||
|
return { |
||||
|
'name': 'inpatient Invoice', |
||||
|
'view_mode': 'tree,form', |
||||
|
'res_model': 'account.move', |
||||
|
'type': 'ir.actions.act_window', |
||||
|
'domain': [('ref', '=', self.name)], |
||||
|
'context': "{'create':False}" |
||||
|
} |
||||
|
|
||||
|
def action_view_tests(self): |
||||
|
"""Returns all lab tests""" |
||||
|
return { |
||||
|
'name': 'Lab Tests', |
||||
|
'res_model': 'patient.lab.test', |
||||
|
'view_mode': 'tree,form', |
||||
|
'type': 'ir.actions.act_window', |
||||
|
'domain': [('inpatient_id', '=', self.id)] |
||||
|
} |
||||
|
|
||||
|
def action_create_lab_test(self): |
||||
|
"""Function for creating lab test""" |
||||
|
return { |
||||
|
'name': 'Create Lab Test', |
||||
|
'res_model': 'lab.test.line', |
||||
|
'view_mode': 'form', |
||||
|
'views': [[False, 'form']], |
||||
|
'target': 'current', |
||||
|
'type': 'ir.actions.act_window', |
||||
|
'context': { |
||||
|
'default_patient_id': self.patient_id.id, |
||||
|
'default_doctor_id': self.attending_doctor_id.id, |
||||
|
'default_patient_type': 'inpatient', |
||||
|
'default_ip_id': self.id |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
def action_view_test(self): |
||||
|
"""View test details""" |
||||
|
return { |
||||
|
'name': 'Created Tests', |
||||
|
'res_model': 'lab.test.line', |
||||
|
'view_mode': 'tree,form', |
||||
|
'target': 'current', |
||||
|
'type': 'ir.actions.act_window', |
||||
|
'domain': [ |
||||
|
('patient_type', '=', 'inpatient'), |
||||
|
('ip_id', '=', self.id) |
||||
|
] |
||||
|
} |
||||
|
|
||||
|
def action_reserve(self): |
||||
|
"""Method for inpatient reservation""" |
||||
|
if self.bed_id: |
||||
|
self.bed_id.state = 'not' |
||||
|
if self.room_id: |
||||
|
self.room_id.state = 'reserve' |
||||
|
self.sudo().write({ |
||||
|
'state': "reserve" |
||||
|
}) |
||||
|
|
||||
|
def action_admit(self): |
||||
|
"""Method for patient admission""" |
||||
|
if self.bed_id: |
||||
|
self.bed_id.state = 'not' |
||||
|
if self.room_id: |
||||
|
self.room_id.state = 'not' |
||||
|
self.sudo().write({ |
||||
|
'state': "admit" |
||||
|
}) |
||||
|
|
||||
|
def action_discharge(self): |
||||
|
"""Method for patient discharge""" |
||||
|
if self.bed_id: |
||||
|
self.bed_id.state = 'avail' |
||||
|
if self.room_id: |
||||
|
self.room_id.state = 'avail' |
||||
|
self.sudo().write({ |
||||
|
'state': "dis" |
||||
|
}) |
||||
|
self.active = False |
||||
|
|
||||
|
def action_invoice(self): |
||||
|
"""Method for creating invoice""" |
||||
|
self.is_invoice = True |
||||
|
self.state = 'invoice' |
||||
|
inv_line_list = [] |
||||
|
invoice = self.env['account.move.line'].sudo().search( |
||||
|
[('move_id.partner_id', '=', self.patient_id.id), |
||||
|
('move_id.state', '=', 'draft'), |
||||
|
('group_tax_id', '=', False), |
||||
|
('date_maturity', '=', False), |
||||
|
('move_id.move_type', '=', 'out_invoice')]) |
||||
|
for rec in self: |
||||
|
if rec.bed_rent_amount: |
||||
|
inv_line_list.append((0, 0, {'name': 'Room/Bed Rent Amount', |
||||
|
'price_unit': rec.bed_rent_amount, |
||||
|
'quantity': rec.admit_days, |
||||
|
})) |
||||
|
elif rec.room_rent_amount: |
||||
|
inv_line_list.append((0, 0, {'name': 'Room/Bed Rent Amount', |
||||
|
'price_unit': rec.room_rent_amount, |
||||
|
'quantity': rec.admit_days, |
||||
|
})) |
||||
|
for line in rec.payment_ids: |
||||
|
inv_line_list.append((0, 0, {'name': line.name, |
||||
|
'price_unit': line.subtotal, |
||||
|
'quantity': 1, |
||||
|
'tax_ids': line.tax_ids |
||||
|
})) |
||||
|
for line in self.test_ids: |
||||
|
if not line.invoice_id: |
||||
|
inv_line_list.append((0, 0, { |
||||
|
'name': line.test_id.name, |
||||
|
'price_unit': line.total_price, |
||||
|
'quantity': 1 |
||||
|
})) |
||||
|
for line in self.prescription_ids: |
||||
|
inv_line_list.append((0, 0, { |
||||
|
'name': line.medicine_id.name, |
||||
|
'price_unit': line.medicine_id.list_price, |
||||
|
'quantity': line.quantity |
||||
|
})) |
||||
|
if invoice: |
||||
|
for line in invoice.read( |
||||
|
['name', 'price_unit', 'quantity']): |
||||
|
inv_line_list.append((0, 0, {'name': line['name'], |
||||
|
'price_unit': line[ |
||||
|
'price_unit'], |
||||
|
'quantity': line['quantity']})) |
||||
|
move = self.env['account.move'].sudo().create({ |
||||
|
'move_type': 'out_invoice', |
||||
|
'date': fields.Date.today(), |
||||
|
'ref': self.name, |
||||
|
'invoice_date': fields.Date.today(), |
||||
|
'partner_id': self.patient_id.id, |
||||
|
'line_ids': inv_line_list |
||||
|
}) |
||||
|
self.invoice_id = move.id |
||||
|
for rec in invoice: |
||||
|
rec.move_id.button_cancel() |
||||
|
return { |
||||
|
'name': 'Invoice', |
||||
|
'res_model': 'account.move', |
||||
|
'view_mode': 'form', |
||||
|
'view_Id': self.env.ref('account.view_move_form').id, |
||||
|
'context': "{'move_type':'out_invoice'}", |
||||
|
'type': 'ir.actions.act_window', |
||||
|
'res_id': move.id |
||||
|
} |
||||
|
|
||||
|
def create_new_in_patient(self, domain): |
||||
|
"""Create in-patient from receptionist dashboard""" |
||||
|
if domain: |
||||
|
patient = self.env['hospital.inpatient'].sudo().search( |
||||
|
[('patient_id', '=', domain['patient_id'])]) |
||||
|
if patient: |
||||
|
return 'Patient already exists' |
||||
|
else: |
||||
|
self.sudo().create({ |
||||
|
'patient_id': domain['patient_id'], |
||||
|
'reason': domain['reason_of_admission'], |
||||
|
'type_admission': domain['admission_type'], |
||||
|
'attending_doctor_id': domain['attending_doctor_id'], |
||||
|
}) |
||||
|
|
||||
|
def fetch_inpatient(self, domain): |
||||
|
"""Returns inpatient details to display on the doctor's dashboard""" |
||||
|
if domain: |
||||
|
return self.env['hospital.inpatient'].sudo().search( |
||||
|
['|', '|', '|', '|', ('name', 'ilike', domain), |
||||
|
('patient_id.name', 'ilike', domain), |
||||
|
('hosp_date', 'ilike', domain), |
||||
|
('discharge_date', 'ilike', domain), |
||||
|
('state', 'ilike', domain)]).read( |
||||
|
['name', 'patient_id', 'ward_id', 'bed_id', |
||||
|
'hosp_date', 'discharge_date', 'type_admission', |
||||
|
'attending_doctor_id', |
||||
|
'state']) |
||||
|
else: |
||||
|
return self.env['hospital.inpatient'].sudo().search_read( |
||||
|
fields=['name', 'patient_id', 'ward_id', 'bed_id', 'hosp_date', |
||||
|
'discharge_date', 'attending_doctor_id', 'state']) |
||||
|
|
||||
|
def action_print_prescription(self): |
||||
|
"""Method for printing prescription""" |
||||
|
data = False |
||||
|
p_list = [] |
||||
|
for rec in self.prescription_ids: |
||||
|
p_list.append({ |
||||
|
'medicine': rec.medicine_id.name, |
||||
|
'intake': rec.no_intakes, |
||||
|
'time': rec.time.capitalize(), |
||||
|
'quantity': rec.quantity, |
||||
|
'note': rec.note.capitalize(), |
||||
|
}) |
||||
|
data = { |
||||
|
'datas': p_list, |
||||
|
'date': fields.date.today(), |
||||
|
'patient_name': self.patient_id.name, |
||||
|
'doctor_name': self.attending_doctor_id.name, |
||||
|
} |
||||
|
return self.env.ref( |
||||
|
'base_hospital_management.action_report_patient_prescription'). \ |
||||
|
report_action(self, data=data) |
||||
|
|
||||
|
@api.model |
||||
|
def hospital_inpatient_list(self): |
||||
|
"""Returns list of inpatients to doctor's dashboard""" |
||||
|
patient_list = [] |
||||
|
patients = self.sudo().search([]) |
||||
|
patient_type = {'emergency': 'Emergency Admission', |
||||
|
'routine': 'Routine Admission'} |
||||
|
for rec in patients: |
||||
|
patient_list.append({ |
||||
|
'id': rec.id, |
||||
|
'name': rec.name, |
||||
|
'patient_id': rec.patient_id.name, |
||||
|
'bed_id': rec.bed_id.name, |
||||
|
'ward_id': rec.ward_id.ward_no, |
||||
|
'room_id': rec.room_id, |
||||
|
'hosp_date': rec.hosp_date, |
||||
|
'attending_doctor_id': rec.attending_doctor_id._origin.name, |
||||
|
'admission_type': patient_type[rec.type_admission], |
||||
|
'discharge_date': rec.discharge_date |
||||
|
}) |
||||
|
return patient_list |
@ -0,0 +1,38 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class HospitalInsurance(models.Model): |
||||
|
"""Class holding insurance details""" |
||||
|
_name = 'hospital.insurance' |
||||
|
_description = 'Hospital Insurance' |
||||
|
|
||||
|
name = fields.Char(string='Provider', help='Name of the insurance provider') |
||||
|
currency_id = fields.Many2one('res.currency', string='Currency', |
||||
|
help='Currency in which insurance will be ' |
||||
|
'calculated', |
||||
|
default=lambda self: self.env.user.company_id |
||||
|
.currency_id.id, |
||||
|
required=True) |
||||
|
total_coverage = fields.Monetary(string='Total Coverage', |
||||
|
help='Total coverage of the insurance') |
@ -0,0 +1,65 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class HospitalLaboratory(models.Model): |
||||
|
"""Class holding laboratory details""" |
||||
|
_name = 'hospital.laboratory' |
||||
|
_description = 'Hospital Laboratory' |
||||
|
|
||||
|
notes = fields.Text(string='Notes', help='Notes regarding the laboratory') |
||||
|
image_130 = fields.Image(max_width=128, max_height=128, string='Image', |
||||
|
help='Image of the laboratory') |
||||
|
phone = fields.Char(string='Phone', help='Phone number of laboratory') |
||||
|
mobile = fields.Char(string='Mobile', help='Mobile number of' |
||||
|
' laboratory') |
||||
|
email = fields.Char(string='Email', help='Email of the laboratory') |
||||
|
street = fields.Char(string='Street', help='Street name of lab') |
||||
|
street2 = fields.Char(string='Street2', help='Street2 name of lab') |
||||
|
zip = fields.Char(string='Zip', help='Zip code of lab') |
||||
|
city = fields.Char(string='City', help="City of lab") |
||||
|
state_id = fields.Many2one("res.country.state", |
||||
|
string='State', |
||||
|
help='State of lab') |
||||
|
country_id = fields.Many2one('res.country', |
||||
|
related='state_id.country_id', |
||||
|
string='Country', |
||||
|
help='Country name of lab') |
||||
|
note = fields.Text(string='Note', help='Notes regarding lab') |
||||
|
name = fields.Char(string='Lab Sequence', help='Sequence number for lab', |
||||
|
copy=False, |
||||
|
readonly=True, index=1, default=lambda self: 'New') |
||||
|
technician_id = fields.Many2one('hr.employee', |
||||
|
string="Lab in charge", |
||||
|
domain=[ |
||||
|
('job_title', '=', 'Lab Technician')], |
||||
|
help='Name of the lab technician who has ' |
||||
|
'the in charge') |
||||
|
|
||||
|
@api.model |
||||
|
def create(self, vals): |
||||
|
"""Method for creating lab sequence number""" |
||||
|
if vals.get('name', 'New') == 'New': |
||||
|
vals['name'] = self.env['ir.sequence'].next_by_code( |
||||
|
'laboratory.sequence') or 'New' |
||||
|
return super().create(vals) |
@ -0,0 +1,317 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
import base64 |
||||
|
from odoo import api, fields, models |
||||
|
from odoo.exceptions import ValidationError |
||||
|
|
||||
|
|
||||
|
class HospitalOutpatient(models.Model): |
||||
|
"""Class holding Outpatient details""" |
||||
|
_name = 'hospital.outpatient' |
||||
|
_description = 'Hospital Outpatient' |
||||
|
_rec_name = 'op_reference' |
||||
|
_inherit = 'mail.thread' |
||||
|
_order = 'op_date desc' |
||||
|
|
||||
|
op_reference = fields.Char(string="OP Reference", readonly=True, |
||||
|
default='New', |
||||
|
help='Op reference number of the patient') |
||||
|
patient_id = fields.Many2one('res.partner', |
||||
|
domain=[('patient_seq', 'not in', |
||||
|
['New', 'Employee', 'User'])], |
||||
|
string='Patient ID', help='Id of the patient', |
||||
|
required=True) |
||||
|
doctor_id = fields.Many2one('doctor.allocation', |
||||
|
string='Doctor', |
||||
|
help='Select the doctor', |
||||
|
required=True, |
||||
|
domain=[('slot_remaining', '>', 0), |
||||
|
('date', '=', fields.date.today()), |
||||
|
('state', '=', 'confirm')]) |
||||
|
op_date = fields.Date(default=fields.Date.today(), string='Date', |
||||
|
help='Date of OP') |
||||
|
reason = fields.Text(string='Reason', help='Reason for visiting hospital') |
||||
|
test_count = fields.Integer(string='Test Created', |
||||
|
help='Number of tests created for the patient', |
||||
|
compute='_compute_test_count') |
||||
|
test_ids = fields.One2many('lab.test.line', 'op_id', |
||||
|
string='Tests', |
||||
|
help='Tests for the patient') |
||||
|
state = fields.Selection( |
||||
|
[('draft', 'Draft'), ('op', 'OP'), ('inpatient', 'In Patient'), |
||||
|
('invoice', 'Invoiced'), ('cancel', 'Canceled')], |
||||
|
default='draft', string='State', help='State of the outpatient') |
||||
|
prescription_ids = fields.One2many('prescription.line', |
||||
|
'outpatient_id', |
||||
|
string='Prescription', |
||||
|
help='Prescription for the patient') |
||||
|
invoiced = fields.Boolean(default=False, string='Invoiced', |
||||
|
help='True for invoiced') |
||||
|
invoice_id = fields.Many2one('account.move', copy=False, |
||||
|
string='Invoice', |
||||
|
help='Invoice of the patient') |
||||
|
attachment_id = fields.Many2one('ir.attachment', |
||||
|
string='Attachment', |
||||
|
help='Attachments related to the' |
||||
|
' outpatient') |
||||
|
active = fields.Boolean(string='Active', help='True for active patients', |
||||
|
default=True) |
||||
|
slot = fields.Float(string='Slot', help='Slot for the patient', |
||||
|
copy=False, readonly=True) |
||||
|
is_sale_created = fields.Boolean(string='Sale Created', |
||||
|
help='True if sale order created') |
||||
|
|
||||
|
@api.model |
||||
|
def create(self, vals): |
||||
|
"""Op number generator""" |
||||
|
if vals.get('op_reference', 'New') == 'New': |
||||
|
last_op = self.search([ |
||||
|
('doctor_id', '=', vals.get('doctor_id')), |
||||
|
('op_reference', '!=', 'New'), |
||||
|
], order='create_date desc', limit=1) |
||||
|
if last_op: |
||||
|
last_number = int(last_op.op_reference[2:]) |
||||
|
new_number = last_number + 1 |
||||
|
vals['op_reference'] = f'OP{str(new_number).zfill(3)}' |
||||
|
else: |
||||
|
vals['op_reference'] = 'OP001' |
||||
|
if self.search([ |
||||
|
('patient_id', '=', vals['patient_id']), |
||||
|
('doctor_id', '=', vals['doctor_id']) |
||||
|
]): |
||||
|
raise ValidationError( |
||||
|
'An OP already exists for this patient under the specified ' |
||||
|
'allocation') |
||||
|
return super().create(vals) |
||||
|
|
||||
|
@api.depends('test_ids') |
||||
|
def _compute_test_count(self): |
||||
|
"""Computes the value of test count""" |
||||
|
self.test_count = len(self.test_ids.ids) |
||||
|
|
||||
|
@api.onchange('op_date') |
||||
|
def _onchange_op_date(self): |
||||
|
"""Method for updating the doamil of doctor_id""" |
||||
|
self.doctor_id = False |
||||
|
return {'domain': {'doctor_id': [('slot_remaining', '>', 0), |
||||
|
('date', '=', self.op_date), |
||||
|
('state', '=', 'confirm'), ( |
||||
|
'patient_type', 'in', |
||||
|
[False, 'outpatient'])]}} |
||||
|
|
||||
|
@api.model |
||||
|
def action_row_click_data(self, op_reference): |
||||
|
"""Returns data to be displayed on clicking op row""" |
||||
|
op_record = self.env['hospital.outpatient'].sudo().search( |
||||
|
[('op_reference', '=', op_reference), |
||||
|
('active', 'in', [True, False])]) |
||||
|
op_data = [op_reference, op_record.patient_id.patient_seq, |
||||
|
op_record.patient_id.name, str(op_record.op_date), |
||||
|
op_record.slot, op_record.reason, |
||||
|
op_record.doctor_id.doctor_id.name, |
||||
|
op_record.is_sale_created] |
||||
|
medicines = [] |
||||
|
for rec in op_record.prescription_ids: |
||||
|
medicines.append( |
||||
|
[rec.medicine_id.name, rec.no_intakes, rec.time, rec.note, |
||||
|
rec.quantity, rec.medicine_id.id]) |
||||
|
return { |
||||
|
'op_data': op_data, |
||||
|
'medicines': medicines |
||||
|
} |
||||
|
|
||||
|
@api.model |
||||
|
def create_medicine_sale_order(self, order_id): |
||||
|
"""Method for creating sale order for medicines""" |
||||
|
order = self.sudo().search([('op_reference', 'ilike', order_id)]) |
||||
|
sale_order = self.env['sale.order'].sudo().create({ |
||||
|
'partner_id': order.patient_id.id, |
||||
|
}) |
||||
|
for i in order.prescription_ids: |
||||
|
self.env['sale.order.line'].sudo().create({ |
||||
|
'product_id': i.medicine_id.id, |
||||
|
'product_uom_qty': i.quantity, |
||||
|
'order': sale_order.id, |
||||
|
}) |
||||
|
self.create_invoice() |
||||
|
|
||||
|
@api.model |
||||
|
def create_file(self, rec_id): |
||||
|
"""Method for creating prescription""" |
||||
|
record = self.env['hospital.outpatient'].sudo().browse(rec_id) |
||||
|
p_list = [] |
||||
|
data = False |
||||
|
for rec in record.prescription_ids: |
||||
|
p_list.append({ |
||||
|
'medicine': rec.medicine_id.name, |
||||
|
'intake': rec.no_intakes, |
||||
|
'time': rec.time.capitalize(), |
||||
|
'quantity': rec.quantity, |
||||
|
'note': rec.note.capitalize() if rec.note else '', |
||||
|
}) |
||||
|
data = { |
||||
|
'datas': p_list, |
||||
|
'date': record.op_date, |
||||
|
'patient_name': record.patient_id.name, |
||||
|
'doctor_name': record.doctor_id.doctor_id.name, |
||||
|
} |
||||
|
pdf = self.env['ir.actions.report'].sudo()._render_qweb_pdf( |
||||
|
'base_hospital_management.action_report_patient_prescription', |
||||
|
rec_id, data=data) |
||||
|
record.attachment_id = self.env['ir.attachment'].sudo().create({ |
||||
|
'datas': base64.b64encode(pdf[0]), |
||||
|
'name': "Prescription", |
||||
|
'type': 'binary', |
||||
|
'res_model': 'hospital.outpatient', |
||||
|
'res_id': rec_id, |
||||
|
}) |
||||
|
return { |
||||
|
'url': f'/web/content' |
||||
|
f'/{record.attachment_id.id}?download=true&' |
||||
|
f';access_token=', |
||||
|
} |
||||
|
|
||||
|
@api.model |
||||
|
def create_new_out_patient(self, kw): |
||||
|
"""Create out patient from receptionist dashboard""" |
||||
|
if kw['id']: |
||||
|
partner = self.env['res.partner'].sudo().search( |
||||
|
['|', ('barcode', '=', kw['id']), |
||||
|
('phone', '=', kw['op_phone'])]) |
||||
|
self.sudo().create({ |
||||
|
'patient_id': partner.id, |
||||
|
'op_date': kw['date'], |
||||
|
'reason': kw['reason'], |
||||
|
'slot': kw['slot'], |
||||
|
'doctor_id': kw['doctor'], |
||||
|
}) |
||||
|
|
||||
|
def action_create_lab_test(self): |
||||
|
"""Button action for creating a lab test""" |
||||
|
return { |
||||
|
'name': 'Create Lab Test', |
||||
|
'res_model': 'lab.test.line', |
||||
|
'view_mode': 'form', |
||||
|
'views': [[False, 'form']], |
||||
|
'target': 'current', |
||||
|
'type': 'ir.actions.act_window', |
||||
|
'context': { |
||||
|
'default_patient_id': self.patient_id.id, |
||||
|
'default_doctor_id': self.doctor_id.id, |
||||
|
'default_patient_type': 'outpatient', |
||||
|
'default_op_id': self.id |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
def action_view_test(self): |
||||
|
"""Method for viewing all lab tests""" |
||||
|
return { |
||||
|
'name': 'Created Tests', |
||||
|
'res_model': 'lab.test.line', |
||||
|
'view_mode': 'tree,form', |
||||
|
'target': 'current', |
||||
|
'type': 'ir.actions.act_window', |
||||
|
'domain': [ |
||||
|
('patient_type', '=', 'outpatient'), |
||||
|
('op_id', '=', self.id) |
||||
|
] |
||||
|
} |
||||
|
|
||||
|
def action_convert_to_inpatient(self): |
||||
|
"""Converts an outpatient to inpatient""" |
||||
|
self.state = 'inpatient' |
||||
|
return { |
||||
|
'name': 'Convert to Inpatient', |
||||
|
'res_model': 'hospital.inpatient', |
||||
|
'view_mode': 'form', |
||||
|
'target': 'current', |
||||
|
'type': 'ir.actions.act_window', |
||||
|
'context': { |
||||
|
'default_patient_id': self.patient_id.id, |
||||
|
'default_attending_doctor_id': self.doctor_id.doctor_id.id, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
def action_op_cancel(self): |
||||
|
"""Button action for cancelling an op""" |
||||
|
self.state = 'cancel' |
||||
|
|
||||
|
def action_confirm(self): |
||||
|
"""Button action for confirming an op""" |
||||
|
if self.doctor_id.latest_slot == 0: |
||||
|
self.slot = self.doctor_id.work_from |
||||
|
else: |
||||
|
self.slot = self.doctor_id.latest_slot + self.doctor_id.time_avg |
||||
|
self.doctor_id.latest_slot = self.slot |
||||
|
self.state = 'op' |
||||
|
|
||||
|
def create_invoice(self): |
||||
|
"""Method for creating invoice""" |
||||
|
self.state = 'invoice' |
||||
|
self.invoice_id = self.env['account.move'].sudo().create({ |
||||
|
'move_type': 'out_invoice', |
||||
|
'date': fields.Date.today(), |
||||
|
'invoice_date': fields.Date.today(), |
||||
|
'partner_id': self.patient_id.id, |
||||
|
'invoice_line_ids': [( |
||||
|
0, 0, { |
||||
|
'name': 'Consultation fee', |
||||
|
'quantity': 1, |
||||
|
'price_unit': self.doctor_id.doctor_id.consultancy_charge, |
||||
|
} |
||||
|
)] |
||||
|
}) |
||||
|
self.invoiced = True |
||||
|
|
||||
|
def action_view_invoice(self): |
||||
|
"""Method for viewing invoice""" |
||||
|
return { |
||||
|
'name': 'Invoice', |
||||
|
'domain': [('id', '=', self.invoice_id.id)], |
||||
|
'type': 'ir.actions.act_window', |
||||
|
'res_model': 'account.move', |
||||
|
'view_mode': 'tree,form', |
||||
|
'context': {'create': False}, |
||||
|
} |
||||
|
|
||||
|
def action_print_prescription(self): |
||||
|
"""Method for printing prescription""" |
||||
|
data = False |
||||
|
p_list = [] |
||||
|
for rec in self.prescription_ids: |
||||
|
datas = { |
||||
|
'medicine': rec.medicine_id.name, |
||||
|
'intake': rec.no_intakes, |
||||
|
'time': rec.time.capitalize(), |
||||
|
'quantity': rec.quantity, |
||||
|
'note': rec.note.capitalize(), |
||||
|
} |
||||
|
p_list.append(datas) |
||||
|
data = { |
||||
|
'datas': p_list, |
||||
|
'date': self.op_date, |
||||
|
'patient_name': self.patient_id.name, |
||||
|
'doctor_name': self.doctor_id.doctor_id.name, |
||||
|
} |
||||
|
return self.env.ref( |
||||
|
'base_hospital_management.action_report_patient_prescription'). \ |
||||
|
report_action(self, data=data) |
@ -0,0 +1,156 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class HospitalPharmacy(models.Model): |
||||
|
"""Class holding Pharmacy details.""" |
||||
|
_name = 'hospital.pharmacy' |
||||
|
_description = 'Pharmacy' |
||||
|
|
||||
|
name = fields.Char(string="Name", help='Name of the pharmacy', |
||||
|
required=True) |
||||
|
pharmacist_id = fields.Many2one('hr.employee', |
||||
|
string="Pharmacist", |
||||
|
help='Name of the pharmacist', |
||||
|
domain=[ |
||||
|
('job_id.name', '=', 'Pharmacist')]) |
||||
|
phone = fields.Char(string='Phone', help='Phone number of the pharmacy') |
||||
|
mobile = fields.Char(string='Mobile', help='Mobile number of the pharmacy') |
||||
|
email = fields.Char(string='Email', help='Email of the pharmacy') |
||||
|
street = fields.Char(string='Street', help='Street of pharmacy') |
||||
|
street2 = fields.Char(string='Street2', help='Street2 of pharmacy') |
||||
|
zip = fields.Char(string='Zip', help='Zip code of pharmacy') |
||||
|
city = fields.Char(string='City', help='City of pharmacy') |
||||
|
state_id = fields.Many2one("res.country.state", string='State', |
||||
|
help='State of pharmacy') |
||||
|
country_id = fields.Many2one('res.country', string='Country', |
||||
|
help='Country of pharmacy') |
||||
|
notes = fields.Text(string='Notes', help='Notes regarding pharmacy') |
||||
|
image_129 = fields.Image(string='Image', help='Image of pharmacy', |
||||
|
max_width=128, max_height=128) |
||||
|
active = fields.Boolean(string='Active', help='True for active pharmacy', |
||||
|
default=True) |
||||
|
medicine_ids = fields.One2many('pharmacy.medicine', |
||||
|
'pharmacy_id', |
||||
|
string='Pharmacy', |
||||
|
help='Indicates the medicines in the ' |
||||
|
'pharmacy') |
||||
|
sales_team_id = fields.Many2one('crm.team', string='Sales Team', |
||||
|
help='Choose the sales-team for the' |
||||
|
' pharmacy') |
||||
|
|
||||
|
@api.model |
||||
|
def create(self, vals): |
||||
|
"""Method for creating CRM team""" |
||||
|
team_id = self.env['crm.team'].sudo().create({ |
||||
|
'name': vals['name'] + ' Pharmacy Team', |
||||
|
'company_id': False, |
||||
|
'user_id': self.env.uid |
||||
|
}) |
||||
|
vals['sales_team_id'] = team_id.id |
||||
|
return super().create(vals) |
||||
|
|
||||
|
@api.model |
||||
|
def create_sale_order(self, kwargs): |
||||
|
"""Creating sale order from pharmacy dashboard""" |
||||
|
if 'op' not in kwargs.keys(): |
||||
|
patient_id = self.env['res.partner'].sudo().search( |
||||
|
[('name', '=', kwargs['name']), ('email', '=', kwargs['email'])]) |
||||
|
else: |
||||
|
patient_id = self.env['hospital.outpatient'].sudo().search( |
||||
|
[('op_reference', '=', kwargs['op'])]).patient_id |
||||
|
if not patient_id: |
||||
|
patient_id = self.env['res.partner'].sudo().create({ |
||||
|
'name': kwargs['name'], |
||||
|
'email': kwargs['email'], |
||||
|
}) |
||||
|
pharmacy_sale_order = self.env['sale.order'].sudo().create({ |
||||
|
'partner_id': patient_id.id, |
||||
|
}) |
||||
|
for rec in kwargs['products']: |
||||
|
pharmacy_sale_order.sudo().write({ |
||||
|
'order_line': [(0, 0, { |
||||
|
'product_id': self.env['product.product'].search([('product_tmpl_id', '=', int(rec['product']))]).id, |
||||
|
'product_uom_qty': float(rec['qty']), |
||||
|
'price_unit': float(rec['price']) if 'price' in rec.keys() else |
||||
|
self.env['product.product'].search([('product_tmpl_id', '=', int(rec['product']))]).list_price |
||||
|
})] |
||||
|
}) |
||||
|
pharmacy_sale_order.action_confirm() |
||||
|
if 'op' in kwargs.keys(): |
||||
|
self.env['hospital.outpatient'].sudo().search( |
||||
|
[('op_reference', '=', kwargs['op'])]).write( |
||||
|
{ |
||||
|
'is_sale_created': True |
||||
|
}) |
||||
|
return {'invoice_id': pharmacy_sale_order.id, 'invoice': pharmacy_sale_order.name} |
||||
|
|
||||
|
@api.model |
||||
|
def company_currency(self): |
||||
|
"""Currency symbol of current company""" |
||||
|
return self.env.user.company_id.currency_id.symbol |
||||
|
|
||||
|
@api.model |
||||
|
def tax_amount(self, kw): |
||||
|
"""Amount in tax of selected product in pharmacy""" |
||||
|
return { |
||||
|
'amount': self.env['account.tax'].sudo().browse(kw).amount |
||||
|
} |
||||
|
|
||||
|
def action_get_inventory(self): |
||||
|
"""Inventory adjustment for medicine""" |
||||
|
med_list = [] |
||||
|
for med in self.medicine_ids.product_id: |
||||
|
for product in self.env['product.product'].sudo().search([]): |
||||
|
if med.id == product.product_tmpl_id.id: |
||||
|
med_list.append(product.id) |
||||
|
return { |
||||
|
'name': 'medicine', |
||||
|
'domain': ['&', ('product_id', 'in', med_list), |
||||
|
('location_id.usage', '=', 'internal')], |
||||
|
'type': 'ir.actions.act_window', |
||||
|
'res_model': 'stock.quant', |
||||
|
'view_id': self.env.ref( |
||||
|
'stock.view_stock_quant_tree_inventory_editable').id, |
||||
|
'view_mode': 'tree', |
||||
|
} |
||||
|
|
||||
|
def action_get_sale_order(self): |
||||
|
"""Sale order view of medicine""" |
||||
|
return { |
||||
|
'name': 'Sales', |
||||
|
'res_model': 'sale.order', |
||||
|
'view_mode': 'tree,form', |
||||
|
'domain': [('team_id', '=', self.sales_team_id.id)], |
||||
|
'type': 'ir.actions.act_window', |
||||
|
'context': {'default_team_id': self.sales_team_id.id} |
||||
|
} |
||||
|
|
||||
|
def fetch_sale_orders(self): |
||||
|
"""Method to fetch all sale orders for displaying on pharmacy |
||||
|
dashboard""" |
||||
|
return self.env['sale.order'].search_read( |
||||
|
[('partner_id.patient_seq', 'not in', ['New', 'Employee', |
||||
|
'User'])], |
||||
|
fields=['name', 'create_date', 'partner_id', 'amount_total', |
||||
|
'state']) |
@ -0,0 +1,155 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from datetime import timedelta |
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class HospitalVaccination(models.Model): |
||||
|
"""Class holding Vaccination details""" |
||||
|
_name = 'hospital.vaccination' |
||||
|
_description = "Vaccination Details" |
||||
|
_order = 'name desc' |
||||
|
|
||||
|
name = fields.Char(string='Vaccination Reference', copy=False, |
||||
|
readonly=True, index=True, help='Name of vaccination', |
||||
|
default=lambda self: 'New') |
||||
|
patient_id = fields.Many2one('res.partner', |
||||
|
domain=[('patient_seq', 'not in', |
||||
|
['New', 'Employee', 'User'])], |
||||
|
required=True, |
||||
|
string="Patient", help='Choose the patient') |
||||
|
vaccine_date = fields.Date(string='Vaccination Date', help='Date of ' |
||||
|
'vaccination', |
||||
|
default=fields.Date.today()) |
||||
|
dose = fields.Float(string='Dose', help='Dose of the vaccine') |
||||
|
vaccine_product_id = fields.Many2one('product.template', |
||||
|
domain="[('vaccine_ok', '=', True)]", |
||||
|
string="Vaccine", help='Choose the ' |
||||
|
'vaccine', |
||||
|
required=True) |
||||
|
vaccine_price = fields.Float(related='vaccine_product_id.list_price', |
||||
|
string="Price", help='Price of vaccine') |
||||
|
sale_order_id = fields.Many2one('sale.order', |
||||
|
string='Sale Order', |
||||
|
help='Sale order for the vaccine') |
||||
|
sold = fields.Boolean(string='Sold', help='True if sale order created') |
||||
|
certificate = fields.Binary(string="Certificate", help='Vaccination ' |
||||
|
'certificate') |
||||
|
attachment_id = fields.Many2one('ir.attachment', |
||||
|
string='Attachment', |
||||
|
help='Attachments added to the vaccination') |
||||
|
recurring_vaccine = fields.Boolean(string='Recurring Vaccine', |
||||
|
help='True for recurring vaccinations') |
||||
|
total_vaccine = fields.Integer(string="Total Dose", |
||||
|
help='Total number of vaccines') |
||||
|
next_vaccine_days = fields.Integer(string="Next Vaccine (In Days)", |
||||
|
help='The number of days to next ' |
||||
|
'vaccine') |
||||
|
next_vaccine = fields.Date(string="Next Vaccination Date", |
||||
|
help='Date of next ' |
||||
|
'vaccine', |
||||
|
readonly=True) |
||||
|
|
||||
|
@api.model |
||||
|
def create(self, vals): |
||||
|
"""Inherits create method for creating the vaccination sequence""" |
||||
|
if vals.get('name', 'New') == 'New': |
||||
|
vals['name'] = self.env['ir.sequence'].next_by_code( |
||||
|
'vaccination.sequence') or 'New' |
||||
|
return super().create(vals) |
||||
|
|
||||
|
@api.onchange('next_vaccine_days') |
||||
|
def _onchange_next_vaccine_days(self): |
||||
|
"""Method for updating the field next_vaccine according to the value |
||||
|
of next_vaccine_days""" |
||||
|
if self.next_vaccine_days: |
||||
|
self.sudo().write({'next_vaccine': fields.Date.today() + timedelta( |
||||
|
self.next_vaccine_days)}) |
||||
|
|
||||
|
def action_create_so(self): |
||||
|
"""Method for creating the sale order for vaccines""" |
||||
|
product_id = self.env['product.product'].sudo().search([ |
||||
|
('product_tmpl_id', '=', self.vaccine_product_id.id) |
||||
|
]) |
||||
|
sale = self.env['sale.order'].search([ |
||||
|
('partner_id.id', '=', self.patient_id.id), |
||||
|
('state', '=', 'draft')], limit=1) |
||||
|
if sale: |
||||
|
sale.sudo().write({ |
||||
|
'order_line': [( |
||||
|
0, 0, { |
||||
|
'product_id': product_id[0].id, |
||||
|
'name': self.vaccine_product_id.name, |
||||
|
'price_unit': self.vaccine_price, |
||||
|
'product_uom_qty': self.dose |
||||
|
} |
||||
|
)] |
||||
|
}) |
||||
|
else: |
||||
|
sale = self.env['sale.order'].sudo().create({ |
||||
|
'partner_id': self.patient_id.id, |
||||
|
'date_order': fields.Date.today(), |
||||
|
'order_line': [(0, 0, { |
||||
|
'product_id': product_id[0].id, |
||||
|
'name': self.vaccine_product_id.name, |
||||
|
'price_unit': self.vaccine_price, |
||||
|
'product_uom_qty': self.dose |
||||
|
})] |
||||
|
}) |
||||
|
self.sold = True |
||||
|
self.sale_order_id = sale.id |
||||
|
|
||||
|
def get_sale_order(self): |
||||
|
"""Smart button action for viewing corresponding sale orders""" |
||||
|
return { |
||||
|
'name': 'Sale order', |
||||
|
'res_model': 'sale.order', |
||||
|
'view_mode': 'form', |
||||
|
'type': 'ir.actions.act_window', |
||||
|
'res_id': self.sale_order_id.id |
||||
|
} |
||||
|
|
||||
|
@api.model |
||||
|
def fetch_vaccination_data(self, **kwargs): |
||||
|
"""Method for fetching vaccine data""" |
||||
|
data = self.sudo().search(kwargs['domain']) |
||||
|
context = [] |
||||
|
for rec in data: |
||||
|
self.env.cr.execute( |
||||
|
f"""SELECT id FROM ir_attachment WHERE |
||||
|
res_id = {rec.id} and res_model='hospital.vaccination' """) |
||||
|
attachment_id = False |
||||
|
attachment = self.env.cr.dictfetchall() |
||||
|
if attachment: |
||||
|
attachment_id = attachment[0]['id'] |
||||
|
context.append({ |
||||
|
'id': rec.id, |
||||
|
'name': rec.name, |
||||
|
'patient_id': [rec.patient_id.id, |
||||
|
rec.patient_id.name], |
||||
|
'vaccine_product_id': rec.vaccine_product_id.name, |
||||
|
'vaccine_price': rec.vaccine_price, |
||||
|
'attachment_id': attachment_id, |
||||
|
'view_id': self.env['ir.ui.view'].sudo().search([ |
||||
|
('name', '=', 'hospital.vaccination.view.form')]).id |
||||
|
}) |
||||
|
return context |
@ -0,0 +1,76 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class HospitalWard(models.Model): |
||||
|
"""Class holding Ward details""" |
||||
|
_name = 'hospital.ward' |
||||
|
_description = 'Hospital Ward' |
||||
|
_rec_name = 'ward_no' |
||||
|
|
||||
|
ward_no = fields.Char(string="Name", |
||||
|
required=True, help='Number of the ward') |
||||
|
building_id = fields.Many2one('hospital.building', |
||||
|
string="Block", help='The building to ' |
||||
|
'which the ward ' |
||||
|
'corresponds to') |
||||
|
floor_no = fields.Integer(string="Floor No.", help='The floor to ' |
||||
|
'which the ward ' |
||||
|
'corresponds to') |
||||
|
note = fields.Text(string="Note", help='Note regarding the ward') |
||||
|
bed_count = fields.Integer(string="Count", compute="_compute_bed_count", |
||||
|
help='The bed count') |
||||
|
nurse_ids = fields.Many2many('hr.employee', string='Nurses', |
||||
|
domain="[('job_id','=','Nurse')]", |
||||
|
help='Nurses corresponds to the ward') |
||||
|
ward_facilities_ids = fields.Many2many('room.facility', |
||||
|
string='Facilities', |
||||
|
help='Facilities corresponds to ' |
||||
|
'ward.') |
||||
|
_sql_constraints = [('unique_ward', 'unique (ward_no)', |
||||
|
'Ward number should be unique!')] |
||||
|
|
||||
|
def _compute_bed_count(self): |
||||
|
"""Method for computing bed count""" |
||||
|
for rec in self: |
||||
|
rec.bed_count = rec.env['hospital.bed'].sudo().search_count([( |
||||
|
'ward_id', '=', rec.ward_no)]) |
||||
|
|
||||
|
@api.onchange('building_id') |
||||
|
def _onchange_building_id(self): |
||||
|
"""Returns domain for the field bed_id""" |
||||
|
return {'domain': { |
||||
|
'bed_id': [ |
||||
|
('ward_id', '=', self.id), |
||||
|
]}} |
||||
|
|
||||
|
def action_get_open_bed(self): |
||||
|
"""Returns form view of bed""" |
||||
|
return { |
||||
|
'name': 'Bed', |
||||
|
'domain': [('ward_id', '=', self.ward_no)], |
||||
|
'type': 'ir.actions.act_window', |
||||
|
'res_model': 'hospital.bed', |
||||
|
'view_mode': 'tree', |
||||
|
'context': {'create': False}, |
||||
|
} |
@ -0,0 +1,100 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import fields, models, _ |
||||
|
from odoo.exceptions import ValidationError |
||||
|
|
||||
|
|
||||
|
class HrEmployee(models.Model): |
||||
|
"""Inherited to add more fields and functions""" |
||||
|
_inherit = 'hr.employee' |
||||
|
|
||||
|
doctor = fields.Boolean(string='Doctor', help='True for Doctors') |
||||
|
currency_id = fields.Many2one('res.currency', string='Currency', |
||||
|
help='Currency in which consultation fee ' |
||||
|
'is calculating', |
||||
|
default=lambda self: self.env.user.company_id |
||||
|
.currency_id.id, |
||||
|
required=True) |
||||
|
coach_id = fields.Many2one('hr.employee', string='Coach', |
||||
|
help='Name of the coach') |
||||
|
consultancy_charge = fields.Monetary(string="Consultation Charge", |
||||
|
help='Charge for consultation') |
||||
|
consultancy_type = fields.Selection([('resident', 'Residential'), |
||||
|
('special', 'Specialist')], |
||||
|
string="Consultation Type", |
||||
|
help='Select the type of Consultation') |
||||
|
time_avg = fields.Float(string='Average Time for a Patient', |
||||
|
help="Average Consultation time " |
||||
|
"per Patient in minutes") |
||||
|
degree_ids = fields.Many2many('hospital.degree', |
||||
|
string="Degree", |
||||
|
help='Degrees of staff') |
||||
|
pharmacy_id = fields.Many2one('hospital.pharmacy', |
||||
|
string="Pharmacy", |
||||
|
help='Name of the pharmacy') |
||||
|
specialization_ids = fields.Many2many('doctor.specialization', |
||||
|
string="Specialization", |
||||
|
help="Doctors specialization for" |
||||
|
" an area") |
||||
|
|
||||
|
def action_create_user(self): |
||||
|
"""Updating employee field of res user to true""" |
||||
|
self.ensure_one() |
||||
|
if self.user_id: |
||||
|
raise ValidationError(_("This employee already has an user.")) |
||||
|
return { |
||||
|
'name': _('Create User'), |
||||
|
'type': 'ir.actions.act_window', |
||||
|
'res_model': 'res.users', |
||||
|
'view_mode': 'form', |
||||
|
'view_id': self.env.ref('hr.view_users_simple_form').id, |
||||
|
'target': 'new', |
||||
|
'context': { |
||||
|
'default_create_employee_id': self.id, |
||||
|
'default_name': self.name, |
||||
|
'default_phone': self.work_phone, |
||||
|
'default_mobile': self.mobile_phone, |
||||
|
'default_login': self.work_email, |
||||
|
'default_employee': True |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
def _inverse_work_contact_details(self): |
||||
|
"""Override to prevent creating patient while creating a staff""" |
||||
|
for employee in self: |
||||
|
if not employee.work_contact_id: |
||||
|
employee.work_contact_id = self.env[ |
||||
|
'res.partner'].sudo().create( |
||||
|
{ |
||||
|
'email': employee.work_email, |
||||
|
'mobile': employee.mobile_phone, |
||||
|
'name': employee.name, |
||||
|
'image_1920': employee.image_1920, |
||||
|
'company_id': employee.company_id.id, |
||||
|
'patient_seq': 'Employee' |
||||
|
}) |
||||
|
else: |
||||
|
employee.work_contact_id.sudo().write({ |
||||
|
'email': employee.work_email, |
||||
|
'mobile': employee.mobile_phone, |
||||
|
'patient_seq': 'Employee' |
||||
|
}) |
@ -0,0 +1,37 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class InpatientPayment(models.Model): |
||||
|
"""Class holding Payment details of Inpatient""" |
||||
|
_name = 'inpatient.payment' |
||||
|
_description = "Inpatient Payments" |
||||
|
|
||||
|
name = fields.Char(string='Name', help='Name of payment') |
||||
|
subtotal = fields.Float(string='Subtotal', help='Total payment') |
||||
|
inpatient_id = fields.Many2one('hospital.inpatient', |
||||
|
string='Inpatient', |
||||
|
help='Inpatient related to the payment') |
||||
|
date = fields.Datetime(string='Date', help="Date of payment") |
||||
|
tax_ids = fields.Many2many('account.tax', string='Tax', |
||||
|
help='Tax for the test') |
@ -0,0 +1,90 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class InpatientSurgery(models.Model): |
||||
|
"""Class holding Surgery details""" |
||||
|
_name = 'inpatient.surgery' |
||||
|
_inherit = ["mail.thread", "mail.activity.mixin"] |
||||
|
_description = 'Inpatient Surgery' |
||||
|
|
||||
|
date = fields.Date(dafault=fields.date.today(), string='Date', |
||||
|
help='Date of adding surgery') |
||||
|
planned_date = fields.Datetime(string='Planned Date', |
||||
|
help='Planned date for surgery', |
||||
|
required=True) |
||||
|
name = fields.Char(string='Name', help='Name of the surgery', |
||||
|
required=True) |
||||
|
doctor_id = fields.Many2one('hr.employee', |
||||
|
string="Operating Doctor", |
||||
|
domain=[('job_id.name', '=', 'Doctor')], |
||||
|
help='Doctor responsible for the surgery', |
||||
|
required=True) |
||||
|
inpatient_id = fields.Many2one('hospital.inpatient', |
||||
|
string='Inpatient',required=True, |
||||
|
help='Inpatient to whom surgery is added') |
||||
|
hours_to_take = fields.Float(string='Duration', |
||||
|
help='Time duration for the surgery') |
||||
|
company_id = fields.Many2one('res.company', string='Company', |
||||
|
default=lambda self: self.env.company.id) |
||||
|
state = fields.Selection([('draft', 'Draft'), ('confirmed', 'Confirmed'), |
||||
|
('done', 'Done'), ('cancel', 'Cancel'), |
||||
|
], default='draft', |
||||
|
string='State', help='State of the slot') |
||||
|
|
||||
|
def action_confirm(self): |
||||
|
"""Function for confirming a surgery""" |
||||
|
self.sudo().write({ |
||||
|
'state': 'confirmed' |
||||
|
}) |
||||
|
|
||||
|
def action_cancel(self): |
||||
|
"""Function for cancelling a surgery""" |
||||
|
self.sudo().write({ |
||||
|
'state': 'cancel' |
||||
|
}) |
||||
|
|
||||
|
def action_done(self): |
||||
|
"""Function for change the state to surgery""" |
||||
|
self.sudo().write({ |
||||
|
'state': 'done' |
||||
|
}) |
||||
|
|
||||
|
@api.model |
||||
|
def get_doctor_slot(self): |
||||
|
"""Function for returning surgery details to doctor's dashboard""" |
||||
|
data_list = [] |
||||
|
state = {'confirmed': 'Confirmed', |
||||
|
'cancel': 'Cancel', |
||||
|
'done': 'Done', |
||||
|
'draft': 'Draft'} |
||||
|
for rec in self.sudo().search( |
||||
|
[('doctor_id.user_id', '=', self.env.user.id)]): |
||||
|
data_list.append({ |
||||
|
'id': rec.id, |
||||
|
'planned_date': rec.planned_date, |
||||
|
'patient_id': rec.inpatient_id.patient_id.name, |
||||
|
'surgery_name': rec.name, |
||||
|
'state': state[rec.state] |
||||
|
}) |
||||
|
return data_list |
@ -0,0 +1,33 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import api, models |
||||
|
|
||||
|
|
||||
|
class IrAttachment(models.Model): |
||||
|
"""Inherited for making the attachments public""" |
||||
|
_inherit = 'ir.attachment' |
||||
|
|
||||
|
@api.model |
||||
|
def create(self, vals): |
||||
|
"""Inherited to make the attachments public""" |
||||
|
vals['public'] = True |
||||
|
return super().create(vals) |
@ -0,0 +1,54 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class LabMedicineLine(models.Model): |
||||
|
"""Class holding Lab medicines""" |
||||
|
_name = 'lab.medicine.line' |
||||
|
_description = 'Lab Medicine Line' |
||||
|
|
||||
|
lab_test_id = fields.Many2one('patient.lab.test', |
||||
|
string='Lab Test Line', |
||||
|
help='Lab test corresponds to the medicine') |
||||
|
test_id = fields.Many2one('lab.test', string='Test', |
||||
|
help='Test corresponds to medicine') |
||||
|
medicine_id = fields.Many2one('product.template', |
||||
|
domain="['|', ('medicine_ok', '=', True)," |
||||
|
"('vaccine_ok', '=', True)" |
||||
|
"]", required=True, string='Medicine', |
||||
|
help='Medicine for the lab test') |
||||
|
quantity = fields.Integer(string='Quantity', default=1, |
||||
|
help='Quantity of medicine') |
||||
|
qty_available = fields.Float(string='Available', help='Available quantity', |
||||
|
related='medicine_id.qty_available') |
||||
|
price = fields.Float(string='Price', help='Price for the medicine', |
||||
|
related='medicine_id.list_price') |
||||
|
sub_total = fields.Float(string='Subtotal', |
||||
|
help='Total cost of the medicine', |
||||
|
compute='_compute_sub_total') |
||||
|
|
||||
|
@api.depends('quantity', 'price') |
||||
|
def _compute_sub_total(self): |
||||
|
"""Method for computing total amount""" |
||||
|
for rec in self: |
||||
|
rec.sub_total = rec.price * rec.quantity |
@ -0,0 +1,47 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class LabTest(models.Model): |
||||
|
"""Class holding lab test details""" |
||||
|
_name = 'lab.test' |
||||
|
_description = 'Laboratory Test' |
||||
|
|
||||
|
name = fields.Char(string='Test', help='Name of the test') |
||||
|
patient_lead = fields.Float(string='Result Within', |
||||
|
help='Time taken to get the result') |
||||
|
price = fields.Monetary(string='Price', help="The cost for the test") |
||||
|
currency_id = fields.Many2one('res.currency', string='Currency', |
||||
|
default=lambda self: |
||||
|
self.env.user.company_id.currency_id.id, |
||||
|
required=True, help='Currency in which ' |
||||
|
'payments will be done') |
||||
|
tax_ids = fields.Many2many('account.tax', string='Tax', |
||||
|
help='Tax for the test') |
||||
|
medicine_ids = fields.One2many('lab.medicine.line', |
||||
|
'test_id', |
||||
|
string='Medicines', |
||||
|
help='Medicines used for the test') |
||||
|
test_type = fields.Selection( |
||||
|
[('range', 'Range'), ('objective', 'Objective')], |
||||
|
string='Type', required=True, help='Type of test') |
@ -0,0 +1,126 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import api, fields, models, _ |
||||
|
from odoo.exceptions import UserError |
||||
|
|
||||
|
|
||||
|
class LabTestLine(models.Model): |
||||
|
"""Class holing lab test line details""" |
||||
|
_name = "lab.test.line" |
||||
|
_description = "Lab Test Line" |
||||
|
|
||||
|
name = fields.Char(string='Test Sequence', required=True, |
||||
|
copy=False, readonly=True, index=True, |
||||
|
default=lambda self: 'New', help='Name of lab test line') |
||||
|
patient_id = fields.Many2one('res.partner', string='Patient', |
||||
|
help='Choose the patient', |
||||
|
domain=[('patient_seq', 'not in', |
||||
|
['New', 'Employee', 'User'])]) |
||||
|
doctor_id = fields.Many2one('hr.employee', string='Doctor', |
||||
|
help='Choose the doctor', |
||||
|
domain=[('job_id.name', '=', 'Doctor')]) |
||||
|
date = fields.Date(default=fields.Date.today(), string='Date', |
||||
|
help='Date of test') |
||||
|
test_ids = fields.Many2many('lab.test', string='Test', |
||||
|
help='All the tests') |
||||
|
patient_type = fields.Selection(selection=[ |
||||
|
('inpatient', 'Inpatient'), ('outpatient', 'Outpatient') |
||||
|
], required=True, string='Patient Type', help='Choose the patient type') |
||||
|
op_id = fields.Many2one('hospital.outpatient', string='OP Number', |
||||
|
help='ID of outpatient') |
||||
|
ip_id = fields.Many2one('hospital.inpatient', string='Inpatient ID', |
||||
|
help='ID of inpatient') |
||||
|
state = fields.Selection(selection=[ |
||||
|
('draft', 'Draft'), ('created', 'created') |
||||
|
], default='draft', string='State', help='State of the record') |
||||
|
|
||||
|
@api.model |
||||
|
def create(self, vals): |
||||
|
"""Sequence generation""" |
||||
|
if vals.get('name', 'New') == 'New': |
||||
|
vals['name'] = self.env['ir.sequence'].next_by_code( |
||||
|
'lab_tests.draft.sequence') or 'New' |
||||
|
return super().create(vals) |
||||
|
|
||||
|
def action_confirm(self): |
||||
|
"""Method for confirming the test""" |
||||
|
if not self.test_ids: |
||||
|
raise UserError(_('You need to add a test before posting.')) |
||||
|
self.state = 'created' |
||||
|
self.env['patient.lab.test'].sudo().create({ |
||||
|
'patient_id': self.patient_id.id, |
||||
|
'test_id': self.id, |
||||
|
'patient_type': self.patient_type, |
||||
|
'state': 'draft', |
||||
|
'test_ids': self.test_ids.ids, |
||||
|
}) |
||||
|
|
||||
|
@api.model |
||||
|
def action_get_patient_data(self, rec_id): |
||||
|
"""Method for fetching patient data""" |
||||
|
data = self.env['lab.test.line'].sudo().browse(rec_id) |
||||
|
if data: |
||||
|
patient_data = { |
||||
|
'id': rec_id, |
||||
|
'name': data.patient_id.name, |
||||
|
'unique': data.patient_id.patient_seq, |
||||
|
'email': data.patient_id.email, |
||||
|
'phone': data.patient_id.phone, |
||||
|
'dob': data.patient_id.date_of_birth, |
||||
|
'image_1920': data.patient_id.image_1920, |
||||
|
'gender': data.patient_id.gender, |
||||
|
'status': data.patient_id.marital_status, |
||||
|
'doctor': data.doctor_id.name, |
||||
|
'patient_type': data.patient_type.capitalize(), |
||||
|
'ticket': data.op_id.op_reference |
||||
|
if data.patient_type == 'outpatient' else data.ip_id.name, |
||||
|
'test_data': [] |
||||
|
} |
||||
|
if data.patient_id.blood_group: |
||||
|
blood_caps = data.patient_id.blood_group.capitalize() |
||||
|
patient_data['blood_group'] = blood_caps + str( |
||||
|
data.patient_id.rh_type), |
||||
|
for test in data.test_ids: |
||||
|
hours = int(test.patient_lead) |
||||
|
minutes = int((test.patient_lead - hours) * 60) |
||||
|
patient_data['test_data'].append({ |
||||
|
'id': test.id, |
||||
|
'name': test.name, |
||||
|
'patient_lead': "{:02d}:{:02d}".format(hours, minutes), |
||||
|
'price': test.price, |
||||
|
}) |
||||
|
return patient_data |
||||
|
|
||||
|
@api.model |
||||
|
def create_lab_tests(self, data): |
||||
|
"""Method for creating lab tests""" |
||||
|
test = self.env['lab.test.line'].sudo().browse(data) |
||||
|
test.state = 'created' |
||||
|
self.env['patient.lab.test'].sudo().create({ |
||||
|
'patient_id': test.patient_id.id, |
||||
|
'test_id': test.id, |
||||
|
'patient_type': test.patient_type.lower(), |
||||
|
'state': 'draft', |
||||
|
}) |
||||
|
return { |
||||
|
'message': 'success', |
||||
|
} |
@ -0,0 +1,91 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class LabTestResult(models.Model): |
||||
|
"""Class holding lab test result""" |
||||
|
_name = 'lab.test.result' |
||||
|
_description = 'Lab Test Result' |
||||
|
_rec_name = 'test_id' |
||||
|
|
||||
|
patient_id = fields.Many2one('res.partner', string='Patient', |
||||
|
domain=[('patient_seq', 'not in', |
||||
|
['New', 'Employee', 'User'])], |
||||
|
help='Patient for whom the test has been done') |
||||
|
result = fields.Char(string='Result', help='Result of the test') |
||||
|
normal = fields.Char(string='Normal', help="The normal rate of the test") |
||||
|
uom_id = fields.Many2one('uom.uom', string='Unit', |
||||
|
help='Unit of the normal and result value') |
||||
|
parent_id = fields.Many2one('patient.lab.test', string='Tests', |
||||
|
help='The tests for which the result' |
||||
|
' corresponds to') |
||||
|
test_id = fields.Many2one('lab.test', string="Test Name", |
||||
|
help='Name of the test') |
||||
|
attachment = fields.Binary(string='Result', help='Result document') |
||||
|
currency_id = fields.Many2one('res.currency', |
||||
|
related='test_id.currency_id', |
||||
|
string='Currency', |
||||
|
help='Currency in which payments to be done') |
||||
|
price = fields.Monetary(string='Cost', help='Cost for the test', |
||||
|
related='test_id.price') |
||||
|
tax_ids = fields.Many2many('account.tax', string='Tax', |
||||
|
help='Tax for the test') |
||||
|
state = fields.Selection(selection=[('processing', 'Processing'), |
||||
|
('published', 'Published')], |
||||
|
string='State', help='State of the result', |
||||
|
default='processing', compute='_compute_state') |
||||
|
|
||||
|
@api.depends('attachment') |
||||
|
def _compute_state(self): |
||||
|
"""Method for computing the state of result based on attachment""" |
||||
|
for rec in self: |
||||
|
if rec.attachment: |
||||
|
rec.state = 'published' |
||||
|
else: |
||||
|
rec.state = 'processing' |
||||
|
|
||||
|
@api.model |
||||
|
def print_test_results(self): |
||||
|
"""Method for printing rest result""" |
||||
|
data = self.sudo().search([]) |
||||
|
context = [] |
||||
|
for rec in data: |
||||
|
self.env.cr.execute( |
||||
|
f"""SELECT id FROM ir_attachment WHERE res_id = {rec.id} |
||||
|
and res_model='lab.test.result' """) |
||||
|
attachment_id = False |
||||
|
attachment = self.env.cr.dictfetchall() |
||||
|
if attachment: |
||||
|
attachment_id = attachment[0]['id'] |
||||
|
context.append({ |
||||
|
'id': rec.id, |
||||
|
'parent_id': rec.parent_id.test_id.name, |
||||
|
'patient_id': [rec.parent_id.patient_id.id, |
||||
|
rec.parent_id.patient_id.name], |
||||
|
'test_id': rec.test_id.name, |
||||
|
'attachment_id': attachment_id, |
||||
|
'normal': rec.normal, |
||||
|
'result': rec.result, |
||||
|
'unit': rec.uom_id.name if rec.uom_id else '' |
||||
|
}) |
||||
|
return context |
@ -0,0 +1,34 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class MedicineBrand(models.Model): |
||||
|
"""Model holding all medicine brands""" |
||||
|
_name = 'medicine.brand' |
||||
|
_description = 'Medicine Brand' |
||||
|
|
||||
|
name = fields.Char(string="Brand", help='Name of the brand') |
||||
|
medicine_ids = fields.One2many('product.template', |
||||
|
'medicine_brand_id', |
||||
|
string='Medicine', |
||||
|
help='All medicines belongs to this brand') |
@ -0,0 +1,36 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class NursingPlan(models.Model): |
||||
|
"""Class holding nursing plan""" |
||||
|
_name = 'nursing.plan' |
||||
|
_description = "Nursing Plan" |
||||
|
|
||||
|
admission_id = fields.Many2one('hospital.inpatient', |
||||
|
string='Patient', |
||||
|
help='Name of the inpatient') |
||||
|
date = fields.Datetime(string='Visit Time', help='Date and time of visit') |
||||
|
status = fields.Char(string='Status', |
||||
|
help='Physical condition of the patient') |
||||
|
notes = fields.Text(string='Note', help='You can add the notes here') |
@ -0,0 +1,308 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class PatientLabTest(models.Model): |
||||
|
"""Class holding Patient lab test details""" |
||||
|
_name = 'patient.lab.test' |
||||
|
_description = 'Patient Lab Test' |
||||
|
_rec_name = 'test_id' |
||||
|
|
||||
|
test_id = fields.Many2one('lab.test.line', string='Test', |
||||
|
help='Name of the test') |
||||
|
patient_id = fields.Many2one('res.partner', string="Patient", |
||||
|
domain=[('patient_seq', 'not in', |
||||
|
['New', 'Employee', 'User'])], |
||||
|
required=True, help='Choose the patient') |
||||
|
patient_type = fields.Selection(selection=[ |
||||
|
('inpatient', 'Inpatient'), ('outpatient', 'Outpatient') |
||||
|
], related='test_id.patient_type', string='Type', |
||||
|
help='Choose the type of patient') |
||||
|
test_ids = fields.Many2many('lab.test', |
||||
|
related='test_id.test_ids', string='Tests', |
||||
|
help='All the tests added for the patient') |
||||
|
date = fields.Date(string='Date', help='Date of test', |
||||
|
default=fields.Date.today()) |
||||
|
total_price = fields.Float(string='Price', help='Total price for the test') |
||||
|
currency_id = fields.Many2one('res.currency', string='Currency', |
||||
|
help='Currency in which lab test amount will' |
||||
|
' be calculated', |
||||
|
default=lambda self: self.env.user.company_id |
||||
|
.currency_id.id, |
||||
|
required=True) |
||||
|
state = fields.Selection([('draft', 'Draft'), |
||||
|
('test', 'Test In Progress'), |
||||
|
('completed', 'Completed')], |
||||
|
string='State', readonly=True, |
||||
|
help='State of test', |
||||
|
default="draft") |
||||
|
result_ids = fields.One2many('lab.test.result', |
||||
|
'parent_id', |
||||
|
string="Result", help='Results of the test') |
||||
|
medicine_ids = fields.One2many('lab.medicine.line', |
||||
|
'lab_test_id', |
||||
|
string='Medicine', |
||||
|
compute='_compute_medicine_ids', |
||||
|
readonly=False, |
||||
|
help='Medicines needed for the test') |
||||
|
notes = fields.Text(string='Notes', help='Notes regarding the test') |
||||
|
lab_id = fields.Many2one('hospital.laboratory', string='Lab', |
||||
|
help='Lab in which test is doing') |
||||
|
invoice_id = fields.Many2one('account.move', string='Invoice', |
||||
|
help='Invoice for the test', copy=False) |
||||
|
order = fields.Integer(string='Sale Order', |
||||
|
help='Number of sale orders for vaccines and ' |
||||
|
'medicines', |
||||
|
copy=False) |
||||
|
started = fields.Boolean(string='Test Started', |
||||
|
help='True if the test has been started', |
||||
|
copy=False) |
||||
|
invoiced = fields.Boolean(string='Invoiced', |
||||
|
help='True if the test has been invoiced', |
||||
|
copy=False) |
||||
|
sold = fields.Boolean(string='Sold', |
||||
|
help='If true, sale order smart button will be ' |
||||
|
'visible ', copy=False) |
||||
|
company_id = fields.Many2one('res.company', string='Company', |
||||
|
default=lambda self: self.env.company.id) |
||||
|
invoice_count = fields.Integer(string='Invoice ' |
||||
|
'Count', |
||||
|
compute='_compute_invoice_count', |
||||
|
help='Total number of invoices for this ' |
||||
|
'patient lab test.') |
||||
|
sale_count = fields.Integer(string='Sale ' |
||||
|
'Count', |
||||
|
compute='_compute_sale_count', |
||||
|
help='Total number of sale orders for this ' |
||||
|
'patient lab test.') |
||||
|
inpatient_id = fields.Many2one('hospital.inpatient', |
||||
|
string='Inpatient', |
||||
|
help='Choose the inpatient') |
||||
|
|
||||
|
@api.depends('test_id') |
||||
|
def _compute_medicine_ids(self): |
||||
|
"""Method for computing medicine_ids""" |
||||
|
for record in self: |
||||
|
record.medicine_ids = self.test_ids.medicine_ids |
||||
|
|
||||
|
def _compute_invoice_count(self): |
||||
|
"""Method for computing invoice_count""" |
||||
|
for record in self: |
||||
|
record.invoice_count = self.env['account.move'].sudo().search_count( |
||||
|
['|', ( |
||||
|
'ref', '=', record.test_id.name), ('payment_reference', '=', |
||||
|
record.test_id.name)]) |
||||
|
|
||||
|
def _compute_sale_count(self): |
||||
|
"""Method for computing sale_count""" |
||||
|
for record in self: |
||||
|
record.sale_count = self.env['sale.order'].sudo().search_count([( |
||||
|
'reference', '=', record.test_id.name)]) |
||||
|
|
||||
|
@api.model |
||||
|
def action_get_patient_data(self, rec_id): |
||||
|
"""Returns data to the lab dashboard""" |
||||
|
data = self.sudo().browse(rec_id) |
||||
|
if data: |
||||
|
patient_data = { |
||||
|
'id': rec_id, |
||||
|
'sequence': data.test_id.name, |
||||
|
'name': data.patient_id.name, |
||||
|
'unique': data.patient_id.patient_seq, |
||||
|
'email': data.patient_id.email, |
||||
|
'phone': data.patient_id.phone, |
||||
|
'dob': data.patient_id.date_of_birth, |
||||
|
'image_1920': data.patient_id.image_1920, |
||||
|
'gender': data.patient_id.gender, |
||||
|
'status': data.patient_id.marital_status, |
||||
|
'doctor': data.test_id.doctor_id.name, |
||||
|
'patient_type': data.patient_type.capitalize(), |
||||
|
'state': data.state, |
||||
|
'invoiced': data.invoiced, |
||||
|
'ticket': data.test_id.op_id.op_reference |
||||
|
if data.patient_type == 'outpatient' |
||||
|
else data.test_id.patient_id.patient_seq, |
||||
|
'test_data': [], |
||||
|
'medicine': [], |
||||
|
'result_ids': [], |
||||
|
} |
||||
|
if data.patient_id.blood_group: |
||||
|
blood_caps = data.patient_id.blood_group.capitalize() |
||||
|
patient_data['blood_group'] = blood_caps + str( |
||||
|
data.patient_id.rh_type), |
||||
|
for test in data.test_ids: |
||||
|
patient_data['test_data'].append({ |
||||
|
'id': test.id, |
||||
|
'name': test.name, |
||||
|
'patient_lead': test.patient_lead, |
||||
|
'price': test.price, |
||||
|
}) |
||||
|
for medicine in data.medicine_ids: |
||||
|
patient_data['medicine'].append({ |
||||
|
'id': medicine.medicine_id.id, |
||||
|
'name': medicine.medicine_id.name, |
||||
|
'quantity': medicine.quantity |
||||
|
}) |
||||
|
for result in data.result_ids: |
||||
|
patient_data['result_ids'].append({ |
||||
|
'id': result.id, |
||||
|
'name': result.test_id.name, |
||||
|
'result': result.result, |
||||
|
'normal': result.normal, |
||||
|
'uom_id': result.uom_id.name, |
||||
|
'attachment': result.attachment, |
||||
|
'cost': result.price, |
||||
|
'state': result.state |
||||
|
}) |
||||
|
return patient_data |
||||
|
|
||||
|
@api.model |
||||
|
def start_test(self, rec_id): |
||||
|
"""Method for creating lab tests from lab dashboard""" |
||||
|
data = self.sudo().browse(rec_id) |
||||
|
data.state = 'test' |
||||
|
data.started = True |
||||
|
med_list = data.medicine_ids.ids |
||||
|
for rec in data.test_ids: |
||||
|
medicine_ids = [item for item in rec.medicine_ids.ids] |
||||
|
data.sudo().write({ |
||||
|
'result_ids': [(0, 0, { |
||||
|
'patient_id': data.patient_id.id, |
||||
|
'test_id': rec.id, |
||||
|
'tax_ids': rec.tax_ids.ids |
||||
|
})] |
||||
|
}) |
||||
|
[med_list.append(i) for i in medicine_ids] |
||||
|
data.medicine_ids = med_list |
||||
|
|
||||
|
@api.model |
||||
|
def test_end(self, rec_id): |
||||
|
"""Method for ending test from lab dashboard""" |
||||
|
data = self.sudo().browse(rec_id) |
||||
|
data.state = 'completed' |
||||
|
|
||||
|
@api.model |
||||
|
def create_invoice(self, rec_id): |
||||
|
"""Method for creating invoice""" |
||||
|
data = self.sudo().browse(rec_id) |
||||
|
order_lines = [] |
||||
|
partner_id = data.patient_id.id |
||||
|
if data.medicine_ids: |
||||
|
for rec in data.medicine_ids: |
||||
|
order_lines.append((0, 0, { |
||||
|
'product_id': self.env['product.product'].sudo().search([ |
||||
|
('product_tmpl_id', '=', rec.medicine_id.id)]).id, |
||||
|
'name': rec.medicine_id.name, |
||||
|
'price_unit': rec.price, |
||||
|
'product_uom_qty': rec.quantity, |
||||
|
})) |
||||
|
sale_order = self.env['sale.order'].sudo().create({ |
||||
|
'partner_id': partner_id, |
||||
|
'date_order': fields.Date.today(), |
||||
|
'reference': data.test_id.name, |
||||
|
'order_line': order_lines |
||||
|
}) |
||||
|
data.sold = True |
||||
|
data.order = sale_order.id |
||||
|
invoice_id = self.env['account.move'].sudo().search( |
||||
|
[('ref', '=', data.test_id.name) |
||||
|
], limit=1) |
||||
|
if not invoice_id: |
||||
|
invoice_id = self.env['account.move'].sudo().create({ |
||||
|
'move_type': 'out_invoice', |
||||
|
'partner_id': partner_id, |
||||
|
'invoice_date': fields.Date.today(), |
||||
|
'date': fields.Date.today(), |
||||
|
'ref': data.test_id.name |
||||
|
}) |
||||
|
for rec in data.result_ids: |
||||
|
invoice_id.sudo().write({ |
||||
|
'invoice_line_ids': [( |
||||
|
0, 0, { |
||||
|
'quantity': 1, |
||||
|
'name': rec.test_id.name, |
||||
|
'price_unit': rec.price, |
||||
|
'tax_ids': rec.tax_ids.ids, |
||||
|
'price_subtotal': rec.price, |
||||
|
} |
||||
|
)] |
||||
|
}) |
||||
|
data.invoiced = True |
||||
|
data.invoice_id = invoice_id.id |
||||
|
|
||||
|
def action_test_end(self): |
||||
|
"""Button action for test end""" |
||||
|
self.state = 'completed' |
||||
|
|
||||
|
def action_start_test(self): |
||||
|
"""Button action for start test""" |
||||
|
self.start_test(self.id) |
||||
|
|
||||
|
def action_create_invoice(self): |
||||
|
"""Button action for creating invoice""" |
||||
|
self.create_invoice(self.id) |
||||
|
|
||||
|
def action_view_invoice(self): |
||||
|
"""Method for viewing invoice from the smart button""" |
||||
|
return { |
||||
|
'name': 'Invoice', |
||||
|
'type': 'ir.actions.act_window', |
||||
|
'res_model': 'account.move', |
||||
|
'view_mode': 'tree,form', |
||||
|
"context": {"create": False, 'default_move_type': 'out_invoice'}, |
||||
|
'domain': [('id', '=', self.invoice_id.id)] |
||||
|
} |
||||
|
|
||||
|
def action_view_sale_order(self): |
||||
|
"""Method for viewing sale order from the smart button""" |
||||
|
sale_order = self.env['sale.order'].sudo().search( |
||||
|
[('partner_id', '=', self.patient_id.id)], limit=1) |
||||
|
return { |
||||
|
'name': 'Sale order', |
||||
|
'res_model': 'sale.order', |
||||
|
'view_mode': 'form', |
||||
|
'type': 'ir.actions.act_window', |
||||
|
'res_id': sale_order.id |
||||
|
} |
||||
|
|
||||
|
def print_lab_tests(self): |
||||
|
"""Method for printing the lab test result""" |
||||
|
test_list = [] |
||||
|
for rec in self.result_ids: |
||||
|
datas = { |
||||
|
'test': rec.test_id.test, |
||||
|
'normal': rec.normal, |
||||
|
'uom_id': rec.uom_id.name, |
||||
|
'result': rec.result, |
||||
|
'cost': rec.price, |
||||
|
'currency': self.env.company.currency_id.symbol |
||||
|
} |
||||
|
test_list.append(datas) |
||||
|
data = { |
||||
|
'datas': test_list, |
||||
|
'date': self.date, |
||||
|
'patient_name': self.patient_id.name, |
||||
|
'doctor_name': self.test_id.doctor_id.name |
||||
|
} |
||||
|
return self.env.ref( |
||||
|
'base_hospital_management.action_report_patient_lab_tests').report_action(self, data=data) |
@ -0,0 +1,67 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class PatientRoom(models.Model): |
||||
|
"""Class holding Patient room details""" |
||||
|
_name = 'patient.room' |
||||
|
_description = 'Patient Room' |
||||
|
|
||||
|
name = fields.Char(string="Name", help='The name of room', required=True) |
||||
|
currency_id = fields.Many2one('res.currency', string='Currency', |
||||
|
default=lambda self: self.env.user.company_id |
||||
|
.currency_id.id, |
||||
|
required=True, help='Currency in which ' |
||||
|
'payments will be done') |
||||
|
building_id = fields.Many2one('hospital.building', |
||||
|
string="Block Name", |
||||
|
required=True, help='Building to which ' |
||||
|
'the room corresponds ' |
||||
|
'to') |
||||
|
nurse_ids = fields.Many2many('hr.employee', string='Nurses', |
||||
|
domain="[('job_id.name','=','Nurse')]", |
||||
|
help='Nurses of the room') |
||||
|
bed_type = fields.Selection([('gatch', 'Gatch Bed'), |
||||
|
('electric', 'Electric'), |
||||
|
('stretcher', 'Stretcher'), |
||||
|
('low', 'Low Bed'), |
||||
|
('air', 'Low Air Loss'), |
||||
|
('circo', 'Circo Electric'), |
||||
|
('clinitron', 'Clinitron'), |
||||
|
], string="Bed Type", help='Select the type ' |
||||
|
'of bed') |
||||
|
rent = fields.Monetary(string='Rent', help='Rent for the room') |
||||
|
state = fields.Selection([('avail', 'Available'), |
||||
|
('reserve', 'Reserve'), |
||||
|
('not', 'Unavailable'), ], |
||||
|
string='State', readonly=True, |
||||
|
default="avail", help='State of room') |
||||
|
room_facilities_ids = fields.Many2many('room.facility', |
||||
|
string='Facilities', |
||||
|
help='Facilities of room') |
||||
|
floor_no = fields.Integer(string="Floor No.", help='The floor to ' |
||||
|
'which the room ' |
||||
|
'corresponds to') |
||||
|
|
||||
|
_sql_constraints = [('unique_room', 'unique (name)', |
||||
|
'Room number should be unique!')] |
@ -0,0 +1,42 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class PharmacyMedicine(models.Model): |
||||
|
"""Class holding Pharmacy medicine details""" |
||||
|
_name = 'pharmacy.medicine' |
||||
|
_description = 'pharmacy Medicine' |
||||
|
_rec_name = 'product_id' |
||||
|
|
||||
|
product_id = fields.Many2one('product.template', |
||||
|
string='Medicine', |
||||
|
help='Name of medicine', |
||||
|
domain="[('medicine_ok', '=', True)]") |
||||
|
pharmacy_id = fields.Many2one('hospital.pharmacy', |
||||
|
string='Pharmacy', |
||||
|
help='Name of pharmacy') |
||||
|
qty_available = fields.Float(related='product_id.qty_available', |
||||
|
string='Available Quantity', |
||||
|
help='The quantity of product available') |
||||
|
list_price = fields.Float(related='product_id.list_price', string='Price', |
||||
|
help='Price of the medicine') |
@ -0,0 +1,65 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class PrescriptionLine(models.Model): |
||||
|
"""Class holding prescription line details""" |
||||
|
_name = 'prescription.line' |
||||
|
_description = 'Prescription Lines' |
||||
|
_rec_name = 'prescription_id' |
||||
|
|
||||
|
prescription_id = fields.Many2one('hospital.prescription', |
||||
|
string='Prescription', |
||||
|
help='Name of the prescription') |
||||
|
medicine_id = fields.Many2one('product.template', domain=[ |
||||
|
'|', ('medicine_ok', '=', True), ('vaccine_ok', '=', True)], |
||||
|
string='Medicine', required=True, |
||||
|
help='Medicines or vaccines') |
||||
|
quantity = fields.Integer(string='Quantity', required=True, |
||||
|
help="The number of medicines for the time " |
||||
|
"period") |
||||
|
no_intakes = fields.Float(string='Intakes', required=True, |
||||
|
help="How much medicine want to take") |
||||
|
time = fields.Selection( |
||||
|
[('once', 'Once in a day'), ('twice', 'Twice in a Day'), |
||||
|
('thrice', 'Thrice in a day'), ('morning', 'In Morning'), |
||||
|
('noon', 'In Noon'), ('evening', 'In Evening')], string='Time', |
||||
|
required=True, |
||||
|
help='The interval for medicine intake') |
||||
|
note = fields.Selection( |
||||
|
[('before', 'Before Food'), ('after', 'After Food')], |
||||
|
string='Before/ After Food', |
||||
|
help='Whether the medicine to be taken before or after food') |
||||
|
inpatient_id = fields.Many2one('hospital.inpatient', |
||||
|
string='Inpatient', |
||||
|
help='The inpatient corresponds to the ' |
||||
|
'prescription line') |
||||
|
outpatient_id = fields.Many2one('hospital.outpatient', |
||||
|
string='Outpatient', |
||||
|
help='The outpatient corresponds to the ' |
||||
|
'prescription line') |
||||
|
res_partner_id = fields.Many2one('res.partner', |
||||
|
string='Patient', |
||||
|
help='The outpatient corresponds to the ' |
||||
|
'prescription line', |
||||
|
related='outpatient_id.patient_id') |
@ -0,0 +1,57 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class ProductTemplate(models.Model): |
||||
|
"""Inherited to add more fields and functions""" |
||||
|
_inherit = 'product.template' |
||||
|
|
||||
|
medicine_ok = fields.Boolean(string='Medicine', help='True for medicines') |
||||
|
vaccine_ok = fields.Boolean(string="Vaccine", help='True for vaccines') |
||||
|
pharmacy_id = fields.Many2one('hospital.pharmacy', |
||||
|
string='Pharmacy', |
||||
|
help='Name of the pharmacy') |
||||
|
medicine_brand_id = fields.Many2one('medicine.brand', |
||||
|
string='Brand', |
||||
|
help='Indicates the brand of medicine ' |
||||
|
'or vaccine') |
||||
|
|
||||
|
@api.model |
||||
|
def action_get_medicine_data(self): |
||||
|
"""Returns medicine list to the pharmacy dashboard""" |
||||
|
medicines = [] |
||||
|
for rec in self.env['product.template'].sudo().search( |
||||
|
[('medicine_ok', '=', True)]): |
||||
|
medicines.append( |
||||
|
[rec.name, rec.list_price, rec.qty_available, rec.image_1920, rec.id]) |
||||
|
return medicines |
||||
|
|
||||
|
@api.model |
||||
|
def action_get_vaccine_data(self): |
||||
|
"""Returns vaccine list to the pharmacy dashboard""" |
||||
|
vaccines = [] |
||||
|
for rec in self.env['product.template'].sudo().search( |
||||
|
[('vaccine_ok', '=', True)]): |
||||
|
vaccines.append( |
||||
|
[rec.name, rec.list_price, rec.qty_available, rec.image_1920]) |
||||
|
return vaccines |
@ -0,0 +1,584 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
import math |
||||
|
import re |
||||
|
import base64 |
||||
|
from datetime import date |
||||
|
from barcode import EAN13 |
||||
|
from barcode.writer import ImageWriter |
||||
|
from dateutil.relativedelta import * |
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class ResPartner(models.Model): |
||||
|
"""Inherited to add more fields and functions""" |
||||
|
_inherit = 'res.partner' |
||||
|
_description = 'Hospital Patients' |
||||
|
|
||||
|
date_of_birth = fields.Date(string='Date of Birth', |
||||
|
help='Date of birth of the patient') |
||||
|
blood_group = fields.Selection(string='Blood Group', |
||||
|
help='Blood group of the patient', |
||||
|
selection=[('a', 'A'), ('b', 'B'), |
||||
|
('o', 'O'), ('ab', 'AB')]) |
||||
|
rh_type = fields.Selection(selection=[('-', '-ve'), ('+', '+ve')], |
||||
|
string='RH Type', |
||||
|
help='Rh type of the blood group') |
||||
|
gender = fields.Selection(selection=[ |
||||
|
('male', 'Male'), ('female', 'Female'), ('other', 'Other') |
||||
|
], string='Gender', help='Gender of the patient') |
||||
|
marital_status = fields.Selection(selection=[ |
||||
|
('married', 'Married'), ('unmarried', 'Unmarried'), ('widow', 'Widow'), |
||||
|
('widower', 'Widower'), ('divorcee', 'Divorcee') |
||||
|
], string='Marital Status', help='Marital status of patient') |
||||
|
is_alive = fields.Selection( |
||||
|
string='Status', |
||||
|
selection=[('alive', 'Alive'), ('dead', 'Dead')], |
||||
|
default='alive', help='True for alive patient') |
||||
|
patient_seq = fields.Char(string='Patient No.', |
||||
|
help='Sequence number of the patient', copy=False, |
||||
|
readonly=True, index=True, |
||||
|
default=lambda self: 'New') |
||||
|
notes = fields.Html(string='Note', help='Notes regarding the notes', |
||||
|
sanitize_style=True) |
||||
|
patient_profession = fields.Char(string="Profession", |
||||
|
help="Profession of patient") |
||||
|
doctor_id = fields.Many2one('hr.employee', |
||||
|
domain=[('job_id.name', '=', 'Doctor')], |
||||
|
string="Family Doctor", |
||||
|
help='Family doctor of the patient') |
||||
|
barcode = fields.Char(string='Barcode', help='Barcode for the patient') |
||||
|
barcode_png = fields.Binary(string='Barcode PNG', |
||||
|
help='Image file of the barcode', readonly=True) |
||||
|
group = fields.Selection(selection=[ |
||||
|
('hindu', 'Hindu'), ('muslim', 'Muslim'), ('christian', 'Christian')], |
||||
|
string="Ethnic Group", help="Specify your religion") |
||||
|
risk = fields.Text(string="Genetic Risks", |
||||
|
help='Genetic risks of the patient') |
||||
|
insurance_id = fields.Many2one('hospital.insurance', |
||||
|
string="Insurance", |
||||
|
help="Patient insurance") |
||||
|
unique_id = fields.Char(string='Unique ID', |
||||
|
help="Unique identifier to fetch " |
||||
|
"patient insurance data") |
||||
|
family_ids = fields.One2many('hospital.family', |
||||
|
'family_id', |
||||
|
string="Family ID", help='Family of a patient') |
||||
|
lab_test_ids = fields.One2many('patient.lab.test', |
||||
|
'patient_id', |
||||
|
string='Lab Test', |
||||
|
help='Lab tests for the patient') |
||||
|
prescription_ids = fields.One2many('prescription.line', |
||||
|
'res_partner_id', |
||||
|
string='Prescription', |
||||
|
help='Prescription for patient') |
||||
|
economic_level = fields.Selection(selection=[ |
||||
|
('low', 'Lower Class'), ('middle', 'Middle Class'), |
||||
|
('upper', 'Upper Class')], string="Socioeconomic", |
||||
|
help="Specify your economic status") |
||||
|
education_level = fields.Selection(selection=[ |
||||
|
('post', 'Post Graduation'), ('graduation', 'Graduation'), |
||||
|
('pre', 'Pre Graduation')], string="Education Level", |
||||
|
help="Education status of patient") |
||||
|
house_level = fields.Selection(selection=[ |
||||
|
('good', 'Good'), ('bad', 'Bad'), ('poor', 'Poor')], |
||||
|
string="House Condition", help="Specify your house's condition") |
||||
|
work_home = fields.Boolean(string='Work At Home', |
||||
|
help='True if you are working from home') |
||||
|
hours_outside = fields.Integer(string='Hours Stay Outside Home', |
||||
|
help="Specify how many hours you stay away " |
||||
|
"from home") |
||||
|
hostile = fields.Boolean(string='Hostile Area', |
||||
|
help="Specify your house in a friendly " |
||||
|
"neighbourhood ") |
||||
|
income = fields.Monetary(string='Income', help="The in come of patient") |
||||
|
currency_id = fields.Many2one('res.currency', string='Currency', |
||||
|
help='Currency in which invoices and payments' |
||||
|
' will be generated', |
||||
|
default=lambda self: self.env.user.company_id |
||||
|
.currency_id.id, required=True) |
||||
|
sanitary = fields.Boolean('Sanitary Sewers', |
||||
|
help="A sewer or sewer system for carrying off " |
||||
|
"wastewater, waste matter from a residence," |
||||
|
" business, etc") |
||||
|
running = fields.Boolean(string='Running Water', |
||||
|
help="water that comes into a building through " |
||||
|
"pipes. A cabin with hot and cold running " |
||||
|
"water.") |
||||
|
electricity = fields.Boolean(string='Electricity', |
||||
|
help='True if you have electricity') |
||||
|
gas = fields.Boolean(string='Gas Supply', |
||||
|
help='True if you have gas supply') |
||||
|
trash = fields.Boolean(string='Trash Collection', |
||||
|
help='True if you have trash collection') |
||||
|
home_phone = fields.Boolean(string='Telephone', |
||||
|
help='True if you have telephone') |
||||
|
tv = fields.Boolean(string='Television', help='True if you have television') |
||||
|
internet = fields.Boolean(string='Internet', |
||||
|
help='True if you have internet') |
||||
|
help = fields.Selection([('yes', 'Yes'), ('no', 'No')], |
||||
|
string="Family Help", |
||||
|
help="Specify whether your family is willing " |
||||
|
"to help or not") |
||||
|
discussion = fields.Selection([('yes', 'Yes'), ('no', 'No')], |
||||
|
string="Family Discussion ", |
||||
|
help="Specify your family have a good " |
||||
|
"discussion at home ") |
||||
|
ability = fields.Selection([('very', 'Very good'), ('good', 'Good'), |
||||
|
('bad', 'Bad'), ('poor', 'Poor')], |
||||
|
string="Family Ability", |
||||
|
help="family status of the patient") |
||||
|
time_sharing = fields.Selection([('yes', 'Yes'), ('no', 'No')], |
||||
|
string=" Family Time Sharing ", |
||||
|
help="Specify your family share time " |
||||
|
"at home ") |
||||
|
affection = fields.Selection([('very', 'Very good'), |
||||
|
('good', 'Good'), |
||||
|
('bad', 'Bad'), ('poor', 'Poor')], |
||||
|
string="Family Affection ", |
||||
|
help="Specify your family's affection ") |
||||
|
single = fields.Boolean(string='Single Parent Family', |
||||
|
help='Whether single parent family or not') |
||||
|
violence = fields.Boolean(string='Domestic Violence', |
||||
|
help='True if you are facing any domestic ' |
||||
|
'violence') |
||||
|
children = fields.Boolean(string='Working Children', |
||||
|
help='Do you have working children') |
||||
|
abuse = fields.Boolean(string='Sexual Abuse', |
||||
|
help='Do you faced any sexual abuse') |
||||
|
drug = fields.Boolean(string='Drug Addiction', |
||||
|
help='Do you have drug addiction') |
||||
|
withdrawal = fields.Boolean(string='Withdrawal', |
||||
|
help='Do you faced any withdrawal symptoms') |
||||
|
in_prison = fields.Boolean(string='Has Been In Prison', |
||||
|
help='True if you had been in prison') |
||||
|
current_prison = fields.Boolean(string='Currently In Prison', |
||||
|
help='True if you are in prison currently') |
||||
|
relative_prison = fields.Boolean(string='Relative In Prison', |
||||
|
help='True if any of your relative is ' |
||||
|
'in prison') |
||||
|
hospital_vaccination_ids = fields.One2many( |
||||
|
'hospital.vaccination', 'patient_id', |
||||
|
string='Vaccination', help='Vaccination details of ' |
||||
|
'patient') |
||||
|
fertile = fields.Boolean(string='Fertile', help="""Capable of developing |
||||
|
into a complete organism; |
||||
|
fertilized. Capable of supporting |
||||
|
plant life; favorable to the |
||||
|
growth of crops and plants.""") |
||||
|
menarche_age = fields.Integer(string='Menarche Age', help="""The first |
||||
|
menstrual period in a female adolescent""") |
||||
|
pause = fields.Boolean(string='Menopause', help="""Menopause is a point in |
||||
|
time 12 months after a woman's last period""") |
||||
|
pause_age = fields.Integer(string='Menopause Age', |
||||
|
help='Age at which menopause occurred') |
||||
|
pap = fields.Boolean(string='PAP Test', |
||||
|
help=""" |
||||
|
A procedure in which a small brush is used to gently |
||||
|
remove cells from the surface of the cervix and the |
||||
|
area around it so they can be checked under a |
||||
|
microscope for cervical cancer or cell changes that |
||||
|
may lead to cervical cancer.""") |
||||
|
colposcopy = fields.Boolean(string='Colposcopy', help=""" test to take a |
||||
|
closer look at your cervix""") |
||||
|
self = fields.Boolean(string='Self breast examination', |
||||
|
help="A breast self-exam for breast awareness is " |
||||
|
"in inspection " |
||||
|
"of your breasts that women do on your own") |
||||
|
mommography = fields.Boolean(string='Mommography', |
||||
|
help="Mammograms can be used to look for " |
||||
|
"breast cancer") |
||||
|
last_pap = fields.Date(string="Last PAP Test", |
||||
|
help='The date on which last PAP test has been done') |
||||
|
last_col = fields.Date(string="Last Colposcopy", |
||||
|
help='The date on which last colposcopy has been ' |
||||
|
'done') |
||||
|
deceased = fields.Boolean(string='Deceased during 1st week', |
||||
|
help='The family member deceased during first ' |
||||
|
'week') |
||||
|
grandiva = fields.Boolean(string='Grandiva', help='True for grandiva') |
||||
|
alive = fields.Boolean(string='Born Alive', help='Whether born alive or ' |
||||
|
'not') |
||||
|
premature = fields.Integer(string='Premature', |
||||
|
help="Premature birth is birth that happens too" |
||||
|
"soon, before 37 weeks of pregnancy") |
||||
|
abortions = fields.Integer(string='No Of Abortions', help='Number of ' |
||||
|
'abortions of ' |
||||
|
'patient') |
||||
|
exercise = fields.Boolean(string='Exercise', help='True if patient doing ' |
||||
|
'exercise regularly') |
||||
|
minute = fields.Integer(string='Minute/Day', help='The duration of ' |
||||
|
'exercise per day') |
||||
|
|
||||
|
day_sleep = fields.Boolean(string='Sleeps At Daytime', help='True if ' |
||||
|
'sleeps at ' |
||||
|
'daytime') |
||||
|
sleep_hrs = fields.Integer(string='Sleep Hours', help='Duration of sleep') |
||||
|
meals = fields.Integer(string='Meals/Day', help='Number of meals per day') |
||||
|
alone = fields.Boolean(string='Eat Alone', help='True if eats alone') |
||||
|
coffee = fields.Boolean(string='Coffee', help='True if you have a habit ' |
||||
|
'of drinking coffee') |
||||
|
cup = fields.Integer(string='Cups/Day', help='Number of cups of coffee ' |
||||
|
'per day') |
||||
|
drink = fields.Boolean(string='Soft Drink', help='True if you drinks soft ' |
||||
|
'drinks') |
||||
|
salt = fields.Boolean(string='Salt', help='True if you use salt') |
||||
|
diet = fields.Boolean(string='Currently On Diet', help='True if you are ' |
||||
|
'on diet currently') |
||||
|
smoke = fields.Boolean(string='Smoker', help='True for smoker') |
||||
|
ex_smoke = fields.Boolean(string='Ex-Smoker', help='True for ex-smoker') |
||||
|
age_start = fields.Integer(string='Age of Started Smoking', |
||||
|
help='Age on which you started your smoking') |
||||
|
cigarettes = fields.Integer(string='Cigarettes/Day', |
||||
|
help='Number of cigarettes per day') |
||||
|
passive = fields.Boolean(string='Passive Smoker', |
||||
|
help='True for passive smokers') |
||||
|
age_quit = fields.Integer(string='Age of Quitting', |
||||
|
help='Age at which you quit your smoking habit') |
||||
|
alcoholic = fields.Boolean(string='Alcoholic', help='True for alcoholics') |
||||
|
ex_alcoholic = fields.Boolean(string='Ex-Alcoholic', help='True for ex- ' |
||||
|
'alcoholics') |
||||
|
age_start_alco = fields.Integer(string='Age to Start Drinking', |
||||
|
help='Age at which you started your ' |
||||
|
'drinking habit') |
||||
|
beer = fields.Integer(string='Beer/Day', |
||||
|
help='Number of beers per day') |
||||
|
liquor = fields.Integer(string='Liquor/Day', |
||||
|
help='Liquors per day') |
||||
|
wine = fields.Integer(string='Wine/Day', |
||||
|
help='Number of wines per day') |
||||
|
age_quit_alcoholic = fields.Integer(string='Age Of Quitting', |
||||
|
help='Age at which you started your ' |
||||
|
'drinking habit') |
||||
|
drugs = fields.Boolean(string='Drug User', help='True for drug users') |
||||
|
ex_drugs = fields.Boolean(string='Ex-Drug User', help='True for Ex drug ' |
||||
|
'user') |
||||
|
iv_user = fields.Boolean(string='IV Drug User', help='True for IV drug ' |
||||
|
'user') |
||||
|
age_start_drug = fields.Integer(string='Age to Start Using Drugs', |
||||
|
help='Age at which you started using drug') |
||||
|
age_quit_drug = fields.Integer(string='Drug Quitting Age', help='Age of ' |
||||
|
'quitting ' |
||||
|
'drug') |
||||
|
orientation = fields.Selection([('straight', 'Straight'), |
||||
|
('homo', 'Homosexual'), |
||||
|
('trans', 'Trans-Gender')], |
||||
|
string="Orientation") |
||||
|
age_sex = fields.Integer(string="Age of First Encounter", |
||||
|
help='Age of first sex encounter') |
||||
|
partners = fields.Integer(string="No of Partners", |
||||
|
help='Number of sex partners') |
||||
|
anti = fields.Selection( |
||||
|
[('pills', 'Contraceptive Pills'), ('ring', 'Contraceptive Ring'), |
||||
|
('injection', 'Contraceptive Injection')], |
||||
|
string="Contraceptive Methods", help='Choose your contraceptive method') |
||||
|
oral = fields.Boolean(string='Oral Sex', help=("uttered by the mouth or in " |
||||
|
"words")) |
||||
|
anal = fields.Boolean(string='Anal Sex', help="True if you are " |
||||
|
"encountering anal sex") |
||||
|
prostitute = fields.Boolean(string='Prostitute', help='True for ' |
||||
|
'prostitutes') |
||||
|
prostitute_sex = fields.Boolean(string='Sex With Prostitute', |
||||
|
help='True if you are encountered sex ' |
||||
|
'with prostitute') |
||||
|
sex_notes = fields.Text(string='Notes', help='Write down the notes') |
||||
|
rider = fields.Boolean(string='Motorcycle Rider', help='True for ' |
||||
|
'motorcycle riders') |
||||
|
helmet = fields.Boolean(string='Uses Helmet', |
||||
|
help='True if you regularly use helmet') |
||||
|
laws = fields.Boolean(string='Obey Traffic Laws', |
||||
|
help='True if you obey traffic rules') |
||||
|
revision = fields.Boolean(string='Car Revision', help='True if car ' |
||||
|
'revision is done') |
||||
|
belt = fields.Boolean(string='Seat Belt', |
||||
|
help='True if you uses seat belt regularly') |
||||
|
safety = fields.Boolean(string='Car Child Safety', |
||||
|
help='True if you have car child safety') |
||||
|
home = fields.Boolean(string='Home Safety', help='True for home safety') |
||||
|
occupation = fields.Char(string='Occupation', help='Your occupation') |
||||
|
|
||||
|
@api.model |
||||
|
def create(self, vals): |
||||
|
"""Inherits create function for sequence generation""" |
||||
|
if vals.get('patient_seq', 'New') == 'New': |
||||
|
vals['patient_seq'] = self.env['ir.sequence'].next_by_code( |
||||
|
'patient.sequence') or 'New' |
||||
|
return super().create(vals) |
||||
|
|
||||
|
def action_view_invoice(self): |
||||
|
"""Returns patient invoice""" |
||||
|
self.ensure_one() |
||||
|
return { |
||||
|
'name': 'Patient Invoice', |
||||
|
'view_mode': 'tree,form', |
||||
|
'res_model': 'account.move', |
||||
|
'type': 'ir.actions.act_window', |
||||
|
'domain': [('partner_id', '=', self.id)], |
||||
|
'context': "{'create':False}" |
||||
|
} |
||||
|
|
||||
|
def name_get(self): |
||||
|
"""Returns the patient name""" |
||||
|
result = [] |
||||
|
for rec in self: |
||||
|
result.append((rec.id, f'{rec.patient_seq} - {rec.name}')) |
||||
|
return result |
||||
|
|
||||
|
def alive_status(self): |
||||
|
"""Function for setting the value of is_alive field""" |
||||
|
if self.is_alive == 'alive': |
||||
|
self.is_alive = 'dead' |
||||
|
else: |
||||
|
self.is_alive = 'alive' |
||||
|
|
||||
|
def action_schedule(self): |
||||
|
"""Returns form view of hospital appointment wizard""" |
||||
|
return { |
||||
|
'type': 'ir.actions.act_window', |
||||
|
'res_model': 'hospital.outpatient', |
||||
|
'view_type': 'form', |
||||
|
'view_mode': 'form', |
||||
|
'target': 'new', |
||||
|
'views': [[False, 'form']], |
||||
|
'context': { |
||||
|
'default_patient_id': self.id |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@api.model |
||||
|
def ean_checksum(self, eancode): |
||||
|
"""Returns the checksum of an ean string of length 13, returns -1 if |
||||
|
the string has the wrong length""" |
||||
|
if len(eancode) != 13: |
||||
|
return -1 |
||||
|
odd_sum = 0 |
||||
|
even_sum = 0 |
||||
|
ean_value = eancode |
||||
|
reverse_value = ean_value[::-1] |
||||
|
final_ean = reverse_value[1:] |
||||
|
for i in range(len(final_ean)): |
||||
|
if i % 2 == 0: |
||||
|
odd_sum += int(final_ean[i]) |
||||
|
else: |
||||
|
even_sum += int(final_ean[i]) |
||||
|
total = (odd_sum * 3) + even_sum |
||||
|
check = int(10 - math.ceil(total % 10.0)) % 10 |
||||
|
return check |
||||
|
|
||||
|
def check_ean(eancode): |
||||
|
"""Returns True if eancode is a valid ean13 string, or null""" |
||||
|
if not eancode: |
||||
|
return True |
||||
|
if len(eancode) != 13: |
||||
|
return False |
||||
|
int(eancode) |
||||
|
return eancode.ean_checksum(eancode) == int(eancode[-1]) |
||||
|
|
||||
|
def generate_ean(self, ean): |
||||
|
"""Creates and returns a valid ean13 from an invalid one""" |
||||
|
if not ean: |
||||
|
return "0000000000000" |
||||
|
ean = re.sub("[A-Za-z]", "0", ean) |
||||
|
ean = re.sub("[^0-9]", "", ean) |
||||
|
ean = ean[:13] |
||||
|
if len(ean) < 13: |
||||
|
ean = ean + '0' * (13 - len(ean)) |
||||
|
return ean[:-1] + str(self.ean_checksum(ean)) |
||||
|
|
||||
|
def action_generate_patient_card(self): |
||||
|
"""Method for generating the patient card""" |
||||
|
current_age = 0 |
||||
|
gender_caps = '' |
||||
|
blood_caps = '' |
||||
|
if not self.barcode: |
||||
|
ean = self.sudo().generate_ean(str(self.id)) |
||||
|
self.sudo().write({'barcode': ean}) |
||||
|
number = self.barcode |
||||
|
my_code = EAN13(number, writer=ImageWriter()) |
||||
|
my_code.save("code") |
||||
|
with open('code.png', 'rb') as f: |
||||
|
self.sudo().write({ |
||||
|
'barcode_png': base64.b64encode(f.read()) |
||||
|
}) |
||||
|
if self.gender: |
||||
|
gender_caps = self.gender.capitalize() |
||||
|
if self.blood_group: |
||||
|
blood_caps = self.blood_group.capitalize() |
||||
|
if self.date_of_birth: |
||||
|
today = date.today() |
||||
|
dob = self.date_of_birth |
||||
|
current_age = relativedelta(today, dob).years |
||||
|
company = self.env['res.company'].sudo().search( |
||||
|
[('id', '=', self.env.context['allowed_company_ids'])]) |
||||
|
data = { |
||||
|
'name': self.name, |
||||
|
'code': self.patient_seq, |
||||
|
'age': current_age, |
||||
|
'gender': gender_caps, |
||||
|
'dob': self.date_of_birth, |
||||
|
'blood': blood_caps + str(self.rh_type), |
||||
|
'street': self.street, |
||||
|
'street2': self.street2, |
||||
|
'state': self.state_id.name, |
||||
|
'country': self.country_id.name, |
||||
|
'city': self.city, |
||||
|
'phone': self.phone, |
||||
|
'image': self.sudo().read(['image_1920'])[0], |
||||
|
'barcode': self.sudo().read(['barcode_png'])[0], |
||||
|
'company_name': company.name, |
||||
|
'company_street': company.street, |
||||
|
'company_street2': company.street2, |
||||
|
'company_city': company.city, |
||||
|
'company_state': company.state_id.name, |
||||
|
'company_zip': company.zip, |
||||
|
} |
||||
|
return self.env.ref( |
||||
|
'base_hospital_management.action_report_patient_card' |
||||
|
).report_action(None, data=data) |
||||
|
|
||||
|
@api.model |
||||
|
def reception_op_barcode(self, kw): |
||||
|
"""Returns a patient based on the barcode""" |
||||
|
values = { |
||||
|
'name': '', |
||||
|
'date_of_birth': '', |
||||
|
'phone': '', |
||||
|
'blood_group': '', |
||||
|
'gender': '', |
||||
|
} |
||||
|
if kw['patient_data']: |
||||
|
patient = self.sudo().search( |
||||
|
['|', ('id', '=', kw['patient_data']), |
||||
|
('phone', '=', kw['patient_data'])]) |
||||
|
if patient: |
||||
|
values = { |
||||
|
'name': patient.name, |
||||
|
'date_of_birth': patient.date_of_birth, |
||||
|
'phone': patient.phone, |
||||
|
'blood_group': patient.blood_group, |
||||
|
'gender': patient.gender, |
||||
|
} |
||||
|
return values |
||||
|
|
||||
|
@api.model |
||||
|
def reception_op_phone(self, phone): |
||||
|
"""Returns a patient details having the phone number""" |
||||
|
patient_phone = self.sudo().search( |
||||
|
[('phone', '=', phone['patient-phone'])]) |
||||
|
return { |
||||
|
'patient_seq': patient_phone.patient_seq, |
||||
|
'name': patient_phone.name, |
||||
|
'date_of_birth': patient_phone.date_of_birth, |
||||
|
'blood_group': patient_phone.blood_group, |
||||
|
'gender': patient_phone.gender, |
||||
|
} |
||||
|
|
||||
|
@api.model |
||||
|
def action_get_patient_data(self, patient_id): |
||||
|
"""Method which returns patient details""" |
||||
|
data = self.sudo().search([ |
||||
|
'|', ('patient_seq', '=', patient_id), |
||||
|
('barcode', '=', patient_id) |
||||
|
]) |
||||
|
patient_history = [] |
||||
|
for rec in self.env['hospital.outpatient'].sudo().search( |
||||
|
[('patient_id', '=', data.id)]): |
||||
|
patient_history.append( |
||||
|
[rec.op_reference, str(rec.op_date), |
||||
|
rec.doctor_id.doctor_id.name]) |
||||
|
values = { |
||||
|
'name': data.name, |
||||
|
'unique': data.patient_seq, |
||||
|
'email': data.email, |
||||
|
'phone': data.phone, |
||||
|
'dob': data.date_of_birth, |
||||
|
'image_1920': data.image_1920, |
||||
|
'status': data.marital_status, |
||||
|
'history': patient_history, |
||||
|
} |
||||
|
if not data.name: |
||||
|
values['name'] = 'Patient Not Found' |
||||
|
if not data.patient_seq: |
||||
|
values['unique'] = '' |
||||
|
if data.blood_group: |
||||
|
blood_caps = data.blood_group.capitalize() |
||||
|
values['blood_group'] = blood_caps + str(data.rh_type) |
||||
|
else: |
||||
|
values['blood_group'] = '' |
||||
|
if data.gender: |
||||
|
gender_caps = data.gender.capitalize() |
||||
|
values['gender'] = gender_caps |
||||
|
else: |
||||
|
values['gender'] = '' |
||||
|
return values |
||||
|
|
||||
|
@api.model |
||||
|
def create_sale_order_pharmacy(self, order): |
||||
|
"""Method for creating sale order for medicines""" |
||||
|
medicine = [] |
||||
|
op_record = self.env['hospital.outpatient'].sudo().search( |
||||
|
[('op_reference', '=', order), '|', |
||||
|
('active', 'in', [False, True])]) |
||||
|
for rec in op_record.prescription_ids: |
||||
|
medicine.append([rec.medicine_id.id, rec.quantity]) |
||||
|
sale_order_pharmacy = self.env['sale.order'].sudo().create({ |
||||
|
'partner_id': op_record.patient_id.id, |
||||
|
}) |
||||
|
for new in medicine: |
||||
|
self.env['sale.order.line'].sudo().create({ |
||||
|
'product_id': new[0], |
||||
|
'product_uom_qty': new[1], |
||||
|
'order_id': sale_order_pharmacy.id, |
||||
|
}) |
||||
|
|
||||
|
@api.model |
||||
|
def create_patient(self, post): |
||||
|
"""Method for creating a patient""" |
||||
|
if post and not post['patient_id']: |
||||
|
patient = self.sudo().search([('name', '=', post['op_name'])]) |
||||
|
if not patient: |
||||
|
|
||||
|
patient = self.sudo().create({ |
||||
|
'name': post['op_name'], |
||||
|
'blood_group': post['op_blood_group'], |
||||
|
'gender': post['op_gender'] |
||||
|
}) |
||||
|
if 'op_dob' in post.keys(): |
||||
|
patient.sudo().write({'date_of_birth': post['op_dob']}) |
||||
|
else: |
||||
|
patient = self.sudo().search([('id', '=', post['patient_id'])]) |
||||
|
out_patient = self.env['hospital.outpatient'].sudo().search([('patient_id','=', patient.id)]) |
||||
|
if not out_patient: |
||||
|
self.env['hospital.outpatient'].sudo().create({ |
||||
|
'patient_id': patient.id, |
||||
|
'op_date': post['date'], |
||||
|
'reason': post['reason'], |
||||
|
'slot': post['slot'], |
||||
|
'doctor_id': self.env['doctor.allocation'].sudo().browse( |
||||
|
post['doctor']).id |
||||
|
}) |
||||
|
|
||||
|
@api.model |
||||
|
def fetch_patient_data(self): |
||||
|
"""Method for returning patient data""" |
||||
|
return self.sudo().search_read( |
||||
|
[('patient_seq', 'not in', ['New', 'Employee', 'User'])]) |
@ -0,0 +1,35 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import api, models |
||||
|
|
||||
|
|
||||
|
class ResUsers(models.Model): |
||||
|
"""Inherited to prevent creating patients while creating users""" |
||||
|
_inherit = 'res.users' |
||||
|
|
||||
|
@api.model_create_multi |
||||
|
def create(self, vals_list): |
||||
|
"""Override to add patient_seq to the partners created from users""" |
||||
|
users = super().create(vals_list) |
||||
|
for user in users: |
||||
|
user.partner_id.patient_seq = 'User' |
||||
|
return users |
@ -0,0 +1,30 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################ |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# |
||||
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Subina P (odoo@cybrosys.com) |
||||
|
# |
||||
|
# You can modify it under the terms of the GNU AFFERO |
||||
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
||||
|
# |
||||
|
# 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 (AGPL v3) for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
|
# (AGPL v3) along with this program. |
||||
|
# If not, see <http://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################ |
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class RoomFacility(models.Model): |
||||
|
"""Class holding room facilities""" |
||||
|
_name = 'room.facility' |
||||
|
_description = 'Room Facility' |
||||
|
|
||||
|
name = fields.Char(string="Facilities", help='Name of room facility') |
@ -0,0 +1,66 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
<!-- Patient lab test report action--> |
||||
|
<record id="action_report_patient_lab_tests" model="ir.actions.report"> |
||||
|
<field name="name">Patient Lab Tests</field> |
||||
|
<field name="model">lab.test.line</field> |
||||
|
<field name="report_type">qweb-pdf</field> |
||||
|
<field name="report_name"> |
||||
|
base_hospital_management.report_patient_lab_tests |
||||
|
</field> |
||||
|
<field name="report_file"> |
||||
|
base_hospital_management.report_patient_lab_tests |
||||
|
</field> |
||||
|
<field name="binding_model_id" ref="model_lab_test_line"/> |
||||
|
<field name="binding_type">report</field> |
||||
|
</record> |
||||
|
<!-- Patient lab test report template--> |
||||
|
<template id="report_patient_lab_tests"> |
||||
|
<t t-call="web.html_container"> |
||||
|
<t t-call="web.external_layout"> |
||||
|
<center> |
||||
|
<h1>Lab Tests</h1> |
||||
|
</center> |
||||
|
<div> |
||||
|
<strong>Date :</strong> |
||||
|
<span t-esc="date"/> |
||||
|
</div> |
||||
|
<div> |
||||
|
<strong>Patient's Name :</strong> |
||||
|
<span t-esc="patient_id"/> |
||||
|
</div> |
||||
|
<div> |
||||
|
<strong>Doctor Name :</strong> |
||||
|
<span t-esc="doctor_name"/> |
||||
|
</div> |
||||
|
<table class="table table-striped"> |
||||
|
<tr> |
||||
|
<th>Test</th> |
||||
|
<th>Normal</th> |
||||
|
<th>Unit</th> |
||||
|
<th>Result</th> |
||||
|
<th>Price Including Tax</th> |
||||
|
</tr> |
||||
|
<tr t-foreach="datas" t-as="line" style="text-align:center"> |
||||
|
<td> |
||||
|
<span t-esc="line['name']"/> |
||||
|
</td> |
||||
|
<td> |
||||
|
<span t-esc="line['normal']"/> |
||||
|
</td> |
||||
|
<td> |
||||
|
<span t-esc="line['uom_id']"/> |
||||
|
</td> |
||||
|
<td> |
||||
|
<span t-esc="line['result']"/> |
||||
|
</td> |
||||
|
<td> |
||||
|
<t t-esc="line['currency']"/> |
||||
|
<span t-esc="line['cost']"/> |
||||
|
</td> |
||||
|
</tr> |
||||
|
</table> |
||||
|
</t> |
||||
|
</t> |
||||
|
</template> |
||||
|
</odoo> |
@ -0,0 +1,208 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
<!--Patient prescription report --> |
||||
|
<record id="action_report_patient_prescription" model="ir.actions.report"> |
||||
|
<field name="name">Patient Prescription</field> |
||||
|
<field name="model">res.partner</field> |
||||
|
<field name="report_type">qweb-pdf</field> |
||||
|
<field name="report_name">base_hospital_management.patient_prescription_report</field> |
||||
|
<field name="report_file">base_hospital_management.patient_prescription_report</field> |
||||
|
<field name="binding_model_id" ref="model_res_partner"/> |
||||
|
<field name="binding_type">report</field> |
||||
|
</record> |
||||
|
<!-- Patient prescription report template--> |
||||
|
<template id="patient_prescription_report"> |
||||
|
<t t-call="web.html_container"> |
||||
|
<t t-call="web.external_layout"> |
||||
|
<center> |
||||
|
<h1>Doctor Prescription</h1></center> |
||||
|
<div> |
||||
|
<strong>Date :</strong> |
||||
|
<span t-esc="date"/> |
||||
|
</div> |
||||
|
<div> |
||||
|
<strong>Patient's Name :</strong> |
||||
|
<span t-esc="patient_name"/> |
||||
|
</div> |
||||
|
<div> |
||||
|
<strong>Doctor :</strong> |
||||
|
<span t-esc="doctor_name"/> |
||||
|
</div> |
||||
|
<table class="table"> |
||||
|
<thead> |
||||
|
<tr style="text-align:left"> |
||||
|
<th>SL.No</th> |
||||
|
<th>Medicine</th> |
||||
|
<th>Intake</th> |
||||
|
<th>Time</th> |
||||
|
<th>Quantity</th> |
||||
|
<th>Before/ After Food</th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<t t-set="i" t-value="0"/> |
||||
|
<tbody> |
||||
|
<center> |
||||
|
<tr t-foreach="datas" t-as="line"> |
||||
|
<td> |
||||
|
<t t-set="i" t-value="i + 1"/> |
||||
|
<span t-esc="i"/> |
||||
|
</td> |
||||
|
<td> |
||||
|
<span t-esc="line['medicine']"/> |
||||
|
</td> |
||||
|
<td> |
||||
|
<span t-esc="line['intake']"/> |
||||
|
</td> |
||||
|
<td> |
||||
|
<span t-esc="line['time']"/> |
||||
|
</td> |
||||
|
<td> |
||||
|
<span t-esc="line['quantity']"/> |
||||
|
</td> |
||||
|
<td> |
||||
|
<span t-esc="line['note']"/> |
||||
|
</td> |
||||
|
</tr> |
||||
|
</center> |
||||
|
</tbody> |
||||
|
</table> |
||||
|
</t> |
||||
|
</t> |
||||
|
</template> |
||||
|
<!--Report paper format--> |
||||
|
<record id="paperformat_patient" model="report.paperformat"> |
||||
|
<field name="name">Custom Paper</field> |
||||
|
<field name="default" eval="True"/> |
||||
|
<field name="format">custom</field> |
||||
|
<field name="page_height">55</field> |
||||
|
<field name="page_width">30</field> |
||||
|
<field name="orientation">Landscape</field> |
||||
|
<field name="margin_top">1.00</field> |
||||
|
<field name="margin_bottom">1.00</field> |
||||
|
<field name="margin_left">0.00</field> |
||||
|
<field name="margin_right">1.00</field> |
||||
|
<field name="header_line" eval="False"/> |
||||
|
<field name="header_spacing">35</field> |
||||
|
<field name="dpi">125</field> |
||||
|
</record> |
||||
|
<!-- Patient card report action--> |
||||
|
<record id="action_report_patient_card" model="ir.actions.report"> |
||||
|
<field name="name">Patient Card</field> |
||||
|
<field name="model">res.partner</field> |
||||
|
<field name="report_type">qweb-pdf</field> |
||||
|
<field name="report_name">base_hospital_management.patient_card_report</field> |
||||
|
<field name="report_file">base_hospital_management.patient_card_report</field> |
||||
|
<field name="binding_model_id" ref="model_res_partner"/> |
||||
|
<field name="paperformat_id" |
||||
|
ref="base_hospital_management.paperformat_patient"/> |
||||
|
<field name="binding_type">report</field> |
||||
|
</record> |
||||
|
<!-- Patient card template--> |
||||
|
<template id="patient_card_report"> |
||||
|
<t t-call="web.html_container"> |
||||
|
<section> |
||||
|
<div style="width: 500px; height: 260px; border: 2px black solid; |
||||
|
border-radius: 5px;"> |
||||
|
<div class="container" |
||||
|
style="width: 500px; height: 50px; background-color:red"> |
||||
|
<span> |
||||
|
<i class="fa fa-wave-pulse" style="color:black;"/> |
||||
|
</span> |
||||
|
<h1 style="margin-left: 150px; padding-top: 10px; color:white; border-radius: 10px;"> |
||||
|
Patient Card |
||||
|
</h1> |
||||
|
<div class="page"> |
||||
|
<h1 style="margin-left: 15px;"> |
||||
|
<t t-esc="name"/> |
||||
|
<br/> |
||||
|
<label style="font-size: 18px;"> |
||||
|
<b>Code : |
||||
|
<t t-esc="code"/> |
||||
|
</b> |
||||
|
</label> |
||||
|
</h1> |
||||
|
<p style="margin-left: 15px;"> |
||||
|
<label> |
||||
|
<b>Gender :</b> |
||||
|
<t t-esc="gender"/> |
||||
|
</label> |
||||
|
<br/> |
||||
|
<label> |
||||
|
<b>Age :</b> |
||||
|
<t t-esc="age"/> |
||||
|
</label> |
||||
|
<br/> |
||||
|
<label> |
||||
|
<b>DOB :</b> |
||||
|
<t t-esc="dob"/> |
||||
|
</label> |
||||
|
<br/> |
||||
|
<label> |
||||
|
<b>Blood Group :</b> |
||||
|
<t t-esc="blood"/> |
||||
|
<br/> |
||||
|
</label> |
||||
|
<label> |
||||
|
<b>Phone :</b> |
||||
|
<t t-esc="phone"/> |
||||
|
</label> |
||||
|
<br/> |
||||
|
<label style="position:absolute; left:350px; top:100px;"> |
||||
|
<img t-attf-src="data:image/png;base64,{{image['image_1920']}}" |
||||
|
style="max-height: 130px; max-width: 130px;"/> |
||||
|
</label> |
||||
|
<br/> |
||||
|
</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
<section> |
||||
|
<div class="container" |
||||
|
style="margin-top:50px"> |
||||
|
<div style="width: 500px; height: 250px; border: 2px black |
||||
|
solid; border-radius: 5px;"> |
||||
|
<div style="margin-left: 10px; margin-top: 10px;"> |
||||
|
<span style="padding-top:5px padding-top:5px"> |
||||
|
<b>Address:</b> |
||||
|
<br/> |
||||
|
<t t-esc="street"/> |
||||
|
<br/> |
||||
|
<t t-esc="street2"/> |
||||
|
<br/> |
||||
|
<t t-esc='city'/> |
||||
|
<t t-esc='state'/> |
||||
|
<br/> |
||||
|
<t t-esc='country'/> |
||||
|
<br/> |
||||
|
<br/> |
||||
|
</span> |
||||
|
<span style="padding-top:5px padding-top:5px"> |
||||
|
<b> |
||||
|
<t t-esc="company_name"/> |
||||
|
</b> |
||||
|
<br/> |
||||
|
<t t-esc="company_street"/> |
||||
|
<br/> |
||||
|
<t t-esc="company_street2"/> |
||||
|
<br/> |
||||
|
<t t-esc='company_city'/> |
||||
|
<t t-esc='company_state'/> |
||||
|
<br/> |
||||
|
<t t-esc='company_zip'/> |
||||
|
<br/> |
||||
|
<br/> |
||||
|
</span> |
||||
|
</div> |
||||
|
<div> |
||||
|
<img style="max-height: 150px; max-width: 180px; |
||||
|
position:absolute; left:310px; top:290px;" |
||||
|
t-attf-src="data:image/gif;base64, |
||||
|
{{barcode['barcode_png']}}"/> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
</t> |
||||
|
</template> |
||||
|
</odoo> |
@ -0,0 +1,42 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
<!-- Hospital Management access category--> |
||||
|
<record id="base_hospital_management_access" model="ir.module.category"> |
||||
|
<field name="name">Hospital Management</field> |
||||
|
<field name="description">User access levels for Hospital Management |
||||
|
</field> |
||||
|
<field name="sequence">10</field> |
||||
|
</record> |
||||
|
<!--Lab Assistant access group--> |
||||
|
<record id="base_hospital_management_group_lab_assistant" |
||||
|
model="res.groups"> |
||||
|
<field name="name">Lab Assistant</field> |
||||
|
<field name="category_id" ref="base_hospital_management_access"/> |
||||
|
</record> |
||||
|
<!--Pharmacist access group--> |
||||
|
<record id="base_hospital_management_group_pharmacist" model="res.groups"> |
||||
|
<field name="name">Pharmacist</field> |
||||
|
<field name="category_id" ref="base_hospital_management_access"/> |
||||
|
</record> |
||||
|
<!-- Nurse access group--> |
||||
|
<record id="base_hospital_management_group_nurse" model="res.groups"> |
||||
|
<field name="name">Nurse</field> |
||||
|
<field name="category_id" ref="base_hospital_management_access"/> |
||||
|
</record> |
||||
|
<!--Doctor access group--> |
||||
|
<record id="base_hospital_management_group_doctor" model="res.groups"> |
||||
|
<field name="name">Doctor</field> |
||||
|
<field name="category_id" ref="base_hospital_management_access"/> |
||||
|
</record> |
||||
|
<!--Receptionist access group--> |
||||
|
<record id="base_hospital_management_group_receptionist" model="res.groups"> |
||||
|
<field name="name">Receptionist</field> |
||||
|
<field name="category_id" ref="base_hospital_management_access"/> |
||||
|
</record> |
||||
|
<!--Manager access group--> |
||||
|
<record id="base_hospital_management_group_manager" |
||||
|
model="res.groups"> |
||||
|
<field name="name">Manager</field> |
||||
|
<field name="category_id" ref="base_hospital_management_access"/> |
||||
|
</record> |
||||
|
</odoo> |
@ -0,0 +1,33 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
<data noupdate="1"> |
||||
|
<!-- Record rule of group doctor to access doctor allocation records--> |
||||
|
<record id="doctor_allocation_rule_doctor" model="ir.rule"> |
||||
|
<field name="name">Doctor Allocation Rule Doctor</field> |
||||
|
<field name="model_id" ref="model_doctor_allocation"/> |
||||
|
<field name="domain_force"> |
||||
|
[('doctor_id.user_id','=',user.id)] |
||||
|
</field> |
||||
|
<field name="groups" |
||||
|
eval="[(4, ref('base_hospital_management.base_hospital_management_group_doctor'))]"/> |
||||
|
</record> |
||||
|
<!-- Record rule of group doctor to access manager allocation records--> |
||||
|
<record id="doctor_allocation_rule_manager" model="ir.rule"> |
||||
|
<field name="name">Doctor Allocation Rule Manager</field> |
||||
|
<field name="model_id" ref="model_doctor_allocation"/> |
||||
|
<field name="domain_force"> |
||||
|
[(1,'=',1)] |
||||
|
</field> |
||||
|
<field name="groups" |
||||
|
eval="[(4, ref('base_hospital_management.base_hospital_management_group_manager'))]"/> |
||||
|
</record> |
||||
|
<!-- Multi company rule for doctor allocation records--> |
||||
|
<record id="doctor_allocation_rule_company" model="ir.rule"> |
||||
|
<field name="name">Doctor Allocation Rule Company</field> |
||||
|
<field name="model_id" ref="model_doctor_slot"/> |
||||
|
<field name="domain_force"> |
||||
|
['|',('company_id','=',False),('company_id', 'in', company_ids)] |
||||
|
</field> |
||||
|
</record> |
||||
|
</data> |
||||
|
</odoo> |
@ -0,0 +1,25 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
<data noupdate="1"> |
||||
|
<!-- Record rule of group doctor to access doctor slot records--> |
||||
|
<record id="doctor_slot_rule_doctor" model="ir.rule"> |
||||
|
<field name="name">Doctor Slot Rule Doctor</field> |
||||
|
<field name="model_id" ref="model_doctor_slot"/> |
||||
|
<field name="domain_force"> |
||||
|
[('doctor_id.user_id','=',user.id)] |
||||
|
</field> |
||||
|
<field name="groups" |
||||
|
eval="[(4, ref('base_hospital_management.base_hospital_management_group_doctor'))]"/> |
||||
|
</record> |
||||
|
<!-- Multi company rule for doctor slot records--> |
||||
|
<record id="doctor_slot_rule_company" model="ir.rule"> |
||||
|
<field name="name">Doctor Slot Rule Company</field> |
||||
|
<field name="model_id" ref="model_doctor_slot"/> |
||||
|
<field name="domain_force"> |
||||
|
['|',('company_id','=',False),('company_id', 'in', company_ids)] |
||||
|
</field> |
||||
|
<field name="groups" |
||||
|
eval="[(4, ref('base_hospital_management.base_hospital_management_group_doctor'))]"/> |
||||
|
</record> |
||||
|
</data> |
||||
|
</odoo> |
|
@ -0,0 +1,23 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
<data noupdate="1"> |
||||
|
<!-- Record rule of group doctor to access patient booking records--> |
||||
|
<record id="patient_booking_rule_doctor" model="ir.rule"> |
||||
|
<field name="name">Patient Booking Rule Doctor</field> |
||||
|
<field name="model_id" ref="model_patient_booking"/> |
||||
|
<field name="domain_force"> |
||||
|
[('doctor_id.doctor_id.user_id','=',user.id)] |
||||
|
</field> |
||||
|
<field name="groups" |
||||
|
eval="[(4, ref('base_hospital_management.base_hospital_management_group_doctor'))]"/> |
||||
|
</record> |
||||
|
<!-- Multi company rule for doctor allocation records--> |
||||
|
<record id="patient_booking_rule_company" model="ir.rule"> |
||||
|
<field name="name">Patient Booking Rule Company</field> |
||||
|
<field name="model_id" ref="model_patient_booking"/> |
||||
|
<field name="domain_force"> |
||||
|
['|',('company_id','=',False),('company_id', 'in', company_ids)] |
||||
|
</field> |
||||
|
</record> |
||||
|
</data> |
||||
|
</odoo> |
@ -0,0 +1,24 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
<data noupdate="1"> |
||||
|
<!--Record rule of group lab assistant to access patient lab test |
||||
|
records--> |
||||
|
<record id="patient_lab_test_rule_lab_assistant" model="ir.rule"> |
||||
|
<field name="name">Patient Lab Test Rule Lab Assistant</field> |
||||
|
<field name="model_id" ref="model_patient_lab_test"/> |
||||
|
<field name="domain_force"> |
||||
|
['|','|',('lab_id.technician_id.user_id','=',user.id),('lab_id.technician_id.user_id','=',False),('lab_id','=',False)] |
||||
|
</field> |
||||
|
<field name="groups" |
||||
|
eval="[(4, ref('base_hospital_management.base_hospital_management_group_lab_assistant'))]"/> |
||||
|
</record> |
||||
|
<!--Multi company rule for patient lab test records--> |
||||
|
<record id="patient_lab_test_rule_company" model="ir.rule"> |
||||
|
<field name="name">Patient Lab Test Rule Company</field> |
||||
|
<field name="model_id" ref="model_patient_lab_test"/> |
||||
|
<field name="domain_force"> |
||||
|
['|',('company_id','=',False),('company_id', 'in', company_ids)] |
||||
|
</field> |
||||
|
</record> |
||||
|
</data> |
||||
|
</odoo> |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 310 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 576 B |
After Width: | Height: | Size: 733 B |
After Width: | Height: | Size: 911 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 673 B |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 878 B |
After Width: | Height: | Size: 653 B |
After Width: | Height: | Size: 905 B |
After Width: | Height: | Size: 839 B |
After Width: | Height: | Size: 427 B |
After Width: | Height: | Size: 627 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 988 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 80 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 589 B |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 565 B |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 967 B |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 4.0 KiB |