diff --git a/base_hospital_management/README.rst b/base_hospital_management/README.rst new file mode 100755 index 000000000..bee1ad8d8 --- /dev/null +++ b/base_hospital_management/README.rst @@ -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 `__ + +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 `__ + +Further information +=================== +HTML Description: ``__ diff --git a/base_hospital_management/__init__.py b/base_hospital_management/__init__.py new file mode 100755 index 000000000..6e6c0808f --- /dev/null +++ b/base_hospital_management/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +from . import controllers +from . import models diff --git a/base_hospital_management/__manifest__.py b/base_hospital_management/__manifest__.py new file mode 100755 index 000000000..bcba83f50 --- /dev/null +++ b/base_hospital_management/__manifest__.py @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +{ + "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, +} diff --git a/base_hospital_management/controllers/__init__.py b/base_hospital_management/controllers/__init__.py new file mode 100755 index 000000000..79a69f8dc --- /dev/null +++ b/base_hospital_management/controllers/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +from . import patient_booking +from . import portal +from . import view_portal diff --git a/base_hospital_management/controllers/patient_booking.py b/base_hospital_management/controllers/patient_booking.py new file mode 100755 index 000000000..02e72ff68 --- /dev/null +++ b/base_hospital_management/controllers/patient_booking.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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} diff --git a/base_hospital_management/controllers/portal.py b/base_hospital_management/controllers/portal.py new file mode 100755 index 000000000..68a6c4d49 --- /dev/null +++ b/base_hospital_management/controllers/portal.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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 diff --git a/base_hospital_management/controllers/view_portal.py b/base_hospital_management/controllers/view_portal.py new file mode 100755 index 000000000..f1742bd95 --- /dev/null +++ b/base_hospital_management/controllers/view_portal.py @@ -0,0 +1,129 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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/', 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) diff --git a/base_hospital_management/data/ir_cron_data.xml b/base_hospital_management/data/ir_cron_data.xml new file mode 100755 index 000000000..a2db6fdf7 --- /dev/null +++ b/base_hospital_management/data/ir_cron_data.xml @@ -0,0 +1,15 @@ + + + + + + Blood Bank Availability + + code + model.action_change_availability() + 3 + months + -1 + + + diff --git a/base_hospital_management/data/ir_sequence_data.xml b/base_hospital_management/data/ir_sequence_data.xml new file mode 100755 index 000000000..17d42dded --- /dev/null +++ b/base_hospital_management/data/ir_sequence_data.xml @@ -0,0 +1,74 @@ + + + + + + Blood Bank Sequence + blood.bank + BB/ + 3 + 1 + 1 + + + + Building Sequence + building.sequence + BC/ + 3 + 1 + 1 + + + + Inpatient sequence + hospital.inpatient + IN/PAT + 3 + 1 + 1 + + + + Lab Test Sequence + lab.test.sequence + LB/TS/ + 3 + 1 + 1 + + + + Lab Test Draft Sequence + lab_tests.draft.sequence + LB/DR/ + 3 + 1 + 1 + + + + Laboratory Sequence + laboratory.sequence + LAB + 3 + + + + Patient sequence + patient.sequence + PAT + 3 + 1 + 1 + + + + Vaccination Sequence + vaccination.sequence + VAC + 3 + + + diff --git a/base_hospital_management/data/website_data.xml b/base_hospital_management/data/website_data.xml new file mode 100755 index 000000000..43a75acdb --- /dev/null +++ b/base_hospital_management/data/website_data.xml @@ -0,0 +1,12 @@ + + + + + + Booking + /patient_booking + + 50 + + + diff --git a/base_hospital_management/demo/hr_job_demo.xml b/base_hospital_management/demo/hr_job_demo.xml new file mode 100755 index 000000000..21f78f68f --- /dev/null +++ b/base_hospital_management/demo/hr_job_demo.xml @@ -0,0 +1,24 @@ + + + + + + Doctor + + + Nurse + + + Receptionist + + + Pharmacist + + + Staff + + + Lab Technician + + + diff --git a/base_hospital_management/doc/RELEASE_NOTES.md b/base_hospital_management/doc/RELEASE_NOTES.md new file mode 100755 index 000000000..c9b7e8443 --- /dev/null +++ b/base_hospital_management/doc/RELEASE_NOTES.md @@ -0,0 +1,7 @@ +## Module + +#### 03.06.2024 +#### Version 17.0.1.0.0 +#### ADD + +- Initial commit for Hospital Management Odoo 17 diff --git a/base_hospital_management/models/__init__.py b/base_hospital_management/models/__init__.py new file mode 100755 index 000000000..c9656bf29 --- /dev/null +++ b/base_hospital_management/models/__init__.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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 diff --git a/base_hospital_management/models/account_payment_register.py b/base_hospital_management/models/account_payment_register.py new file mode 100755 index 000000000..d1d4f867a --- /dev/null +++ b/base_hospital_management/models/account_payment_register.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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) diff --git a/base_hospital_management/models/blood_bank.py b/base_hospital_management/models/blood_bank.py new file mode 100755 index 000000000..b94d582df --- /dev/null +++ b/base_hospital_management/models/blood_bank.py @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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' diff --git a/base_hospital_management/models/blood_donation.py b/base_hospital_management/models/blood_donation.py new file mode 100755 index 000000000..2c7cacc5e --- /dev/null +++ b/base_hospital_management/models/blood_donation.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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') diff --git a/base_hospital_management/models/contra_indication.py b/base_hospital_management/models/contra_indication.py new file mode 100755 index 000000000..6ab260f04 --- /dev/null +++ b/base_hospital_management/models/contra_indication.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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') diff --git a/base_hospital_management/models/doctor_allocation.py b/base_hospital_management/models/doctor_allocation.py new file mode 100755 index 000000000..d224775e7 --- /dev/null +++ b/base_hospital_management/models/doctor_allocation.py @@ -0,0 +1,220 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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 diff --git a/base_hospital_management/models/doctor_round.py b/base_hospital_management/models/doctor_round.py new file mode 100755 index 000000000..decdaae0d --- /dev/null +++ b/base_hospital_management/models/doctor_round.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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') diff --git a/base_hospital_management/models/doctor_slot.py b/base_hospital_management/models/doctor_slot.py new file mode 100755 index 000000000..69a66e82a --- /dev/null +++ b/base_hospital_management/models/doctor_slot.py @@ -0,0 +1,128 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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' + }) diff --git a/base_hospital_management/models/doctor_specialization.py b/base_hospital_management/models/doctor_specialization.py new file mode 100755 index 000000000..8d4839d20 --- /dev/null +++ b/base_hospital_management/models/doctor_specialization.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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') diff --git a/base_hospital_management/models/hospital_bed.py b/base_hospital_management/models/hospital_bed.py new file mode 100755 index 000000000..c73849ba3 --- /dev/null +++ b/base_hospital_management/models/hospital_bed.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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") diff --git a/base_hospital_management/models/hospital_building.py b/base_hospital_management/models/hospital_building.py new file mode 100755 index 000000000..44fe52299 --- /dev/null +++ b/base_hospital_management/models/hospital_building.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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}, + } diff --git a/base_hospital_management/models/hospital_degree.py b/base_hospital_management/models/hospital_degree.py new file mode 100755 index 000000000..6b0a0dfec --- /dev/null +++ b/base_hospital_management/models/hospital_degree.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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') diff --git a/base_hospital_management/models/hospital_family.py b/base_hospital_management/models/hospital_family.py new file mode 100755 index 000000000..50f7657cb --- /dev/null +++ b/base_hospital_management/models/hospital_family.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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') diff --git a/base_hospital_management/models/hospital_inpatient.py b/base_hospital_management/models/hospital_inpatient.py new file mode 100755 index 000000000..f34bed536 --- /dev/null +++ b/base_hospital_management/models/hospital_inpatient.py @@ -0,0 +1,484 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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 diff --git a/base_hospital_management/models/hospital_insurance.py b/base_hospital_management/models/hospital_insurance.py new file mode 100755 index 000000000..a1cce4718 --- /dev/null +++ b/base_hospital_management/models/hospital_insurance.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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') diff --git a/base_hospital_management/models/hospital_laboratory.py b/base_hospital_management/models/hospital_laboratory.py new file mode 100755 index 000000000..7331917af --- /dev/null +++ b/base_hospital_management/models/hospital_laboratory.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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) diff --git a/base_hospital_management/models/hospital_outpatient.py b/base_hospital_management/models/hospital_outpatient.py new file mode 100755 index 000000000..fb15e8dd9 --- /dev/null +++ b/base_hospital_management/models/hospital_outpatient.py @@ -0,0 +1,317 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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) diff --git a/base_hospital_management/models/hospital_pharmacy.py b/base_hospital_management/models/hospital_pharmacy.py new file mode 100755 index 000000000..915ba7665 --- /dev/null +++ b/base_hospital_management/models/hospital_pharmacy.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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']) diff --git a/base_hospital_management/models/hospital_vaccination.py b/base_hospital_management/models/hospital_vaccination.py new file mode 100755 index 000000000..15484505c --- /dev/null +++ b/base_hospital_management/models/hospital_vaccination.py @@ -0,0 +1,155 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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 diff --git a/base_hospital_management/models/hospital_ward.py b/base_hospital_management/models/hospital_ward.py new file mode 100755 index 000000000..1397f8c54 --- /dev/null +++ b/base_hospital_management/models/hospital_ward.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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}, + } diff --git a/base_hospital_management/models/hr_employee.py b/base_hospital_management/models/hr_employee.py new file mode 100755 index 000000000..faa896559 --- /dev/null +++ b/base_hospital_management/models/hr_employee.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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' + }) diff --git a/base_hospital_management/models/inpatient_payment.py b/base_hospital_management/models/inpatient_payment.py new file mode 100755 index 000000000..966700ac5 --- /dev/null +++ b/base_hospital_management/models/inpatient_payment.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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') diff --git a/base_hospital_management/models/inpatient_surgery.py b/base_hospital_management/models/inpatient_surgery.py new file mode 100755 index 000000000..07ad57bfa --- /dev/null +++ b/base_hospital_management/models/inpatient_surgery.py @@ -0,0 +1,90 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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 diff --git a/base_hospital_management/models/ir_attachment.py b/base_hospital_management/models/ir_attachment.py new file mode 100755 index 000000000..80575a5bf --- /dev/null +++ b/base_hospital_management/models/ir_attachment.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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) diff --git a/base_hospital_management/models/lab_medicine_line.py b/base_hospital_management/models/lab_medicine_line.py new file mode 100755 index 000000000..054dfd2fc --- /dev/null +++ b/base_hospital_management/models/lab_medicine_line.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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 diff --git a/base_hospital_management/models/lab_test.py b/base_hospital_management/models/lab_test.py new file mode 100755 index 000000000..f8a6a1e96 --- /dev/null +++ b/base_hospital_management/models/lab_test.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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') diff --git a/base_hospital_management/models/lab_test_line.py b/base_hospital_management/models/lab_test_line.py new file mode 100755 index 000000000..4370c70b0 --- /dev/null +++ b/base_hospital_management/models/lab_test_line.py @@ -0,0 +1,126 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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', + } diff --git a/base_hospital_management/models/lab_test_result.py b/base_hospital_management/models/lab_test_result.py new file mode 100755 index 000000000..c23d4766b --- /dev/null +++ b/base_hospital_management/models/lab_test_result.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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 diff --git a/base_hospital_management/models/medicine_brand.py b/base_hospital_management/models/medicine_brand.py new file mode 100755 index 000000000..eb09b73a5 --- /dev/null +++ b/base_hospital_management/models/medicine_brand.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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') diff --git a/base_hospital_management/models/nursing_plan.py b/base_hospital_management/models/nursing_plan.py new file mode 100755 index 000000000..d9d82a393 --- /dev/null +++ b/base_hospital_management/models/nursing_plan.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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') diff --git a/base_hospital_management/models/patient_lab_test.py b/base_hospital_management/models/patient_lab_test.py new file mode 100755 index 000000000..87f0d4ab0 --- /dev/null +++ b/base_hospital_management/models/patient_lab_test.py @@ -0,0 +1,308 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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) diff --git a/base_hospital_management/models/patient_room.py b/base_hospital_management/models/patient_room.py new file mode 100755 index 000000000..4a88cdfa4 --- /dev/null +++ b/base_hospital_management/models/patient_room.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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!')] diff --git a/base_hospital_management/models/pharmacy_medicine.py b/base_hospital_management/models/pharmacy_medicine.py new file mode 100755 index 000000000..f21303291 --- /dev/null +++ b/base_hospital_management/models/pharmacy_medicine.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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') diff --git a/base_hospital_management/models/prescription_line.py b/base_hospital_management/models/prescription_line.py new file mode 100755 index 000000000..d7eea0468 --- /dev/null +++ b/base_hospital_management/models/prescription_line.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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') diff --git a/base_hospital_management/models/product_template.py b/base_hospital_management/models/product_template.py new file mode 100755 index 000000000..8d8f47fae --- /dev/null +++ b/base_hospital_management/models/product_template.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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 diff --git a/base_hospital_management/models/res_partner.py b/base_hospital_management/models/res_partner.py new file mode 100755 index 000000000..bd143e88d --- /dev/null +++ b/base_hospital_management/models/res_partner.py @@ -0,0 +1,584 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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'])]) diff --git a/base_hospital_management/models/res_users.py b/base_hospital_management/models/res_users.py new file mode 100755 index 000000000..e39971b37 --- /dev/null +++ b/base_hospital_management/models/res_users.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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 diff --git a/base_hospital_management/models/room_facility.py b/base_hospital_management/models/room_facility.py new file mode 100755 index 000000000..9baa4df28 --- /dev/null +++ b/base_hospital_management/models/room_facility.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2024-TODAY Cybrosys Technologies(). +# 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 . +# +################################################################################ +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') diff --git a/base_hospital_management/report/lab_test_line_reports.xml b/base_hospital_management/report/lab_test_line_reports.xml new file mode 100755 index 000000000..4e96823ad --- /dev/null +++ b/base_hospital_management/report/lab_test_line_reports.xml @@ -0,0 +1,66 @@ + + + + + Patient Lab Tests + lab.test.line + qweb-pdf + + base_hospital_management.report_patient_lab_tests + + + base_hospital_management.report_patient_lab_tests + + + report + + + + diff --git a/base_hospital_management/report/res_partner_reports.xml b/base_hospital_management/report/res_partner_reports.xml new file mode 100755 index 000000000..00aa6a768 --- /dev/null +++ b/base_hospital_management/report/res_partner_reports.xml @@ -0,0 +1,208 @@ + + + + + Patient Prescription + res.partner + qweb-pdf + base_hospital_management.patient_prescription_report + base_hospital_management.patient_prescription_report + + report + + + + + + Custom Paper + + custom + 55 + 30 + Landscape + 1.00 + 1.00 + 0.00 + 1.00 + + 35 + 125 + + + + Patient Card + res.partner + qweb-pdf + base_hospital_management.patient_card_report + base_hospital_management.patient_card_report + + + report + + + + diff --git a/base_hospital_management/security/base_hospital_management_groups.xml b/base_hospital_management/security/base_hospital_management_groups.xml new file mode 100755 index 000000000..8fdb1bc69 --- /dev/null +++ b/base_hospital_management/security/base_hospital_management_groups.xml @@ -0,0 +1,42 @@ + + + + + Hospital Management + User access levels for Hospital Management + + 10 + + + + Lab Assistant + + + + + Pharmacist + + + + + Nurse + + + + + Doctor + + + + + Receptionist + + + + + Manager + + + diff --git a/base_hospital_management/security/doctor_allocation_security.xml b/base_hospital_management/security/doctor_allocation_security.xml new file mode 100755 index 000000000..80d10f1a0 --- /dev/null +++ b/base_hospital_management/security/doctor_allocation_security.xml @@ -0,0 +1,33 @@ + + + + + + Doctor Allocation Rule Doctor + + + [('doctor_id.user_id','=',user.id)] + + + + + + Doctor Allocation Rule Manager + + + [(1,'=',1)] + + + + + + Doctor Allocation Rule Company + + + ['|',('company_id','=',False),('company_id', 'in', company_ids)] + + + + diff --git a/base_hospital_management/security/doctor_slot_security.xml b/base_hospital_management/security/doctor_slot_security.xml new file mode 100755 index 000000000..9aa6189d3 --- /dev/null +++ b/base_hospital_management/security/doctor_slot_security.xml @@ -0,0 +1,25 @@ + + + + + + Doctor Slot Rule Doctor + + + [('doctor_id.user_id','=',user.id)] + + + + + + Doctor Slot Rule Company + + + ['|',('company_id','=',False),('company_id', 'in', company_ids)] + + + + + diff --git a/base_hospital_management/security/ir.model.access.csv b/base_hospital_management/security/ir.model.access.csv new file mode 100755 index 000000000..168e9e1eb --- /dev/null +++ b/base_hospital_management/security/ir.model.access.csv @@ -0,0 +1,214 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink + +access_medicine_brand_lab_assistant,access.medicine.brand_lab.assistant,model_medicine_brand,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,0,0 +access_medicine_brand_pharmacist,access.medicine.brand.pharmacist,model_medicine_brand,base_hospital_management.base_hospital_management_group_pharmacist,1,1,1,1 +access_medicine_brand_nurse,access.medicine.brand.nurse,model_medicine_brand,base_hospital_management.base_hospital_management_group_nurse,1,1,0,0 +access_medicine_brand_doctor,access.medicine.brand.doctor,model_medicine_brand,base_hospital_management.base_hospital_management_group_doctor,1,1,1,1 +access_medicine_brand_receptionist,access.medicine.brand.receptionist,model_medicine_brand,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,0 +access_medicine_brand_manager,access.medicine.brand.manager,model_medicine_brand,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_doctor_specialization_lab_assistant,access.doctor.specialization.lab.assistant,model_doctor_specialization,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,0,0 +access_doctor_specialization_pharmacist,access.doctor.specialization.pharmacist,model_doctor_specialization,base_hospital_management.base_hospital_management_group_pharmacist,1,1,0,0 +access_doctor_specialization_nurse,access.doctor.specialization.nurse,model_doctor_specialization,base_hospital_management.base_hospital_management_group_nurse,1,1,1,0 +access_doctor_specialization_doctor,model_doctor_specialization,model_doctor_specialization,base_hospital_management.base_hospital_management_group_doctor,1,1,1,0 +access_doctor_specialization_receptionist,model_doctor_specialization,model_doctor_specialization,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,0 +access_doctor_specialization_manager,model_doctor_specialization,model_doctor_specialization,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_contra_indication_lab_assistant,access.contra.indication.lab.assistant,model_contra_indication,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,0,0 +access_contra_indication_pharmacist,access.contra.indication.pharmacist,model_contra_indication,base_hospital_management.base_hospital_management_group_pharmacist,1,1,1,0 +access_contra_indication_nurse,access.contra.indication.nurse,model_contra_indication,base_hospital_management.base_hospital_management_group_nurse,1,1,1,0 +access_contra_indication_doctor,access.contra.indication.doctor,model_contra_indication,base_hospital_management.base_hospital_management_group_doctor,1,1,1,0 +access_contra_indication_receptionist,access.contra.indication.receptionist,model_contra_indication,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,1 +access_contra_indication_manager,access.contra.indication.manager,model_contra_indication,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_hospital_degree_lab_assistant,access.hospital.degree.lab.assistant,model_hospital_degree,base_hospital_management.base_hospital_management_group_lab_assistant,1,0,0,0 +access_hospital_degree_pharmacist,access.hospital.degree.pharmacist,model_hospital_degree,base_hospital_management.base_hospital_management_group_pharmacist,1,0,0,0 +access_hospital_degree_nurse,access.hospital.degree.nurse,model_hospital_degree,base_hospital_management.base_hospital_management_group_nurse,1,1,0,0 +access_hospital_degree_doctor,access.hospital.degree.doctor,model_hospital_degree,base_hospital_management.base_hospital_management_group_doctor,1,0,0,0 +access_hospital_degree_receptionist,access.hospital.degree.receptionist,model_hospital_degree,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,0 +access_hospital_degree_manager,access.hospital.degree.manager,model_hospital_degree,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_room_facility_lab_assistant,access.room.facility.lab.assistant,model_room_facility,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,0,0 +access_room_facility_pharmacist,access.room.facility.pharmacist,model_room_facility,base_hospital_management.base_hospital_management_group_pharmacist,1,1,0,0 +access_room_facility_nurse,access.room.facility.nurse,model_room_facility,base_hospital_management.base_hospital_management_group_nurse,1,1,0,0 +access_room_facility_doctor,access.room.facility.doctor,model_room_facility,base_hospital_management.base_hospital_management_group_doctor,1,0,0,0 +access_room_facility_receptionist,access.room.facility.receptionist,model_room_facility,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,1 +access_room_facility_manager,access.room.facility.manager,model_room_facility,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_hospital_laboratory_lab_assistant,access.hospital.laboratory.lab.assistant,model_hospital_laboratory,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,1,0 +access_hospital_laboratory_pharmacist,access.hospital.laboratory.pharmacist,model_hospital_laboratory,base_hospital_management.base_hospital_management_group_pharmacist,1,1,0,0 +access_hospital_laboratory_nurse,access.hospital.laboratory.nurse,model_hospital_laboratory,base_hospital_management.base_hospital_management_group_nurse,1,1,0,0 +access_hospital_laboratory_doctor,access.hospital.laboratory.doctor,model_hospital_laboratory,base_hospital_management.base_hospital_management_group_doctor,1,1,0,0 +access_hospital_laboratory_receptionist,access.hospital.laboratory.receptionist,model_hospital_laboratory,base_hospital_management.base_hospital_management_group_receptionist,1,1,0,0 +access_hospital_laboratory_manager,access.hospital.laboratory.manager,model_hospital_laboratory,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_lab_test_lab_assistant,access.lab.test.lab.assistant,model_lab_test,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,1,0 +access_lab_test_pharmacist,access.lab.test.pharmacist,model_lab_test,base_hospital_management.base_hospital_management_group_pharmacist,1,1,0,0 +access_lab_test_nurse,access.lab.test.nurse,model_lab_test,base_hospital_management.base_hospital_management_group_nurse,1,1,0,0 +access_lab_test_doctor,access.lab.test.doctor,model_lab_test,base_hospital_management.base_hospital_management_group_doctor,1,1,0,0 +access_lab_test_receptionist,access.lab.test.receptionist,model_lab_test,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,0 +access_lab_test_manager,access.lab.test.manager,model_lab_test,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_doctor_slot_lab_assistant,access.doctor.slot.lab.assistant,model_doctor_slot,base_hospital_management.base_hospital_management_group_lab_assistant,1,0,0,0 +access_doctor_slot_pharmacist,access.doctor.slot.pharmacist,model_doctor_slot,base_hospital_management.base_hospital_management_group_pharmacist,1,1,0,0 +access_doctor_slot_nurse,access.doctor.slot.nurse,model_doctor_slot,base_hospital_management.base_hospital_management_group_nurse,1,1,1,0 +access_doctor_slot_doctor,access.doctor.slot.doctor,model_doctor_slot,base_hospital_management.base_hospital_management_group_doctor,1,1,1,0 +access_doctor_slot_receptionist,access.doctor.slot.receptionist,model_doctor_slot,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,0 +access_doctor_slot_manager,access.doctor.slot.manager,model_doctor_slot,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_hospital_pharmacy_lab_assistant,access.hospital.pharmacy.lab.assistant,model_hospital_pharmacy,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,0,0 +access_hospital_pharmacy_pharmacist,access.hospital.pharmacy.pharmacist,model_hospital_pharmacy,base_hospital_management.base_hospital_management_group_pharmacist,1,1,1,0 +access_hospital_pharmacy_nurse,access.hospital.pharmacy.nurse,model_hospital_pharmacy,base_hospital_management.base_hospital_management_group_nurse,1,1,0,0 +access_hospital_pharmacy_doctor,access.hospital.pharmacy.doctor,model_hospital_pharmacy,base_hospital_management.base_hospital_management_group_doctor,1,1,0,0 +access_hospital_pharmacy_receptionist,access.hospital.pharmacy.receptionist,model_hospital_pharmacy,base_hospital_management.base_hospital_management_group_receptionist,1,1,0,0 +access_hospital_pharmacy_manager,access.hospital.pharmacy.manager,model_hospital_pharmacy,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_pharmacy_medicine_manager,access.pharmacy.medicine.manager,model_pharmacy_medicine,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 +access_pharmacy_pharmacist,access.pharmacy.medicine.pharmacist,model_pharmacy_medicine,base_hospital_management.base_hospital_management_group_pharmacist,1,1,1,1 +access_hospital_building_lab_assistant,access.hospital.building.lab.assistant,model_hospital_building,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,0,0 +access_hospital_building_pharmacist,access.hospital.building.pharmacist,model_hospital_building,base_hospital_management.base_hospital_management_group_pharmacist,1,1,0,0 +access_hospital_building_nurse,access.hospital.building.nurse,model_hospital_building,base_hospital_management.base_hospital_management_group_nurse,1,1,0,0 +access_hospital_building_doctor,access.hospital.building.doctor,model_hospital_building,base_hospital_management.base_hospital_management_group_doctor,1,1,0,0 +access_hospital_building_receptionist,access.hospital.building.receptionist,model_hospital_building,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,0 +access_hospital_building_manager,access.hospital.building.manager,model_hospital_building,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_patient_room_lab_assistant,access.patient.room.lab.assistant,model_patient_room,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,0,0 +access_patient_room_pharmacist,access.patient.room.pharmacist,model_patient_room,base_hospital_management.base_hospital_management_group_pharmacist,1,1,0,0 +access_patient_room_nurse,access.patient.room.nurse,model_patient_room,base_hospital_management.base_hospital_management_group_nurse,1,1,0,0 +access_patient_room_doctor,access.patient.room.doctor,model_patient_room,base_hospital_management.base_hospital_management_group_doctor,1,1,0,0 +access_patient_room_receptionist,access.patient.room.receptionist,model_patient_room,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,0 +access_patient_room_manager,access.patient.room.manager,model_patient_room,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_hospital_ward_lab_assistant,access.hospital.ward.lab.assistant,model_hospital_ward,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,0,0 +access_hospital_ward_pharmacist,access.hospital.ward.pharmacist,model_hospital_ward,base_hospital_management.base_hospital_management_group_pharmacist,1,1,0,0 +access_hospital_ward_nurse,access.hospital.ward.nurse,model_hospital_ward,base_hospital_management.base_hospital_management_group_nurse,1,1,0,0 +access_hospital_ward_doctor,access.hospital.ward.doctor,model_hospital_ward,base_hospital_management.base_hospital_management_group_doctor,1,1,0,0 +access_hospital_ward_receptionist,access.hospital.ward.receptionist,model_hospital_ward,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,0 +access_hospital_ward_manager,access.hospital.ward.manager,model_hospital_ward,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_hospital_bed_lab_assistant,access.hospital.bed.lab.assistant,model_hospital_bed,base_hospital_management.base_hospital_management_group_lab_assistant,1,0,0,0 +access_hospital_bed_pharmacist,access.hospital.bed.pharmacist,model_hospital_bed,base_hospital_management.base_hospital_management_group_pharmacist,1,0,0,0 +access_hospital_bed_nurse,access.hospital.bed.nurse,model_hospital_bed,base_hospital_management.base_hospital_management_group_nurse,1,0,0,0 +access_hospital_bed_doctor,access.hospital.bed.doctor,model_hospital_bed,base_hospital_management.base_hospital_management_group_doctor,1,0,0,0 +access_hospital_bed_receptionist,access.hospital.bed.receptionist,model_hospital_bed,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,0 +access_hospital_bed_manager,access.hospital.bed.manager,model_hospital_bed,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_hospital_inpatient_lab_assistant,access.hospital.inpatient.lab.assistant,model_hospital_inpatient,base_hospital_management.base_hospital_management_group_lab_assistant,1,0,0,0 +access_hospital_inpatient_pharmacist,access.hospital.inpatient.pharmacist,model_hospital_inpatient,base_hospital_management.base_hospital_management_group_pharmacist,1,0,0,0 +access_hospital_inpatient_nurse,access.hospital.inpatient.nurse,model_hospital_inpatient,base_hospital_management.base_hospital_management_group_nurse,1,1,1,0 +access_hospital_inpatient_doctor,access.hospital.inpatient.doctor,model_hospital_inpatient,base_hospital_management.base_hospital_management_group_doctor,1,1,1,0 +access_hospital_inpatient_receptionist,access.hospital.inpatient.receptionist,model_hospital_inpatient,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,0 +access_hospital_inpatient_manager,access.hospital.inpatient.manager,model_hospital_inpatient,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_blood_bank_lab_assistant,access.blood.bank.lab.assistant,model_blood_bank,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,0,0 +access_blood_bank_pharmacist,access.blood.bank.pharmacist,model_blood_bank,base_hospital_management.base_hospital_management_group_pharmacist,1,1,0,0 +access_blood_bank_nurse,access.blood.bank.nurse,model_blood_bank,base_hospital_management.base_hospital_management_group_nurse,1,0,0,0 +access_blood_bank_doctor,access.blood.bank.doctor,model_blood_bank,base_hospital_management.base_hospital_management_group_doctor,1,1,1,0 +access_blood_bank_receptionist,access.blood.bank.receptionist,model_blood_bank,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,0 +access_blood_bank_manager,access.blood.bank.manager,model_blood_bank,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_hospital_outpatient_lab_assistant,access.hospital.outpatient.lab.assistant,model_hospital_outpatient,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,1,0 +access_hospital_outpatient_pharmacist,access.hospital.outpatient.pharmacist,model_hospital_outpatient,base_hospital_management.base_hospital_management_group_pharmacist,1,1,1,0 +access_hospital_outpatient_nurse,access.hospital.outpatient.model_hospital_outpatient,model_hospital_outpatient,base_hospital_management.base_hospital_management_group_nurse,1,1,1,0 +access_hospital_outpatient_doctor,access.hospital.outpatient.doctor,model_hospital_outpatient,base_hospital_management.base_hospital_management_group_doctor,1,1,1,0 +access_hospital_outpatient_receptionist,access.hospital.outpatient.receptionist,model_hospital_outpatient,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,0 +access_hospital_outpatient_manager,access.hospital.outpatient.manager,model_hospital_outpatient,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_hospital_insurance_lab_assistant,access.hospital.insurance.lab.assistant,model_hospital_insurance,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,0,0 +access_hospital_insurance_pharmacist,access.hospital.insurance.pharmacist,model_hospital_insurance,base_hospital_management.base_hospital_management_group_pharmacist,1,1,0,0 +access_hospital_insurance_nurse,access.hospital.insurance.nurse,model_hospital_insurance,base_hospital_management.base_hospital_management_group_nurse,1,1,0,0 +access_hospital_insurance_doctor,access.hospital.insurance.doctor,model_hospital_insurance,base_hospital_management.base_hospital_management_group_doctor,1,0,0,0 +access_hospital_insurance_receptionist,access.hospital.insurance.receptionist,model_hospital_insurance,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,0 +access_hospital_insurance_manager,access.hospital.insurance.manager,model_hospital_insurance,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_hospital_family_lab_assistant,access.hospital.family.lab.assistant,model_hospital_family,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,0,0 +access_hospital_family_pharmacist,access.hospital.family.pharmacist,model_hospital_family,base_hospital_management.base_hospital_management_group_pharmacist,1,1,0,0 +access_hospital_family_nurse,access.hospital.family.nurse,model_hospital_family,base_hospital_management.base_hospital_management_group_nurse,1,1,0,0 +access_hospital_family_doctor,access.hospital.family.doctor,model_hospital_family,base_hospital_management.base_hospital_management_group_doctor,1,1,0,0 +access_hospital_family_receptionist,access.hospital.family.receptionist,model_hospital_family,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,0 +access_hospital_family_manager,access.hospital.family.manager,model_hospital_family,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_hospital_vaccination_lab_assistant,access.hospital.vaccination.lab.assistant,model_hospital_vaccination,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,1,1 +access_hospital_vaccination_pharmacist,access.hospital.vaccination.pharmacist,model_hospital_vaccination,base_hospital_management.base_hospital_management_group_pharmacist,1,1,1,0 +access_hospital_vaccination_nurse,access.hospital.vaccination.nurse,model_hospital_vaccination,base_hospital_management.base_hospital_management_group_nurse,1,1,0,0 +access_hospital_vaccination_doctor,access.hospital.vaccination.doctor,model_hospital_vaccination,base_hospital_management.base_hospital_management_group_doctor,1,1,1,0 +access_hospital_vaccination_receptionist,access.hospital.vaccination.receptionist,model_hospital_vaccination,base_hospital_management.base_hospital_management_group_receptionist,1,1,0,0 +access_hospital_vaccination_manager,access.hospital.vaccination.manager,model_hospital_vaccination,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_lab_test_line_lab_assistant,access.lab.test.line.lab.assistant,model_lab_test_line,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,1,0 +access_lab_test_line_pharmacist,access.lab.test.line.pharmacist,model_lab_test_line,base_hospital_management.base_hospital_management_group_pharmacist,1,1,0,0 +access_lab_test_line_nurse,access.lab.test.line.nurse,model_lab_test_line,base_hospital_management.base_hospital_management_group_nurse,1,1,1,0 +access_lab_test_line_doctor,access.lab.test.line.doctor,model_lab_test_line,base_hospital_management.base_hospital_management_group_doctor,1,1,0,0 +access_lab_test_line_receptionist,access.lab.test.line.receptionist,model_lab_test_line,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,0 +access_lab_test_line_lab_tests_manager,access.lab.test.line.manager,model_lab_test_line,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_lab_test_result_lab_assistant,access.lab.test.result.lab.assistant,model_lab_test_result,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,1,0 +access_lab_test_result_pharmacist,access.lab.test.result.pharmacist,model_lab_test_result,base_hospital_management.base_hospital_management_group_pharmacist,1,1,0,0 +access_lab_test_result_nurse,access.lab.test.result.nurse,model_lab_test_result,base_hospital_management.base_hospital_management_group_nurse,1,1,0,0 +access_lab_test_result_doctor,access.lab.test.result.doctor,model_lab_test_result,base_hospital_management.base_hospital_management_group_doctor,1,1,0,0 +access_lab_test_result_receptionist,access.lab.test.result.receptionist,model_lab_test_result,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,0 +access_lab_test_result_manager,access.lab.test.result.manager,model_lab_test_result,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_doctor_allocation_lab_assistant,access.doctor.allocation.lab.assistant,model_doctor_allocation,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,0,0 +access_doctor_allocation_pharmacist,access.doctor.allocation.pharmacist,model_doctor_allocation,base_hospital_management.base_hospital_management_group_pharmacist,1,1,0,0 +access_doctor_allocation_nurse,access.doctor.allocation.nurse,model_doctor_allocation,base_hospital_management.base_hospital_management_group_nurse,1,1,0,0 +access_doctor_allocation_doctor,access.doctor.allocation.doctor,model_doctor_allocation,base_hospital_management.base_hospital_management_group_doctor,1,1,1,0 +access_doctor_allocation_receptionist,access.doctor.allocation.receptionist,model_doctor_allocation,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,0 +access_doctor_allocation_manager,access.doctor.allocation.manager,model_doctor_allocation,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 +access_doctor_allocation_portal,access.doctor.allocation.portal,model_doctor_allocation,base.group_portal,1,0,0,0 + +access_lab_medicine_line_lab_assistant,access.lab.medicine.line.lab.assistant,model_lab_medicine_line,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,1,0 +access_lab_medicine_line_pharmacist,access.lab.medicine.line.pharmacist,model_lab_medicine_line,base_hospital_management.base_hospital_management_group_pharmacist,1,1,1,0 +access_lab_medicine_line_nurse,access.lab.medicine.line.nurse,model_lab_medicine_line,base_hospital_management.base_hospital_management_group_nurse,1,1,0,0 +access_lab_medicine_line_doctor,access.lab.medicine.line.doctor,model_lab_medicine_line,base_hospital_management.base_hospital_management_group_doctor,1,1,0,0 +access_lab_medicine_line_receptionist,access.lab.medicine.line.receptionist,model_lab_medicine_line,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,0 +access_lab_medicine_line_manager,access.lab.medicine.line.manager,model_lab_medicine_line,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_nursing_plan_lab_assistant,access.nursing.plan.lab.assistant,model_nursing_plan,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,0,0 +access_nursing_plan_pharmacist,access.nursing.plan.pharmacist,model_nursing_plan,base_hospital_management.base_hospital_management_group_pharmacist,1,1,0,0 +access_nursing_plan_nurse,access.nursing.plan.nurse,model_nursing_plan,base_hospital_management.base_hospital_management_group_nurse,1,1,1,0 +access_nursing_plan_doctor,access.nursing.plan.doctor,model_nursing_plan,base_hospital_management.base_hospital_management_group_doctor,1,1,1,0 +access_nursing_plan_receptionist,access.nursing.plan.receptionist,model_nursing_plan,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,0 +access_nursing_plan_manager,access.nursing.plan.manager,model_nursing_plan,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_doctor_round_lab_assistant,access.doctor.round.lab.assistant,model_doctor_round,base_hospital_management.base_hospital_management_group_lab_assistant,1,0,0,0 +access_doctor_round_pharmacist,access.doctor.round.pharmacist,model_doctor_round,base_hospital_management.base_hospital_management_group_pharmacist,1,0,0,0 +access_doctor_round_nurse,access.doctor.round.nurse,model_doctor_round,base_hospital_management.base_hospital_management_group_nurse,1,1,1,1 +access_doctor_round_doctor,access.doctor.round.doctor,model_doctor_round,base_hospital_management.base_hospital_management_group_doctor,1,1,1,1 +access_doctor_round_receptionist,access.doctor.round.receptionist,model_doctor_round,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,1 +access_doctor_round_manager,access.doctor.round.manager,model_doctor_round,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_prescription_line_lab_assistant,access.prescription.line.lab.assistant,model_prescription_line,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,0,0 +access_prescription_line_pharmacist,access.prescription.line.pharmacist,model_prescription_line,base_hospital_management.base_hospital_management_group_pharmacist,1,1,1,0 +access_prescription_line_nurse,access.prescription.line.nurse,model_prescription_line,base_hospital_management.base_hospital_management_group_nurse,1,1,1,0 +access_prescription_line_doctor,access.prescription.line.doctor,model_prescription_line,base_hospital_management.base_hospital_management_group_doctor,1,1,1,0 +access_prescription_line_receptionist,access.prescription.line.receptionist,model_prescription_line,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,1 +access_prescription_line_manager,access.prescription.line.manager,model_prescription_line,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_blood_donation_lab_assistant,access.blood.donation.lab.assistant,model_blood_donation,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,0,0 +access_blood_donation_pharmacist,access.blood.donation.lab.pharmacist,model_blood_donation,base_hospital_management.base_hospital_management_group_pharmacist,1,1,1,0 +access_blood_donation_nurse,access.blood.donation.lab.nurse,model_blood_donation,base_hospital_management.base_hospital_management_group_nurse,1,1,1,0 +access_blood_donation_doctor,access.blood.donation.lab.doctor,model_blood_donation,base_hospital_management.base_hospital_management_group_doctor,1,1,1,0 +access_blood_donation_receptionist,access.blood.donation.lab.receptionist,model_blood_donation,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,1 +access_blood_donation_manager,access.blood.donation.lab.manager,model_blood_donation,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_inpatient_payment_lab_assistant,access.inpatient.payment.lab.assistant,model_inpatient_payment,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,0,0 +access_inpatient_payment_pharmacist,access.inpatient.payment.pharmacist,model_inpatient_payment,base_hospital_management.base_hospital_management_group_pharmacist,1,1,1,0 +access_inpatient_payment_nurse,access.inpatient.payment.nurse,model_inpatient_payment,base_hospital_management.base_hospital_management_group_nurse,1,1,1,0 +access_inpatient_payment_doctor,access.inpatient.payment.doctor,model_inpatient_payment,base_hospital_management.base_hospital_management_group_doctor,1,1,1,0 +access_inpatient_payment_receptionist,access.inpatient.payment.receptionis,model_inpatient_payment,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,1 +access_inpatient_payment_manager,access.inpatient.payment.manager,model_inpatient_payment,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_inpatient_surgery_lab_assistant,access.inpatient.surgery.lab.assistant,model_inpatient_surgery,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,0,0 +access_inpatient_surgery_pharmacist,access.inpatient.surgery.pharmacist,model_inpatient_surgery,base_hospital_management.base_hospital_management_group_pharmacist,1,1,1,0 +access_inpatient_surgery_nurse,access.inpatient.surgery.nurse,model_inpatient_surgery,base_hospital_management.base_hospital_management_group_nurse,1,1,1,0 +access_inpatient_surgery_doctor,access.inpatient.surgery.doctor,model_inpatient_surgery,base_hospital_management.base_hospital_management_group_doctor,1,1,1,0 +access_inpatient_surgery_receptionist,access.inpatient.surgery.receptionist,model_inpatient_surgery,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,1 +access_inpatient_surgery_manager,access.inpatient.surgery.manager,model_inpatient_surgery,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 + +access_patient_lab_test_lab_assistant,access.patient.lab.test.lab.assistant,model_patient_lab_test,base_hospital_management.base_hospital_management_group_lab_assistant,1,1,0,0 +access_patient_lab_test_pharmacist,access.patient.lab.test.pharmacist,model_patient_lab_test,base_hospital_management.base_hospital_management_group_pharmacist,1,1,0,0 +access_patient_lab_test_nurse,access.patient.lab.test.nurse,model_patient_lab_test,base_hospital_management.base_hospital_management_group_nurse,1,1,0,0 +access_patient_lab_test_doctor,access.patient.lab.test.doctor,model_patient_lab_test,base_hospital_management.base_hospital_management_group_doctor,1,1,0,0 +access_patient_lab_test_receptionist,access.patient.lab.test.receptionist,model_patient_lab_test,base_hospital_management.base_hospital_management_group_receptionist,1,1,1,1 +access_patient_lab_test_manager,access.patient.lab.test.manager,model_patient_lab_test,base_hospital_management.base_hospital_management_group_manager,1,1,1,1 diff --git a/base_hospital_management/security/patient_booking_security.xml b/base_hospital_management/security/patient_booking_security.xml new file mode 100755 index 000000000..fbe7fad1e --- /dev/null +++ b/base_hospital_management/security/patient_booking_security.xml @@ -0,0 +1,23 @@ + + + + + + Patient Booking Rule Doctor + + + [('doctor_id.doctor_id.user_id','=',user.id)] + + + + + + Patient Booking Rule Company + + + ['|',('company_id','=',False),('company_id', 'in', company_ids)] + + + + diff --git a/base_hospital_management/security/patient_lab_test_security.xml b/base_hospital_management/security/patient_lab_test_security.xml new file mode 100755 index 000000000..a5c9cac48 --- /dev/null +++ b/base_hospital_management/security/patient_lab_test_security.xml @@ -0,0 +1,24 @@ + + + + + + Patient Lab Test Rule Lab Assistant + + + ['|','|',('lab_id.technician_id.user_id','=',user.id),('lab_id.technician_id.user_id','=',False),('lab_id','=',False)] + + + + + + Patient Lab Test Rule Company + + + ['|',('company_id','=',False),('company_id', 'in', company_ids)] + + + + diff --git a/base_hospital_management/static/description/assets/icons/capture (1).png b/base_hospital_management/static/description/assets/icons/capture (1).png new file mode 100644 index 000000000..8824deafc Binary files /dev/null and b/base_hospital_management/static/description/assets/icons/capture (1).png differ diff --git a/base_hospital_management/static/description/assets/icons/check.png b/base_hospital_management/static/description/assets/icons/check.png new file mode 100644 index 000000000..c8e85f51d Binary files /dev/null and b/base_hospital_management/static/description/assets/icons/check.png differ diff --git a/base_hospital_management/static/description/assets/icons/chevron.png b/base_hospital_management/static/description/assets/icons/chevron.png new file mode 100644 index 000000000..2089293d6 Binary files /dev/null and b/base_hospital_management/static/description/assets/icons/chevron.png differ diff --git a/base_hospital_management/static/description/assets/icons/cogs.png b/base_hospital_management/static/description/assets/icons/cogs.png new file mode 100644 index 000000000..95d0bad62 Binary files /dev/null and b/base_hospital_management/static/description/assets/icons/cogs.png differ diff --git a/base_hospital_management/static/description/assets/icons/consultation.png b/base_hospital_management/static/description/assets/icons/consultation.png new file mode 100644 index 000000000..8319d4baa Binary files /dev/null and b/base_hospital_management/static/description/assets/icons/consultation.png differ diff --git a/base_hospital_management/static/description/assets/icons/ecom-black.png b/base_hospital_management/static/description/assets/icons/ecom-black.png new file mode 100644 index 000000000..a9385ff13 Binary files /dev/null and b/base_hospital_management/static/description/assets/icons/ecom-black.png differ diff --git a/base_hospital_management/static/description/assets/icons/education-black.png b/base_hospital_management/static/description/assets/icons/education-black.png new file mode 100644 index 000000000..3eb09b27b Binary files /dev/null and b/base_hospital_management/static/description/assets/icons/education-black.png differ diff --git a/base_hospital_management/static/description/assets/icons/hotel-black.png b/base_hospital_management/static/description/assets/icons/hotel-black.png new file mode 100644 index 000000000..130f613be Binary files /dev/null and b/base_hospital_management/static/description/assets/icons/hotel-black.png differ diff --git a/base_hospital_management/static/description/assets/icons/img.png b/base_hospital_management/static/description/assets/icons/img.png new file mode 100644 index 000000000..70197f477 Binary files /dev/null and b/base_hospital_management/static/description/assets/icons/img.png differ diff --git a/base_hospital_management/static/description/assets/icons/license.png b/base_hospital_management/static/description/assets/icons/license.png new file mode 100644 index 000000000..a5869797e Binary files /dev/null and b/base_hospital_management/static/description/assets/icons/license.png differ diff --git a/base_hospital_management/static/description/assets/icons/lifebuoy.png b/base_hospital_management/static/description/assets/icons/lifebuoy.png new file mode 100644 index 000000000..658d56ccc Binary files /dev/null and b/base_hospital_management/static/description/assets/icons/lifebuoy.png differ diff --git a/base_hospital_management/static/description/assets/icons/manufacturing-black.png b/base_hospital_management/static/description/assets/icons/manufacturing-black.png new file mode 100644 index 000000000..697eb0e9f Binary files /dev/null and b/base_hospital_management/static/description/assets/icons/manufacturing-black.png differ diff --git a/base_hospital_management/static/description/assets/icons/photo-capture.png b/base_hospital_management/static/description/assets/icons/photo-capture.png new file mode 100644 index 000000000..06c111758 Binary files /dev/null and b/base_hospital_management/static/description/assets/icons/photo-capture.png differ diff --git a/base_hospital_management/static/description/assets/icons/pos-black.png b/base_hospital_management/static/description/assets/icons/pos-black.png new file mode 100644 index 000000000..97c0f90c1 Binary files /dev/null and b/base_hospital_management/static/description/assets/icons/pos-black.png differ diff --git a/base_hospital_management/static/description/assets/icons/puzzle.png b/base_hospital_management/static/description/assets/icons/puzzle.png new file mode 100644 index 000000000..65cf854e7 Binary files /dev/null and b/base_hospital_management/static/description/assets/icons/puzzle.png differ diff --git a/base_hospital_management/static/description/assets/icons/restaurant-black.png b/base_hospital_management/static/description/assets/icons/restaurant-black.png new file mode 100644 index 000000000..4a35eb939 Binary files /dev/null and b/base_hospital_management/static/description/assets/icons/restaurant-black.png differ diff --git a/base_hospital_management/static/description/assets/icons/service-black.png b/base_hospital_management/static/description/assets/icons/service-black.png new file mode 100644 index 000000000..301ab51cb Binary files /dev/null and b/base_hospital_management/static/description/assets/icons/service-black.png differ diff --git a/base_hospital_management/static/description/assets/icons/trading-black.png b/base_hospital_management/static/description/assets/icons/trading-black.png new file mode 100644 index 000000000..9398ba2f1 Binary files /dev/null and b/base_hospital_management/static/description/assets/icons/trading-black.png differ diff --git a/base_hospital_management/static/description/assets/icons/training.png b/base_hospital_management/static/description/assets/icons/training.png new file mode 100644 index 000000000..884ca024d Binary files /dev/null and b/base_hospital_management/static/description/assets/icons/training.png differ diff --git a/base_hospital_management/static/description/assets/icons/update.png b/base_hospital_management/static/description/assets/icons/update.png new file mode 100644 index 000000000..ecbc5a01a Binary files /dev/null and b/base_hospital_management/static/description/assets/icons/update.png differ diff --git a/base_hospital_management/static/description/assets/icons/user.png b/base_hospital_management/static/description/assets/icons/user.png new file mode 100644 index 000000000..6ffb23d9f Binary files /dev/null and b/base_hospital_management/static/description/assets/icons/user.png differ diff --git a/base_hospital_management/static/description/assets/icons/wrench.png b/base_hospital_management/static/description/assets/icons/wrench.png new file mode 100644 index 000000000..6c04dea0f Binary files /dev/null and b/base_hospital_management/static/description/assets/icons/wrench.png differ diff --git a/base_hospital_management/static/description/assets/misc/Cybrosys R.png b/base_hospital_management/static/description/assets/misc/Cybrosys R.png new file mode 100644 index 000000000..da4058087 Binary files /dev/null and b/base_hospital_management/static/description/assets/misc/Cybrosys R.png differ diff --git a/base_hospital_management/static/description/assets/misc/categories.png b/base_hospital_management/static/description/assets/misc/categories.png new file mode 100644 index 000000000..bedf1e0b1 Binary files /dev/null and b/base_hospital_management/static/description/assets/misc/categories.png differ diff --git a/base_hospital_management/static/description/assets/misc/check-box.png b/base_hospital_management/static/description/assets/misc/check-box.png new file mode 100644 index 000000000..42caf24b9 Binary files /dev/null and b/base_hospital_management/static/description/assets/misc/check-box.png differ diff --git a/base_hospital_management/static/description/assets/misc/compass.png b/base_hospital_management/static/description/assets/misc/compass.png new file mode 100644 index 000000000..d5fed8faa Binary files /dev/null and b/base_hospital_management/static/description/assets/misc/compass.png differ diff --git a/base_hospital_management/static/description/assets/misc/corporate.png b/base_hospital_management/static/description/assets/misc/corporate.png new file mode 100644 index 000000000..2eb13edbf Binary files /dev/null and b/base_hospital_management/static/description/assets/misc/corporate.png differ diff --git a/base_hospital_management/static/description/assets/misc/customer-support.png b/base_hospital_management/static/description/assets/misc/customer-support.png new file mode 100644 index 000000000..79efc72ed Binary files /dev/null and b/base_hospital_management/static/description/assets/misc/customer-support.png differ diff --git a/base_hospital_management/static/description/assets/misc/cybrosys-logo.png b/base_hospital_management/static/description/assets/misc/cybrosys-logo.png new file mode 100644 index 000000000..cc3cc0ccf Binary files /dev/null and b/base_hospital_management/static/description/assets/misc/cybrosys-logo.png differ diff --git a/base_hospital_management/static/description/assets/misc/email.svg b/base_hospital_management/static/description/assets/misc/email.svg new file mode 100644 index 000000000..15291cdc3 --- /dev/null +++ b/base_hospital_management/static/description/assets/misc/email.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/base_hospital_management/static/description/assets/misc/features.png b/base_hospital_management/static/description/assets/misc/features.png new file mode 100644 index 000000000..b41769f77 Binary files /dev/null and b/base_hospital_management/static/description/assets/misc/features.png differ diff --git a/base_hospital_management/static/description/assets/misc/logo.png b/base_hospital_management/static/description/assets/misc/logo.png new file mode 100644 index 000000000..478462d3e Binary files /dev/null and b/base_hospital_management/static/description/assets/misc/logo.png differ diff --git a/base_hospital_management/static/description/assets/misc/phone.svg b/base_hospital_management/static/description/assets/misc/phone.svg new file mode 100644 index 000000000..b7bd7f251 --- /dev/null +++ b/base_hospital_management/static/description/assets/misc/phone.svg @@ -0,0 +1,3 @@ + + + diff --git a/base_hospital_management/static/description/assets/misc/pictures.png b/base_hospital_management/static/description/assets/misc/pictures.png new file mode 100644 index 000000000..56d255fe9 Binary files /dev/null and b/base_hospital_management/static/description/assets/misc/pictures.png differ diff --git a/base_hospital_management/static/description/assets/misc/pie-chart.png b/base_hospital_management/static/description/assets/misc/pie-chart.png new file mode 100644 index 000000000..426e05244 Binary files /dev/null and b/base_hospital_management/static/description/assets/misc/pie-chart.png differ diff --git a/base_hospital_management/static/description/assets/misc/right-arrow.png b/base_hospital_management/static/description/assets/misc/right-arrow.png new file mode 100644 index 000000000..730984a06 Binary files /dev/null and b/base_hospital_management/static/description/assets/misc/right-arrow.png differ diff --git a/base_hospital_management/static/description/assets/misc/star (1) 2.svg b/base_hospital_management/static/description/assets/misc/star (1) 2.svg new file mode 100644 index 000000000..5ae9f507a --- /dev/null +++ b/base_hospital_management/static/description/assets/misc/star (1) 2.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/base_hospital_management/static/description/assets/misc/star.png b/base_hospital_management/static/description/assets/misc/star.png new file mode 100644 index 000000000..2eb9ab29f Binary files /dev/null and b/base_hospital_management/static/description/assets/misc/star.png differ diff --git a/base_hospital_management/static/description/assets/misc/support (1) 1.svg b/base_hospital_management/static/description/assets/misc/support (1) 1.svg new file mode 100644 index 000000000..7d37a8f30 --- /dev/null +++ b/base_hospital_management/static/description/assets/misc/support (1) 1.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/base_hospital_management/static/description/assets/misc/support-email.svg b/base_hospital_management/static/description/assets/misc/support-email.svg new file mode 100644 index 000000000..eb70370d6 --- /dev/null +++ b/base_hospital_management/static/description/assets/misc/support-email.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/base_hospital_management/static/description/assets/misc/support.png b/base_hospital_management/static/description/assets/misc/support.png new file mode 100644 index 000000000..4f18b8b82 Binary files /dev/null and b/base_hospital_management/static/description/assets/misc/support.png differ diff --git a/base_hospital_management/static/description/assets/misc/tick-mark.svg b/base_hospital_management/static/description/assets/misc/tick-mark.svg new file mode 100644 index 000000000..2dbb40187 --- /dev/null +++ b/base_hospital_management/static/description/assets/misc/tick-mark.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/base_hospital_management/static/description/assets/misc/whatsapp 1.svg b/base_hospital_management/static/description/assets/misc/whatsapp 1.svg new file mode 100644 index 000000000..0bfaf8fc6 --- /dev/null +++ b/base_hospital_management/static/description/assets/misc/whatsapp 1.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/base_hospital_management/static/description/assets/misc/whatsapp.png b/base_hospital_management/static/description/assets/misc/whatsapp.png new file mode 100644 index 000000000..d513a5356 Binary files /dev/null and b/base_hospital_management/static/description/assets/misc/whatsapp.png differ diff --git a/base_hospital_management/static/description/assets/misc/whatsapp.svg b/base_hospital_management/static/description/assets/misc/whatsapp.svg new file mode 100644 index 000000000..b618aea1d --- /dev/null +++ b/base_hospital_management/static/description/assets/misc/whatsapp.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/base_hospital_management/static/description/assets/modules/1.gif b/base_hospital_management/static/description/assets/modules/1.gif new file mode 100644 index 000000000..beb106101 Binary files /dev/null and b/base_hospital_management/static/description/assets/modules/1.gif differ diff --git a/base_hospital_management/static/description/assets/modules/1.jpg b/base_hospital_management/static/description/assets/modules/1.jpg new file mode 100644 index 000000000..b54c849a1 Binary files /dev/null and b/base_hospital_management/static/description/assets/modules/1.jpg differ diff --git a/base_hospital_management/static/description/assets/modules/2.jpg b/base_hospital_management/static/description/assets/modules/2.jpg new file mode 100644 index 000000000..6f6063ea9 Binary files /dev/null and b/base_hospital_management/static/description/assets/modules/2.jpg differ diff --git a/base_hospital_management/static/description/assets/modules/3.jpg b/base_hospital_management/static/description/assets/modules/3.jpg new file mode 100644 index 000000000..ab375ff3a Binary files /dev/null and b/base_hospital_management/static/description/assets/modules/3.jpg differ diff --git a/base_hospital_management/static/description/assets/modules/4.jpg b/base_hospital_management/static/description/assets/modules/4.jpg new file mode 100644 index 000000000..9f7bf6c1c Binary files /dev/null and b/base_hospital_management/static/description/assets/modules/4.jpg differ diff --git a/base_hospital_management/static/description/assets/modules/5.jpg b/base_hospital_management/static/description/assets/modules/5.jpg new file mode 100644 index 000000000..b957c613f Binary files /dev/null and b/base_hospital_management/static/description/assets/modules/5.jpg differ diff --git a/base_hospital_management/static/description/assets/modules/6.jpg b/base_hospital_management/static/description/assets/modules/6.jpg new file mode 100644 index 000000000..d1c43c6b4 Binary files /dev/null and b/base_hospital_management/static/description/assets/modules/6.jpg differ diff --git a/base_hospital_management/static/description/assets/screenshots/h1.png b/base_hospital_management/static/description/assets/screenshots/h1.png new file mode 100644 index 000000000..c2109bb24 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h1.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h10.png b/base_hospital_management/static/description/assets/screenshots/h10.png new file mode 100644 index 000000000..ecc323d08 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h10.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h11.png b/base_hospital_management/static/description/assets/screenshots/h11.png new file mode 100644 index 000000000..c9c5772bd Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h11.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h12.png b/base_hospital_management/static/description/assets/screenshots/h12.png new file mode 100644 index 000000000..263f3e978 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h12.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h13.pdf b/base_hospital_management/static/description/assets/screenshots/h13.pdf new file mode 100644 index 000000000..6d9846964 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h13.pdf differ diff --git a/base_hospital_management/static/description/assets/screenshots/h14.png b/base_hospital_management/static/description/assets/screenshots/h14.png new file mode 100644 index 000000000..529910f7f Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h14.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h15.png b/base_hospital_management/static/description/assets/screenshots/h15.png new file mode 100644 index 000000000..1bc19357d Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h15.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h16.png b/base_hospital_management/static/description/assets/screenshots/h16.png new file mode 100644 index 000000000..3028cef92 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h16.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h17.png b/base_hospital_management/static/description/assets/screenshots/h17.png new file mode 100644 index 000000000..c4880e13f Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h17.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h18.png b/base_hospital_management/static/description/assets/screenshots/h18.png new file mode 100644 index 000000000..03da0e35f Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h18.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h19.png b/base_hospital_management/static/description/assets/screenshots/h19.png new file mode 100644 index 000000000..db2e8b0f2 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h19.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h2.png b/base_hospital_management/static/description/assets/screenshots/h2.png new file mode 100644 index 000000000..791b2d716 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h2.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h20.png b/base_hospital_management/static/description/assets/screenshots/h20.png new file mode 100644 index 000000000..5a609fda0 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h20.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h21.png b/base_hospital_management/static/description/assets/screenshots/h21.png new file mode 100644 index 000000000..f38aea85f Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h21.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h22.png b/base_hospital_management/static/description/assets/screenshots/h22.png new file mode 100644 index 000000000..9b9adf6cf Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h22.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h23.png b/base_hospital_management/static/description/assets/screenshots/h23.png new file mode 100644 index 000000000..e23859b06 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h23.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h24.png b/base_hospital_management/static/description/assets/screenshots/h24.png new file mode 100644 index 000000000..59c969e8d Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h24.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h25.png b/base_hospital_management/static/description/assets/screenshots/h25.png new file mode 100644 index 000000000..055c6d9b2 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h25.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h26.png b/base_hospital_management/static/description/assets/screenshots/h26.png new file mode 100644 index 000000000..55953d440 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h26.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h27.png b/base_hospital_management/static/description/assets/screenshots/h27.png new file mode 100644 index 000000000..1448788f9 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h27.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h28.png b/base_hospital_management/static/description/assets/screenshots/h28.png new file mode 100644 index 000000000..03b79a8ed Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h28.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h29.png b/base_hospital_management/static/description/assets/screenshots/h29.png new file mode 100644 index 000000000..8c98f86a3 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h29.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h3.png b/base_hospital_management/static/description/assets/screenshots/h3.png new file mode 100644 index 000000000..0a4df0f76 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h3.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h30.png b/base_hospital_management/static/description/assets/screenshots/h30.png new file mode 100644 index 000000000..dae7ed2df Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h30.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h31.png b/base_hospital_management/static/description/assets/screenshots/h31.png new file mode 100644 index 000000000..27915e6f1 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h31.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h32.png b/base_hospital_management/static/description/assets/screenshots/h32.png new file mode 100644 index 000000000..6013f7121 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h32.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h33.png b/base_hospital_management/static/description/assets/screenshots/h33.png new file mode 100644 index 000000000..472bfe7c1 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h33.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h34.png b/base_hospital_management/static/description/assets/screenshots/h34.png new file mode 100644 index 000000000..52f3bdc94 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h34.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h35.png b/base_hospital_management/static/description/assets/screenshots/h35.png new file mode 100644 index 000000000..26be0a541 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h35.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h36.png b/base_hospital_management/static/description/assets/screenshots/h36.png new file mode 100644 index 000000000..334435f56 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h36.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h37.png b/base_hospital_management/static/description/assets/screenshots/h37.png new file mode 100644 index 000000000..4ad10cecb Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h37.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h38.png b/base_hospital_management/static/description/assets/screenshots/h38.png new file mode 100644 index 000000000..18d036cbf Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h38.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h39.png b/base_hospital_management/static/description/assets/screenshots/h39.png new file mode 100644 index 000000000..15d832875 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h39.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h4.png b/base_hospital_management/static/description/assets/screenshots/h4.png new file mode 100644 index 000000000..92f36e056 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h4.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h40.png b/base_hospital_management/static/description/assets/screenshots/h40.png new file mode 100644 index 000000000..de4a1d470 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h40.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h41.png b/base_hospital_management/static/description/assets/screenshots/h41.png new file mode 100644 index 000000000..ba1dd9557 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h41.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h42.png b/base_hospital_management/static/description/assets/screenshots/h42.png new file mode 100644 index 000000000..0ebd96a4f Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h42.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h43.png b/base_hospital_management/static/description/assets/screenshots/h43.png new file mode 100644 index 000000000..61c2097fe Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h43.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h44.png b/base_hospital_management/static/description/assets/screenshots/h44.png new file mode 100644 index 000000000..21ba869cc Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h44.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h45.png b/base_hospital_management/static/description/assets/screenshots/h45.png new file mode 100644 index 000000000..e67f6e658 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h45.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h5.png b/base_hospital_management/static/description/assets/screenshots/h5.png new file mode 100644 index 000000000..54f345aa6 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h5.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h6.png b/base_hospital_management/static/description/assets/screenshots/h6.png new file mode 100644 index 000000000..1595d7e79 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h6.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h7.png b/base_hospital_management/static/description/assets/screenshots/h7.png new file mode 100644 index 000000000..0dcb616b5 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h7.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h8.png b/base_hospital_management/static/description/assets/screenshots/h8.png new file mode 100644 index 000000000..28f327883 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h8.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/h9.png b/base_hospital_management/static/description/assets/screenshots/h9.png new file mode 100644 index 000000000..0d777b693 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/h9.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/hero.gif b/base_hospital_management/static/description/assets/screenshots/hero.gif new file mode 100644 index 000000000..1011498b4 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/hero.gif differ diff --git a/base_hospital_management/static/description/assets/screenshots1.zip b/base_hospital_management/static/description/assets/screenshots1.zip new file mode 100644 index 000000000..9cb9620bc Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots1.zip differ diff --git a/base_hospital_management/static/description/assets/screenshots1/h19.png b/base_hospital_management/static/description/assets/screenshots1/h19.png new file mode 100644 index 000000000..db2e8b0f2 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots1/h19.png differ diff --git a/base_hospital_management/static/description/assets/screenshots1/h2.png b/base_hospital_management/static/description/assets/screenshots1/h2.png new file mode 100644 index 000000000..791b2d716 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots1/h2.png differ diff --git a/base_hospital_management/static/description/assets/screenshots1/h20.png b/base_hospital_management/static/description/assets/screenshots1/h20.png new file mode 100644 index 000000000..5a609fda0 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots1/h20.png differ diff --git a/base_hospital_management/static/description/assets/screenshots1/h21.png b/base_hospital_management/static/description/assets/screenshots1/h21.png new file mode 100644 index 000000000..f38aea85f Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots1/h21.png differ diff --git a/base_hospital_management/static/description/assets/screenshots1/h22.png b/base_hospital_management/static/description/assets/screenshots1/h22.png new file mode 100644 index 000000000..9b9adf6cf Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots1/h22.png differ diff --git a/base_hospital_management/static/description/assets/screenshots1/h3.png b/base_hospital_management/static/description/assets/screenshots1/h3.png new file mode 100644 index 000000000..0a4df0f76 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots1/h3.png differ diff --git a/base_hospital_management/static/description/assets/screenshots1/h36.png b/base_hospital_management/static/description/assets/screenshots1/h36.png new file mode 100644 index 000000000..334435f56 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots1/h36.png differ diff --git a/base_hospital_management/static/description/assets/screenshots1/h37.png b/base_hospital_management/static/description/assets/screenshots1/h37.png new file mode 100644 index 000000000..4ad10cecb Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots1/h37.png differ diff --git a/base_hospital_management/static/description/assets/screenshots1/h38.png b/base_hospital_management/static/description/assets/screenshots1/h38.png new file mode 100644 index 000000000..18d036cbf Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots1/h38.png differ diff --git a/base_hospital_management/static/description/assets/screenshots1/h39.png b/base_hospital_management/static/description/assets/screenshots1/h39.png new file mode 100644 index 000000000..15d832875 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots1/h39.png differ diff --git a/base_hospital_management/static/description/assets/screenshots1/h4.png b/base_hospital_management/static/description/assets/screenshots1/h4.png new file mode 100644 index 000000000..92f36e056 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots1/h4.png differ diff --git a/base_hospital_management/static/description/assets/screenshots1/h5.png b/base_hospital_management/static/description/assets/screenshots1/h5.png new file mode 100644 index 000000000..54f345aa6 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots1/h5.png differ diff --git a/base_hospital_management/static/description/banner.jpg b/base_hospital_management/static/description/banner.jpg new file mode 100644 index 000000000..22c90b947 Binary files /dev/null and b/base_hospital_management/static/description/banner.jpg differ diff --git a/base_hospital_management/static/description/icon.png b/base_hospital_management/static/description/icon.png new file mode 100644 index 000000000..ccedeeae1 Binary files /dev/null and b/base_hospital_management/static/description/icon.png differ diff --git a/base_hospital_management/static/description/index.html b/base_hospital_management/static/description/index.html new file mode 100755 index 000000000..1017bae09 --- /dev/null +++ b/base_hospital_management/static/description/index.html @@ -0,0 +1,1587 @@ + + + + + + + Odoo App 3 Index + + + + + + + + +
+
+
+
+
+ +
+
+
+ Community +
+
+ Enterprise +
+
+
+
+
+
+

