diff --git a/base_hospital_management/README.rst b/base_hospital_management/README.rst new file mode 100755 index 000000000..b9b0a8c50 --- /dev/null +++ b/base_hospital_management/README.rst @@ -0,0 +1,46 @@ +.. 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 16 +=========================== +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:(V16) Ahammed Harshad P, Nihala MK, Gee Paul Joby, Mohamed Savad V, Athira P S, Unnimaya C O, 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..dfd4453a7 --- /dev/null +++ b/base_hospital_management/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..9c98fa36e --- /dev/null +++ b/base_hospital_management/__manifest__.py @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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 16", + "version": "16.0.1.0.0", + "category": "Industries", + "summary": """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""", + "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", + "report/res_partner_reports.xml", + "report/lab_test_line_reports.xml", + "views/lab_test_line_views.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/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/css/lab_dashboard.css", + "base_hospital_management/static/src/xml/pharmacy_dashboard_templates.xml", + "base_hospital_management/static/src/js/pharmacy_dashboard.js", + "base_hospital_management/static/src/css/pharmacy_dashboard.css", + "base_hospital_management/static/src/xml/reception_dashboard_templates.xml", + "base_hospital_management/static/src/js/reception_dashboard.js", + "base_hospital_management/static/src/css/reception_dashboard.css", + "base_hospital_management/static/src/css/doctor_dashboard.css", + ], + }, + "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..a57f9e4b7 --- /dev/null +++ b/base_hospital_management/controllers/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..2f0456497 --- /dev/null +++ b/base_hospital_management/controllers/patient_booking.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..72d922bc7 --- /dev/null +++ b/base_hospital_management/controllers/portal.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..2ffe5f76b --- /dev/null +++ b/base_hospital_management/controllers/view_portal.py @@ -0,0 +1,130 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..f96e7005e --- /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..6948336ea --- /dev/null +++ b/base_hospital_management/doc/RELEASE_NOTES.md @@ -0,0 +1,7 @@ +## Module + +#### 27.12.2023 +#### Version 16.0.1.0.0 +#### ADD + +- Initial commit for Hospital Management Odoo 16 diff --git a/base_hospital_management/models/__init__.py b/base_hospital_management/models/__init__.py new file mode 100755 index 000000000..f02d44d8d --- /dev/null +++ b/base_hospital_management/models/__init__.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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 contra_indication +from . import blood_donation +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..79b745544 --- /dev/null +++ b/base_hospital_management/models/account_payment_register.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..9b721d40e --- /dev/null +++ b/base_hospital_management/models/blood_bank.py @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..4c1f82c59 --- /dev/null +++ b/base_hospital_management/models/blood_donation.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..c36a66470 --- /dev/null +++ b/base_hospital_management/models/contra_indication.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..38a3b859e --- /dev/null +++ b/base_hospital_management/models/doctor_allocation.py @@ -0,0 +1,220 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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 = 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 = 0 + + @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 {'record': 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..1ef807159 --- /dev/null +++ b/base_hospital_management/models/doctor_round.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..a576d5e25 --- /dev/null +++ b/base_hospital_management/models/doctor_slot.py @@ -0,0 +1,136 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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 { + 'record': 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 { + 'record': 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 { + 'record': 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 { + 'record': 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..10574efec --- /dev/null +++ b/base_hospital_management/models/doctor_specialization.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..4c34d0964 --- /dev/null +++ b/base_hospital_management/models/hospital_bed.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..14df8375d --- /dev/null +++ b/base_hospital_management/models/hospital_building.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..5448406c1 --- /dev/null +++ b/base_hospital_management/models/hospital_degree.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..0116c5ec5 --- /dev/null +++ b/base_hospital_management/models/hospital_family.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..49383aab5 --- /dev/null +++ b/base_hospital_management/models/hospital_inpatient.py @@ -0,0 +1,482 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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: + 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 + }) + data = { + 'record': patient_list + } + return data diff --git a/base_hospital_management/models/hospital_insurance.py b/base_hospital_management/models/hospital_insurance.py new file mode 100755 index 000000000..8c12f9578 --- /dev/null +++ b/base_hospital_management/models/hospital_insurance.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..4e3a30147 --- /dev/null +++ b/base_hospital_management/models/hospital_laboratory.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..6ceb15869 --- /dev/null +++ b/base_hospital_management/models/hospital_outpatient.py @@ -0,0 +1,318 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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]) + values = { + 'op_data': op_data, + 'medicines': medicines + } + return values + + @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..caf55e2e2 --- /dev/null +++ b/base_hospital_management/models/hospital_pharmacy.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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().create({ + 'name': kwargs['name'], + }) + else: + patient_id = self.env['hospital.outpatient'].sudo().search( + [('op_reference', '=', kwargs['op'])]).patient_id + 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': int( + rec['prod']) if 'op' not in kwargs.keys() else + self.env[ + 'product.product'].search( + [('product_tmpl_id', '=', int(rec['prod']))]).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['prod']))]).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 pharmacy_sale_order + + @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..43f61e653 --- /dev/null +++ b/base_hospital_management/models/hospital_vaccination.py @@ -0,0 +1,155 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..f5a72c790 --- /dev/null +++ b/base_hospital_management/models/hospital_ward.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..3f407b305 --- /dev/null +++ b/base_hospital_management/models/hr_employee.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..90c7b88c0 --- /dev/null +++ b/base_hospital_management/models/inpatient_payment.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..f1d5d951d --- /dev/null +++ b/base_hospital_management/models/inpatient_surgery.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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', + 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 { + 'record': 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..a0f886f69 --- /dev/null +++ b/base_hospital_management/models/ir_attachment.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..2b341942b --- /dev/null +++ b/base_hospital_management/models/lab_medicine_line.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..7ae8081d1 --- /dev/null +++ b/base_hospital_management/models/lab_test.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..4567fd3f7 --- /dev/null +++ b/base_hospital_management/models/lab_test_line.py @@ -0,0 +1,131 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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=1, 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_ids = [] + test = self.env['lab.test.line'].sudo().browse(data['id']) + test.state = 'created' + if data: + for rec in data['test_data']: + test_ids.append(rec['id']) + self.env['patient.lab.test'].sudo().create({ + 'patient_id': test.patient_id.id, + 'test_id': data['id'], + 'patient_type': data['patient_type'].lower(), + 'state': 'draft', + 'test_ids': test_ids, + }) + 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..f1abcc361 --- /dev/null +++ b/base_hospital_management/models/lab_test_result.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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, **kwargs): + """Method for printing rest result""" + 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='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..23a4d09eb --- /dev/null +++ b/base_hospital_management/models/medicine_brand.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..157fc302a --- /dev/null +++ b/base_hospital_management/models/nursing_plan.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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_booking.py b/base_hospital_management/models/patient_booking.py new file mode 100755 index 000000000..dbc60788c --- /dev/null +++ b/base_hospital_management/models/patient_booking.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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 PatientBooking(models.Model): + """Class holding patient booking""" + _name = 'patient.booking' + _inherit = 'mail.thread' + _description = 'Patient Booking' + _rec_name = 'patient_id' + + booking_reference = fields.Char(string="OP Number", + help='Reference number indicating ' + 'the booking', readonly=True, + default='New') + patient_id = fields.Many2one('res.partner', string='Patient', + domain=[('patient_seq', 'not in', + ['New', 'Employee', 'User'])], + help='Choose the patient for booking', + 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')]) + 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) + consultation_fee = fields.Monetary( + related='doctor_id.doctor_id.consultancy_charge', string="Fee", + help='Consultation fee', + readonly=True) + booking_date = fields.Date(string="Booking Date", help='Date of booking', + default=fields.Date.today()) + reason = fields.Text(string='Reason', help='Reason for booking') + state = fields.Selection( + [('draft', 'Draft'), ('confirm', 'Confirmed'), + ('cancel', 'Cancelled')], + default='draft', string='State', help='State of patient booking') + company_id = fields.Many2one('res.company', string='Company', + default=lambda self: self.env.company.id) + slot = fields.Float(string='Slot', help='Slot for the patient', + copy=False) + + @api.model + def create(self, vals): + """Method for creating booking reference""" + if vals.get('booking_reference', 'New') == 'New': + vals['booking_reference'] = self.env['ir.sequence'].next_by_code( + 'patient.booking') or 'New' + return super().create(vals) + + @api.onchange('booking_date') + def _onchange_booking_date(self): + """Method for adding domain for doctor_id""" + return {'domain': {'doctor_id': [('slot_remaining', '>', 0), + ('date', '=', self.booking_date), + ('state', '=', 'confirm')]}} + + def action_confirm_booking(self): + """Confirmation of booking""" + 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 = 'confirm' + + def action_booking_cancel(self): + """Method for cancelling a booking""" + self.state = 'cancel' 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..72e061726 --- /dev/null +++ b/base_hospital_management/models/patient_lab_test.py @@ -0,0 +1,308 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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': ['|', ( + 'ref', '=', self.name), ('payment_reference', '=', self.name)] + } + + def action_view_sale_order(self): + """Method for viewing sale order from the smart button""" + return { + 'name': 'Sale order', + 'res_model': 'sale.order', + 'view_mode': 'form', + 'type': 'ir.actions.act_window', + 'res_id': self.env['sale.order'].sudo().search([('reference', '=', + self.name)])[0].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..287b344f6 --- /dev/null +++ b/base_hospital_management/models/patient_room.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..dcbc90b7f --- /dev/null +++ b/base_hospital_management/models/pharmacy_medicine.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..a00633ac5 --- /dev/null +++ b/base_hospital_management/models/prescription_line.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..5cef9e0e2 --- /dev/null +++ b/base_hospital_management/models/product_template.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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]) + values = { + 'medicine': medicines, + } + return values + + @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]) + values = { + 'medicine': vaccines, + } + return values diff --git a/base_hospital_management/models/res_partner.py b/base_hospital_management/models/res_partner.py new file mode 100755 index 000000000..870f696c8 --- /dev/null +++ b/base_hospital_management/models/res_partner.py @@ -0,0 +1,584 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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 fetch_view_id(self): + """Returns the view id of patient""" + return self.env['ir.ui.view'].sudo().search([ + ('name', '=', 'hospital.patient.view.form')]).id + + 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( + ['|', ('patient_seq', '=', 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'])]) + values = { + '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, + } + return values + + @api.model + def action_get_patient_data(self, patient_id): + """Method which returns patient details""" + data = self.sudo().search([ + '|', ('patient_seq', '=', patient_id.upper()), + ('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['id']: + 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([('patient_seq', '=', post['id'])]) + 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 + }) + + 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..f8e77518a --- /dev/null +++ b/base_hospital_management/models/res_users.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..de2eed38b --- /dev/null +++ b/base_hospital_management/models/room_facility.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions (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..8e285f784 --- /dev/null +++ b/base_hospital_management/report/res_partner_reports.xml @@ -0,0 +1,209 @@ + + + + + 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..7550b182e --- /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/check.png b/base_hospital_management/static/description/assets/icons/check.png new file mode 100755 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 100755 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 100755 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 100755 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 100755 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 100755 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 100755 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/license.png b/base_hospital_management/static/description/assets/icons/license.png new file mode 100755 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 100755 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 100755 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/pos-black.png b/base_hospital_management/static/description/assets/icons/pos-black.png new file mode 100755 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 100755 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 100755 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 100755 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 100755 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 100755 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 100755 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 100755 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 100755 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/categories.png b/base_hospital_management/static/description/assets/misc/categories.png new file mode 100755 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 100755 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 100755 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 100755 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 100755 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 100755 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/features.png b/base_hospital_management/static/description/assets/misc/features.png new file mode 100755 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 100755 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/pictures.png b/base_hospital_management/static/description/assets/misc/pictures.png new file mode 100755 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 100755 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 100755 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.png b/base_hospital_management/static/description/assets/misc/star.png new file mode 100755 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.png b/base_hospital_management/static/description/assets/misc/support.png new file mode 100755 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/whatsapp.png b/base_hospital_management/static/description/assets/misc/whatsapp.png new file mode 100755 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/modules/car.png b/base_hospital_management/static/description/assets/modules/car.png new file mode 100755 index 000000000..3cdfc0af5 Binary files /dev/null and b/base_hospital_management/static/description/assets/modules/car.png differ diff --git a/base_hospital_management/static/description/assets/modules/fleet.png b/base_hospital_management/static/description/assets/modules/fleet.png new file mode 100755 index 000000000..2d2d873a7 Binary files /dev/null and b/base_hospital_management/static/description/assets/modules/fleet.png differ diff --git a/base_hospital_management/static/description/assets/modules/lab.png b/base_hospital_management/static/description/assets/modules/lab.png new file mode 100755 index 000000000..27d752e6e Binary files /dev/null and b/base_hospital_management/static/description/assets/modules/lab.png differ diff --git a/base_hospital_management/static/description/assets/modules/legal.png b/base_hospital_management/static/description/assets/modules/legal.png new file mode 100755 index 000000000..05ed0b5ef Binary files /dev/null and b/base_hospital_management/static/description/assets/modules/legal.png differ diff --git a/base_hospital_management/static/description/assets/modules/library.png b/base_hospital_management/static/description/assets/modules/library.png new file mode 100755 index 000000000..5965a8ce0 Binary files /dev/null and b/base_hospital_management/static/description/assets/modules/library.png differ diff --git a/base_hospital_management/static/description/assets/modules/spa.png b/base_hospital_management/static/description/assets/modules/spa.png new file mode 100755 index 000000000..4fda77f38 Binary files /dev/null and b/base_hospital_management/static/description/assets/modules/spa.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/add_doctor.png b/base_hospital_management/static/description/assets/screenshots/add_doctor.png new file mode 100755 index 000000000..952438ac5 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/add_doctor.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/add_medicine.png b/base_hospital_management/static/description/assets/screenshots/add_medicine.png new file mode 100755 index 000000000..309962f3b Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/add_medicine.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/add_pharmacy.png b/base_hospital_management/static/description/assets/screenshots/add_pharmacy.png new file mode 100755 index 000000000..7a0e320c7 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/add_pharmacy.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/add_result.png b/base_hospital_management/static/description/assets/screenshots/add_result.png new file mode 100755 index 000000000..96b5f0d4f Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/add_result.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/add_room.png b/base_hospital_management/static/description/assets/screenshots/add_room.png new file mode 100755 index 000000000..9e72948c3 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/add_room.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/add_vaccine.png b/base_hospital_management/static/description/assets/screenshots/add_vaccine.png new file mode 100755 index 000000000..baff252b5 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/add_vaccine.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/admit.png b/base_hospital_management/static/description/assets/screenshots/admit.png new file mode 100755 index 000000000..3157f65ba Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/admit.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/all_op.png b/base_hospital_management/static/description/assets/screenshots/all_op.png new file mode 100644 index 000000000..c8bf174cf Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/all_op.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/all_patients.png b/base_hospital_management/static/description/assets/screenshots/all_patients.png new file mode 100644 index 000000000..2830810a2 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/all_patients.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/all_test.png b/base_hospital_management/static/description/assets/screenshots/all_test.png new file mode 100755 index 000000000..fb5e7ad52 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/all_test.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/allocation.png b/base_hospital_management/static/description/assets/screenshots/allocation.png new file mode 100755 index 000000000..373434520 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/allocation.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/appointment.png b/base_hospital_management/static/description/assets/screenshots/appointment.png new file mode 100755 index 000000000..c9a6493a2 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/appointment.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/booking.png b/base_hospital_management/static/description/assets/screenshots/booking.png new file mode 100755 index 000000000..6629558d4 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/booking.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/booking_tab.png b/base_hospital_management/static/description/assets/screenshots/booking_tab.png new file mode 100755 index 000000000..6f47e9ec4 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/booking_tab.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/card.png b/base_hospital_management/static/description/assets/screenshots/card.png new file mode 100755 index 000000000..cfee9dab7 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/card.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/card_print.png b/base_hospital_management/static/description/assets/screenshots/card_print.png new file mode 100755 index 000000000..874ff95a0 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/card_print.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/consultation.png b/base_hospital_management/static/description/assets/screenshots/consultation.png new file mode 100755 index 000000000..47f5ab91c Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/consultation.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/create_consultation.png b/base_hospital_management/static/description/assets/screenshots/create_consultation.png new file mode 100755 index 000000000..26a3dc8aa Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/create_consultation.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/create_inpatient.png b/base_hospital_management/static/description/assets/screenshots/create_inpatient.png new file mode 100755 index 000000000..9d08a8f4e Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/create_inpatient.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/create_invoice.png b/base_hospital_management/static/description/assets/screenshots/create_invoice.png new file mode 100755 index 000000000..eb690e628 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/create_invoice.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/create_patient.png b/base_hospital_management/static/description/assets/screenshots/create_patient.png new file mode 100755 index 000000000..3bddd9129 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/create_patient.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/create_sale.png b/base_hospital_management/static/description/assets/screenshots/create_sale.png new file mode 100644 index 000000000..0939abb99 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/create_sale.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/create_test.png b/base_hospital_management/static/description/assets/screenshots/create_test.png new file mode 100755 index 000000000..aa97a081d Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/create_test.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/create_test_wizard.png b/base_hospital_management/static/description/assets/screenshots/create_test_wizard.png new file mode 100755 index 000000000..2467a286c Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/create_test_wizard.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/created_test.png b/base_hospital_management/static/description/assets/screenshots/created_test.png new file mode 100755 index 000000000..2c54ed68d Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/created_test.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/doc_round.png b/base_hospital_management/static/description/assets/screenshots/doc_round.png new file mode 100755 index 000000000..6f613f405 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/doc_round.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/doctor_db.png b/base_hospital_management/static/description/assets/screenshots/doctor_db.png new file mode 100755 index 000000000..86c734cf1 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/doctor_db.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/doctor_surgery.png b/base_hospital_management/static/description/assets/screenshots/doctor_surgery.png new file mode 100644 index 000000000..6a1d3233c Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/doctor_surgery.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/family.png b/base_hospital_management/static/description/assets/screenshots/family.png new file mode 100755 index 000000000..bd4a0423f Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/family.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 100755 index 000000000..8b6faf249 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/screenshots/inpatient.png b/base_hospital_management/static/description/assets/screenshots/inpatient.png new file mode 100755 index 000000000..6f2a763c6 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/inpatient.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/invoice.png b/base_hospital_management/static/description/assets/screenshots/invoice.png new file mode 100755 index 000000000..af1432b73 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/invoice.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/lab_assistant.png b/base_hospital_management/static/description/assets/screenshots/lab_assistant.png new file mode 100755 index 000000000..d1e7754e4 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/lab_assistant.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/lab_dashboard.png b/base_hospital_management/static/description/assets/screenshots/lab_dashboard.png new file mode 100755 index 000000000..20febe4b6 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/lab_dashboard.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/lab_test.png b/base_hospital_management/static/description/assets/screenshots/lab_test.png new file mode 100755 index 000000000..e8f0db5f2 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/lab_test.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/lifestyle.png b/base_hospital_management/static/description/assets/screenshots/lifestyle.png new file mode 100755 index 000000000..c5f9afd70 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/lifestyle.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/manager.png b/base_hospital_management/static/description/assets/screenshots/manager.png new file mode 100755 index 000000000..ba3177db7 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/manager.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/medicines.png b/base_hospital_management/static/description/assets/screenshots/medicines.png new file mode 100755 index 000000000..b63c0c9a9 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/medicines.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/nurse.png b/base_hospital_management/static/description/assets/screenshots/nurse.png new file mode 100755 index 000000000..22171fd3b Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/nurse.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/op_line.png b/base_hospital_management/static/description/assets/screenshots/op_line.png new file mode 100644 index 000000000..ba79e9466 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/op_line.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/orders.png b/base_hospital_management/static/description/assets/screenshots/orders.png new file mode 100644 index 000000000..df784973e Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/orders.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/patient.png b/base_hospital_management/static/description/assets/screenshots/patient.png new file mode 100755 index 000000000..a6f277649 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/patient.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/patient_history.png b/base_hospital_management/static/description/assets/screenshots/patient_history.png new file mode 100755 index 000000000..937d4a2a0 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/patient_history.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/patient_rec.png b/base_hospital_management/static/description/assets/screenshots/patient_rec.png new file mode 100644 index 000000000..c5f151021 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/patient_rec.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/patient_search.png b/base_hospital_management/static/description/assets/screenshots/patient_search.png new file mode 100755 index 000000000..8aaffc56e Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/patient_search.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/patient_tab.png b/base_hospital_management/static/description/assets/screenshots/patient_tab.png new file mode 100755 index 000000000..814227ffa Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/patient_tab.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/pha_db.png b/base_hospital_management/static/description/assets/screenshots/pha_db.png new file mode 100755 index 000000000..652014102 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/pha_db.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/pha_home.png b/base_hospital_management/static/description/assets/screenshots/pha_home.png new file mode 100755 index 000000000..7e6baf811 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/pha_home.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/pharmacist.png b/base_hospital_management/static/description/assets/screenshots/pharmacist.png new file mode 100755 index 000000000..446a84257 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/pharmacist.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/portal.png b/base_hospital_management/static/description/assets/screenshots/portal.png new file mode 100755 index 000000000..a4d958cd1 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/portal.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/prescription.png b/base_hospital_management/static/description/assets/screenshots/prescription.png new file mode 100755 index 000000000..af77fdb61 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/prescription.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/print_prescription.png b/base_hospital_management/static/description/assets/screenshots/print_prescription.png new file mode 100755 index 000000000..8d6d8013a Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/print_prescription.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/published_result.png b/base_hospital_management/static/description/assets/screenshots/published_result.png new file mode 100755 index 000000000..cb54b0cba Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/published_result.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/rec_db.png b/base_hospital_management/static/description/assets/screenshots/rec_db.png new file mode 100755 index 000000000..5b4c37b86 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/rec_db.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/receptionist.png b/base_hospital_management/static/description/assets/screenshots/receptionist.png new file mode 100755 index 000000000..33009574d Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/receptionist.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/register_payment.png b/base_hospital_management/static/description/assets/screenshots/register_payment.png new file mode 100755 index 000000000..80a0351ae Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/register_payment.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/result_line.png b/base_hospital_management/static/description/assets/screenshots/result_line.png new file mode 100755 index 000000000..8aff4eec4 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/result_line.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/room.png b/base_hospital_management/static/description/assets/screenshots/room.png new file mode 100755 index 000000000..9d5fa983a Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/room.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/room.png.png b/base_hospital_management/static/description/assets/screenshots/room.png.png new file mode 100644 index 000000000..48f5cdac8 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/room.png.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/sale.png b/base_hospital_management/static/description/assets/screenshots/sale.png new file mode 100755 index 000000000..f9ff6c10b Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/sale.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/shift.png b/base_hospital_management/static/description/assets/screenshots/shift.png new file mode 100755 index 000000000..af07db671 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/shift.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/socio.png b/base_hospital_management/static/description/assets/screenshots/socio.png new file mode 100755 index 000000000..50da0c2a6 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/socio.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/start_test.png b/base_hospital_management/static/description/assets/screenshots/start_test.png new file mode 100755 index 000000000..85d4f3aa0 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/start_test.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/surgery.png b/base_hospital_management/static/description/assets/screenshots/surgery.png new file mode 100755 index 000000000..490cd1fb3 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/surgery.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/surgery.png.png b/base_hospital_management/static/description/assets/screenshots/surgery.png.png new file mode 100644 index 000000000..2fad09229 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/surgery.png.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/test2.png b/base_hospital_management/static/description/assets/screenshots/test2.png new file mode 100755 index 000000000..7eb2e3e92 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/test2.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/test_create.png b/base_hospital_management/static/description/assets/screenshots/test_create.png new file mode 100755 index 000000000..2a66b26df Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/test_create.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/test_details.png b/base_hospital_management/static/description/assets/screenshots/test_details.png new file mode 100755 index 000000000..5745d5f8c Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/test_details.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/user_doctor.png b/base_hospital_management/static/description/assets/screenshots/user_doctor.png new file mode 100755 index 000000000..5218b1d70 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/user_doctor.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/user_manager.png b/base_hospital_management/static/description/assets/screenshots/user_manager.png new file mode 100755 index 000000000..3f1332d18 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/user_manager.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/vac_tab.png b/base_hospital_management/static/description/assets/screenshots/vac_tab.png new file mode 100755 index 000000000..ac2901bdc Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/vac_tab.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/vac_wizard.png b/base_hospital_management/static/description/assets/screenshots/vac_wizard.png new file mode 100755 index 000000000..d502a0e29 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/vac_wizard.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/vaccine.png b/base_hospital_management/static/description/assets/screenshots/vaccine.png new file mode 100755 index 000000000..73f1acdd8 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/vaccine.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/view_inpatient.png b/base_hospital_management/static/description/assets/screenshots/view_inpatient.png new file mode 100644 index 000000000..8b31f2bbe Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/view_inpatient.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/view_op.png b/base_hospital_management/static/description/assets/screenshots/view_op.png new file mode 100644 index 000000000..c962b0a45 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/view_op.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/view_outpatient.png b/base_hospital_management/static/description/assets/screenshots/view_outpatient.png new file mode 100644 index 000000000..5f3b89728 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/view_outpatient.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/view_patients.png b/base_hospital_management/static/description/assets/screenshots/view_patients.png new file mode 100644 index 000000000..cef6b9676 Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/view_patients.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/view_sale.png b/base_hospital_management/static/description/assets/screenshots/view_sale.png new file mode 100644 index 000000000..9a43d779d Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/view_sale.png differ diff --git a/base_hospital_management/static/description/assets/screenshots/website.png b/base_hospital_management/static/description/assets/screenshots/website.png new file mode 100755 index 000000000..bde2cd77f Binary files /dev/null and b/base_hospital_management/static/description/assets/screenshots/website.png differ diff --git a/base_hospital_management/static/description/banner.jpg b/base_hospital_management/static/description/banner.jpg new file mode 100755 index 000000000..e3cd0a1ea 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 100755 index 000000000..1e63215f3 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..a49ebeaa3 --- /dev/null +++ b/base_hospital_management/static/description/index.html @@ -0,0 +1,1017 @@ +
+ +
+ +
+
+ Community +
+
+ Enterprise +
+
+
+ + +
+
+
+

+ Hospital Management Odoo 16

+

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

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

+ Explore This + Module

+
+ + + +
+
+ +
+

+ Overview +

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

+ Features +

+
+
+
+
+ + Dashboard Services +
+
+ + Patient Management +
+
+ + Laboratory Management +
+
+ + Stock Management System +
+
+ + Blood Bank Management +
+
+ + Vaccination Management +
+
+ + Doctor's Allocation and Service Managment +
+
+ + Other Amenities +
+
+ + Medicine and Related Product Management +
+
+ + Other Amenities +
+
+ + Online Booking +
+
+
+ + +
+
+ +
+

+ Screenshots +

+
+
+
+

+ 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 Medicine

+

+ Navigate to Medicine menu under Configuration and add new + medicines. +

+ +
+
+

+ Add Vaccine

+

+ By navigating to Configuration -> Vaccine, a new vaccine can be + added. +

+ +
+
+

+ Add Pharmacy

+

+ By navigating to Infrastructure > Pharmacy, a new pharmacy can be + added. +

+ +
+
+

+ Add Room

+

+ By navigating to Infrastructure -> Room, a new room can be added. +

+ +
+
+

+ Add Lab Test

+

+ By navigating to Laboratory -> Lab Test, a new lab test can be + added. +

+ +
+
+

+ Add Doctor Allocation

+

+ By navigating to Appointment -> Allocation, a new allocation + can + be added and click CONFIRM. +

+ +
+
+

+ Give the user access to the user group Doctor.

+ +
+
+

+ Doctor's Dashboard.

+ +
+
+

+ Consultation tab of Doctor's dashboard.

+

+ Click on Create button for adding new consultation.

+ +
+
+

+ Create new Consultation

+ +
+
+

+ Patient tab of Doctor's dashboard

+

+ There is a search option for searching a patient. +

+ +
+
+

+ Inpatient tab of Doctor's dashboard

+

+ There is a Search option for searching an inpatient. +

+ +
+
+

+ Surgery tab of Doctor's dashboard

+ +
+
+

+ Shift Allocation tab of Doctor's dashboard

+ +
+
+

+ Create new Patient

+

+ By navigating to Patient menu, a new patient can be added. +

+ +
+
+

+ Click on Patient Card for generating the patient card. +

+ +
+
+

+ Generated Patient Card. +

+ +
+
+

+ Create Inpatient. +

+

+ By navigating to Appointment -> Inpatient, a new Inpatient can be + added. +

+ +
+
+

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

+ +
+
+

+ Admit an Inpatient by clicking ADMIT button.

+ +
+
+

+ Click on PRESCRIPTION to print the prescription.

+ +
+
+

+ Printed Prescription

+ +
+
+

+ Click on CREATE TEST to create new test for an Inpatient.

+ +
+
+

+ Add the test details and click CONFIRM button

+ +
+
+

+ Create invoice by clicking the CREATE INVOICE button.

+ +
+
+

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

+ +
+
+

+ Lab Assistant's Dashboard

+ +
+
+

+ Click on the Create button under Tests to Confirm tab for + creating a new test.

+ +
+
+

+ Add lab test details and click CONFIRM button.

+ +
+
+

+ Click on any test. +

+ +
+
+

+ Click on CONFIRM button.

+ +
+
+

+ The test will be added to Process Test. Click on any test + line.

+ +
+
+

+ Click the START button.

+ +
+
+

+ Click on result line.

+ +
+
+

+ Add test result.

+ +
+
+

+ Published tab will provide all published test results. It is + possible to download the result.

+ +
+
+

+ Vaccinations can be created by clicking the Create button under + Vaccination tab

+ +
+
+

+ Add vaccination details

+ +
+
+

+ Give the user access to the user group Pharmacist.

+ +
+
+

+ Pharmacist's Dashboard +

+ +
+
+

+ Medicines tab of Pharmacist's dashboard

+ +
+
+

+ Vaccines tab of Pharmacist's dashboard

+ +
+
+

+ Orders tab of Pharmacist's dashboard

+ +
+
+

+ Patient search from Pharmacist's dashboard

+ +
+
+

+ Click any OP line

+ +
+
+

+ We can see the OP details here. Click CREATE SALE ORDER for + creating + sale order for medicines.

+ +
+
+

+ You can view the sales order in the "Orders" tab.

+ +
+
+

+ Give the user access to the user group Receptionist.

+ +
+
+

+ Receptionist's Dashboard

+ +
+
+

+ Patient Tab of Receptionist's Dashboard. It is possible to + create new Patients here.

+ +
+
+

+ Click VIEW PATIENTS button to view all patients.

+ +
+
+

+ All Patients.

+ +
+
+

+ Appointment tab of Receptionist's Dashboard. It is possible to + create Inpatient and Outpatient here.

+ +
+
+

+ Click VIEW OUTPATIENTS button to view all Outpatients.

+ +
+
+

+ Click VIEW INPATIENTS button to view all Inpatients.

+ +
+
+

+ Room/Ward tab of Receptionist's Dashboard. Here, it is possible + to search for a Room/Ward.

+ +
+
+

+ Booking through website.

+ +
+
+

+ Documents of portal user.

+ +
+
+ + +
+
+ +
+

+ Related + Products +

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

+ Our Services +

+
+
+
+
+
+ +
+
+ Odoo + Customization
+
+
+
+ +
+
+ Odoo + Implementation
+
+
+
+ +
+
+ Odoo + Support
+
+
+
+ +
+
+ Hire + Odoo + Developer
+
+
+
+ +
+
+ Odoo + Integration
+
+
+
+ +
+
+ Odoo + Migration
+
+
+
+ +
+
+ Odoo + Consultancy
+
+
+
+ +
+
+ Odoo + Implementation
+
+
+
+ +
+
+ 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 86068 + 27707

+
+
+
+
+
+
+
+ +
+
+
+ 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..45dbe9c84 --- /dev/null +++ b/base_hospital_management/static/src/css/doctor_dashboard.css @@ -0,0 +1,27 @@ +.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; + } + } 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..9155855bb --- /dev/null +++ b/base_hospital_management/static/src/css/lab_dashboard.css @@ -0,0 +1,41 @@ +.dashButtonContainer { + height : 90vh; + display: grid; + justify-content : center; +} +.dashButton { + height : 18vh; + border-radius: 10px; + box-shadow:0px 1px 3px 3px #c9c9c9;; + width : 200px; + display: grid; + justify-content : center; + align-items : center; +} +.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; +} 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..90c40e5a5 --- /dev/null +++ b/base_hospital_management/static/src/css/pharmacy_dashboard.css @@ -0,0 +1,382 @@ +.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..3e5a119b2 --- /dev/null +++ b/base_hospital_management/static/src/css/reception_dashboard.css @@ -0,0 +1,549 @@ +.r_dashButtonContainer { + height: fit-content; + justify-content: center; + display: flex; + align-items:flex-end; + flex-wrap:wrap; + width: 100%; +} + +.r_dashButton { + height: 100px; + border-radius: 10px; + box-shadow: 0px 1px 3px 3px #e1e1e1; + width: 388px; + 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: 100px; + border-radius: 10px; + box-shadow: 0px 1px 3px 3px #e1e1e1; + width: 388px; + 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 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:30rem; + min-height:4rem; + border-radius:5px; + margin-bottom:10px; +} +#op_table label{ + display: inline-block; + padding-bottom: 8px; +} + +.o_inpatient_button{ + height: 100px; + border-radius: 10px; + box-shadow: 0px 1px 3px 3px #e1e1e1; + width: 388px; + 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: 100px; + border-radius: 5px; + box-shadow: 0px 1px 3px 3px #e1e1e1; + width: 388px; + 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: 100px; + border-radius: 5px; + box-shadow: 0px 1px 3px 3px #e1e1e1; + width: 388px; + 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; + box-shadow: 0px 1px 3px 3px #c9c9c9; + 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/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/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/js/doctor_dashboard.js b/base_hospital_management/static/src/js/doctor_dashboard.js new file mode 100755 index 000000000..69d52cd00 --- /dev/null +++ b/base_hospital_management/static/src/js/doctor_dashboard.js @@ -0,0 +1,532 @@ +odoo.define('base_hospital_management.doctor_dashboard_action', function (require){ + "use strict"; + var AbstractAction = require('web.AbstractAction'); + var core = require('web.core'); + var QWeb = core.qweb; + var _t = core._t; + var rpc = require('web.rpc'); + var ajax = require('web.ajax'); + var DoctorDashboard = AbstractAction.extend({ + template: 'DoctorDashboard', + init: function(parent, context) { + this._super(parent, context); + }, + //Events + events :{ + 'click .patient_search': 'fetch_patient_data', + 'click #patient': 'list_patient_data', + 'click #consultation' : 'fetch_consultation', + 'click #shift' : 'fetch_allocation_lines', + 'click #scheduled_activity':'fetch_doctors_schedule', + 'click #cancel_slot':'action_slot_cancel', + 'click #inpatient':'action_list_inpatient', + 'change #filter': '_onChangeSelection', + 'click .inpatient_row': 'fetch_inpatientRow', + 'click .listpatientdata': 'fetch_patientRow', + 'click .op-consultation': 'create_op_consultation', + 'click .search': 'search_patient_from_list', + 'click .view_slot':'view_doctors_schedule', + 'click .outpatient_row': 'view_outpatient', + 'click .booking_item': 'fetch_bookingItem' + }, + start: function() { + this.set("title", 'Dashboard'); + return this._super().then(function() {}) + }, + refresh: function(){ + const btns = $('.n_active') + if (btns.length != 0){console.log(btns), btns.click()} + }, + listPatient:[], + //Function for feting patient data + list_patient_data: function(){ + if(this.$('#welcome')){ + this.$('#welcome').remove() + } + var self = this; + rpc.query({ + model: 'res.partner', + method:'fetch_patient_data', + args: [[['patient_seq', '!=', ['New','Employee']]]] + }).then(function (result){ + if (self.$('.n_active')[0]){ + self.$('.n_active')[0].classList.remove('n_active'); + } + self.$('.patient_data')[0].classList.add('n_active'); + self.$('.r_AppntBtn').html(''); + self.listPatient = result; + self.$('#main-view').html(`
+ +
+
+ + + + + + + + + +
SequenceNameGenderDate Of Birth
`) + var count=0; + result.forEach(element => { + var gender = (element.gender ? element.gender : ''); + var date_of_birth = (element.date_of_birth ? element.date_of_birth : ''); + self.$('#patientlist').append(` + ${element.patient_seq + || ''} + ${element.name || ''} + ${gender || ''} + ${date_of_birth || ''} + `) + count += 1; + }) + }) + }, + //Method for returning the details of a patient + fetch_patientRow: function(ev){ + var self = this; + var record_id = parseInt($(ev.target).data('index')) + var record = self.listPatient[record_id]; + rpc.query({ + model: 'res.partner', + method: 'fetch_view_id', + args: [[['patient_seq', '!=', ['New','Employee']]]] + }).then(function (result){ + self.do_action({ + name: _t("Patient Details"), + type: 'ir.actions.act_window', + res_model: 'res.partner', + res_id: record.id, + view_mode: 'form', + view_type: 'form', + views: [[result, 'form']], + target: 'new', + }) + }); + }, + //Method for searching for a patient + search_patient_from_list: function(){ + const btns = this.$('.n_active'); + if (btns.length != 0){ + if(btns[0].id === 'patient'){ + var search_key = this.$('#patient_search_pad').val() + var self = this; + rpc.query({ + model: 'res.partner', + method: 'search_read', + kwargs: {domain: ['|','|', + ['date_of_birth', 'ilike', search_key], + ['patient_seq', 'ilike', search_key], + ['name', 'ilike', search_key]]}, + }).then(function (result){ + self.listPatient = result; + self.$('#patientlist').html(''); + var count = 0; + result.forEach(element => { + self.$('#patientlist').append(` + + ${element.patient_seq || ''} + ${element.name || ''} + ${element.gender || ''} + ${element.date_of_birth || ''} + + `) + count += 1; + }) + }) + } + else if(btns[0].id === 'inpatient'){ + var search_key = this.$('#inpatient_search').val() + var self = this; + rpc.query({ + model: 'hospital.inpatient', + method: 'fetch_inpatient', + args: [false, search_key] + }).then(function (result){ + self.InPatientData = result; + self.$('#inpatient_list').html(''); + var count = 0; + result.forEach(element => { + self.$('#inpatient_list').append(` + + ${element.name || ''} + ${element.patient_id[1] || ''} + ${element.type_admission || ''} + ${element.attending_doctor_id[1] || ''} + ${element.hosp_date || ''} + + `) + count += 1; + }) + }) + } + else if(btns[0].id === 'consultation'){ + var search_key = this.$('#outpatient_search').val() + var self = this; + rpc.query({ + model: 'hospital.outpatient', + method: 'search_read', + kwargs: {domain: ['|','|','|','|', + ['slot', 'ilike', search_key], + ['op_reference', 'ilike', search_key], + ['patient_id.name', 'ilike', search_key], + ['op_date', 'ilike', search_key], + ['state', 'ilike', search_key]]}, + }).then(function (result){ + self.outpatientList = result; + self.$('#outpatient_list').html(''); + var count = 0; + result.forEach(element => { + self.$('#outpatient_list').append(` + + ${element.display_name || ''} + ${element.patient_id[1] || ''} + ${element.doctor_id[1] || ''} + + `) + count += 1; + }) + }) + } + } + }, + //Method for fetching a booking item + fetch_bookingItem : function(ev){ + var self = this; + var record_id = parseInt(self.$(ev.target).data('index')) + var record = self.bookingData[record_id]; + this.do_action({ + name: _t("Patient Booking"), + type: 'ir.actions.act_window', + res_model: 'patient.booking', + res_id: record.id, + view_mode: 'form', + view_type: 'form', + views: [[false, 'form']], + target: 'new', + }) + }, + //Method fo fetching patient data + fetch_patient_data: function() { + var self = this; + if(self.$('#welcome')){self.$('#welcome').remove()} + rpc.query({ + model: 'res.partner', + method: 'action_get_patient_data', + args: [self.$('#patient_search').val()], + }).then(function (result){ + self.$('#patient-name').text(`${result.name} - (${result.unique})`); + self.$('#patient-age').text(result.dob || ''); + self.$('#patient-blood').text(result.blood_group || ''); + self.$('#patient-blood').text(result.blood_group || ''); + self.$('#patient-gender').text(result.gender || ''); + self.$('#patient-status').text(result.status || ''); + self.$('#patient-phone').text(result.phone || ''); + self.$('#patient-email').text(result.email || ''); + self.$('#patient-image').attr('src', 'data:image/png;base64, '+result.image_1920); + }) + }, + inpatientList: [], + //method for generating list of inpatients + action_list_inpatient: function() { + var self = this; + if(self.$('#welcome')){self.$('#welcome').remove()} + self.$('#view_secondary').html(''); + if (self.$('.n_active')[0]){self.$('.n_active')[0].classList.remove('n_active');} + self.$('.inpatient_button')[0].classList.add('n_active'); + rpc.query({ + model: 'hospital.inpatient', + method: 'hospital_inpatient_list', + }).then(function (result){ + self.inpatientList = result; + self.$('#main-view').html( + `
+ +
+
+ + + + + + + + + + +
SequencePatientAdmissionAttending DoctorHospitalization Date
`) + var count = 0; + result['record'].forEach(element => { + self.$('#inpatient_list').append(` + ${element['name']} + + ${element['patient_id']} + + ${element['admission_type']} + + ${element['attending_doctor_id'] || ''} + + ${element['hosp_date']} + `) + count += 1; + }) + }) + }, + //Method for fetching a particular patient + fetch_inpatientRow: function(ev){ + var self = this; + var record_id = parseInt(self.$(ev.target).data('index')) + var record = self.inpatientList.record[record_id]; + this.do_action({ + name: _t("Inpatient Details"), + type: 'ir.actions.act_window', + res_model: 'hospital.inpatient', + res_id: record.id, + view_mode: 'form', + view_type: 'form', + views: [[false, 'form']], + target: 'new', + }) + }, + scheduleList: [], + //Fetch doctor's schedule + fetch_doctors_schedule: function() { + if (this.$('.n_active')[0]){this.$('.n_active')[0].classList.remove('n_active');} + this.$('.scheduled_activity')[0].classList.add('n_active'); + var self = this; + if(self.$('#welcome')){self.$('#welcome').remove()} + rpc.query({ + model: 'inpatient.surgery', + method: 'get_doctor_slot', + args: [], + }).then(function (line){ + self.scheduleList = line; + self.$('#main-view').html(` +
+
+ + + + + + + + + + +
+ Planned Date + + Patient ID + + Surgery + + State +
`) + var count = 0; + line['record'].forEach(element => { + self.$('#doctors_slot').append(` + ${element['planned_date'] || ''} + ${element['patient_id'] || ''} + ${element['surgery_name'] || ''} + ${element['state'] || ''} + ${element['id'] || ''} + `); + count += 1; + }) + }) + }, + //Method for viewing doctor's schedule + view_doctors_schedule : function(ev) { + var self = this; + var record_id = parseInt(self.$(ev.target).data('index')) + var record = self.scheduleList.record[record_id]; + this.do_action({ + name: _t("Schedules"), + type: 'ir.actions.act_window', + res_model: 'inpatient.surgery', + res_id: record.id, + view_mode: 'form', + view_type: 'form', + views: [[false, 'form']], + target: 'new', + }) + }, + outpatientList:[], + //Method for fetching consultation details + fetch_consultation: function(){ + var self = this; + if(self.$('#welcome')){self.$('#welcome').remove()} + if (self.$('.n_active')[0]){self.$('.n_active')[0].classList.remove('n_active');} + self.$('.outpatient_button')[0].classList.add('n_active'); + var self = this; + rpc.query({ + model: 'hospital.outpatient', + method: 'search_read', + }).then(function (result){ + self.outpatientList = result; + $('#main-view').html( + `
+ +
+
+ + + + + + + + + + + + +
SequencePatientDoctorDateSlotState
+
`) + var count = 0; + result.forEach(element => { + self.$('#outpatient_list').append(` + ${element.display_name || ''} + ${element.patient_id[1] || ''} + ${element.doctor_id[1] || ''} + ${element.op_date || ''} + ${element.slot || ''} + ${element.state.toUpperCase() || ''} + `) + count += 1; + }) + }) + }, + //Method for viewing outpatients + view_outpatient:function(ev){ + var self = this; + var record_id = parseInt($(ev.target).data('index')) + var record = self.outpatientList[record_id]; + this.do_action({ + name: _t("Inpatient Details"), + type: 'ir.actions.act_window', + res_model: 'hospital.outpatient', + res_id: record.id, + view_mode: 'form', + view_type: 'form', + views: [[false, 'form']], + target: 'new', + }) + }, + //Method for creating OP consultation + create_op_consultation: function(){ + this.do_action({ + name: _t("Consultation"), + type: 'ir.actions.act_window', + res_model: 'hospital.outpatient', + view_mode: 'form', + view_type: 'form', + views: [[false, 'form']], + target: 'new', + }); + this.fetch_consultation(); + }, + //Method for fetching allocated hours. + fetch_allocation_lines: function() { + var self = this; + if(self.$('#welcome')){self.$('#welcome').remove()} + if (self.$('.n_active')[0]){self.$('.n_active')[0].classList.remove('n_active');} + self.$('.shift')[0].classList.add('n_active'); + rpc.query({ + model: 'doctor.allocation', + method: 'get_allocation_lines', + args: [], + }).then(function (result){ + self.$('#main-view').html(` + + + + + + + + + + + +
+ Name + + Date + + Patient Type + + Limit + + Patient Count +
`) + var count = 0; + result['record'].forEach(element => { + $('#doctors_shift').append(` + ${element['name'] || ''} + + ${element['date'] || ''} + + ${element['patient_type'].toUpperCase() || ''} + + ${element['patient_limit'] || ''} + + ${element['patient_count'] || 0}`); + count += 1; + }) + }) + } + }) + core.action_registry.add('doctor_dashboard_tags', DoctorDashboard); + return 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..c04eb9c5d --- /dev/null +++ b/base_hospital_management/static/src/js/lab_dashboard.js @@ -0,0 +1,811 @@ +odoo.define('base_hospital_management.lab_dashboard_action', function (require){ + "use strict"; + var AbstractAction = require('web.AbstractAction'); + var core = require('web.core'); + var QWeb = core.qweb; + var _t = core._t; + var rpc = require('web.rpc'); + var ajax = require('web.ajax'); + var uom_lst= []; + var LabDashBoard = AbstractAction.extend({ + template: 'LabDashboard', + init: function(parent, context) { + this._super(parent, context); + }, + //Events + events :{ + 'click #btn_patient_search': '_Search', + 'click .test_item': '_fetchTestData', + 'click .all_test_item': 'fetch_all_test_data', + 'click .removeTest': 'removeTest', + 'click #confirm-test': 'confirmLabTest', + 'click #create': 'Create', + 'click #start-test': 'startLabTest', + 'click #test-result-edit': 'testResultEdit', + 'change #result-attachment': '_onChangeFile', + 'change #recurring': '_onChangeRecurring', + 'change #vaccine-patient-name': '_onChangeRecurring', + 'click #create-vaccination': '_createVaccination', + 'click #update-result': 'testResultUpdate', + 'click #end-test': 'endLabTest', + 'click #invoice-test': 'invoiceLabTest', + 'click #print-test-invoice': 'printInvoiceLabTest', + 'click #print-test-sale': 'printSaleLabTest', + 'click #all-test': '_allLabTest', + 'click #test-create': '_loadTestData', + 'click #published-test': '_loadPublished', + 'click #vaccination': '_vaccination', + 'click .vaccine-data': 'fetchVaccineData', + }, + listVaccine:[], + start: function() { + var self = this; + this.set("title", 'Dashboard'); + return this._super().then(function() { + self._loadTestData(); + }) + }, + state: '', + //Search function + _Search: function() { + var self = this + if (self.state == 'patient.lab.test'){ + var search_key = $('#patient_search').val(); + rpc.query({ + model: 'patient.lab.test', + method: 'search_read', + kwargs: {domain: ['|','|','|',['test_id.name', 'ilike', search_key], + ['name', 'ilike', search_key], + ['patient_id.patient_seq', 'ilike', search_key], + ['patient_id.name', 'ilike', search_key]]}, + }).then(function (result){ + self.testData = result; + var count = 0; + self.$('#main-view').html( + ` + +
SequencePatientDatePriceState
`) + result.reverse().forEach(element => { + self.$('#record_list').append(` + + ${element.test_id.name || ''} + ${element.patient_id[1] || ''} + ${element.date || ''} + ${element.total_price || 0} + ${element.state.toUpperCase() || ''} + + ${element.attachment_id ? ` + + ` : ''} + + + `) + count += 1; + }) + }) + } + else if (self.state == 'hospital.vaccination'){ + var search_key = self.$('#patient_search').val(); + rpc.query({ + model: 'hospital.vaccination', + method: 'fetch_vaccination_data', + kwargs: {domain: ['|','|','|',['vaccine_product_id.name', 'ilike', search_key], + ['name', 'ilike', search_key], + ['patient_id.patient_seq', 'ilike', search_key], + ['patient_id.name', 'ilike', search_key]]}, + }).then(function (result){ + var count = 1; + self.$('#main-view').html( + ` + +
SequencePatientVaccinePriceCertificate
`) + result.forEach(element => { + self.$('#record_list').append(` + + ${element.name || ''} + ${element.patient_id[1] || ''} + ${element.vaccine_product_id || ''} + ${element.vaccine_price || ''} + + ${element.attachment_id ? ` +
+ ` : ''} + + + `) + count += 1; + }) + }) + } + else if (self.state == 'lab.test.result'){ + var search_key = self.$('#patient_search').val(); + rpc.query({ + model: 'lab.test.result', + method: 'print_test_results', + kwargs: {domain: ['|','|', + ['test_id.name', 'ilike', search_key], + ['parent_id.patient_id.patient_seq', 'ilike', search_key], + ['parent_id.patient_id.name', 'ilike', search_key]]}, + }).then(function (result){ + var count = 1; + self.$('#main-view').html( + ` + + + + + + + + + +
SequencePatientTestResult
`) + result.reverse().forEach(element => { + self.$('#record_list').append(` + + ${element.parent_id || ''} + ${element.patient_id[1] || ''} + ${element.test_id || ''} + + ${element.attachment_id ? ` +
+ ` : ''} + + + `) + count += 1; + }) + }) + } + else if (self.state == 'lab.test.line'){ + var self = this; + var search_key = self.$('#patient_search').val(); + self.state = 'lab.test.line' + rpc.query({ + model: 'lab.test.line', + method: 'search_read', + kwargs: {domain: ['|','|',['name', 'ilike', search_key], + ['patient_id.patient_seq', 'ilike', search_key], + ['patient_id.name', 'ilike', search_key], + ['state', '=', 'draft']]}, + }).then(function (result){ + self.testData = result; + var count = 0; + self.$('#main-view').html( + ` + + + + + + + + + + +
SequencePatientDoctorTypeDate
`) + result.reverse().forEach(element => { + self.$('#record_list').append(` + + ${element.name || ''} + ${element.patient_id[1] || ''} + ${element.doctor_id[1] || ''} + ${element.patient_type.toUpperCase() || ''} + ${element.date || ''} + + `) + count += 1; + }) + }) + } + }, + //Method for returning the details of a vaccination + fetchVaccineData: function(ev){ + var self = this; + var record_id = parseInt($(ev.target).data('index')) + var record = self.listVaccine[record_id]; + rpc.query({ + model: 'hospital.vaccination', + method: 'fetch_vaccination_data', + kwargs: {domain: []}, + }).then(function (result){ + self.do_action({ + name: _t("Vaccinations"), + type: 'ir.actions.act_window', + res_model: 'hospital.vaccination', + res_id: record.id, + view_mode: 'form', + view_type: 'form', + views: [[result['view_id'], 'form']], + target: 'new', + }) + }); + }, + //Method for fetching all lab tests + _allLabTest: function() { + var self = this + self.state = 'patient.lab.test' + self.$('#create-button').html('') + rpc.query({ + model: 'patient.lab.test', + method: 'search_read', + }).then(function (result){ + self.$('#form-view').attr('hidden', 'true'); + self.testData = result; + var count = 0; + self.$('#main-view').html( + ` + + + + + + + + + + +
SequencePatientDatePriceState
`) + result.reverse().forEach(element => { + self.$('#record_list').append(` + + ${element.test_id[1] || ''} + ${element.patient_id[1] || ''} + ${element.date || ''} + ${element.total_price || ''} + ${element.state.toUpperCase() || ''} + + `) + count += 1; + }) + }) + }, + //Method for creating vaccinations + Create: function(){ + var self = this + if (self.state == 'hospital.vaccination') + { + this.do_action({ + name: _t("Vaccination"), + type: 'ir.actions.act_window', + res_model: 'hospital.vaccination', + view_mode: 'form', + view_type: 'form', + views: [[false, 'form']], + target: 'new', + }); + } + else{ + this.do_action({ + name: _t("Lab Test"), + type: 'ir.actions.act_window', + res_model: 'lab.test.line', + view_mode: 'form', + view_type: 'form', + views: [[false, 'form']], + target: 'new', + }, { + on_close: function () { + self._loadTestData(); + }}); + } + }, + //Method for recurrent vaccination + _onChangeRecurring: function(){ + if(self.$('#recurring').is(':checked')){ + self.$('#data-recurring').show() + var patient_id = parseInt(self.$('#vaccine-patient-name').val()) + if (patient_id){ + rpc.query({ + model: 'hospital.vaccination', + method: 'search_read', + kwargs: { + fields: ['id', 'name'], + domain: [['patient_id', '=', patient_id], + ['recurring_vaccine', '=', true]] + } + }).then(function (result){ + self.$('#old-data').html('') + result.forEach(element => { + self.$('#old-data').append(` + + `) + }) + + }); + } + }else{ + self.$('#data-recurring').hide() + } + }, + //Method for creating draft tests + CreateDraftTest: function(){ + var self = this; + var patient_id = self.$('#test-patient-name').val(); + var patient_type = self.$('#test-patient-type').val(); + var doctor_id = self.$('#test-doctor').val(); + var date = self.$('#test-date').val(); + var value = { + patient_id : parseInt(patient_id), + doctor_id : parseInt(doctor_id), + patient_type : patient_type + } + this._rpc({ + model: self.state, + method: 'create', + args: [value], + }) + .then(function (result) { + self.$('#test-modal-close').click() + self._loadTestData() + }) + }, + //Method for creating vaccinations + _createVaccination: function(){ + var self = this; + var data = { + patient_id :parseInt(self.$('#vaccine-patient-name').val()), + dose : parseFloat(self.$('#vaccine-dose').val()), + vaccine_product_id : parseInt(self.$('#vaccine-name').val()), + } + if(self.$('#recurring').is(':checked')){ + data['recurring_vaccine'] = true + data['parent_id'] = parseInt(self.$('#old-data')) + } + this._rpc({ + model: self.state, + method: 'create', + args: [data], + }) + .then(function (result) { + self.$('.btn-close').click() + self._vaccination() + }) + }, + testData: [], + //Method for getting all test data + fetch_all_test_data: function(ev){ + var self = this; + var record_id = parseInt($(ev.target).data('index')) + self.load_all_test_data(record_id) + }, + //Method for loading all test data + load_all_test_data: function(record_id){ + var self = this; + var record = self.testData[record_id]; + rpc.query({ + model: 'patient.lab.test', + method: 'action_get_patient_data', + args: [record.id], + }).then(function (result){ + self.load_data(result) + self.$('#action-table').html(` +

Tests

+
    +

    Medicines

    + + +
    SlMedicineQuantity
    + `) + result['test_data'].forEach(element => { + self.$('#tests').append(`
  • ${element.name}
  • `) + }) + if(result.result_ids.length > 0){ + self.$('#action-table').append(` +

    Results

    + + +
    NameResultNormalUnitCostState
    + `) + result['result_ids'].forEach(element => { + self.$('#result-list').append(` + + ${element.name || ''} + ${element.result || ''} + ${element.normal || ''} + ${element.uom_id[1] || ''} + ${element.cost || ''} + ${element.state.toUpperCase() || ''} + + `) + }) + } + var count = 1 + result['medicine'].forEach(element => { + self.$('#medicine-list').append(` + + ${count} + ${element.name} + ${element.quantity} + + `) + }) + if (result.state == 'draft'){ + self.$('#action-button').html(` + + `) + }else if(result.state == 'test'){ + self.$('#action-button').html(` + + `) + if(!result.invoiced){ + self.$('#action-button').append(` + + `) + }else{ + self.$('#action-button').append(` + + + `) + } + }else if(result.state == 'completed'){ + self.$('#action-button').html('') + if(!result.invoiced){ + self.$('#action-button').html(` + + `) + }else{ + self.$('#action-button').append(` + + + `) + } + } + }) + }, + //Method for starting the lab test + startLabTest: function(ev){ + var self = this + var record_id = parseInt($(ev.target).data('id')) + var index_id = parseInt($(ev.target).data('index')) + rpc.query({ + model: 'patient.lab.test', + method: 'start_test', + args: [record_id], + }).then(function (result){ + self.load_all_test_data(index_id) + }) + }, + //Method for ending la test + endLabTest: function(ev){ + var self = this + var record_id = parseInt($(ev.target).data('id')) + var index_id = parseInt($(ev.target).data('index')) + rpc.query({ + model: 'patient.lab.test', + method: 'test_end', + args: [record_id], + }).then(function (result){ + self.load_all_test_data(index_id) + }) + }, + //Method for invoicing lab test + invoiceLabTest: function(ev){ + var self = this + var record_id = parseInt($(ev.target).data('id')) + var index_id = parseInt($(ev.target).data('index')) + rpc.query({ + model: 'patient.lab.test', + method: 'create_invoice', + args: [record_id], + }).then(function (result){ + self.load_all_test_data(index_id) + }) + }, + //Method for printing lab test + printInvoiceLabTest: function(ev){ + var self = this + var record_id = parseInt($(ev.target).data('id')) + var index_id = parseInt($(ev.target).data('index')) + rpc.query({ + model: 'patient.lab.test', + method: 'search_read', + kwargs: { + fields: ['invoice_id'], + domain: [['id', '=', record_id]] + } + }).then(function (result){ + if (result){ + self.do_action({ + 'type': 'ir.actions.act_url', + 'url': `/report/pdf/account.report_invoice/${result[0].invoice_id[0]}`, + 'target': 'new', + }) + } + }) + }, + //Print lab test sale order + printSaleLabTest :function(ev){ + var self = this + var record_id = parseInt($(ev.target).data('id')) + var index_id = parseInt($(ev.target).data('index')) + rpc.query({ + model: 'patient.lab.test', + method: 'search_read', + kwargs: { + fields: ['order'], + domain: [['id', '=', record_id]] + } + }).then(function (result){ + if (result){ + self.do_action({ + 'type': 'ir.actions.act_url', + 'url': `/report/pdf/sale.report_saleorder/${result[0].order}`, + 'target': 'new', + }) + } + }) + }, + //Method to fetch uom + fetch_uom: function () { + var self = this; + return rpc.query({ + model: 'uom.uom', + method: 'search_read', + args: [''], + }).then(function (result) { + self.uom_lst = result; + return result; + }); + }, + //Method to update the test result + testResultEdit: function (ev) { + var self = this; + var record_id = parseInt($(ev.target).data('id')); + var index_id = parseInt($(ev.target).data('index')); + self.fetch_uom().then(function () { + self.$('.select_uom').html(''); + if (self.uom_lst) { + self.uom_lst.forEach(element => { + self.$('.select_uom').append(` + + `); + }); + } + rpc.query({ + model: 'lab.test.result', + method: 'search_read', + kwargs: { + fields: ['display_name', 'id', 'normal', 'result', 'uom_id', 'parent_id'], + domain: [['id', '=', record_id]] + } + }).then(function (result) { + self.$('#resultModalLabel').text(result[0].display_name || ''); + self.$('#normal-range').val(result[0].normal || ''); + self.$('#result-unit').val(result[0].uom_id || ''); + self.$('#result-result').val(result[0].result || ''); + self.$('#result-id').val(result[0].id || ''); + self.$('#result-index').val(parseInt(index_id, 10).toString()); + }); + }); + }, + //Method for changing the attached file + _onChangeFile: function (ev) { + const element = $(ev.target); + var files = element[0].files[0] + const reader = new FileReader(); + reader.onloadend = () => { + element.attr('data-file', reader.result.split(',')[1]) + }; + reader.readAsDataURL(files); + }, + //Method for updating the rest result + testResultUpdate : function(ev){ + var self = this; + var result_id = parseInt(this.$('#result-id').val()) + var normal_range = this.$('#normal-range').val() + var index_id = parseInt(this.$('#result-index').val()) + var result_unit = this.$('#result-unit').val() + var result_result = this.$('#result-result').val() + var result_attachment = this.$('#result-attachment').data('file') + var data = { + 'result': result_result, + 'normal': normal_range, + 'uom_id': result_unit, + 'attachment': result_attachment + } + rpc.query({ + model: 'lab.test.result', + method: 'write', + args: [[result_id], data] + }).then(function (result){ + self.load_all_test_data(index_id) + self.$('#modal-close').click() + }) + }, + //Method for getting the lab test data + _loadTestData : function(){ + var self = this; + self.state = 'lab.test.line' + rpc.query({ + model: 'lab.test.line', + method: 'search_read', + kwargs: {domain: [['state', '=', 'draft']]}, + }).then(function (result){ + self.$('#form-view').attr('hidden', 'true'); + self.testData = result; + var count = 0; + self.$('#main-view').html( + ` + +
    SequencePatientDoctorTypeDate
    `) + result.reverse().forEach(element => { + self.$('#record_list').append(` + + ${element.name || ''} + ${element.patient_id[1] || ''} + ${element.doctor_id[1] || ''} + ${element.patient_type.toUpperCase() || ''} + ${element.date || ''} + + `) + count += 1; + }) + self.$('#create-button').html('') + }) + }, + //Method for getting the data of a particular lab test + _fetchTestData : function(ev){ + var self = this; + var record_id = parseInt($(ev.target).data('index')) + var record = self.testData[record_id]; + rpc.query({ + model: 'lab.test.line', + method: 'action_get_patient_data', + args: [record.id], + }).then(function (result){ + self.load_data(result) + self.$('#action-table').html(` + + +
    SlNameLeadPrice
    + `) + self.$('#action-button').html(` + `) + self.$('#test-list').html('') + var count = 0; + result['test_data'].forEach(element =>{ + self.$('#test-list').append(` + + ${count+1 || ''} + ${element.name || ''} + ${element.patient_lead || ''} + ${element.price || ''} + + + `) + count += 1 + }) + }) + }, + //Method for getting result published lab tests + _loadPublished: function (){ + var self = this; + self.state = 'lab.test.result' + self.$('#create-button').html('') + rpc.query({ + model: 'lab.test.result', + method: 'print_test_results', + kwargs: {domain: []}, + }).then(function (result){ + self.$('#form-view').attr('hidden', 'true'); + var count = 1; + self.$('#main-view').html( + ` + + + + +
    SequencePatientTestNormalResultUnitAttachment
    `) + result.reverse().forEach(element => { + self.$('#record_list').append(` + + ${element.parent_id || ''} + ${element.patient_id[1] || ''} + ${element.test_id || ''} + ${element.normal || ''} + ${element.result || ''} + ${element.unit || ''} + + ${element.attachment_id ? ` +
    + ` : ''} + + + `) + count += 1; + }) + }) + }, + //Method for fetching all vaccinations + _vaccination: function(){ + var self = this + self.state = 'hospital.vaccination' + self.$('#create-button').html('') + rpc.query({ + model: 'hospital.vaccination', + method: 'fetch_vaccination_data', + kwargs: {domain: []}, + }).then(function (result){ + self.listVaccine=result; + self.$('#form-view').attr('hidden', 'true'); + self.testData = result; + var count = 0; + self.$('#main-view').html( + ` + +
    SequencePatientVaccinePriceCertificate
    `) + result.forEach(element => { + self.$('#record_list').append(` + + ${element.name || ''} + ${element.patient_id[1] || ''} + ${element.vaccine_product_id || ''} + ${element.vaccine_price || ''} + + ${element.attachment_id ? ` +
    + ` : ''} + + `) + count += 1; + }) + }) + }, + currentData: [], + //Method for displaying the patient data + load_data: function(result){ + var self = this; + self.currentData = result + self.$('#form-view').removeAttr('hidden') + self.$('.LabReport').removeAttr('hidden') + self.$('#patient-name').text(`${result.name} - (${result.unique})`); + self.$('#patient-age').text(result.dob || ''); + self.$('#patient-blood').text(result.blood_group || ''); + self.$('#patient-gender').text(result.gender || ''); + self.$('#patient-status').text(result.status || ''); + self.$('#patient-phone').text(result.phone || ''); + self.$('#patient-email').text(result.email || ''); + self.$('#patient-doctor').text(result.doctor || ''); + self.$('#patient-slot').text(result.slot || ''); + self.$('#patient-patient_type').text(result.patient_type || ''); + self.$('#patient-image').attr('src', 'data:image/png;base64, '+result.image_1920); + }, + //Method for creating lab test + confirmLabTest: function(ev){ + var self = this; + rpc.query({ + model: 'lab.test.line', + method: 'create_lab_tests', + args: [self.currentData], + }).then(function (result){ + self._allLabTest() + }) + }, + //Method for removing a lab test + removeTest: function(ev){ + var self = this + self.currentData['test_data'].splice($(ev.target).data('index'),1); + $(ev.target).parent().parent().css({ 'color': 'red'}) + }, + }) + core.action_registry.add('lab_dashboard_tags', LabDashBoard); + return 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..9561fef90 --- /dev/null +++ b/base_hospital_management/static/src/js/pharmacy_dashboard.js @@ -0,0 +1,625 @@ +odoo.define('base_hospital_management.pharmacy_dashboard_action', function (require) { + "use strict"; + var AbstractAction = require('web.AbstractAction'); + var core = require('web.core'); + var QWeb = core.qweb; + var rpc = require('web.rpc'); + var ajax = require('web.ajax'); + var medicine=0; + var sl_prod=0; + var prod_uom=0; + var next_line_prod=0; + var currency=0; + var quantity=0; + var amount=0; + var sub_t=0; + var pro_list=[]; + var uom_lst= []; + var tax_lst= []; + var invoice_id=0; + var tax_amount=0; + var tax=0; + localStorage.setItem('next_line_prod',next_line_prod); + var PharmacyDashboard = AbstractAction.extend({ + template: 'PharmacyDashboard', + init: function (parent, context) { + this._super(parent, context); + }, + //Events + events: { + 'click .search_btn': 'fetch_patient_data', + 'click .home': 'create_order', + 'click .sale_orders': 'fetch_sale_orders', + 'click .medicine_search': 'fetch_medicine_data', + 'click .vaccine_search': 'fetch_vaccine_data', + 'click .clear_btn': 'clear_data', + 'click .row-click': 'click_op_row', + 'keydown .amount': 'next_line', + 'change .select_prod': '_onChange_prod_price', + 'change .qty': '_onChange_prod_qty', + 'click .home': 'fetch_product', + 'click .qty': 'fetch_uom', + 'change .home': 'fetch_tax', + 'click .create_sale_order': 'create_sale_order', + 'click .saleorder': 'createSaleOrder', + 'click .print_sale_order': 'PrintSaleOrder', + 'click .delete_row': 'DeleteRow', + 'click .order_row': 'viewOrder' + }, + start: function () { + var self = this; + this.set("title", 'Dashboard'); + return this._super().then(function () { + self.create_order(); + self.fetch_product(); + self.fetch_uom(); + self.fetch_tax(); + }) + }, + //Method for viewing doctor's schedule + viewOrder : function(ev) { + var self = this; + rpc.query({ + model: 'sale.order', + method: 'search_read', + args: [[['partner_id.patient_seq','not in', ['New', 'Employee', 'User']]], ['name', 'create_date', 'partner_id', 'amount_total', + 'state']], + }).then(function (result){ + var orderList = result; + var record_id = parseInt(self.$(ev.target).data('index')) + var record = orderList[record_id]; + self.do_action({ + name: "Sale Order", + type: 'ir.actions.act_window', + res_model: 'sale.order', + res_id: record.id, + view_mode: 'form', + view_type: 'form', + views: [[false, 'form']], + target: 'new', + }) + }) + }, + //Fetch patient details + fetch_patient_data: function () { + var self = this; + rpc.query({ + model: 'res.partner', + method: 'action_get_patient_data', + args: [self.$('#patient_search').val()], + }).then(function (result) { + self.$('#patient-name').text(`${result.name} - (${result.unique})`); + self.$('#patient-title').text(result.name || ''); + self.$('#patient-code').text(result.unique || ''); + self.$('#patient-age').text(result.dob || ''); + self.$('#patient-blood').text(result.blood_group || ''); + self.$('#patient-blood').text(result.blood_group || ''); + self.$('#patient-gender').text(result.gender || ''); + self.$('#patient-image').attr('src', 'data:image/png;base64, ' + result.image_1920); + if (result.name == 'Patient Not Found') { + self.$('#content_div').html(''); + self.$('#medical_list').html(''); + self.$('#hist_head').html('') + self.$('#patient-image').attr('src', 'https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_1280.png'); + } + else { + self.$('#medical_list').html(''); + self.$('#hist_head').html('') + self.$('#content_div').html('') + self.$('#medical_list').html(` +
    +

    OP History

    + + + + + + + + + +
    OP CodeDateDoctor
    +
    `); + result.history.forEach(res => { + $('#history').append(`${res[0]}${res[1]}${res[2]}`) + }) + } + }) + }, + //Method fo creating a sale order for medicine + create_order: function () { + rpc.query({ + model: 'hospital.pharmacy', + method: 'company_currency', + }).then(function (result){ + self.$('#symbol'+ currency).text(result || ''); + self. $('#symbol').text(result || ''); + }) + self.$('#content_div').html(`

    Sale Order

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

    Medicine List


    +
    + + + + + + + + + + + + + + + + + + +
    NameQuantityUnit Of MeasurePriceSub Total(incl.Tax) +
    + + + + + + + + +
    +
    + + Grand Total : +
    + + ₹ +
    + + + +
    + + +
    + `) + self.$('.select_prod').html('') + this.product_lst.forEach(element => { + self.$('.select_prod').append(` + + `) + }) + self.$('.select_uom').html('') + if (this.uom_lst){ + this.uom_lst.forEach(element => { + self.$('.select_uom').append(` + + `) + }) + } + }, + //Method fo fetching all sale orders + fetch_sale_orders: function () { + rpc.query({ + model: 'sale.order', + method: 'search_read', + args: [[['partner_id.patient_seq','not in', ['New', 'Employee', 'User']]], ['name', 'create_date', 'partner_id', 'amount_total', + 'state']], + }).then(function (result){ + self.$('#content_div').html(``); + var count = 0; + self.$('#content_div').html(` +

    Sale Orders

    +
    + + + + + + + + +
    NumberCreation DateCustomerTotalStatus
    `); + result.forEach(res => { + self.$('#order_items').append(` + + ${res.name || ''} + ${res.create_date || ''} + ${res.partner_id[1] || ''} + ${res.amount_total || 0} + ${res.state.toUpperCase() || ''} + + `); + count += 1; + }); + }); + }, + //Add new line for entering all fields while clicking Enter. + next_line: function (ev) { + var sub_t_list=[] + if (ev.key == 'Enter') { + sl_prod=sl_prod+1; + prod_uom=prod_uom+1; + quantity=quantity+1; + amount=amount+1; + sub_t=sub_t+1; + next_line_prod=next_line_prod+1 + var row='row_'+next_line_prod + rpc.query({ + model: 'hospital.pharmacy', + method: 'company_currency', + }).then(function (result){ + self.$('#symbol'+currency).text(result || ''); + }) + self.$('#bill_table').append(` + + + + + + + + + + + + + + `); + } else { + // If sale is already created, hide the button + self.$('#saleorder').hide(); + } }) + }, + }) + core.action_registry.add('pharmacy_dashboard_tags', PharmacyDashboard); + return PharmacyDashboard; +}) 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..49edaa343 --- /dev/null +++ b/base_hospital_management/static/src/js/prescription.js @@ -0,0 +1,23 @@ +odoo.define('base_hospital_management.prescription', function (require) { + 'use strict'; + var publicWidget = require('web.public.widget'); + var rpc = require('web.rpc'); + publicWidget.registry.prescriptionWidget = publicWidget.Widget.extend({ + //Extends the publicWidget.Widget class to hide and show the button and calculate the distance between locations. + 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']); + }); + }, + }); + return 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..3309ab677 --- /dev/null +++ b/base_hospital_management/static/src/js/reception_dashboard.js @@ -0,0 +1,1174 @@ +odoo.define('base_hospital_management.reception_dashboard_action', function (require){ + "use strict"; + var AbstractAction = require('web.AbstractAction'); + var FormController = require('web.FormController'); + var core = require('web.core'); + var QWeb = core.qweb; + var _t = core._t; + var rpc = require('web.rpc'); + var ajax = require('web.ajax'); + var patient_lst = []; + var patient_id_lst = []; + var dr_lst = []; + var attending_dr_lst = []; + localStorage.setItem('patient_lst',patient_lst); + var ReceptionDashBoard = AbstractAction.extend({ + template: 'ReceptionDashboard', + init: function(parent, context) { + this._super(parent, context); + }, + //Events + events :{ + 'click .o_patient_button': 'createPatient', + 'click .patient_item': 'fetch_patient', + 'click .outpatient_item': 'fetch_outPatientItem', + 'click .inpatient_item': 'fetch_inPatientItem', + 'click .booking_item': 'fetch_bookingItem', + 'click .o_appointment_button': 'fetchAppointmentData', + 'click .patient_create': 'createPatient', + 'click .inpatient_create': 'createInPatient', + 'click .outpatient_create': 'createOutPatient', + 'click .allocation_create': 'createAllocation', + 'click #view_patient_profile': 'patientBackendView', + 'change #patient-img': 'fileCreate', + 'click .save_patient': 'savePatient', + 'change #op_date': 'fetchAllocation', + 'click .save_out_patient': 'save_out_patient_data', + 'click .save_in_patient': 'save_in_patient_data', + 'click .saveandnew_patient': 'save_and_new', + 'click .saveandnew_out_patient': 'o_save_and_new', + 'click .saveandnew_in_patient': 'i_save_and_new', + 'click .o_patient_history_button': 'fetchPatientsData', + 'click .o_out_patient_history_button': 'fetchOutPatient', + 'click .ward_create': 'createWard', + 'click .o_room_ward_button': 'fetchRoomWard', + 'click .o_outpatient_button': 'createOutPatient', + 'click .o_inpatient_button': 'createInPatient', + 'click .o_in_patient_history_button': 'fetchInPatient', + 'click .o_room_button': 'fetchRoom', + 'click .o_ward_button': 'fetchWard', + 'click .o_doctor_allocation': 'createAllocation', + 'click .search': '_Search', + 'click .select_type': 'patient_card', + 'change #sl_patient': 'fetch_patient_id', + 'change #o_patient-phone': 'fetch_patient_phone', + }, + start: function() { + var self = this; + this.set("title", 'Dashboard'); + self.createPatient(); + }, + //Patient search function + _Search: function(){ + var self=this + const btns = self.$('.r_active') + const apptmnt_btns = self.$('.r_active1') + const roomward_btns = self.$('.r_active2') + if(btns[0].id === 'patient'){ + var search_key = self.$('#patient_search').val() + var self = this; + rpc.query({ + model: 'res.partner', + method: 'search_read', + kwargs: {domain: ['|','|', + ['date_of_birth', 'ilike', search_key], + ['patient_seq', 'ilike', search_key], + ['name', 'ilike', search_key]]}, + }).then(function (result){ + self.patientData = result; + self.$('#record_list').html(''); + var count = 0; + result.forEach(element => { + self.$('#record_list').append(` + + ${element.patient_seq || ''} + ${element.name || ''} + ${element.gender.toUpperCase() || ''} + ${element.date_of_birth || ''} + + `) + count += 1; + }) + }) + } + else if(btns[0].id === 'booking'){ + var search_key = self.$('#booking_search').val() + var self = this; + rpc.query({ + model: 'patient.booking', + method: 'search_read', + kwargs: {domain: ['|','|','|','|', + ['booking_reference', 'ilike', search_key], + ['patient_id.name', 'ilike', search_key], + ['patient_id.patient_seq', 'ilike', search_key], + ['state', 'ilike', search_key], + ['booking_date', 'ilike', search_key]]}, + }).then(function (result){ + self.bookingData = result; + self.$('#record_list').html(''); + var count = 0; + result.forEach(element => { + self.$('#record_list').append(` + ${element.booking_reference|| '' } + ${element.patient_id[1]|| ''} + ${element.doctor_id[1] || ''} + ${element.booking_date || ''} + ${element.state.toUpperCase() || ''} + `) + count += 1; + }) + }) + } + if (apptmnt_btns.length != 0){ + if(apptmnt_btns[0].id === 'outpatient'){ + var search_key = $('#outpatient_search').val() + var self = this; + rpc.query({ + model: 'hospital.outpatient', + method: 'search_read', + kwargs: {domain: ['|','|','|','|', + ['slot', 'ilike', search_key], + ['patient_id.patient_seq', 'ilike', search_key], + ['patient_id.name', 'ilike', search_key], + ['op_date', 'ilike', search_key], + ['state', 'ilike', search_key]]}, + }).then(function (result){ + self.OutPatientData = result; + self.$('#record_list').html(''); + var count = 0; + result.forEach(element => { + self.$('#record_list').append(` + + ${element.display_name || ''} + ${element.slot === 0.0 ? '' : self.floatToTime(element.slot) || ''} + ${element.patient_id[1] || ''} + ${element.doctor_id[1] || ''} + ${element.op_date || ''} + ${element.state.toUpperCase()|| ''} + + `) + count += 1; + }) + }) + } + else if(apptmnt_btns[0].id === 'inpatient'){ + var search_key = $('#inpatient_search').val() + var self = this; + rpc.query({ + model: 'hospital.inpatient', + method: 'fetch_inpatient', + args: [false, search_key] + }).then(function (result){ + self.InPatientData = result; + self.$('#record_list').html(''); + var count = 0; + result.forEach(element => { + self.$('#record_list').append(` + + ${element.name|| + ''} + ${element.patient_id[1] || ''} + ${element.ward_id[1] || ''} + ${element.bed_id[1] || ''} + ${element.attending_doctor_id[1] || ''} + ${element.hosp_date || ''} + ${element.discharge_date || ''} + ${element.state.toUpperCase() || ''} + + `) + count += 1; + }) + }) + } + else if(apptmnt_btns[0].id === 'doctor_slot'){ + var self = this; + var search_key = $('#allocation_search').val() + rpc.query({ + model: 'doctor.allocation', + method: 'search_read', + kwargs: {domain: ['|','|','|', + ['doctor_id.name', 'ilike', search_key], + ['department_id', 'ilike', search_key], + ['date', 'ilike', search_key], + ['op_number', 'ilike', search_key]]}, + }).then(function (result){ + self.$('#record_list').html(''); + self.doctorData = result; + var count = 0; + result.forEach(element => { + self.$('#record_list').append(` + ${element.doctor_id[1] || ''} + ${element.department_id[1] || ''} + ${element.date || ''} + ${element.op_number || ''}`) + count += 1; + }) + }); + } + } + if (roomward_btns.length != 0){ + if(roomward_btns[0].id === 'room'){ + var search_key = $('#room_search').val() + var self = this; + rpc.query({ + model: 'patient.room', + method: 'search_read', + kwargs: {domain: ['|','|', + ['name', 'ilike', search_key], + ['bed_type', 'ilike', search_key], + ['rent', 'ilike', search_key],]} + }).then(function (result){ + self.roomData = result; + self.$('#record_list').html(''); + var count = 0; + result.forEach(element => { + self.$('#record_list').append(` + ${element + .display_name || ''} + ${element.bed_type.toUpperCase() || ''} + ${element.rent || ''}`) + count += 1; + }) + }); + } + else if(roomward_btns[0].id === 'ward'){ + var search_key = $('#ward_search').val() + var self = this; + rpc.query({ + model: 'hospital.ward', + method: 'search_read', + kwargs: {domain: ['|','|', + ['ward_no', 'ilike', search_key], + ['building_id', 'ilike', search_key], + ['floor_no', 'ilike', search_key]]} + }).then(function (result){ + self.wardData = result; + self.$('#record_list').html(''); + var count = 0; + result.forEach(element => { + self.$('#record_list').append(` + ${element.display_name || ''} + ${element.building_id[1] || ''} + ${element.floor_no || ''}`) + count += 1; + }) + }); + }} + }, + fetchAllocation: function(){ + //Method for fetching dictor allocation for chosen date + var self = this; + var selectedDate = self.$('#op_date').val(); + rpc.query({ + model: 'doctor.allocation', + method: 'search_read', + args: [[ + ['slot_remaining', '>', 0], + ['date', '=', selectedDate], + ['state', '=', 'confirm'] + ]], + }).then(function (result) { + self.dr_lst=result + self.$('.select_dr').html('') + self.dr_lst.forEach(element => { + self.$('.select_dr').append(` + + `) + }) + }) + }, + floatToTime: function(floatValue) { + //Method to convert float value to time + var hour = Math.floor(floatValue); + var minute = Math.round((floatValue - hour) * 60); + var formattedTime = hour + ":" + (minute < 10 ? "0" : "") + minute; + return formattedTime; + }, + patientData: [], + //Method for fetching all patients + fetchPatientsData: function(){ + var self = this; + rpc.query({ + model: 'res.partner', + method: 'fetch_patient_data', + args: [[]] + }).then(function (result){ + self.patientData = result; + if (self.$('.r_active')[0]){$('.r_active')[0].classList.remove('r_active');} + self.$('.o_patient_button')[0].classList.add('r_active'); + self.$('.r_AppntBtn').html(''); + if(self.$('#welcome')){self.$('#welcome').remove();} + self.$('#controls').html(``) + self.$('#content').html(`
    + + + + + + + + + + +
    Patient IDPatient NameGenderDate of Birth
    +
    `); + self.$('#record_list').html(''); + var count = 0; + result.forEach(element => { + var gender = (element.gender ? element.gender : ''); + var date_of_birth = (element.date_of_birth ? element.date_of_birth : ''); + self.$('#record_list').append(` + + ${element + .patient_seq || ''} + ${element.name || ''} + ${gender.toUpperCase() + || ''} + ${date_of_birth || ''} + + `) + count += 1; + }) + }) + }, + //Returns backend view of a patient + patientBackendView: function(ev){ + var p_id = self.$(ev.target).data('patient_id') + var self = this; + rpc.query({ + model: 'res.partner', + method: 'fetch_view_id', + args: [null] + }).then(function (result){ + self.do_action({ + name: _t("Create Patient"), + type: 'ir.actions.act_window', + res_model: 'res.partner', + res_id: p_id, + view_mode: 'form', + view_type: 'form', + views: [[result, 'form']], + target: 'new', + }) + }); + }, + OutPatientData: [], + //Method for fetching all outpatients + fetchOutPatient: function(){ + var self = this; + self.$('#view_secondary').html(''); + if (self.$('.r_active1')[0]){self.$('.r_active1')[0].classList.remove('r_active1');} + $('.o_outpatient_button')[0].classList.add('r_active1'); + rpc.query({ + model: 'hospital.outpatient', + method: 'search_read', + }).then(function (result){ + self.OutPatientData = result; + self.$('#controls').html(` + `) + self.$('#content').html('') + self.$('#content').html(`
    + + + + + + + + + + + + +
    OP referenceSlotPatient IDDoctor NameOP DateState
    +
    `); + self.$('#record_list').html(''); + var count = 0; + result.forEach(element => { + var op_date = (element.op_date ? element.op_date : ''); + self.$('#record_list').append(` + + ${element + .display_name || ''} + ${element.slot === 0.0 ? '' : self.floatToTime(element.slot) || ''} + ${element.patient_id[1] || ''} + ${element.doctor_id[1] || ''} + ${op_date || ''} + ${element.state.toUpperCase() || ''} + + `) + count += 1; + }) + }) + }, + //Creates new outpatient + createOutPatient : function(){ + var self = this; + const date = new Date(); + var formattedCurrentDate = date.toISOString().split('T')[0]; + rpc.query({ + model: 'res.partner', + method: 'fetch_patient_data', + args: [[]] + }).then(function (result){ + self.patient_lst=result + self.$('.select_patient').html('') + self.patient_lst.forEach(element => { + self.$('.select_patient').append(` + + + `) + }) + }), + rpc.query({ + model : 'doctor.allocation', + method :'search_read', + args:[[['slot_remaining', '>', 0], + ['date','=',formattedCurrentDate], + ['state', '=', 'confirm']]], + }).then(function (result){ + self.dr_lst=result + self.$('.select_dr').html('') + self.dr_lst.forEach(element => { + self.$('.select_dr').append(` + + `) + }) + }), + self.$('#controls').html(``); + self.$('#content').html(` +

    Create Outpatient

    +
    +
    + + + + + + + + + + + + +
    +
    + + + + + + + + + + + + + + + + + +
    +
    `) + self.$('#content').html(`
    + + + + + + + + + + + +
    IP referencePatient IDWardBedAttending DoctorHospitalized DateDischarge DateState
    +
    `); + self.$('#record_list').html(''); + var count = 0; + result.forEach(element => { + var hosp_date = (element.hosp_date ? element.hosp_date : ''); + var discharge_date = (element.discharge_date ? element.discharge_date : ''); + self.$('#record_list').append(` + + ${element.name || ''} + ${element.patient_id[1] || ''} + ${element.ward_id[1] || ''} + ${element.bed_id[1] || ''} + ${element.attending_doctor_id[1] || ''} + ${element.hosp_date || ''} + ${discharge_date || ''} + ${element.state.toUpperCase() || ''} + + `); + count += 1; + }) + }) + }, + //Method for creating inpatient + createInPatient : function(){ + var self = this + rpc.query({ + model : 'res.partner', + method :'fetch_patient_data', + args:[[]], + }).then(function (result){ + self.patient_id_lst=result + self.$('.select_patient_id').html('') + self.patient_id_lst.forEach(element => { + $('.select_patient_id').append(` + + `) + }) + }), + rpc.query({ + model : 'hr.employee', + method :'search_read', + args:[[['job_id.name', '=', 'Doctor']]], + }).then(function (result){ + self.attending_dr_lst=result + self.$('.attending_doctor_id').html('') + self.attending_dr_lst.forEach(element => { + self.$('.attending_doctor_id').append(` + + `) + }) + }), + self.$('#controls').html(``); + self.$('#content').html(` + +

    Create Inpatient

    + + + +
    Patient ID* :
    Reason of Admission : +
    Admission Type :
    Attending Doctor* + :
    +
    + + +
    + + `) + }, + //Method for fetching inpatient data + fetch_in_patient_data: function(){ + var self = this; + var patient_id = self.$('#sl_patient_id').val(); + var reason_of_admission = self.$('#reason_of_admission').val(); + var admission_type = self.$('#admission_type').val(); + var attending_doctor_id = self.$('#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 + save_in_patient_data: function(){ + var self = this; + var data = this.fetch_in_patient_data() + if (data != false || data != null || data != undefined){ + rpc.query({ + model: 'hospital.inpatient', + method: 'create_new_in_patient', + args: [null,data] + }).then(function (){ + self.fetchInPatient(); + }); + }}, + //Method for creating new inpatient and clearing all fields + i_save_and_new: function() { + var self = this; + var data = this.fetch_in_patient_data() + if (data !== false){ + rpc.query({ + model: 'hospital.inpatient', + method: 'create_new_in_patient', + args: [null, data] + }).then(function (){ + self.createInPatient(); + }); + }}, + //Method for fetching an inpatient + fetch_inPatientItem : function(ev){ + var self = this; + var record_id = parseInt($(ev.target).data('index')) + var record = self.InPatientData[record_id]; + this.do_action({ + name: _t("Inpatient"), + type: 'ir.actions.act_window', + res_model: 'hospital.inpatient', + res_id: record.id, + view_mode: 'form', + view_type: 'form', + views: [[false, 'form']], + target: 'new', + }) + }, + //Method for fetching an outpatient + fetch_outPatientItem : function(ev){ + var self = this; + var record_id = parseInt($(ev.target).data('index')) + var record = self.OutPatientData[record_id]; + this.do_action({ + name: _t("Outpatient"), + type: 'ir.actions.act_window', + res_model: 'hospital.outpatient', + res_id: record.id, + view_mode: 'form', + view_type: 'form', + views: [[false, 'form']], + target: 'new', + }) + }, + //Method for getting a patient + fetch_patient: function(ev) { + var self = this; + var record_id = parseInt($(ev.target).data('index')) + var record = self.patientData[record_id]; + self.$('#view_secondary').html(`
    + + + + + + + + + + + + + + + + + + +

    Phone :

    Email:

    Date of Birth :

    Blood Group :

    Doctor :

    Gender :

    Marital Status :

    +

    + `) + self.$('#patient-name').text(record.display_name || ''); + self.$('#patient-dob').text(record.date_of_birth || ''); + self.$('#patient-blood').text(`${record.blood_group} ${record.rh_type}`); + self.$('#patient-gender').text(record.gender || ''); + self.$('#patient-status').text(record.marital_status || ''); + self.$('#patient-phone').text(record.phone || ''); + self.$('#patient-email').text(record.email || ''); + self.$('#view_patient_profile').attr('data-patient_id', record.id); + self.$('#patient-image').attr('src', 'data:image/png;base64, '+record.image_1920); + }, + //Method for creating new file + fileCreate: function(ev){ + var self = this; + const element = $(ev.target) + var file = element[0].files[0]; + const reader = new FileReader(); + reader.onloadend = () => { + element.attr('data-file', reader.result.split(',')[1]) + }; + reader.readAsDataURL(file); + }, + //Method which returns the details of a patient + fetch_patient_data: function(){ + var self = this; + var patient_name = self.$('#patient-name').val(); + var patient_img = self.$('#patient-img').data('file'); + var patient_phone = self.$('#patient-phone').val(); + var patient_mail = self.$('#patient-mail').val(); + var patient_dob = self.$('#patient-dob').val(); + var patient_bloodgroup = self.$('#patient-bloodgroup').val(); + var patient_m_status = self.$('#patient-m-status').val() || ''; + var patient_rhtype = self.$("input[name='rhtype']:checked").val(); + var patient_gender = self.$("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 for creating a patient + savePatient: function(){ + var self = this; + var data = this.fetch_patient_data() + rpc.query({ + model: 'res.partner', + method: 'create', + args: [data] + }).then(function (){ + self.fetchPatientsData() + }) + }, + //Method for creating a patient and clearing all fields + save_and_new: function(){ + var self = this; + var data = this.fetch_patient_data() + rpc.query({ + model: 'res.partner', + method: 'create', + args: [data] + }).then(function (){ + self.createPatient() + }) + }, + //Method for creating patient + createPatient: function(){ + self.$('#buttons').html(`
    + +
    + `); + self.$('#controls').html(''); + self.$('#content').html(`
    +

    Create Patient

    +
    + + + + + + + + + +
    Name :
    Photo :
    Phone :
    Email:
    Date of Birth :
    Blood Group : + + + +
    Gender : +
    + + + + + + +
    +
    Marital Status :
    +
    +
    + + +
    + +
    `) + }, + //Method for creating ward + createWard: function(){ + this.do_action({ + name: _t("Create Ward"), + type: 'ir.actions.act_window', + res_model: 'hospital.ward', + view_mode: 'form', + view_type: 'form', + views: [[false, 'form']], + target: 'new', + }) + }, + //Method for fetching appointment data + fetchAppointmentData: function(){ + var self = this; + self.$('#view_secondary').html(''); + if (self.$('.r_active')[0]){$('.r_active')[0].classList.remove('r_active');} + self.$('.o_appointment_button')[0].classList.add('r_active'); + self.$('#content').html(''); + self.$('#controls').html(''); + if(self.$('#welcome')){self.$('#welcome').remove();} + self.$('.r_AppntBtn').html(` +
    +
    +
    + +

    Outpatient

    +
    +
    +
    +
    + +

    Inpatient

    +
    +
    +
    + `); + this.createOutPatient(); + }, + //Method for getting booking item + fetch_bookingItem : function(ev){ + var self = this; + var record_id = parseInt($(ev.target).data('index')) + var record = self.bookingData[record_id]; + this.do_action({ + name: _t("Patient Booking"), + type: 'ir.actions.act_window', + res_model: 'patient.booking', + res_id: record.id, + view_mode: 'form', + view_type: 'form', + views: [[false, 'form']], + target: 'new', + }) + }, + //Method for getting room or ward details + fetchRoomWard: function(){ + var self = this; + self.$('#view_secondary').html(''); + if (self.$('.r_active')[0]){$('.r_active')[0].classList.remove('r_active');} + self.$('.o_room_ward_button')[0].classList.add('r_active'); + self.$('#content').html(''); + self.$('#controls').html(''); + if(self.$('#welcome')){$('#welcome').remove();} + self.$('.r_AppntBtn').html(` +
    +
    + +

    Rooms

    +
    +
    +
    +
    + +

    Wards

    +
    +
    `); + }, + roomData :[], + //Method for getting room details + fetchRoom: function(){ + var self = this; + if (self.$('.r_active2')[0]){$('.r_active2')[0].classList.remove('r_active2');} + self.$('.o_room_button')[0].classList.add('r_active2'); + rpc.query({ + model: 'patient.room', + method: 'search_read', + }).then(function (result){ + self.roomData = result; + self.$('#controls').html(` +
    +
    + +
    +
    `) + self.$('#content').html(`
    + + + + + + + + + + +
    Room No.Bed TypeRentStatus
    +
    `); + self.$('#record_list').html(''); + var count = 0; + result.forEach(element => { + self.$('#record_list').append(` + + ${element + .display_name || ''} + ${element.bed_type.toUpperCase() || ''} + ${element.rent || ''} + ${element.state.toUpperCase() || ''}`) + count += 1; + }) + }); + }, + wardData :[], + //Method for getting ward details + fetchWard: function(){ + var self = this; + if (self.$('.r_active2')[0]){self.$('.r_active2')[0].classList.remove('r_active2');} + self.$('.o_ward_button')[0].classList.add('r_active2'); + rpc.query({ + model: 'hospital.ward', + method: 'search_read', + }).then(function (result){ + self.wardData = result; + self.$('#controls').html(` +
    +
    + +
    +
    `) + self.$('#content').html(`
    + + + + + + + + + +
    Ward NameBlock NameFloor No.No. of Beds Available
    +
    `); + self.$('#record_list').html(''); + var count = 0; + result.forEach(element => { + self.$('#record_list').append(` + ${element.display_name || ''} + ${element.building_id[1] || ''} + ${element.floor_no || ''} + ${element.bed_count || ''}`) + count += 1; + }) + }); + }, + }) + core.action_registry.add('reception_dashboard_tags', ReceptionDashBoard); + return 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..028444ca5 --- /dev/null +++ b/base_hospital_management/static/src/js/website_page.js @@ -0,0 +1,61 @@ +odoo.define('base_hospital_management.website_page', function (require) { + 'use strict'; + var publicWidget = require('web.public.widget'); + var ajax = require('web.ajax'); + publicWidget.registry.doctorWidget = publicWidget.Widget.extend({ + //Extends the publicWidget.Widget class to hide and show the button and calculate the distance between locations. + selector: '#booking_form', + events: { + 'change #booking_date': 'changeBookingDate', + 'change #doctor-department': 'updateDoctorOptions', + }, + start: function () { + this.changeBookingDate(); + }, + changeBookingDate: function () { + //Update the doctor selection field + var self = this; + var selectedDate = this.$('#booking_date').val(); + ajax.jsonRpc('/patient_booking/get_doctors', 'call', { + selected_date: selectedDate, department:false + }).then(function (data) { + self.$('#doctor-name').empty(); + // Add the fetched doctors to the dropdown + _.each(data['doctors'], function (doctor) { + self.$('#doctor-name').append($('