├── reports ├── __init__.py ├── sale_report_inherit.xml ├── patient_report.py ├── appointment_report.xml └── report.xml ├── controllers ├── __init__.py └── controllers.py ├── picture ├── 1.png ├── 2.png ├── 3.png ├── 4.png ├── 5.png ├── 6.png ├── 7.png ├── 8.png ├── 9.png ├── 10.png ├── 11.png ├── 12.png ├── 13.png ├── 14.png ├── 15.png ├── 16.png └── 17.png ├── wizard ├── __init__.py ├── appointment_report_view.xml ├── create_appointment.py ├── appointment_report.py └── create_appointment_view.xml ├── static └── description │ └── icon.png ├── __init__.py ├── models ├── saleOrder.py ├── __init__.py ├── equipmentSale.py ├── medicaltest.py ├── department.py ├── patient.py ├── doctor.py └── appointment.py ├── .github └── workflows │ └── greetings.yml ├── data └── appointment_seq.xml ├── views ├── sales_order.xml ├── department_view.xml ├── equipment_sale.xml ├── medicaltest_view.xml ├── website_patient_view.xml ├── website_apntment_form.xml ├── website_patient_form.xml ├── doctor_view.xml ├── patient_view.xml └── appointment_view.xml ├── .gitignore ├── security ├── security.xml └── ir.model.access.csv ├── __manifest__.py └── README.md /reports/__init__.py: -------------------------------------------------------------------------------- 1 | from . import patient_report -------------------------------------------------------------------------------- /controllers/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from . import controllers -------------------------------------------------------------------------------- /picture/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KamrulSh/km_hospital/HEAD/picture/1.png -------------------------------------------------------------------------------- /picture/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KamrulSh/km_hospital/HEAD/picture/2.png -------------------------------------------------------------------------------- /picture/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KamrulSh/km_hospital/HEAD/picture/3.png -------------------------------------------------------------------------------- /picture/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KamrulSh/km_hospital/HEAD/picture/4.png -------------------------------------------------------------------------------- /picture/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KamrulSh/km_hospital/HEAD/picture/5.png -------------------------------------------------------------------------------- /picture/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KamrulSh/km_hospital/HEAD/picture/6.png -------------------------------------------------------------------------------- /picture/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KamrulSh/km_hospital/HEAD/picture/7.png -------------------------------------------------------------------------------- /picture/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KamrulSh/km_hospital/HEAD/picture/8.png -------------------------------------------------------------------------------- /picture/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KamrulSh/km_hospital/HEAD/picture/9.png -------------------------------------------------------------------------------- /picture/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KamrulSh/km_hospital/HEAD/picture/10.png -------------------------------------------------------------------------------- /picture/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KamrulSh/km_hospital/HEAD/picture/11.png -------------------------------------------------------------------------------- /picture/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KamrulSh/km_hospital/HEAD/picture/12.png -------------------------------------------------------------------------------- /picture/13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KamrulSh/km_hospital/HEAD/picture/13.png -------------------------------------------------------------------------------- /picture/14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KamrulSh/km_hospital/HEAD/picture/14.png -------------------------------------------------------------------------------- /picture/15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KamrulSh/km_hospital/HEAD/picture/15.png -------------------------------------------------------------------------------- /picture/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KamrulSh/km_hospital/HEAD/picture/16.png -------------------------------------------------------------------------------- /picture/17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KamrulSh/km_hospital/HEAD/picture/17.png -------------------------------------------------------------------------------- /wizard/__init__.py: -------------------------------------------------------------------------------- 1 | from . import appointment_report 2 | from . import create_appointment 3 | -------------------------------------------------------------------------------- /static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KamrulSh/km_hospital/HEAD/static/description/icon.png -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from . import controllers 4 | from . import models 5 | from . import reports 6 | from . import wizard -------------------------------------------------------------------------------- /models/saleOrder.py: -------------------------------------------------------------------------------- 1 | from odoo import models, fields, api 2 | 3 | 4 | class EquipmentSaleOrder(models.Model): 5 | _inherit = 'sale.order' 6 | _description = 'Equipment Sales Order' -------------------------------------------------------------------------------- /models/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from . import patient 4 | from . import doctor 5 | from . import department 6 | from . import appointment 7 | from . import medicaltest 8 | from . import equipmentSale 9 | from . import saleOrder 10 | -------------------------------------------------------------------------------- /models/equipmentSale.py: -------------------------------------------------------------------------------- 1 | from odoo import models, fields 2 | 3 | 4 | class CourseSale(models.Model): 5 | _inherit = 'product.template' 6 | _description = 'Hospital equipment Add' 7 | 8 | name = fields.Char(string="Hospital equipment") 9 | price = fields.Float(string="Price") 10 | image = fields.Binary(string='Photo', attachment=True) -------------------------------------------------------------------------------- /models/medicaltest.py: -------------------------------------------------------------------------------- 1 | from odoo import models, fields, api 2 | 3 | class HospitalMedicalTest(models.Model): 4 | _name = 'kmhospital.medicaltest' 5 | _description = 'Medical Test' 6 | 7 | name = fields.Char(string="Medical test name", required=True) 8 | price = fields.Integer(string="Price", required=True) 9 | medical_test_ids = fields.Many2many(string="Medical tests") -------------------------------------------------------------------------------- /models/department.py: -------------------------------------------------------------------------------- 1 | from odoo import models, fields, api 2 | 3 | # class HospitalDepartment(models.Model): 4 | # _name = 'kmhospital.department' 5 | # _description = 'Hospital Department' 6 | 7 | # name = fields.Char(string='Department Name', required=True) 8 | # description = fields.Char(string='Department details') 9 | 10 | class HospitalDepartment(models.Model): 11 | _inherit = "hr.department" -------------------------------------------------------------------------------- /.github/workflows/greetings.yml: -------------------------------------------------------------------------------- 1 | name: Greetings 2 | 3 | on: [pull_request, issues] 4 | 5 | jobs: 6 | greeting: 7 | runs-on: ubuntu-latest 8 | permissions: 9 | issues: write 10 | pull-requests: write 11 | steps: 12 | - uses: actions/first-interaction@v1 13 | with: 14 | repo-token: ${{ secrets.GITHUB_TOKEN }} 15 | issue-message: 'Message that will be displayed on users first issue' 16 | pr-message: 'Message that will be displayed on users first pull request' 17 | -------------------------------------------------------------------------------- /data/appointment_seq.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Appointment Sequence 7 | kmhospital.appointment 8 | AS 9 | 5 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /views/sales_order.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | sale.list 5 | sale.order 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /reports/sale_report_inherit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 14 | 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # sphinx build directories 2 | _build/ 3 | 4 | # dotfiles 5 | .* 6 | !.gitignore 7 | !.github 8 | !.mailmap 9 | # compiled python files 10 | *.py[co] 11 | __pycache__/ 12 | # setup.py egg_info 13 | *.egg-info 14 | # emacs backup files 15 | *~ 16 | # hg stuff 17 | *.orig 18 | status 19 | # odoo filestore 20 | odoo/filestore 21 | # maintenance migration scripts 22 | odoo/addons/base/maintenance 23 | 24 | # generated for windows installer? 25 | install/win32/*.bat 26 | install/win32/meta.py 27 | 28 | # needed only when building for win32 29 | setup/win32/static/less/ 30 | setup/win32/static/wkhtmltopdf/ 31 | setup/win32/static/postgresql*.exe 32 | 33 | # various virtualenv 34 | /bin/ 35 | /build/ 36 | /dist/ 37 | /include/ 38 | /lib/ 39 | /man/ 40 | /share/ 41 | /src/ 42 | -------------------------------------------------------------------------------- /views/department_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Department 6 | ir.actions.act_window 7 | hr.department 8 | tree,form,kanban 9 | 10 |