+ Hospital Management Odoo 17

+

+ This Module Helps to Manage Patients Records, Doctors Details, + Lab Management , Employee Management etc. And there is Dashboard + Created under the module that help to Analyze Services like Patient Details, + Lab Details, Test Details Doctor's Allocations +

+
+ +
+
+
+
+
+

+ Key Highlights +

+
+
+
+
+
+ +
+
+

+ Dashboard Services

+
+
+
+
+
+
+ +
+
+

+ Patient Management

+
+
+
+
+
+
+ +
+
+

+ Laboratory Management

+
+
+
+
+
+
+ +
+
+

+ Stock Management System

+
+
+
+
+
+
+ +
+
+

+ Blood Bank Management

+
+
+
+
+
+
+ +
+
+

+ Vaccination Management

+
+
+
+
+
+
+ +
+
+

+ Doctor's Allocation and Service Management

+
+
+
+
+
+
+ +
+
+

+ Other Amenities

+
+
+
+
+
+
+ +
+
+

+ Medicine and Related Product Management

+
+
+
+
+
+
+ +
+
+

+ Online Booking

+
+
+
+
+
+
+ +
+
+
+
+
+ +
+
+

+ Give the user access to the user group Manager.

+

+

+
+
+
+
+
+
+ +
+
+

+ Add Staff +

