You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
482 lines
22 KiB
482 lines
22 KiB
# -*- coding: utf-8 -*-
|
|
################################################################################
|
|
#
|
|
# Cybrosys Technologies Pvt. Ltd.
|
|
#
|
|
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
|
|
# 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 <http://www.gnu.org/licenses/>.
|
|
#
|
|
################################################################################
|
|
import datetime
|
|
from odoo import api, fields, models
|
|
|
|
|
|
class HospitalInpatient(models.Model):
|
|
"""Class holding inpatient details"""
|
|
_name = 'hospital.inpatient'
|
|
_description = 'Inpatient'
|
|
_inherit = ['mail.thread.cc', 'mail.activity.mixin']
|
|
|
|
patient_id = fields.Many2one('res.partner', string="Patient",
|
|
domain=[('patient_seq', 'not in',
|
|
['New', 'Employee', 'User'])],
|
|
required=True, help='Choose the patient')
|
|
name = fields.Char(string="Sequence Number", store=True,
|
|
copy=False, readonly=True, index=True,
|
|
help='Sequence number of inpatient for uniquely '
|
|
'identifying',
|
|
default=lambda self: 'New')
|
|
reason = fields.Text(
|
|
string="Reason For Admission",
|
|
help="Current reason for hospitalization of the patient")
|
|
bed_id = fields.Many2one('hospital.bed', string='Bed',
|
|
help='Choose the bed')
|
|
room_id = fields.Many2one('patient.room', string='Room',
|
|
help='Choose the room to which patient admitted'
|
|
' to')
|
|
building_id = fields.Many2one(
|
|
'hospital.building', related='room_id.building_id',
|
|
string="Block", help='Name of the block')
|
|
room_building_id = fields.Many2one(
|
|
'hospital.building', related='room_id.building_id',
|
|
string="Room Building",
|
|
help='Name of the building to which room belongs to')
|
|
ward_id = fields.Many2one('hospital.ward',
|
|
related='bed_id.ward_id',
|
|
string='Ward',
|
|
help='Ward to which the bed belongs to')
|
|
type_admission = fields.Selection([('emergency',
|
|
'Emergency Admission'),
|
|
('routine', 'Routine Admission')],
|
|
string="Admission Type",
|
|
help='The type of admission',
|
|
required=True)
|
|
attending_doctor_id = fields.Many2one('hr.employee',
|
|
string="Attending Doctor",
|
|
required=True,
|
|
help='Name of attending doctor',
|
|
domain=[
|
|
('job_id.name', '=', 'Doctor')])
|
|
operating_doctor_id = fields.Many2one('hr.employee',
|
|
string="Operating Doctor",
|
|
help='Name of operating doctor',
|
|
domain=[
|
|
('job_id.name', '=', 'Doctor')])
|
|
hosp_date = fields.Date(string="Admission Date",
|
|
help='Date of hospitalisation',
|
|
default=fields.date.today())
|
|
discharge_date = fields.Date(string="Discharge Date",
|
|
help='Date of discharge', copy=False)
|
|
condition = fields.Text(
|
|
string="Condition Before Hospitalization",
|
|
help="The condition of the patient before he/she is admitted to"
|
|
" the hospital")
|
|
nursing_plan_ids = fields.One2many('nursing.plan',
|
|
'admission_id',
|
|
string='Nursing Plan',
|
|
help='Nursing plan of the inpatient')
|
|
active = fields.Boolean(string='Active', default=True,
|
|
help='True for active inpatients')
|
|
doctor_round_ids = fields.One2many('doctor.round',
|
|
'admission_id',
|
|
string='Doctor Rounds',
|
|
help='Doctor rounds of the patient')
|
|
discharge_plan = fields.Text(string="Discharge Plan",
|
|
help='Discharge plan of the inpatient')
|
|
notes = fields.Text(string="Notes", help='Notes regarding the inpatient')
|
|
bed_rent = fields.Monetary(string='Rent Per Day', related='bed_id.bed_rent',
|
|
help='Rent for the bed')
|
|
currency_id = fields.Many2one('res.currency', string='Currency',
|
|
help='Currency in which rent is calculating',
|
|
default=lambda self: self.env.user.company_id
|
|
.currency_id.id)
|
|
state = fields.Selection([('draft', 'Draft'),
|
|
('reserve', 'Reserved'),
|
|
('admit', 'Admitted'), ('invoice', 'Invoiced'),
|
|
('dis', 'Discharge')],
|
|
string='State', readonly=True,
|
|
help='State of inpatient',
|
|
default="draft")
|
|
bed_rent_amount = fields.Monetary(string="Total Bed Rent",
|
|
help='Total rent '
|
|
'for stayed '
|
|
'days',
|
|
compute='_compute_bed_rent_amount',
|
|
copy=False)
|
|
invoice_id = fields.Many2one('account.move', string='Invoice',
|
|
help='Invoice id of the inpatient', copy=False)
|
|
admit_days = fields.Integer(string='Days',
|
|
help='Number of days the inpatient admitted',
|
|
compute='_compute_admit_days',
|
|
copy=False)
|
|
bed_type = fields.Selection([('gatch', 'Gatch Bed'),
|
|
('electric', 'Electric'),
|
|
('stretcher', 'Stretcher'),
|
|
('low', 'Low Bed'),
|
|
('air', 'Low Air Loss'),
|
|
('circo', 'Circo Electric'),
|
|
('clinitron', 'Clinitron'),
|
|
], string="Bed Type",
|
|
help='Indicates the type of bed')
|
|
is_ward = fields.Selection([('ward', 'Ward'), ('room', 'Room')],
|
|
string='Room/Ward',
|
|
help='Choose where the patient is admitted to')
|
|
payment_ids = fields.One2many('inpatient.payment',
|
|
'inpatient_id',
|
|
string='Payment Details',
|
|
help='Payment details of the patient')
|
|
is_invoice = fields.Boolean(string='Is Invoice',
|
|
help='View invoice button will be visible if '
|
|
'this field is true')
|
|
prescription_ids = fields.One2many('prescription.line',
|
|
'inpatient_id',
|
|
string='Prescription',
|
|
help='Medical prescriptions of patient')
|
|
enable_outpatient = fields.Boolean(string='Prescription History',
|
|
help='If checked, the prescription '
|
|
'history of the patient will be '
|
|
'added')
|
|
lab_test_ids = fields.One2many('patient.lab.test',
|
|
'inpatient_id',
|
|
string='Lab Test',
|
|
help='Lab tests of the inpatient')
|
|
test_count = fields.Integer(string='Test Created',
|
|
help='Number of tests of the inpatient',
|
|
compute='_compute_test_count')
|
|
test_ids = fields.One2many('patient.lab.test',
|
|
'inpatient_id', string='Test Line',
|
|
help='Details of the lab test')
|
|
surgery_ids = fields.One2many('inpatient.surgery',
|
|
'inpatient_id',
|
|
string='Surgery/Operation',
|
|
help='Surgery details of the patient')
|
|
room_rent = fields.Monetary(string='Rent per day', help='Rent for the room',
|
|
related='room_id.rent')
|
|
room_rent_amount = fields.Monetary(string="Total Room Rent",
|
|
compute='_compute_room_rent_amount',
|
|
help='Total rent for the room',
|
|
copy=False)
|
|
|
|
@api.model
|
|
def create(self, vals):
|
|
"""Sequence number generation"""
|
|
if vals.get('name', 'New') == 'New':
|
|
vals['name'] = self.env['ir.sequence'].next_by_code(
|
|
'hospital.inpatient') or 'New'
|
|
return super().create(vals)
|
|
|
|
@api.depends('test_ids')
|
|
def _compute_test_count(self):
|
|
"""Method for computing test count"""
|
|
self.test_count = self.env['lab.test.line'].sudo().search_count(
|
|
[('id', 'in', self.test_ids.ids)])
|
|
|
|
def _compute_admit_days(self):
|
|
"""Method for computing admit days"""
|
|
if self.hosp_date:
|
|
if self.discharge_date:
|
|
self.admit_days = (self.discharge_date - self.hosp_date +
|
|
datetime.timedelta(days=1)).days
|
|
else:
|
|
self.admit_days = (fields.date.today() - self.hosp_date +
|
|
datetime.timedelta(days=1)).days
|
|
|
|
@api.depends('hosp_date', 'discharge_date',
|
|
'admit_days', 'room_id')
|
|
def _compute_room_rent_amount(self):
|
|
"""Method for computing room rent amount"""
|
|
if self.hosp_date:
|
|
if self.discharge_date:
|
|
self.admit_days = (self.discharge_date - self.hosp_date +
|
|
datetime.timedelta(days=1)).days
|
|
self.room_rent_amount = self.room_id.rent * self.admit_days
|
|
else:
|
|
self.admit_days = (fields.date.today() - self.hosp_date +
|
|
datetime.timedelta(days=1)).days
|
|
self.room_rent_amount = self.room_id.rent * self.admit_days
|
|
self.room_rent_amount = self.room_id.rent * self.admit_days
|
|
|
|
@api.depends('hosp_date', 'discharge_date', 'room_rent_amount',
|
|
'admit_days')
|
|
def _compute_bed_rent_amount(self):
|
|
"""Method for computing bed rent amount"""
|
|
if self.hosp_date:
|
|
if self.discharge_date:
|
|
self.admit_days = (self.discharge_date - self.hosp_date +
|
|
datetime.timedelta(days=1)).days
|
|
self.bed_rent_amount = self.bed_id.bed_rent * self.admit_days
|
|
else:
|
|
self.admit_days = (fields.date.today() - self.hosp_date +
|
|
datetime.timedelta(days=1)).days
|
|
self.bed_rent_amount = self.bed_id.bed_rent * self.admit_days
|
|
else:
|
|
self.bed_rent_amount = self.bed_id.bed_rent
|
|
|
|
@api.onchange('enable_outpatient')
|
|
def _onchange_enable_outpatient(self):
|
|
"""Method for adding prescription lines of patient"""
|
|
self.prescription_ids = False
|
|
if self.enable_outpatient:
|
|
outpatient_id = self.env['hospital.outpatient'].sudo().search(
|
|
[('patient_id', '=', self.patient_id.id)])
|
|
self.sudo().write({
|
|
'prescription_ids': [(0, 0, {
|
|
'medicine_id': rec.medicine_id.id,
|
|
'quantity': rec.quantity,
|
|
'no_intakes': rec.no_intakes,
|
|
'note': rec.note,
|
|
'time': rec.time,
|
|
}) for rec in outpatient_id.prescription_ids]
|
|
})
|
|
|
|
@api.onchange('bed_type')
|
|
def _onchange_bed_type(self):
|
|
"""Method for filtering beds according to the bed type"""
|
|
return {'domain': {
|
|
'bed_id': [
|
|
('bed_type', '=', self.bed_type),
|
|
('state', '=', 'avail')
|
|
], 'room_id': [
|
|
('bed_type', '=', self.bed_type),
|
|
('state', '=', 'avail')
|
|
]}}
|
|
|
|
def action_view_invoice(self):
|
|
"""Method for viewing Invoice"""
|
|
self.ensure_one()
|
|
return {
|
|
'name': 'inpatient Invoice',
|
|
'view_mode': 'tree,form',
|
|
'res_model': 'account.move',
|
|
'type': 'ir.actions.act_window',
|
|
'domain': [('ref', '=', self.name)],
|
|
'context': "{'create':False}"
|
|
}
|
|
|
|
def action_view_tests(self):
|
|
"""Returns all lab tests"""
|
|
return {
|
|
'name': 'Lab Tests',
|
|
'res_model': 'patient.lab.test',
|
|
'view_mode': 'tree,form',
|
|
'type': 'ir.actions.act_window',
|
|
'domain': [('inpatient_id', '=', self.id)]
|
|
}
|
|
|
|
def action_create_lab_test(self):
|
|
"""Function for creating lab test"""
|
|
return {
|
|
'name': 'Create Lab Test',
|
|
'res_model': 'lab.test.line',
|
|
'view_mode': 'form',
|
|
'views': [[False, 'form']],
|
|
'target': 'current',
|
|
'type': 'ir.actions.act_window',
|
|
'context': {
|
|
'default_patient_id': self.patient_id.id,
|
|
'default_doctor_id': self.attending_doctor_id.id,
|
|
'default_patient_type': 'inpatient',
|
|
'default_ip_id': self.id
|
|
}
|
|
}
|
|
|
|
def action_view_test(self):
|
|
"""View test details"""
|
|
return {
|
|
'name': 'Created Tests',
|
|
'res_model': 'lab.test.line',
|
|
'view_mode': 'tree,form',
|
|
'target': 'current',
|
|
'type': 'ir.actions.act_window',
|
|
'domain': [
|
|
('patient_type', '=', 'inpatient'),
|
|
('ip_id', '=', self.id)
|
|
]
|
|
}
|
|
|
|
def action_reserve(self):
|
|
"""Method for inpatient reservation"""
|
|
if self.bed_id:
|
|
self.bed_id.state = 'not'
|
|
if self.room_id:
|
|
self.room_id.state = 'reserve'
|
|
self.sudo().write({
|
|
'state': "reserve"
|
|
})
|
|
|
|
def action_admit(self):
|
|
"""Method for patient admission"""
|
|
if self.bed_id:
|
|
self.bed_id.state = 'not'
|
|
if self.room_id:
|
|
self.room_id.state = 'not'
|
|
self.sudo().write({
|
|
'state': "admit"
|
|
})
|
|
|
|
def action_discharge(self):
|
|
"""Method for patient discharge"""
|
|
if self.bed_id:
|
|
self.bed_id.state = 'avail'
|
|
if self.room_id:
|
|
self.room_id.state = 'avail'
|
|
self.sudo().write({
|
|
'state': "dis"
|
|
})
|
|
self.active = False
|
|
|
|
def action_invoice(self):
|
|
"""Method for creating invoice"""
|
|
self.is_invoice = True
|
|
self.state = 'invoice'
|
|
inv_line_list = []
|
|
invoice = self.env['account.move.line'].sudo().search(
|
|
[('move_id.partner_id', '=', self.patient_id.id),
|
|
('move_id.state', '=', 'draft'),
|
|
('group_tax_id', '=', False),
|
|
('date_maturity', '=', False),
|
|
('move_id.move_type', '=', 'out_invoice')])
|
|
for rec in self:
|
|
if rec.bed_rent_amount:
|
|
inv_line_list.append((0, 0, {'name': 'Room/Bed Rent Amount',
|
|
'price_unit': rec.bed_rent_amount,
|
|
'quantity': rec.admit_days,
|
|
}))
|
|
elif rec.room_rent_amount:
|
|
inv_line_list.append((0, 0, {'name': 'Room/Bed Rent Amount',
|
|
'price_unit': rec.room_rent_amount,
|
|
'quantity': rec.admit_days,
|
|
}))
|
|
for line in rec.payment_ids:
|
|
inv_line_list.append((0, 0, {'name': line.name,
|
|
'price_unit': line.subtotal,
|
|
'quantity': 1,
|
|
'tax_ids': line.tax_ids
|
|
}))
|
|
for line in self.test_ids:
|
|
if not line.invoice_id:
|
|
inv_line_list.append((0, 0, {
|
|
'name': line.test_id.name,
|
|
'price_unit': line.total_price,
|
|
'quantity': 1
|
|
}))
|
|
for line in self.prescription_ids:
|
|
inv_line_list.append((0, 0, {
|
|
'name': line.medicine_id.name,
|
|
'price_unit': line.medicine_id.list_price,
|
|
'quantity': line.quantity
|
|
}))
|
|
if invoice:
|
|
for line in invoice.read(
|
|
['name', 'price_unit', 'quantity']):
|
|
inv_line_list.append((0, 0, {'name': line['name'],
|
|
'price_unit': line[
|
|
'price_unit'],
|
|
'quantity': line['quantity']}))
|
|
move = self.env['account.move'].sudo().create({
|
|
'move_type': 'out_invoice',
|
|
'date': fields.Date.today(),
|
|
'ref': self.name,
|
|
'invoice_date': fields.Date.today(),
|
|
'partner_id': self.patient_id.id,
|
|
'line_ids': inv_line_list
|
|
})
|
|
self.invoice_id = move.id
|
|
for rec in invoice:
|
|
rec.move_id.button_cancel()
|
|
return {
|
|
'name': 'Invoice',
|
|
'res_model': 'account.move',
|
|
'view_mode': 'form',
|
|
'view_Id': self.env.ref('account.view_move_form').id,
|
|
'context': "{'move_type':'out_invoice'}",
|
|
'type': 'ir.actions.act_window',
|
|
'res_id': move.id
|
|
}
|
|
|
|
def create_new_in_patient(self, domain):
|
|
"""Create in-patient from receptionist dashboard"""
|
|
if domain:
|
|
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
|
|
|