11 | Create your first Employee 12 |

13 |
14 |
15 | 16 | 17 | 18 | 19 | 24 | 25 | 26 | 27 |
-------------------------------------------------------------------------------- /security/security.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hospital Management 5 | Category For Hospital 6 | 45 7 | 8 | 9 | 10 | Lab man 11 | 12 | 13 | 14 | 15 | Admin 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /reports/patient_report.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from odoo import api, models 4 | 5 | 6 | class PatientReport(models.AbstractModel): 7 | _name = 'report.km_hospital.report_patient_card' 8 | _description = 'Patient Report' 9 | 10 | @api.model 11 | def _get_report_values(self, docids, data=None): 12 | 13 | docs = self.env['kmhospital.patient'].browse(docids) 14 | appointments = self.env['kmhospital.appointment'].search([("name", "=", docids)]) 15 | appointment_list = [] 16 | for appointment in appointments: 17 | values = { 18 | "checkup_date": appointment.checkup_date, 19 | "status": appointment.status, 20 | "appointed_doctor_id": appointment.appointed_doctor_id.name, 21 | } 22 | appointment_list.append(values) 23 | return { 24 | 'doc_model': 'kmhospital.patient', 25 | 'data': data, 26 | 'docs': docs, 27 | 'appointment_list': appointment_list, 28 | } 29 | -------------------------------------------------------------------------------- /views/equipment_sale.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | product.list 5 | product.template 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | product.form 16 | product.template 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 |
28 |
29 |
-------------------------------------------------------------------------------- /wizard/appointment_report_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | kmhospital.appointment.report.wizard.form 6 | kmhospital.appointment.report.wizard 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 |
15 |
18 |
19 |
20 |
21 | 22 | 23 | Print Appointment 24 | ir.actions.act_window 25 | kmhospital.appointment.report.wizard 26 | form 27 | 28 | new 29 | 30 | 31 |
32 | -------------------------------------------------------------------------------- /wizard/create_appointment.py: -------------------------------------------------------------------------------- 1 | from odoo.exceptions import ValidationError 2 | from odoo import models, fields, api, _ 3 | 4 | 5 | class HospitalAppointmentWizard(models.TransientModel): 6 | _name = 'kmhospital.appointment.wizard' 7 | _description = 'Create Appointment' 8 | 9 | name = fields.Char(string='Appointment Reference', required=True, copy=False, readonly=True, 10 | default=lambda self: _('New')) 11 | patient_id = fields.Many2one("kmhospital.patient", string='Patient Name', required=True) 12 | gender = fields.Selection([ 13 | ('male', 'Male'), 14 | ('female', 'Female') 15 | ], related='patient_id.gender') 16 | phone = fields.Char(string='Phone', related='patient_id.phone') 17 | email = fields.Char(string='Email', related='patient_id.email') 18 | age = fields.Integer(string='Age', related='patient_id.age') 19 | description = fields.Text() 20 | appointment_date = fields.Datetime(string='Appointment Date', default=fields.datetime.now()) 21 | checkup_date = fields.Datetime(string='Checkup Date', required=True) 22 | appointed_doctor_id = fields.Many2one("kmhospital.doctor", string="Doctor name", required=True) 23 | 24 | @api.constrains('appointment_date', 'checkup_date') 25 | def _check_date_validation(self): 26 | for record in self: 27 | if record.checkup_date < record.appointment_date: 28 | raise ValidationError('Checkup date should not be previous date.') 29 | -------------------------------------------------------------------------------- /__manifest__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | { 3 | 'name': "KM Hospital", 4 | 'sequence': 1, 5 | 'summary': """ 6 | A hospital management module.""", 7 | 8 | 'description': """ 9 | A hospital management module for creating patient, doctor, 10 | department, medical test, and appointments. 11 | """, 12 | 13 | 'author': "Kamrul & Niazi", 14 | 'website': "http://www.yourcompany.com", 15 | 'category': 'Services', 16 | 'version': '0.1', 17 | 'license': 'LGPL-3', 18 | # any module necessary for this one to work correctly 19 | 'depends': ['base', 'hr', 'website', 'website_sale', 'mail'], 20 | 21 | # always loaded 22 | 'data': [ 23 | 'security/security.xml', 24 | 'security/ir.model.access.csv', 25 | 'data/appointment_seq.xml', 26 | 'wizard/create_appointment_view.xml', 27 | 'wizard/appointment_report_view.xml', 28 | 'views/patient_view.xml', 29 | 'views/doctor_view.xml', 30 | 'views/department_view.xml', 31 | 'views/appointment_view.xml', 32 | 'views/medicaltest_view.xml', 33 | 'views/website_patient_form.xml', 34 | 'views/website_patient_view.xml', 35 | 'views/website_apntment_form.xml', 36 | 'views/equipment_sale.xml', 37 | 'views/sales_order.xml', 38 | 'reports/report.xml', 39 | 'reports/sale_report_inherit.xml', 40 | 'reports/appointment_report.xml', 41 | ], 42 | 'installable': True, 43 | 'application': True, 44 | 'auto_install': False, 45 | } 46 | -------------------------------------------------------------------------------- /wizard/appointment_report.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from odoo.exceptions import ValidationError 4 | from odoo import api, fields, models, _ 5 | 6 | 7 | class AppointmentReportWizard(models.TransientModel): 8 | _name = "kmhospital.appointment.report.wizard" 9 | _description = "Print Appointment Wizard" 10 | 11 | date_from = fields.Datetime(string='Date from', required=False) 12 | date_to = fields.Datetime(string='Date to', required=False) 13 | patient_id = fields.Many2one('kmhospital.patient', string="Patient", required=True) 14 | 15 | def action_print_report(self): 16 | patient_id = self.patient_id 17 | domain = [] 18 | if patient_id: 19 | domain += [('patient_id', '=', patient_id.id)] 20 | date_from = self.date_from 21 | if date_from: 22 | domain += [('checkup_date', '>=', date_from)] 23 | date_to = self.date_to 24 | if date_to: 25 | domain += [('checkup_date', '<=', date_to)] 26 | # print("\n\nTest................\n", domain) 27 | 28 | appointments = self.env['kmhospital.appointment'].search_read(domain) 29 | 30 | data = { 31 | 'form_data': self.read()[0], 32 | 'appointments': appointments 33 | } 34 | return self.env.ref('km_hospital.action_report_appointment_card').report_action(self, data=data) 35 | 36 | @api.constrains('date_from', 'date_to') 37 | def _check_date_validation(self): 38 | for record in self: 39 | if record.date_from > record.date_to: 40 | raise ValidationError("Date from must be previous than date to.") 41 | -------------------------------------------------------------------------------- /wizard/create_appointment_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | kmhospital.appointment.wizard.form 5 | kmhospital.appointment.wizard 6 | 7 |
8 |
9 |

10 | 11 |

12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 |
30 |
31 | 32 | 33 | Create Appointments 34 | ir.actions.act_window 35 | kmhospital.appointment.wizard 36 | form 37 | 38 | new 39 | 40 | 41 |
-------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # km_hospital 2 | 3 | Created an hospital management module where there are 5 menus for Patients, Doctors, Departments, Appointments, Medical test. 4 | Each menu have different views (Tree, Form, Search). 5 | 6 | ## 0. Patients model & view: 7 | 8 | Here all the patients information will show in tree view and there is an option for creating new Patient information.
9 | ![Patients1](./picture/1.png) 10 | 11 | Shows all the patients information on the specific row.
12 | ![Departments3](./picture/2.png) 13 | 14 | **One2many**: One Patients have many appointments.
15 | ![Patients2](./picture/3.png) 16 | 17 | ## 1. Doctors model & view: 18 | 19 | Here all the Doctors information will show and there is an option for creating new Doctor information.
20 | 21 | ![Doctors1](./picture/4.png) 22 | ![Doctors2](./picture/5.png) 23 | ![Doctors3](./picture/7.png) 24 | 25 | Advanced map view is implemented for showing doctor's location. 26 | ![Doctors4](./picture/6.png) 27 | 28 | ## 2. Department model & view: 29 | 30 | Here all the Department information will show and there is an option for creating new Department.
31 | 32 | ![Department1](./picture/8.png) 33 | 34 | ## 3. Appointments model & view: 35 | 36 | Here all the Appointments information will show and there is an option for creating new Appointments.
37 | 38 | ![Appointments1](./picture/9.png) 39 | ![Appointments2](./picture/10.png) 40 | ![Appointments3](./picture/11.png) 41 | Appointments list view: 42 | ![Appointments4](./picture/12.png) 43 | Appointments kanban view: 44 | ![Appointments5](./picture/13.png) 45 | Appointments calender view: 46 | ![Appointments6](./picture/14.png) 47 | Appointments pivot view: 48 | ![Appointments7](./picture/15.png) 49 | Appointments gantt view: 50 | ![Appointments8](./picture/16.png) 51 | Appointments graph view: 52 | ![Appointments9](./picture/17.png) 53 | -------------------------------------------------------------------------------- /controllers/controllers.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from odoo import http 3 | from odoo.http import request 4 | 5 | class KmHospital(http.Controller): 6 | 7 | @http.route('/patient_webform', type='http', auth='user', website=True) 8 | def patient_webform(self, **kw): 9 | return http.request.render('km_hospital.create_patient', {}) 10 | 11 | @http.route('/create/webpatient', type="http", auth="user", website=True) 12 | def create_webpatient(self, **kw): 13 | # print("\nData Received.....", kw) 14 | request.env['kmhospital.patient'].sudo().create(kw) 15 | return request.render("km_hospital.patient_thanks", {}) 16 | 17 | # route for show all the patient information 18 | @http.route('/patient_view', type='http', auth='public', website=True) 19 | def view_patient_web(self, **kw): 20 | patients = request.env['kmhospital.patient'].sudo().search([]) 21 | # print("\nData Received.....", patients) 22 | return http.request.render('km_hospital.view_patient', { 23 | 'patients': patients 24 | }) 25 | 26 | # route for appointment website 27 | @http.route('/appointment_webform', type='http', auth='user', website=True) 28 | def appointment_webform(self, **kw): 29 | patient_rec = request.env['kmhospital.patient'].sudo().search([]) 30 | doctor_rec = request.env['kmhospital.doctor'].sudo().search([]) 31 | return http.request.render('km_hospital.create_appointment', { 32 | 'patient_rec': patient_rec, 33 | 'doctor_rec': doctor_rec 34 | }) 35 | 36 | @http.route('/create/webappointment', type="http", auth="user", website=True) 37 | def create_webappointment(self, **kw): 38 | print("\nData Received.....", kw) 39 | request.env['kmhospital.appointment'].sudo().create(kw) 40 | return request.render("km_hospital.appointment_thanks", {}) -------------------------------------------------------------------------------- /security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | access_kmhospital_appointment,kmhospital_appointment,model_kmhospital_appointment,km_hospital.group_hospital_admin,1,1,1,1 3 | access_kmhospital_doctor,kmhospital_doctor,model_kmhospital_doctor,km_hospital.group_hospital_admin,1,1,1,1 4 | access_kmhospital_patient,kmhospital_patient,model_kmhospital_patient,km_hospital.group_hospital_admin,1,1,1,1 5 | access_kmhospital_medicaltest,kmhospital_medicaltest,model_kmhospital_medicaltest,km_hospital.group_hospital_admin,1,0,0,0 6 | access_kmhospital_appointment_prescription_medicine,kmhospital_appointment_prescription_medicine,model_kmhospital_appointment_prescription_medicine,km_hospital.group_hospital_admin,1,1,1,1 7 | access_appointment_report_wizard,kmhospital_appointment_report_wizard,model_kmhospital_appointment_report_wizard,km_hospital.group_hospital_admin,1,1,1,1 8 | access_kmhospital_appointment_wizard,kmhospital_appointment_wizard,model_kmhospital_appointment_wizard,km_hospital.group_hospital_admin,1,1,1,1 9 | 10 | access_kmhospital_appointment1,kmhospital_appointment,model_kmhospital_appointment,km_hospital.group_hospital_labman,1,0,0,0 11 | access_kmhospital_doctor1,kmhospital_doctor,model_kmhospital_doctor,km_hospital.group_hospital_labman,1,0,0,0 12 | access_kmhospital_patient1,kmhospital_patient,model_kmhospital_patient,km_hospital.group_hospital_labman,1,0,0,0 13 | access_kmhospital_medicaltest1,kmhospital_medicaltest,model_kmhospital_medicaltest,km_hospital.group_hospital_labman,1,1,1,1 14 | access_kmhospital_appointment_prescription_medicine1,kmhospital_appointment_prescription_medicine,model_kmhospital_appointment_prescription_medicine,km_hospital.group_hospital_labman,1,0,0,0 15 | access_appointment_report_wizard1,kmhospital_appointment_report_wizard,model_kmhospital_appointment_report_wizard,km_hospital.group_hospital_labman,1,0,0,0 16 | access_kmhospital_appointment_wizard1,kmhospital_appointment_wizard,model_kmhospital_appointment_wizard,km_hospital.group_hospital_labman,1,0,0,0 17 | -------------------------------------------------------------------------------- /views/medicaltest_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | kmhospital.medicaltest.tree 6 | kmhospital.medicaltest 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | kmhospital.medicaltest.form 16 | kmhospital.medicaltest 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 |
27 |
28 | 29 | 30 | kmhospital.medicaltest.search 31 | kmhospital.medicaltest 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | Medicaltest 41 | ir.actions.act_window 42 | kmhospital.medicaltest 43 | tree,form,search 44 | 45 |

46 | Create medical test List 47 |

48 |
49 |
50 | 51 | 55 | 56 |
-------------------------------------------------------------------------------- /views/website_patient_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Patients List 6 | /patient_view 7 | 8 | 56 9 | 10 | 45 | 46 | -------------------------------------------------------------------------------- /models/patient.py: -------------------------------------------------------------------------------- 1 | from odoo import models, fields, api 2 | from odoo.exceptions import ValidationError 3 | import re 4 | 5 | 6 | class HospitalPatient(models.Model): 7 | _name = 'kmhospital.patient' 8 | _description = 'Hospital Patient' 9 | _order = 'id desc' 10 | _inherit = ['mail.thread', 'mail.activity.mixin'] 11 | 12 | name = fields.Char(string='Patient Name', required=True, tracking=True) 13 | address = fields.Char(string='Address', tracking=True) 14 | gender = fields.Selection([ 15 | ('male', 'Male'), 16 | ('female', 'Female') 17 | ], default="male", tracking=True) 18 | phone = fields.Char(string='Phone', required=True, tracking=True) 19 | age = fields.Integer(string='Age', required=True, tracking=True) 20 | email = fields.Char(string='Email', tracking=True) 21 | patient_appointment_ids = fields.One2many('kmhospital.appointment', 'patient_id', string="Appointment Count", 22 | readonly=True) 23 | total_appointments = fields.Integer(string='No. of appointments', compute='_compute_appointments') 24 | 25 | # check if the patient is already exists based on the patient name and phone number 26 | @api.constrains('name', 'phone') 27 | def _check_patient_exists(self): 28 | for record in self: 29 | patient = self.env['kmhospital.patient'].search( 30 | [('name', '=', record.name), ('phone', '=', record.phone), ('id', '!=', record.id)]) 31 | if patient: 32 | raise ValidationError(f'Patient {record.name} already exists') 33 | 34 | @api.constrains('email') 35 | def _check_email(self): 36 | for record in self: 37 | valid_email = re.match('^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$', 38 | record.email) 39 | if valid_email is None: 40 | raise ValidationError('Please provide a valid Email') 41 | 42 | @api.constrains('age') 43 | def _check_patient_age(self): 44 | for record in self: 45 | if record.age <= 0: 46 | raise ValidationError('Age must be greater than 0') 47 | 48 | # compute appointments of individual patient 49 | def _compute_appointments(self): 50 | for record in self: 51 | record.total_appointments = self.env['kmhospital.appointment'].search_count( 52 | [('patient_id', '=', record.id)]) 53 | 54 | def action_url(self): 55 | return { 56 | "type": "ir.actions.act_url", 57 | "url": "https://github.com/KamrulSh/km_hospital", 58 | "target": "new", 59 | } 60 | -------------------------------------------------------------------------------- /models/doctor.py: -------------------------------------------------------------------------------- 1 | from odoo import models, fields, api 2 | from odoo.exceptions import ValidationError 3 | import re 4 | 5 | 6 | class HospitalDoctor(models.Model): 7 | _name = 'kmhospital.doctor' 8 | _description = 'Hospital Doctor' 9 | _inherit = ['mail.thread', 'mail.activity.mixin'] 10 | 11 | name = fields.Char(string='Doctor Name', required=True, tracking=True) 12 | college = fields.Char(string='College', tracking=True) 13 | address = fields.Char(string='Address', tracking=True) 14 | gender = fields.Selection([ 15 | ('male', 'Male'), 16 | ('female', 'Female') 17 | ], default='male') 18 | phone = fields.Char(string='Phone', required=True, tracking=True) 19 | email = fields.Char(string='Email', required=True, tracking=True) 20 | department_id = fields.Many2one("hr.department", string='Department', required=True, tracking=True) 21 | view_appointment_ids = fields.One2many('kmhospital.appointment', 'appointed_doctor_id', string="Appointment Count", 22 | readonly=True) 23 | age = fields.Integer(string='Age', required=True, tracking=True) 24 | status = fields.Selection([ 25 | ('fulltime', 'Full time'), 26 | ('parttime', 'Part time') 27 | ], required=True, default='fulltime', tracking=True) 28 | description = fields.Text() 29 | joined_from = fields.Date(string='Joined Date', tracking=True) 30 | image = fields.Binary(string='Image', attachment=True) 31 | total_appointments = fields.Integer(string='Total appointments', compute='_compute_appointments') 32 | 33 | def action_status_halftime(self): 34 | self.status = 'parttime' 35 | 36 | def action_status_fulltime(self): 37 | self.status = 'fulltime' 38 | 39 | @api.constrains('email') 40 | def _check_email(self): 41 | for record in self: 42 | valid_email = re.match('^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$', 43 | record.email) 44 | 45 | if valid_email is None: 46 | raise ValidationError('Please provide a valid E-mail') 47 | 48 | @api.constrains('age') 49 | def _check_doctor_age(self): 50 | for record in self: 51 | if record.age <= 0: 52 | raise ValidationError('Age must be greater than 0') 53 | 54 | # same as view_appointment_ids but implemented using computed fields 55 | # compute appointments of individual doctor 56 | def _compute_appointments(self): 57 | for record in self: 58 | record.total_appointments = self.env['kmhospital.appointment'].search_count( 59 | [('appointed_doctor_id', '=', record.id)]) 60 | -------------------------------------------------------------------------------- /reports/appointment_report.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Patient Card 6 | kmhospital.appointment.report.wizard 7 | qweb-pdf 8 | km_hospital.report_appointment_card 9 | km_hospital.report_appointment_card 10 | 11 | report 12 | 13 | 14 | 80 | 81 | -------------------------------------------------------------------------------- /models/appointment.py: -------------------------------------------------------------------------------- 1 | from odoo.exceptions import ValidationError 2 | from odoo import models, fields, api, _ 3 | 4 | 5 | class HospitalAppointment(models.Model): 6 | _name = 'kmhospital.appointment' 7 | _description = 'Appointments' 8 | _order = "id desc" 9 | _inherit = ['mail.thread', 'mail.activity.mixin'] 10 | 11 | name = fields.Char(string='Appointment Reference', required=True, copy=False, readonly=True, 12 | default=lambda self: _('New')) 13 | patient_id = fields.Many2one("kmhospital.patient", string='Patient Name', required=True) 14 | gender = fields.Selection([ 15 | ('male', 'Male'), 16 | ('female', 'Female') 17 | ], related='patient_id.gender') 18 | phone = fields.Char(string='Phone', related='patient_id.phone') 19 | email = fields.Char(string='Email', related='patient_id.email') 20 | age = fields.Integer(string='Age', related='patient_id.age') 21 | description = fields.Text() 22 | note = fields.Text() 23 | status = fields.Selection([ 24 | ('draft', 'Draft'), 25 | ('confirm', 'Confirmed'), 26 | ('done', 'Done'), 27 | ('cancel', 'Canceled') 28 | ], default='draft', required=True, tracking=True) 29 | appointment_date = fields.Datetime(string='Appointment Date', default=fields.datetime.now(), tracking=True) 30 | checkup_date = fields.Datetime(string='Checkup Date', required=True, tracking=True) 31 | prescription_medicine_ids = fields.One2many("kmhospital.appointment.prescription.medicine", 32 | "appointment_medicine_id", string="Prescription Medicine") 33 | appointed_doctor_id = fields.Many2one("kmhospital.doctor", string="Doctor name", required=True) 34 | prescription_medical_test_ids = fields.Many2many("kmhospital.medicaltest", "medical_test_ids", 35 | string="Medical tests") 36 | 37 | @api.constrains('appointment_date', 'checkup_date') 38 | def _check_date_validation(self): 39 | for record in self: 40 | if record.checkup_date < record.appointment_date: 41 | raise ValidationError('Checkup date should not be previous date.') 42 | 43 | # changing the status 44 | def action_status_draft(self): 45 | self.status = 'draft' 46 | 47 | def action_status_confirm(self): 48 | self.status = 'confirm' 49 | 50 | def action_status_done(self): 51 | self.status = 'done' 52 | 53 | def action_status_cancel(self): 54 | self.status = 'cancel' 55 | 56 | @api.model 57 | def create(self, vals): 58 | if not vals['description']: 59 | vals['description'] = "Enter the description here" 60 | if vals.get('name', _('New')) == _('New'): 61 | vals['name'] = self.env['ir.sequence'].next_by_code('kmhospital.appointment') or _('New') 62 | 63 | res = super(HospitalAppointment, self).create(vals) 64 | return res 65 | 66 | @api.onchange('patient_id') 67 | def _change_appointment_note(self): 68 | if self.patient_id: 69 | if not self.note: 70 | self.note = "New appointment" 71 | else: 72 | self.note = "" 73 | 74 | 75 | # for medicine record in patient appointment 76 | class AppointmentPrescriptionMedicine(models.Model): 77 | _name = "kmhospital.appointment.prescription.medicine" 78 | _description = "Appointment Prescription Medicine" 79 | 80 | name = fields.Char(string="Medicine", required=True) 81 | quantity = fields.Integer(string="Quantity") 82 | appointment_medicine_id = fields.Many2one("kmhospital.appointment", string="Appointment medicine") 83 | -------------------------------------------------------------------------------- /views/website_apntment_form.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Create appointment 6 | /appointment_webform 7 | 8 | 55 9 | 10 | 11 | 57 | 58 | 59 | Thanks 60 | qweb 61 | /appointment-thank-you 62 | True 63 | km_hospital.appointment_thanks 64 | 65 | 66 | 67 |
68 |
69 |

Thanks!

70 |
71 |
72 |
The appointment has been Created successfully.
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | 82 |
-------------------------------------------------------------------------------- /views/website_patient_form.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Create Patient 6 | /patient_webform 7 | 8 | 55 9 | 10 | 11 | 55 | 56 | 57 | Thanks 58 | qweb 59 | /patient-thank-you 60 | True 61 | km_hospital.patient_thanks 62 | 63 | 64 | 65 |
66 |
67 |

Thanks!

68 |
69 |
70 |
The Patient has been Created successfully.
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | 80 |
-------------------------------------------------------------------------------- /views/doctor_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | kmhospital.doctor.tree 5 | kmhospital.doctor 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | kmhospital.doctor.form 25 | kmhospital.doctor 26 | 27 |
28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 |

53 | 54 |

55 |
56 | 57 |
58 |
59 |
60 |
61 | 62 | 63 | 64 |
65 |
66 |
67 |
68 | 69 | 70 | kmhospital.doctor.search 71 | kmhospital.doctor 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | Doctors 88 | ir.actions.act_window 89 | kmhospital.doctor 90 | tree,form,search,kanban 91 | 92 |

93 | Create Doctors List 94 |

95 |
96 |
97 | 98 | 99 | kmhospital.doctor.kanban 100 | kmhospital.doctor 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 |
113 |
114 |

115 | 116 |

117 |
    118 |
  • Gender : 119 | 120 |
  • 121 |
  • Phone : 122 | 123 |
  • 124 |
  • Email : 125 | 126 |
  • 127 |
  • College : 128 | 129 |
  • 130 |
  • Status : 131 | 132 |
  • 133 |
  • Department : 134 | 135 |
  • 136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 | 145 | 146 | Confirm Parttime 147 | ir.actions.server 148 | 149 | 150 | list,form 151 | code 152 | records.action_status_halftime() 153 | 154 | 155 | 156 | Confirm Fulltime 157 | ir.actions.server 158 | 159 | 160 | list,form 161 | code 162 | records.action_status_fulltime() 163 | 164 | 165 | 169 | 170 |
-------------------------------------------------------------------------------- /views/patient_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | kmhospital.patient.tree 6 | kmhospital.patient 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | kmhospital.patient.form 22 | kmhospital.patient 23 | 24 |
25 |
26 |
28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 |

45 | 46 |

47 |
48 | 49 |
50 |
51 |
52 |
53 | 54 | 55 | 56 |
57 |
58 |
59 |
60 | 61 | 62 | kmhospital.patient.search 63 | kmhospital.patient 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | kmhospital.patient.kanban 76 | kmhospital.patient 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 |
86 |
87 |

88 | 89 |

90 |
    91 |
  • Gender : 92 | 93 |
  • 94 |
  • Phone : 95 | 96 |
  • 97 |
  • Email : 98 | 99 |
  • 100 |
  • Age : 101 | 102 |
  • 103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 | 112 | 113 | All Patients 114 | ir.actions.act_window 115 | kmhospital.patient 116 | tree,form,search,kanban 117 | 118 |

119 | Create Patients List 120 |

121 |
122 |
123 | 124 | 125 | Male Patients 126 | ir.actions.act_window 127 | kmhospital.patient 128 | tree,form,search,kanban 129 | {'default_gender' : 'male', 'hide_gender' : 1} 130 | [('gender','=', 'male')] 131 | 132 |

133 | Create Patients List 134 |

135 |
136 |
137 | 138 | 139 | Female Patients 140 | ir.actions.act_window 141 | kmhospital.patient 142 | tree,form,search,kanban 143 | {'default_gender' : 'female', 'hide_gender' : 1} 144 | [('gender','=', 'female')] 145 | 146 |

147 | Create Patients List 148 |

149 |
150 |
151 | 152 | 153 | 154 | Create appointment 155 | ir.actions.server 156 | 157 | 158 | form 159 | code 160 | 161 | if record: 162 | actions_values = env.ref('km_hospital.appointment_action').sudo().read()[0] 163 | actions_values.update({'context': env.context}) 164 | action = actions_values 165 | 166 | 167 | 168 | 169 | 170 | Hospital equipment 171 | product.template 172 | tree,form 173 | 174 | 175 | 176 | 177 | Sales order 178 | sale.order 179 | tree,form 180 | 181 | 182 | 185 | 186 | 191 | 192 | 197 | 198 | 203 | 204 | 209 | 210 | 216 | 217 | 223 | 224 |
-------------------------------------------------------------------------------- /reports/report.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Patient Card 5 | kmhospital.patient 6 | qweb-pdf 7 | km_hospital.report_patient_card 8 | km_hospital.report_patient_card 9 | 10 | report 11 | 12 | 13 | 169 | 170 | -------------------------------------------------------------------------------- /views/appointment_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | kmhospital.appointment.tree 6 | kmhospital.appointment 7 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | kmhospital.appointment.form 25 | kmhospital.appointment 26 | 27 |
28 |
29 |
39 | 40 |
41 |

42 | 43 |

44 |
45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 |
87 |
88 | 89 | 90 | 91 |
92 | 93 |
94 |
95 | 96 | 97 | kmhospital.appointment.search 98 | kmhospital.appointment 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | kmhospital.appointment.kanban 120 | kmhospital.appointment 121 | 122 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 |
132 |
133 |

134 | 135 |

136 |
    137 |
  • Name : 138 | 139 |
  • 140 |
  • Phone : 141 | 142 |
  • 143 |
  • Checkup date : 144 | 145 |
  • 146 |
  • Status : 147 | 148 |
  • 149 |
  • Appointed doctor: 150 | 151 |
  • 152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 | 161 | 162 | 163 | kmhospital.appointment.calendar 164 | kmhospital.appointment 165 | 166 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | kmhospital.appointment.pivot 176 | kmhospital.appointment 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | Appointments 186 | ir.actions.act_window 187 | kmhospital.appointment 188 | tree,form,search,kanban,calendar,pivot 189 | {} 190 | 191 | 192 |

193 | Create New Appointment 194 |

195 |
196 |
197 | 198 | 199 | Kids Appointments 200 | ir.actions.act_window 201 | kmhospital.appointment 202 | tree,form,search,kanban,calendar,pivot 203 | [('age', '<=', 10)] 204 | 205 |

206 | Create New Appointment 207 |

208 |
209 |
210 | 211 | 212 | 213 | Confirm appointment 214 | ir.actions.server 215 | 216 | 217 | list,form 218 | code 219 | records.action_status_confirm() 220 | 221 | 222 | 223 | 224 | Done appointment 225 | ir.actions.server 226 | 227 | 228 | list,form 229 | code 230 | records.action_status_done() 231 | 232 | 233 | 236 | 237 | 241 | 242 | 246 | 247 | 251 | 252 | 256 | 257 |
--------------------------------------------------------------------------------