+

+ Navigate to Staff menu under Configuration. + Add the Job Position. Also add Consultation + Type, Average Time for a Patient and + Consultation Charge for Doctors. +

+
+
+
+
+
+
+ +
+
+

+ Add Pharmacy +

+

+

+
+
+
+
+
+
+ +
+
+

+ Add Medicine +

+

+

+
+
+
+
+
+
+ +
+
+

+ Add Vaccine +

+

+

+
+
+
+
+
+
+ +
+
+

+ Add Rooms +

+

+

+
+
+
+
+
+
+ +
+
+

+ Add Lab test +

+

+

+
+
+
+
+
+
+ +
+
+

+ Add Doctor Allocation +

+

+

+
+
+
+
+
+
+ +
+
+

+ Give the user access to the user group Doctor. +

+

+

+
+
+
+
+
+
+ +
+
+

+

+

+ Doctor's Dashboard. +

+
+
+
+
+
+
+ +
+
+

+

+

+ Create Patient +

+
+
+
+
+
+
+ +
+
+

+ Download patient card here +

+

+

+
+
+
+
+
+
+ +
+
+

+

+

+ Create Inpatient here +

+
+
+
+
+
+
+ +
+
+

+

+

+ Give the user access to the user group Nurse. +

+
+
+
+
+
+
+ +
+
+

+

+

+ Can change the stage into Admitted by + clicking on the button Admit. +

+
+
+
+
+
+
+ +
+
+

+

+

+

+
+
+
+
+
+
+ +
+
+

+

+

+

+
+
+
+
+
+
+ +
+
+

+

+

+

+
+
+
+
+
+
+ +
+
+

+

+

+

+
+
+
+
+
+
+ +
+
+

+

+

+

+
+
+
+
+
+
+ +
+
+

+

+

+ Give the user access to the user group Lab Assistant. +

+
+
+
+
+
+
+ +
+
+

+

+

+ Lab Assistant Dashboard. +

+
+
+
+
+
+
+ +
+
+

+

+

+ Confirm the test on clicking the Confirm button +

+
+
+
+
+
+
+ +
+
+

+

+

+ Process tests +

+
+
+
+
+
+
+ +
+
+

+

+

+

+
+
+
+
+
+
+ +
+
+

+

+

+

+
+
+
+
+
+
+ +
+
+

+

+

+

+
+
+
+
+
+
+ +
+
+

+

+

+ Published tests +

+
+
+
+
+
+
+ +
+
+

+

+

+ Give the user access to the user group Pharmacist. +

+
+
+
+
+
+ +
+
+

+

+

+ Pharmacist Dashboard +

+
+
+
+
+
+ +
+
+

+

+

+

+
+
+
+
+
+ +
+
+

+

+

+

+
+
+
+
+
+ +
+
+

+

+

+

+
+
+
+
+
+ +
+
+

+

+

+ Give the user access to receptionist dashboard. +

+
+
+
+
+
+
+ +
+
+

+

+

+ Receptionist Dashboard +

+
+
+
+
+
+
+ +
+
+

+

+

+

+
+
+
+
+
+ +
+
+

+

+

+

+
+
+
+
+
+ +
+
+

+

+

+

+
+
+
+
+
+ +
+
+

+

+

+

+
+
+
+
+
+ +
+
+

+

+

+

+
+
+
+
+
+ +
+
+

+

+

+ Patient booking through website. +

+
+
+
+
+
+
+ +
+
+

+

+

+

+
+
+
+
+
+
+ +
+
+

+

+

+

+
+
+
+
+
+
+
    +
  • + + Dashboard Services +
  • +
  • + + Patient Management +
  • +
  • + + Laboratory Management +
  • +
  • + + Stock Management System +
  • +
  • + + Blood Bank Management +
  • +
  • + + Vaccination Management +
  • +
  • + + Doctor's Allocation and Service Management +
  • +
  • + + Medicine and Related Product Management +
  • +
+
+
+
+
+
+
Version + 17.0.1.0.0|Released on:29th February 2024 +
+

+ Initial Commit for Hospital Management Odoo 17

+
+
+
+
+
+
+
+

+ Related Products

+
+
+ +
+
+

+ Our Services

+ +
+
+
+
+
+
+
+
+ service-icon +
+
+

Odoo + Customization

+
+
+
+
+
+
+ service-icon +
+
+

Odoo + Implementation

+
+
+
+
+
+
+ service-icon +
+
+

Odoo + Support

+
+
+
+
+
+
+ service-icon +
+
+

Hire + Odoo Developer

+
+
+
+
+ +
+
+ service-icon +
+
+

Odoo + Integration

+
+
+
+
+
+
+ service-icon +
+
+

Odoo + Migration

+
+
+
+
+
+
+ service-icon +
+
+

Odoo + Consultancy

+
+
+
+
+
+
+ service-icon +
+
+

Odoo + Implementation

+
+
+
+
+
+
+ service-icon +
+
+

Odoo + Licensing Consultancy

+
+
+
+
+
+
+

+ Our Industries

+ +
+
+
+
+
+
+ +

Trading

+

Easily procure and sell your products

+
+
+
+
+ +

POS

+

Easy configuration and convivial experience

+
+
+
+
+ +

+ Education

+

A platform for educational management

+
+
+
+
+ +

+ Manufacturing

+

Plan, track and schedule your operations

+
+
+
+
+ +

E-commerce & + Website

+

Mobile friendly, awe-inspiring product pages

+
+
+
+
+ +

Service + Management

+

Keep track of services and invoice

+
+
+
+
+ +

+ Restaurant

+

Run your bar or restaurant methodically

+
+
+
+
+ +

Hotel + Management

+

An all-inclusive hotel management application

+
+
+
+
+
+
+

+ Support

+
+
+
+
+
+
+
+ +
+ Need + Help? +

Got + questions or need help? Get in touch.

+
odoo@cybrosys.com +
+
+
+
+
+
+
+
+ +
+ WhatsApp +

Say hi to + us on WhatsApp!

+
+91 + 99456767686 +
+
+
+
+
+
+
+
+
+ + + + + + diff --git a/base_hospital_management/static/src/css/doctor_dashboard.css b/base_hospital_management/static/src/css/doctor_dashboard.css new file mode 100755 index 000000000..1842c009a --- /dev/null +++ b/base_hospital_management/static/src/css/doctor_dashboard.css @@ -0,0 +1,34 @@ +.n_card-body{ + margin-top: -285px; + margin-left: 76px; +} +.n_Container{ + width:681px; + padding:2rem; + max-height: 90vh; + min-height: 90vh; + margin-right:21px; + margin-left:60px; + margin-top:10px; + margin-bottom:10px; + overflow-x: scroll; + overflow-y: scroll; + border-radius: 5px; + box-shadow: 0px 1px 3px 3px #c9c9c9; + } + .n_active,.n_active1,.n_active2{ + background-color: rgb(215, 215, 215); +} + @media screen and (max-width: 545px) { + .p_list tr th{ + font-size: 9px; + padding: 18px 0px !important; + } + } +.title{ + font-size: 49px; + color:blue; + text-align:center; + margin-top: -285px; + margin-left: 753px; +} diff --git a/base_hospital_management/static/src/css/lab_dashboard.css b/base_hospital_management/static/src/css/lab_dashboard.css new file mode 100755 index 000000000..cd2e22ef6 --- /dev/null +++ b/base_hospital_management/static/src/css/lab_dashboard.css @@ -0,0 +1,57 @@ +.dashButtonContainer { + height : 90vh; + display: grid; + justify-content : center; + background-color: aliceblue; +} +.dashButton { + height : 18vh; + border-radius: 10px; + box-shadow:0px 1px 3px 3px #c9c9c9;; + width : 200px; + display: grid; + justify-content : center; + align-items : center; + background-color: lightcoral; +} +.PatientContainer { + padding:2rem; + max-height: 90vh; + min-height: 90vh; + margin-top:10px; + margin-bottom:10px; + overflow-x: scroll; + border-radius: 10px; + box-shadow: 0px 1px 3px 3px #c9c9c9; +} +.LabReport { + margin-top:10px; + margin-bottom:10px; + height : 90vh; + justify-content : center; +} +.ReportContainer { + height: 18vh; + margin: 10px; + margin-top: 25px; + border-radius: 10px; + box-shadow: 0px 1px 3px 3px #c9c9c9; +} +#patient-image { + width: 96px; + border-radius: 13px; +} +.button-title{ + font-size: large; + color: cyan; +} +.welcome{ +color:blue; + text-align:center; + margin-top: -285px; + margin-left: -24px; +font-size: 49px; +} +.custom_tr{ + height:40px; +} diff --git a/base_hospital_management/static/src/css/pharmacy_dashboard.css b/base_hospital_management/static/src/css/pharmacy_dashboard.css new file mode 100755 index 000000000..50c610a3b --- /dev/null +++ b/base_hospital_management/static/src/css/pharmacy_dashboard.css @@ -0,0 +1,383 @@ +.menu_item { + font-size: 26px; + list-style: none; + padding-bottom: 30px; + color: black; +} +.fa-plus-circle { + font-size: 30px; +} +.menu_ul { + margin-top: 200px; + display:flex; + align-items:center; + justify-content:center; + padding-top:1.6rem: +} +.menu_link { + text-decoration: none; +} +.menu_item:hover { + text-decoration: none; + color: rgb(113, 118, 185); +} + +.menu_class { + margin-top: 20p; +} +.patient { + padding-top: 100px; +} + +.main_div { + width: 600px; + background-color: rgb(255, 255, 255); + height: auto; + padding-left: 4px; +} + +.profile_div { + width: 446px; + height: 210px; + background-color: rgb(113, 118, 185); + border-radius: 0px 40px 0px 0px; + display: grid; + justify-content: center; + align-items: center; +} + +.profile_pic { + height: 100px; + width: 100px; + border-radius: 50px; + margin-top: 25px; + margin-left: 23px; + border: 8px rgb(173, 186, 243) solid; +} + +.profile_name { + margin-top: -150px; + margin-left: 138px; + color: white; +} + +.profile_code { + margin-top: -100px; + margin-left: 138px; + color: white; +} + +.profile_gender { + margin-top: -50px; + margin-left: 138px; + color: white; +} + +.profile_bloodgroup { + margin-top: -25px; + margin-left: 138px; + color: white; +} + +.search_box { + margin-top: 25px; + margin-left: 10px; +} + +.search_icon { + margin-left: 50px; +} + +.medical_list { + width: 446px; + height: 572px; + background-color: white; + margin-top: 32px; + border-radius: 0px 0px 40px 0px; +} + +.row-click{ + cursor:pointer; +} + +.saleorder{ + width:130px; + margin-top : 12px; + font-size:11px; +} + +.pharma_container { + background-color: rgb(173, 186, 243); + width: 1700px; + height: 800px; + border-radius: 44px; + +} +.patient_search{ + width:30vh; height:5vh;margin-left:3vh; + +} +.p_search{ + display:flex; + align-items:center; + justify-content:center; +} + +.g_total{ + float: left; width: 20%;line-height: 37px;padding-right: 0; +} + + +.search_pe{ + margin-left:1vh; width:5vh; height:5vh; font-size:20px; +} + +.card { + width: 42%; + height: fit-content; + margin-top: 2rem; + margin-right: 2rem; +} +.add_medicine { + width:130px; + margin-top:12px; + font-size:11px; +} +.add_med{ + display:flex; + gap:10px; +} + +@media screen and (max-width:1400px){ + #content_div h1{ + padding-top:20px; + } + .pharma_container{ + width: 100%!important; + height: 155px!important; + border-radius: 44px 44px 0px 0px; + } + .pharma_2 { + width: 98%!important; + height: 142px!important; + border-radius: 40px 40px 0px 0px!important; + } + .menu-ul { + display: flex!important; + gap:20%!important; + align-items:center!important; + justify-content:center!important; + } + + .patient{ + padding-top:0px; + } + .main_div { + width: 50%; + } + .profile_div { + width: 50%; + border-radius: 0px 0px 0px 0px; + } + .profile_pic { + margin-left: 0px; + } + .patient_search{ + width:30vh; + height:5vh; + margin-left:2vh; + } + .medical_list { + width: 556px; + } + + .ms-2 { + margin-left: 0 !important; + } +} + +@media screen and (max-width:1200px){ + .medical_list { + width: 454px; + } + .card { + width: 42%; + height: fit-content; + margin-top: 2rem; + margin-right: 2rem; + } + .card-title { + font-size:16px; + } +} + +@media screen and (max-width:991px){ + .tbl-medicine-list { + width: 679px; + } + + .content_div container{ + margin-top:22px; + overflow-y: auto; + } + + .tbl-medicine-list .sub_total{ + + width:11vw !important; + } + + .tbl-medicine-list .amount{ + + width:18vw !important; + } + + + .tbl-medicine-list .qty{ + + width:18vw !important; + } + + .tbl-medicine-list .sub_total{ + width:24vw !important; + + } + + + .container-tbl-medicine-list{ + overflow-x:scroll; + } + + + .patient_search { + width: 24vh; + height: 5vh; + + } + .profile_pic { + margin-left: 35px; + } + .medical_list { + width: 100%; + } + .btn-div{ + display:flex; + gap:10px; + } + .g_total { + width:40%; + } + .card { + width: 100%; + } +} +@media screen and (max-width:768px){ + .main_div { + width: 100%; + } + .profile_div { + width: 100%; + border-radius: 0px 0px 0px 0px; + } + .patient_search { + width: 26vh; + height: 5vh; + + } + .medical_list { + width: 543px; + } + .medical_list { + width: 543px; + } + .card { + width: 44%; + } +} + +@media screen and (max-width:574px){ + .menu_item { + font-size: 20px; + } + + .menu-ul { + display: flex!important; + gap: 5%!important; + } + .medical_list { + width: 520px; + + } + #op_table label { + padding-left: 5px; + } + + .btn-div{ + display:flex; + gap:10px; + } + .g_total { + width:40%; + } + .search_pe{ + font-size:16px; + } + .card { + width: 42%; + } + .pharma_2 { + width: 96%!important; + } + .add_medicine { + width: 102px; + +} +} +@media screen and (max-width:530px){ + +.medical_list { + width: 400px; + + } +} +} +@media screen and (max-width:510px){ + .card { + width: 60%; + } + .medical_list { + width: 350px; + } +} + +@media screen and (max-width:420px){ + .card { + width: 100%; + } + .medical_list { + width: 360px; + } +} +#order_items { + font-family: Arial, Helvetica, sans-serif; + border-collapse: collapse; +} + +#order_items td{ + border: 1px solid #ddd; + padding: 8px; +} +#order_items tr:nth-child(odd){background-color: #f2f2f2;} +#order_items tr:hover {background-color: #ddd;} +#order_items th { + padding-top: 12px; + padding-bottom: 12px; + text-align: center; + position: sticky; + top:0px; + background-color: #f2f2f2; +} +@media screen and (max-width:370px){ +.patient_search { + width: 19vh; +} +} diff --git a/base_hospital_management/static/src/css/reception_dashboard.css b/base_hospital_management/static/src/css/reception_dashboard.css new file mode 100755 index 000000000..647046ec4 --- /dev/null +++ b/base_hospital_management/static/src/css/reception_dashboard.css @@ -0,0 +1,494 @@ +.r_dashButtonContainer { + height: fit-content; + justify-content: center; + display: flex; + align-items:flex-end; + flex-wrap:wrap; + width: 100%; +} + +.r_dashButton { + height: 75px; + border-radius: 10px; + box-shadow: 0px 1px 3px 3px #e1e1e1; + width: 330px; + display: grid; + margin: 16px; + justify-content: center; + align-items: center; + cursor: pointer; + background: #2b8d72; + font-size: 24px; + color: #ffffff; + font-weight: 700; + display: flex; +} +.rd_buttons, .r_AppntBtn{ + margin-left:0% +} + +.row.r_Profile table td { + padding: 9px; + margin: auto; + display:block; +} + +.patient_img{ + justify-content: center; + padding-right:20px ; +} +.apnmnt_img{ + justify-content: center; + padding-right:20px ; +} +.booking_img{ + justify-content: center; + padding-right:20px ; +} +.room_ward_img{ + justify-content: center; + padding-right:20px ; +} +.out_p_image{ + justify-content: center; + padding-right:20px ; +} +.in_p_img{ + justify-content: center; + padding-right:20px ; +} +.o_outpatient_button{ + float:right; + height: 75px; + border-radius: 10px; + box-shadow: 0px 1px 3px 3px #e1e1e1; + width: 330px; + display: grid; + margin: 20px; + justify-content: center; + align-items: center; + cursor: pointer; + background: #2b8d72; + font-size: 24px; + color: #ffffff; + font-weight: 700; + display: flex; + } + +#op_table label{ + display: inline-block; + padding-bottom: 8px; +} + +#op_table input[type="text"], input[type="tel"],input[type="date"], #op_table select, #patient-bloodgroup,#patient-m-status,#sl_patient_id,#admission_type,#attending_doctor_id,#reason_of_admission +{ + max-width:20rem; + min-height:3rem; + border-radius:5px; + margin-bottom:10px; +} + +.o_inpatient_button{ + height: 75px; + border-radius: 10px; + box-shadow: 0px 1px 3px 3px #e1e1e1; + width: 330px; + display: grid; + margin: 20px; + justify-content: center; + align-items: center; + cursor: pointer; + background: #2b8d72; + font-size: 24px; + color: #ffffff; + font-weight: 700; + display: flex; +} + +.r_AppointmentBtn, .r_RoomWard{ + height : 4vh; + border-radius: 10px; + box-shadow:0px 1px 3px 3px #c9c9c9; + width : inherit; + display: grid; + justify-content : center; + align-items : center; + padding: 5px; + text-align: center; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + cursor: pointer; +} + +.o_room_button{ + float:right; + height: 75px; + border-radius: 5px; + box-shadow: 0px 1px 3px 3px #e1e1e1; + width: 330px; + display: grid; + margin: 20px; + justify-content: center; + align-items: center; + cursor: pointer; + background: #2b8d72; + font-size: 24px; + color: #ffffff; + font-weight: 700; + display: flex; +} + +.o_ward_button{ + height: 75px; + border-radius: 5px; + box-shadow: 0px 1px 3px 3px #e1e1e1; + width: 330px; + display: grid; + margin: 20px; + justify-content: center; + align-items: center; + cursor: pointer; + background: #2b8d72; + font-size: 24px; + color: #ffffff; + font-weight: 700; + display: flex; + +} + +.r_AppointmentBtn:hover, .r_RoomWard:hover{ + transition: 500ms; + background-color: rgb(215, 215, 215); +} + +.r_dashButton:hover{ + transition: 500ms; + background-color: rgb(215, 215, 215); +} + +.r_active,.r_active1,.r_active2{ + background-color: rgb(215, 215, 215); +} + +#view_main{ + padding-top: 15px; + border-radius: 5px; + box-shadow: 0px 1px 3px 3px #c9c9c9; + width: 90%; + margin: 0 auto; +} + +.r_Container { + padding: 10px; + min-height: 90vh; + margin-bottom: 10px; +} + +.r_View { + margin-left: auto; + margin-bottom:10px; + padding: 10px; + height : 90vh; + justify-content : center; +} + +.r_Profile{ + padding: 20px; + margin-top: 10px; + margin-right: auto; + border-radius: 5px; + height: max-content; +} +.r_ReportContainer { + height: 18vh; + margin: 10px; + margin-top: 25px; + margin-right: 27px; + border-radius: 10px; + box-shadow: 0px 1px 3px 3px #c9c9c9; +} + +#r_patient-image { + width: 96px; + border-radius: 13px; +} + +#view_patient_profile { + margin-left: -17px; +} + +.patient_create, .outpatient_create, .allocation_create, .inpatient_create, .booking_create, .ward_create, .room_create{ + width: 96px; + border-radius: 13px; + margin-left: auto; + border-radius: 0.25rem; +} +.save_patient{ + width:200px; + +} +.saveandnew_patient{ + width:200px; +} +.o_patient_history_button{ + color: #446e0d; + border: 0; + float:right; +} +.o_in_patient_history_button{ + color: #446e0d; + border: 0; + float:right; +} +.o_out_patient_history_button{ + color: #446e0d; + border: 0; + float:right; +} +.hsp_table { + padding:1rem 0; + margin-left:6%; + width:40%; +} +.hsp_table input{ + max-width:30rem!important; + padding: 0.8em; +} + +select{ + background: transparent url("data:image/svg+xml,") no-repeat 98% center !important; +} + +
+ input class="mr-2" + label +
+ +@media (max-width: 575.98px) { + .o_patient_button{ + FONT-SIZE: 12PX; + } +} +#p_radio { + padding:0 !important; + margin-right:8px; +} + +.radio { + padding: 3px 8px; +} + +.save_out_patient { + width:200px +} + +.saveandnew_out_patient { + width: 200px; +} + +.save { + display:flex; + justify-content:center; + gap:30px; +} + +.o_radio_input { + margin-left: 12px; +} + +@media screen and (max-width:1800px) { + #ward_search,#room_search { + margin-left:7px !important; + } +} + +@media (min-width: 1400px){ + .container{ + max-width:1320px !important; + } + #ward_search, #room_search{ + margin-left:0px !important; + } +} +@media screen and (max-width:1398px) { + .search-container { + padding-left: 48px !important; + } + .dashButton{ + width:160px; + } +} + +@media screen and (max-width:1200px) { + .PatientContainer{ + width:82%; + margin:auto; + } + .dashButton{ + width:113px; + } + #ward_search,#room_search { + margin-left:7px !important; + } + .search-container{ + padding-left:38px !important; + } + .o_room_button{ + float:right; + width:75%; + } + .o_ward_button{ + width:75%; + } + .r_Profile { + box-shadow:0px 0px 0px 0px #fff; + } + .hsp_table{ + width:421px; + margin:auto; + } + .r_Container .row{ + margin-left:0px !important; + } + .rd_buttons, .r_AppntBtn { + margin-left:0px !important; + } + .o_outpatient_button{ + margin-left:0px !important; + } +} + +@media screen and (max-width: 991px) { + .o_inpatient_button{ + width:280px !important; + } + .PatientContainer{ + width:82%; + } + .dashButton{ + width:113px; + } + .search-container { + padding-left: 15px !important; + } + .r_Container{ + margin-left:0px; + padding-left:0px; + max-width:100% !important; + } + .r_AppntBtn{ + margin:auto !important; + } + .r_AppntBtn .col{ + padding-left:0px; + } + .o_outpatient_button{ + width:280px !important; + } + .o_room_button { + min-width:-webkit-fill-available; + margin:8px; + } + .o_ward_button { + min-width:100%; + margin:8px; + } +} + +@media screen and (max-width: 767px) { + .o_outpatient_button { + width:100%; + margin:0px; + } + .PatientContainer{ + width:97%; + margin:auto; + } + .dashButton { + width: 184px; + } + .o_inpatient_button{ + width:100% !important; + } + .o_outpatient_button{ + width:100%!important; + } + .o_inpatient_button { + width:100%; + margin:0px; + margin-top:22px; + } + .rd_buttons { + margin:0px; + } + .r_AppntBtn{ + margin-left:0px; + width:100%; + } + #view_main{ + margin-top:31px; + } + #op_table{ + margin-left:0px !important; + } + [type="text"], [type="password"], [type="number"], [type="email"], [type="tel"], textarea, select{ + max-width:100% !important; + } + .hsp_table{ + width:100%; + } +} + +@media screen and (max-width: 545px) { + .hsp_table{ + width:100%; + } + .r_AppntBtn .col{ + padding-right:0px; + } + .r_AppntBtn{ + width:95% !important; + } + .dashButton { + width: 184px; + } + .o_ward_button { + min-width: -webkit-fill-available; + } + .saveandnew_out_patient{ + width: 35% important!; + } + .tr_name { + display: contents; + width: 100%; + } + .td_name { + display: block; + } + .center { + padding-left:0px; + padding-right:0px; + } + .r_Profile{ + padding: 0px; + } + o_room_button { + max-width:100%; + } + o_ward_button { + max-width:100%; + } +} + +.search-container{ + padding-left:0px; +} + +html .o_web_client{ + overflow:auto !important; +} + +html .o_web_client > .o_action_manager{ + overflow:auto !important; +} diff --git a/base_hospital_management/static/src/img/in_p.png b/base_hospital_management/static/src/img/in_p.png new file mode 100755 index 000000000..7db028633 Binary files /dev/null and b/base_hospital_management/static/src/img/in_p.png differ diff --git a/base_hospital_management/static/src/img/lab_test.svg b/base_hospital_management/static/src/img/lab_test.svg new file mode 100644 index 000000000..a7e043695 --- /dev/null +++ b/base_hospital_management/static/src/img/lab_test.svg @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/base_hospital_management/static/src/img/medicine.png b/base_hospital_management/static/src/img/medicine.png new file mode 100755 index 000000000..bf4d09bbf Binary files /dev/null and b/base_hospital_management/static/src/img/medicine.png differ diff --git a/base_hospital_management/static/src/img/op_ticket.svg b/base_hospital_management/static/src/img/op_ticket.svg new file mode 100644 index 000000000..096e64de8 --- /dev/null +++ b/base_hospital_management/static/src/img/op_ticket.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/base_hospital_management/static/src/img/out_p.png b/base_hospital_management/static/src/img/out_p.png new file mode 100755 index 000000000..cc5e61eb2 Binary files /dev/null and b/base_hospital_management/static/src/img/out_p.png differ diff --git a/base_hospital_management/static/src/img/vaccination1.png b/base_hospital_management/static/src/img/vaccination1.png new file mode 100644 index 000000000..0dd505513 Binary files /dev/null and b/base_hospital_management/static/src/img/vaccination1.png differ diff --git a/base_hospital_management/static/src/js/doctor_dashboard.js b/base_hospital_management/static/src/js/doctor_dashboard.js new file mode 100755 index 000000000..fc2354863 --- /dev/null +++ b/base_hospital_management/static/src/js/doctor_dashboard.js @@ -0,0 +1,82 @@ +/** @odoo-module */ +import { registry} from '@web/core/registry'; +import { useService } from "@web/core/utils/hooks"; +import { useRef } from "@odoo/owl"; +import { Component, useState } from "@odoo/owl"; +import { _t } from "@web/core/l10n/translation"; + +// Doctor dashboard component initialization +export class DoctorDashboard extends Component { + setup() { + super.setup(...arguments); + this.ref = useRef('root') + this.orm = useService('orm') + this.user = useService("user"); + this.actionService = useService("action"); + this.welcome = useRef("welcome"); + this.state = useState({ + patients : [], + search_button : false, + patients_search :[], + }); + } + //Function for feting patient data + async list_patient_data(){ + this.actionService.doAction({ + name: _t('Patient details'), + type: 'ir.actions.act_window', + res_model: 'res.partner', + view_mode: 'tree,form', // Specify both tree and form view modes + views: [[false, 'list'],[false, 'form']], + domain: [['patient_seq', 'not in', ['New', 'Employee', 'User']]] + }); + const patients = await this.orm.call('res.partner', 'fetch_patient_data', [],); + if (self.$('.n_active')[0]){ + self.$('.n_active')[0].classList.remove('n_active'); + } + self.$('.patient_data')[0].classList.add('n_active'); + self.listPatient = patients; + } +// Method for generating list of inpatients + action_list_inpatient() { + this.actionService.doAction({ + name: _t('Inpatient details'), + type: 'ir.actions.act_window', + res_model: 'hospital.inpatient', + view_mode: 'tree,form', // Specify both tree and form view modes + views: [[false, 'list'],[false, 'form']], + }); + } +// Fetch surgery details + fetch_doctors_schedule() { + this.actionService.doAction({ + name: _t('Surgery details'), + type: 'ir.actions.act_window', + res_model: 'inpatient.surgery', + view_mode: 'tree,form', // Specify both tree and form view modes + views: [[false, 'tree'],[false, 'form']], + }); + } +// Fetch op details + fetch_consultation(){ + this.actionService.doAction({ + name: _t('Outpatient Details'), + type: 'ir.actions.act_window', + res_model: 'hospital.outpatient', + view_mode: 'tree,form', // Specify both tree and form view modes + views: [[false, 'tree']], // Specify the view type as 'tree' + }); + } +// Fetch allocation details + fetch_allocation_lines() { + this.actionService.doAction({ + name: _t('Doctor Allocation'), + type: 'ir.actions.act_window', + res_model: 'doctor.allocation', + view_mode: 'tree,form', // Specify both tree and form view modes + views: [[false, 'list'],[false, 'form']] + }); + } +} +DoctorDashboard.template = "DoctorDashboard" +registry.category("actions").add('doctor_dashboard_tags', DoctorDashboard); diff --git a/base_hospital_management/static/src/js/lab_dashboard.js b/base_hospital_management/static/src/js/lab_dashboard.js new file mode 100755 index 000000000..3b685c7cb --- /dev/null +++ b/base_hospital_management/static/src/js/lab_dashboard.js @@ -0,0 +1,103 @@ +/** @odoo-module */ +import { registry} from '@web/core/registry'; +import { useService } from "@web/core/utils/hooks"; +import { Component, onMounted, useState, useRef } from "@odoo/owl"; +import { _t } from "@web/core/l10n/translation"; + +export class LabDashBoard extends Component { +//Initialize LabDashBoard + setup() { + super.setup(...arguments); + this.orm = useService('orm') + this.user = useService("user"); + this.ref = useRef("root"); + this.actionService = useService("action"); + this.form_view = useRef("form_view"); + this.form_view_copy = useRef("form_view_copy"); + this.published_data =useRef("published_data"); + this.main_view = useRef("main_view"); + this.process_test_view = useRef('process_test_view'); + var record_id; + this.state= useState({ + tests_confirm :[], + tests_confirm_data :[], + test_data :[], + all_test_data :[], + process_data :[], + process_test_data :[], + published_data :[], + }); + onMounted(async () => { + await this._loadTestData(); + }); + } +// Method for getting the lab test data + async _loadTestData (){ + this.form_view.el.classList.add("d-none") + this.process_test_view.el.classList.add("d-none") + this.published_data.el.classList.add("d-none") + this.main_view.el.classList.remove("d-none") + self.state = 'lab.test.line' + var domain = [['state', '=', 'draft']]; + var result = await this.orm.call('lab.test.line', 'search_read',[domain],); + this.state.tests_confirm = result, + $('#form-view').attr('hidden', 'true'); + $('#create-button').html('') + } +// Method on clicking the tests to confirm button + async _fetchTestData (ev){ + this.main_view.el.classList.add("d-none") + this.form_view.el.classList.remove("d-none") + var record_id = parseInt($(ev.target).closest('tr').data('index')); + var record_id = this.state.tests_confirm[record_id].id + this.record_id = record_id + var result = await this.orm.call('lab.test.line', 'action_get_patient_data', [record_id],); + this.state.tests_confirm_data = result, + this.state.test_data = result['test_data'] + } +// Method on clicking confirm button in the tests to confirm + confirmLabTest (){ + this.orm.call('lab.test.line','create_lab_tests',[this.record_id], + ).then(function (result){ + $('#action-button').hide(); + alert('The test has been confirmed '); + }) + } +// Method for fetching all lab tests on clicking second button click + async _allLabTest () { + this.form_view.el.classList.add("d-none") + this.process_test_view.el.classList.remove("d-none") + this.published_data.el.classList.add("d-none") + this.main_view.el.classList.add("d-none") + var result = await this.orm.call('patient.lab.test','search_read',); + this.state.all_test_data = result + } +// Method for getting all test data + fetch_all_test_data (ev){ + var self = this; + var record_id = parseInt($(ev.target).closest('tr').data('index')); + self.load_all_test_data(record_id) + } +// Method for loading all test data + async load_all_test_data (record_id){ + const action = await this.actionService.doAction({ + name: _t('Inpatient details'), + type: 'ir.actions.act_window', + res_model: 'patient.lab.test', + res_id: record_id, + views: [[false, "form"]], + }); + return action; + } +// Method for getting result published lab tests + async _loadPublished (){ + this.form_view.el.classList.add("d-none") + this.process_test_view.el.classList.add("d-none") + this.published_data.el.classList.remove("d-none") + this.main_view.el.classList.add("d-none") + var result = await this.orm.call('lab.test.result','print_test_results',) + this.state.published_data = result + } +} +LabDashBoard.template = "LabDashboard" +registry.category("actions").add('lab_dashboard_tags', LabDashBoard); diff --git a/base_hospital_management/static/src/js/pharmacy_dashboard.js b/base_hospital_management/static/src/js/pharmacy_dashboard.js new file mode 100755 index 000000000..6eab6bb51 --- /dev/null +++ b/base_hospital_management/static/src/js/pharmacy_dashboard.js @@ -0,0 +1,175 @@ +/** @odoo-module */ +import { registry} from '@web/core/registry'; +import { useRef } from "@odoo/owl"; +import { useService } from "@web/core/utils/hooks"; +import { _t } from "@web/core/l10n/translation"; +const { Component, onWillStart, useState} = owl +import { PharmacyOrderLines } from "./pharmacy_orderlines"; + var currency=0; + var quantity=0; + var amount=0; + var sub_t=0; + var sub_total=0; + var product_lst=[]; + var uom_lst= []; + var invoice=0; + var invoice_id=0; + var tax=0; +export class PharmacyDashboard extends Component { +//Initialize Pharmacy Dashboard + setup() { + super.setup(...arguments); + this.ref = useRef('root') + this.vaccine_div = useRef('vaccine_div') + this.medicine_div = useRef('medicine_div') + this.home_content = useRef('home_content') + this.patient_name = useRef('PatientName'); + this.patient_email = useRef('Email'); + this.patient_search = useRef('PatientSearch'); + this.orders_div = useRef('orders_div') + this.orm = useService('orm') + this.user = useService("user"); + this.actionService = useService("action"); + this.state = useState({ + product_lst :[], + medicines :[], + units :[], + sub_total, + vaccine :[], + order_data:[], + order_line: [], + menu: 'home', + }); + this.fetch_product(); + onWillStart(async () => { + this.state.med = await this.orm.call('product.template','action_get_medicine_data',[],)}) + } +// Fetch product details + async fetch_product() { + const domain = [['medicine_ok', '=', true]]; + const result = await this.orm.call('product.template', 'search_read', [domain]); + this.state.product_lst = result; + this.create_order(); + } +// Method for creating sale order + async create_order() { + this.vaccine_div?.el?.classList.add("d-none"); + this.medicine_div?.el?.classList.add("d-none"); + this.home_content?.el?.classList.remove("d-none"); + this.orders_div?.el?.classList.add("d-none"); + await this.orm.call('hospital.pharmacy','company_currency', + ).then(function (result){ + $('#symbol'+ currency).text(result || ''); + $('#symbol').text(result || ''); + }) + this.state.medicines = await this.product_lst; + this.state.units = await this.uom_lst; + } +// To update the orderline of sale order + updateOrderLine(line, id) { + const orderline = this.state.order_line.filter(orderline => orderline.id === id)[0] + orderline.product = line.product + orderline.qty = parseInt(line.qty) + orderline.uom = line.uom + orderline.price = line.price + orderline.sub_total = line.sub_total + } +// To add new row in the sale order line + addRow () { + const data = [...this.state.order_line, owl.reactive({id: new Date(), product: false, qty: 1, uom: 0, price: 0, sub_total: 0})] + this.state.order_line = data + } +// To remove the line if not needed + removeLine(id){ + const filteredData = this.state.order_line.filter(line => line.id != id) + this.state.order_line = filteredData + } +// Create sale order + async create_sale_order () { + var data ={}; + data['name'] = $('#patient-name').val(); + data['phone'] = $('#patient-phone').val(); + data['email']= $('#patient-mail').val(); + data['dob'] = $('#patient-dob').val(); + data['products']= this.state.order_line; + let hasInvalidQuantity = false; + if (hasInvalidQuantity) { + alert('Medicine quantity must be greater than or equal to 1.'); + return; + } + if(this.patient_name.el.value === "") + { + alert("Please enter the Name") + return; + } + if(this.patient_email.el.value === "") + { + alert("Please enter the Email") + return; + } + this.orm.call('hospital.pharmacy', 'create_sale_order',[data] + ).then(function (result) { + alert('The sale order has been created with refernce number ' +result.invoice) + window.location.reload() + }) + } +// Fetch patient data + async fetch_patient_data () { + var self = this; + await this.orm.call('res.partner', 'action_get_patient_data', + [[this.patient_search.el.value]], + ).then(function (result) { + $('#patient-title').text(result.name || ''); + $('#patient-code').text(result.unique || ''); + $('#patient-age').text(result.dob || ''); + $('#patient-blood').text(result.blood_group || ''); + $('#patient-blood').text(result.blood_group || ''); + $('#patient-gender').text(result.gender || ''); + $('#patient-image').attr('data:image/png;base64, ' + result.image_1920); + if (result.name == 'Patient Not Found') { + $('#hist_head').html('') + $('#patient-image').attr('src', 'https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_1280.png'); + } + else { + } + }) + } +// Fetch medicine data while clicking Medicine button + async fetch_medicine_data () { + this.vaccine_div?.el?.classList.add("d-none"); + this.home_content?.el?.classList.add("d-none"); + this.medicine_div?.el?.classList.remove("d-none"); + this.orders_div?.el?.classList.add("d-none"); + } +// Fetch vaccine data + async fetch_vaccine_data () { + this.vaccine_div?.el?.classList.remove("d-none"); + this.home_content?.el?.classList.add("d-none"); + this.medicine_div?.el?.classList.add("d-none"); + this.orders_div?.el?.classList.add("d-none"); + this.state.vaccine = await this.orm.call('product.template','action_get_vaccine_data', [],) + } +// Method fo fetching all sale orders + async fetch_sale_orders () { + this.vaccine_div?.el?.classList.add("d-none"); + this.home_content?.el?.classList.add("d-none"); + this.medicine_div?.el?.classList.add("d-none"); + this.orders_div?.el?.classList.remove("d-none"); + this.state.order_data = await this.orm.call('sale.order', 'search_read', + [[['partner_id.patient_seq','not in', ['New', 'Employee', 'User']]], ['name', 'create_date', 'partner_id', 'amount_total', 'state']],) + + } +// Method for emptying the data + async clear_data () { + this.patient_search.el.value = ''; + $('#hist_head').html('') + $('#patient-title').html('') + $('#patient-code').html('') + $('#patient-gender').html('') + $('#patient-blood').html('') + $('#patient-image').attr('src', 'https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_1280.png'); + } +} +PharmacyDashboard.template = "PharmacyDashboard" +registry.category("actions").add('pharmacy_dashboard_tags', PharmacyDashboard); +PharmacyDashboard.components = { PharmacyOrderLines } diff --git a/base_hospital_management/static/src/js/pharmacy_orderlines.js b/base_hospital_management/static/src/js/pharmacy_orderlines.js new file mode 100644 index 000000000..2dfe05ada --- /dev/null +++ b/base_hospital_management/static/src/js/pharmacy_orderlines.js @@ -0,0 +1,89 @@ +/** @odoo-module */ +import { registry} from '@web/core/registry'; +import { useRef } from "@odoo/owl"; +import { useService } from "@web/core/utils/hooks"; +const { Component, useState } = owl +import {Dropdown} from "@web/core/dropdown/dropdown"; +import {DropdownItem} from "@web/core/dropdown/dropdown_item"; +import { _t } from "@web/core/l10n/translation"; + var currency=0; +export class PharmacyOrderLines extends Component { + setup() { + super.setup(...arguments); + this.ref = useRef('root') + this.orm = useService('orm') + this.user = useService("user"); + this.actionService = useService("action"); + this.state = useState({ + product_lst :[], + medicines :[], + units :[], + medicine :[], + table_row: [{}] + }); + this.lineState = useState({ + product: this.props.line.product, + qty: this.props.line.qty, + uom: this.props.line.uom, + price: this.props.line.price, + sub_total: this.props.line.sub_total, + }) + this.fetch_product(); + this.fetch_uom(); + this.fetch_tax(); + } +// Fetch product details + async fetch_product() { + var product_lst= []; + var domain = [['medicine_ok', '=', true]]; // Define the search domain as a list of lists + var result =await this.orm.call('product.template', 'search_read', [domain]); + this.product_lst=result + this.create_order() + } +// Fetch UOM of selected product + async fetch_uom (){ + var uom_lst= []; + var result= await this.orm.call( 'uom.uom','search_read',) + this.uom_lst=result + } +// Fetch tax amount of product. + async fetch_tax(){ + var tax_lst= []; + var result= await this.orm.call( 'account.tax','search_read',) + this.tax_lst=result + } +// Method for creating sale order + async create_order() { + await this.orm.call('hospital.pharmacy','company_currency', + ).then(function (result){ + $('#symbol'+ currency).text(result || ''); + $('#symbol').text(result || ''); + }) + this.state.medicines = await this.product_lst; + this.state.units = await this.uom_lst; + } +// To calculate the subtotal of the medicine + calculateSubtotal(qty, price) { + return qty *price + } +// Method on changing the product in the sale order + async _onChange_prod_price (med_id) { + this.lineState.product = med_id + const medicine = this.state.medicines.filter(med => med.id === med_id)[0] + this.lineState.price = medicine.list_price + this.lineState.sub_total = this.calculateSubtotal(this.lineState.qty, medicine.list_price) + this.props.updateOrderLine(this.lineState, this.props.id) + } +// Calculation of sub total based on product quantity + async _onChange_prod_qty () { + var self = this; + this.lineState.sub_total = this.calculateSubtotal(this.lineState.qty, this.lineState.price) + this.props.updateOrderLine(this.lineState, this.props.id) + } +// To remove the added line + async remove_line () { + this.props.removeLine(this.props.id) + } +} +PharmacyOrderLines.template = "PharmacyOrderLines" +PharmacyOrderLines.components = { Dropdown, DropdownItem } diff --git a/base_hospital_management/static/src/js/prescription.js b/base_hospital_management/static/src/js/prescription.js new file mode 100755 index 000000000..a60a1c8f3 --- /dev/null +++ b/base_hospital_management/static/src/js/prescription.js @@ -0,0 +1,21 @@ +/** @odoo-module **/ +import publicWidget from "@web/legacy/js/public/public_widget"; + +publicWidget.registry.prescriptionWidget = publicWidget.Widget.extend({ + //Extends the publicWidget.Widget class to create prescriptionWidget + selector: '#my_prescriptions', + events: { + 'click .pr_download': 'onDownloadClick', + }, + onDownloadClick: function (ev) { + var rec_id = $(ev.currentTarget).data('id'); + rpc.query({ + model: 'hospital.outpatient', + method: 'create_file', + args: [rec_id], + }).then(function (result) { + window.open(result['url']); + }); + }, +}); +export default publicWidget.registry.prescriptionWidget; diff --git a/base_hospital_management/static/src/js/reception_dashboard.js b/base_hospital_management/static/src/js/reception_dashboard.js new file mode 100755 index 000000000..8cb95a5ec --- /dev/null +++ b/base_hospital_management/static/src/js/reception_dashboard.js @@ -0,0 +1,300 @@ +/** @odoo-module */ +import { registry} from '@web/core/registry'; +import { useService } from "@web/core/utils/hooks"; +import { Component, onMounted, useState, useRef } from "@odoo/owl"; +import { _t } from "@web/core/l10n/translation"; + +class ReceptionDashBoard extends Component{ + setup() { + this.ref = useRef('root'); + this.patient_creation = useRef('patient_creation'); + this.inpatient = useRef('inpatient'); + this.out_patient = useRef('out-patient'); + this.rd_buttons = useRef('rd_buttons'); + this.room_ward = useRef('room_ward'); + this.ward = useRef('ward'); + this.room = useRef('room'); + this.action = useService('action'); + this.orm = useService("orm"); + this.state = useState({ + patient_lst : [], + ward_data : [], + room_data : [], + }); + onMounted(async () => { + await this.createPatient(); + }); + } +// Method for creating patient + createPatient(){ + if ($('.r_active')[0]){$('.r_active')[0].classList.remove('r_active');} + $('.o_patient_button')[0].classList.add('r_active'); + this.room_ward.el.classList.add("d-none") + this.patient_creation.el.classList.remove("d-none"); + this.out_patient.el.classList.add("d-none"); + this.inpatient.el.classList.add("d-none"); + this.rd_buttons.el.classList.add("d-none"); + this.ward.el.classList.add("d-none"); + this.room.el.classList.add("d-none"); + } +// Method for creating patient + async savePatient (){ + var data = await this.fetch_patient_data() + if( data['name']=="" || data['phone']==""){ + alert("Please fill the name and phone") + return; + } + await this.orm.call('res.partner','create',[[data]]).then(function (){ + alert("the patient record has been created") + window.location.reload() + }) + } +// Method which returns the details of a patient given in the form + fetch_patient_data (){ + var patient_name = $('#patient-name').val(); + var patient_img = $('#patient-img').data('file'); + var patient_phone = $('#patient-phone').val(); + var patient_mail = $('#patient-mail').val(); + var patient_dob = $('#patient-dob').val(); + var patient_bloodgroup = $('#patient-bloodgroup').val(); + var patient_m_status = $('#patient-m-status').val() || ''; + var patient_rhtype = $("input[name='rhtype']:checked").val(); + var patient_gender = $("input[name='gender']:checked").val(); + var data = { + 'name' : patient_name, + 'blood_group' : patient_bloodgroup, + 'rh_type' : patient_rhtype, + 'gender' : patient_gender, + 'marital_status' : patient_m_status, + 'phone' : patient_phone, + 'email' : patient_mail, + 'image_1920': patient_img + } + if (patient_dob) { + data['date_of_birth'] = patient_dob; + } + return data + } +// Method on clicking appointment button + fetchAppointmentData (){ + if ($('.r_active')[0]){$('.r_active')[0].classList.remove('r_active');} + $('.o_appointment_button')[0].classList.add('r_active'); + this.room_ward.el.classList.add("d-none") + this.patient_creation.el.classList.add("d-none"); + this.out_patient.el.classList.remove("d-none"); + this.inpatient.el.classList.add("d-none"); + this.rd_buttons.el.classList.remove("d-none"); + this.ward.el.classList.add("d-none"); + this.room.el.classList.add("d-none"); + this.createOutPatient();//the outpatient creation page will be shown by default + } +// Creates new outpatient + async createOutPatient (){ + var self = this; + const date = new Date(); + var formattedCurrentDate = date.toISOString().split('T')[0]; + const result = await this.orm.call('res.partner','fetch_patient_data',[],) + this.state.patient_lst = result + self.patient_lst=result + self.patient_lst.forEach(element => { + $('.select_patient').append(` + + + `) + }) + await this.orm.call('doctor.allocation','search_read',[] + ).then(function (result){ + self.dr_lst=result + $('.select_dr').html('') + self.dr_lst.forEach(element => { + $('.select_dr').append(` + + `) + }) + }), + $('#controls').html(``); + var currentDate = new Date(); + $('#op_date').val(currentDate.toISOString().split('T')[0]) + } +// Method for creating inpatient + async createInPatient (){ + var self = this + this.room_ward.el.classList.add("d-none") + this.patient_creation.el.classList.add("d-none"); + this.out_patient.el.classList.add("d-none"); + this.inpatient.el.classList.remove("d-none"); + this.ward.el.classList.add("d-none"); + this.room.el.classList.add("d-none"); + var domain = [['job_id.name', '=', 'Doctor']]; + await this.orm.call('res.partner','fetch_patient_data',[]).then(function (result){ + self.patient_id_lst=result + $('.select_patient_id').html('') + self.patient_id_lst.forEach(element => { + $('.select_patient_id').append(` + + `) + }) + }), + await this.orm.call('hr.employee','search_read',[domain],) + .then(function (result){ + self.attending_dr_lst=result + $('.attending_doctor_id').html('') + self.attending_dr_lst.forEach(element => { + $('.attending_doctor_id').append(` + + `) + }) + }) + } +// Method for saving outpatient + async save_out_patient_data (){ + var self = this; + var data = await self.fetch_out_patient_data () + if (data != false){ + var result = await this.orm.call('res.partner','create_patient',[data]) + alert('the outpatient is created'); + $('#o_patient-name').val(""); + $('#sl_patient').val(""); + $('#o_patient-phone').val(""); + $('#o_patient-dob').val(""); + + } + } +// Method for displaying patient card + patient_card () { + if($('#select_type').val() === 'dont_have_card'){ + $('#sl_patient').hide(); + $('#patient_label').hide(); + } + else{ + $('#sl_patient').show(); + $('#patient_label').show(); + } + } +// Method for fetching OP details + async fetch_op_details () { + var patient_id=$('#sl_patient').val() + var phone=$('#o_patient-phone').val() + var data={ + 'patient_data':patient_id, + 'patient-phone':phone + } + return data + } +// Method for fetching patient details + async fetch_patient_id () { + var data = await this.fetch_op_details() + await this.orm.call('res.partner', 'reception_op_barcode',[data] + ).then(function (result) { + $('#o_patient-name').val(result.name) + $('#o_patient-dob').val(result.date_of_birth) + $('#o_patient_bloodgroup').val(result.blood_group) + $('#o_patient-gender').val(result.gender) + if (result.phone){ + $('#o_patient-phone').val(result.phone) + } + }); + } +// Method for fetching outpatient data + async fetch_out_patient_data () { + var o_patient_name = $('#o_patient-name').val(); + var o_patient_phone = $('#o_patient-phone').val(); + var o_patient_dob = $('#o_patient-dob').val(); + var o_patient_blood_group = $("#o_patient_bloodgroup").val(); + var o_patient_rhtype = $("input[id='o_rhtype']:checked").val(); + var o_patient_gender = $("input[id='o_patient-gender']:checked").val(); + var patient_id = $('#sl_patient').val(); + var op_date = $('#op_date').val(); + var reason = $('#reason').val(); + var ticket_no = $('#slot').val(); + var doctor = $('#sl_dr').val(); + if (o_patient_name === '' || doctor === '' || op_date === '') { + alert('Please fill out all the required fields.'); + return false; // Prevent form submission + } + else{ + var data = { + 'op_name':o_patient_name, + 'op_phone':o_patient_phone, + 'op_blood_group':o_patient_blood_group, + 'op_rh':o_patient_rhtype, + 'op_gender':o_patient_gender, + 'patient_id' : patient_id, + 'date' : op_date, + 'reason' : reason, + 'slot' : 0.00, + 'doctor' : doctor, + } + if (o_patient_dob) { + data['op_dob'] = o_patient_dob; + } + return data + } + } +// Method for fetching inpatient data + async fetch_in_patient_data (){ + var patient_id = $('#sl_patient_id').val(); + var reason_of_admission = $('#reason_of_admission').val(); + var admission_type = $('#admission_type').val(); + var attending_doctor_id = $('#attending_doctor_id').val(); + if (patient_id === null || attending_doctor_id === null || + admission_type === null) { + alert('Please fill out all the required fields.'); + return false; // Prevent form submission + } + else{ + var data = { + 'patient_id' : patient_id, + 'reason_of_admission' : reason_of_admission, + 'admission_type' : admission_type, + 'attending_doctor_id' : attending_doctor_id, + } + return data + } + } +// Method for creating new inpatient + async save_in_patient_data (){ + var data = await this.fetch_in_patient_data() + if (data != false || data != null || data != undefined){ + this.orm.call('hospital.inpatient','create_new_in_patient',[null,data] + ).then(function (){ + alert('Inpatient is created'); + $('#sl_patient_id').val(""); + $('#reason_of_admission').val(""); + $('#admission_type').val(""); + $('#attending_doctor_id').val(""); + }); + } + } +// Method for getting room or ward details + fetchRoomWard (){ + $('#view_secondary').html(''); + this.room_ward.el.classList.remove("d-none") + this.patient_creation.el.classList.add("d-none"); + this.out_patient.el.classList.add("d-none"); + this.inpatient.el.classList.add("d-none"); + this.rd_buttons.el.classList.add("d-none"); + if ($('.r_active')[0]){$('.r_active')[0].classList.remove('r_active');} + $('.o_room_ward_button')[0].classList.add('r_active'); + } +// Method for getting ward details + async fetchWard (){ + this.ward.el.classList.remove("d-none"); + this.room.el.classList.add("d-none"); + if ($('.r_active2')[0]){$('.r_active2')[0].classList.remove('r_active2');} + $('.o_ward_button')[0].classList.add('r_active2'); + var result = await this.orm.call('hospital.ward','search_read',) + this.state.ward_data = result + } +// Method for getting room details + async fetchRoom (){ + this.room.el.classList.remove("d-none"); + this.ward.el.classList.add("d-none"); + if ($('.r_active2')[0]){$('.r_active2')[0].classList.remove('r_active2');} + $('.o_room_button')[0].classList.add('r_active2'); + var result= await this.orm.call('patient.room','search_read',) + this.state.room_data = result + } +} +ReceptionDashBoard.template = "ReceptionDashboard" +registry.category('actions').add('reception_dashboard_tags', ReceptionDashBoard); diff --git a/base_hospital_management/static/src/js/website_page.js b/base_hospital_management/static/src/js/website_page.js new file mode 100644 index 000000000..86f55c019 --- /dev/null +++ b/base_hospital_management/static/src/js/website_page.js @@ -0,0 +1,60 @@ +/** @odoo-module **/ +import publicWidget from "@web/legacy/js/public/public_widget"; +import { jsonrpc } from "@web/core/network/rpc_service"; + +publicWidget.registry.doctorWidget = publicWidget.Widget.extend({ +// Extends the publicWidget.Widget class to add doctor widget + selector: '#booking_form', + events: { + 'change #booking_date': 'changeBookingDate', + 'change #doctor-department': 'updateDoctorOptions', + }, + init: function () { + this.changeBookingDate(); + }, +// Update the doctor selection field + async changeBookingDate () { + var self = this; + var selectedDate = $('#booking_date').val(); + await jsonrpc('/patient_booking/get_doctors', { + selected_date: selectedDate, department:false + }).then(function (data) { + $('#doctor-name').empty(); + // Add the fetched doctors to the dropdown + $.each(data['doctors'], function (index,doctor) { + self.$('#doctor-name').append($('