Merge pull request #24410 from ruchamahabal/service-units-in-appointment
feat: Allow selecting admission service unit in Patient Appointment for inpatients
This commit is contained in:
commit
8dc9d2f103
@ -655,6 +655,34 @@ def get_purchase_invoices(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
return frappe.db.sql(query, filters)
|
return frappe.db.sql(query, filters)
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
@frappe.validate_and_sanitize_search_inputs
|
||||||
|
def get_healthcare_service_units(doctype, txt, searchfield, start, page_len, filters):
|
||||||
|
query = """
|
||||||
|
select name
|
||||||
|
from `tabHealthcare Service Unit`
|
||||||
|
where
|
||||||
|
is_group = 0
|
||||||
|
and company = {company}
|
||||||
|
and name like {txt}""".format(
|
||||||
|
company = frappe.db.escape(filters.get('company')), txt = frappe.db.escape('%{0}%'.format(txt)))
|
||||||
|
|
||||||
|
if filters and filters.get('inpatient_record'):
|
||||||
|
from erpnext.healthcare.doctype.inpatient_medication_entry.inpatient_medication_entry import get_current_healthcare_service_unit
|
||||||
|
service_unit = get_current_healthcare_service_unit(filters.get('inpatient_record'))
|
||||||
|
|
||||||
|
# if the patient is admitted, then appointments should be allowed against the admission service unit,
|
||||||
|
# inspite of it being an Inpatient Occupancy service unit
|
||||||
|
if service_unit:
|
||||||
|
query += " and (allow_appointments = 1 or name = {service_unit})".format(service_unit = frappe.db.escape(service_unit))
|
||||||
|
else:
|
||||||
|
query += " and allow_appointments = 1"
|
||||||
|
else:
|
||||||
|
query += " and allow_appointments = 1"
|
||||||
|
|
||||||
|
return frappe.db.sql(query, filters)
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
@frappe.validate_and_sanitize_search_inputs
|
@frappe.validate_and_sanitize_search_inputs
|
||||||
def get_tax_template(doctype, txt, searchfield, start, page_len, filters):
|
def get_tax_template(doctype, txt, searchfield, start, page_len, filters):
|
||||||
|
@ -264,7 +264,7 @@ def get_filters(entry):
|
|||||||
|
|
||||||
def get_current_healthcare_service_unit(inpatient_record):
|
def get_current_healthcare_service_unit(inpatient_record):
|
||||||
ip_record = frappe.get_doc('Inpatient Record', inpatient_record)
|
ip_record = frappe.get_doc('Inpatient Record', inpatient_record)
|
||||||
if ip_record.inpatient_occupancies:
|
if ip_record.status in ['Admitted', 'Discharge Scheduled'] and ip_record.inpatient_occupancies:
|
||||||
return ip_record.inpatient_occupancies[-1].service_unit
|
return ip_record.inpatient_occupancies[-1].service_unit
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -142,11 +142,15 @@ def create_inpatient(patient):
|
|||||||
return inpatient_record
|
return inpatient_record
|
||||||
|
|
||||||
|
|
||||||
def get_healthcare_service_unit():
|
def get_healthcare_service_unit(unit_name=None):
|
||||||
|
if not unit_name:
|
||||||
service_unit = get_random("Healthcare Service Unit", filters={"inpatient_occupancy": 1})
|
service_unit = get_random("Healthcare Service Unit", filters={"inpatient_occupancy": 1})
|
||||||
|
else:
|
||||||
|
service_unit = frappe.db.exists("Healthcare Service Unit", {"healthcare_service_unit_name": unit_name})
|
||||||
|
|
||||||
if not service_unit:
|
if not service_unit:
|
||||||
service_unit = frappe.new_doc("Healthcare Service Unit")
|
service_unit = frappe.new_doc("Healthcare Service Unit")
|
||||||
service_unit.healthcare_service_unit_name = "Test Service Unit Ip Occupancy"
|
service_unit.healthcare_service_unit_name = unit_name or "Test Service Unit Ip Occupancy"
|
||||||
service_unit.company = "_Test Company"
|
service_unit.company = "_Test Company"
|
||||||
service_unit.service_unit_type = get_service_unit_type()
|
service_unit.service_unit_type = get_service_unit_type()
|
||||||
service_unit.inpatient_occupancy = 1
|
service_unit.inpatient_occupancy = 1
|
||||||
|
@ -33,10 +33,10 @@ frappe.ui.form.on('Patient Appointment', {
|
|||||||
|
|
||||||
frm.set_query('service_unit', function() {
|
frm.set_query('service_unit', function() {
|
||||||
return {
|
return {
|
||||||
|
query: 'erpnext.controllers.queries.get_healthcare_service_units',
|
||||||
filters: {
|
filters: {
|
||||||
'is_group': false,
|
company: frm.doc.company,
|
||||||
'allow_appointments': true,
|
inpatient_record: frm.doc.inpatient_record
|
||||||
'company': frm.doc.company
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -18,6 +18,7 @@ from erpnext.healthcare.utils import check_fee_validity, get_service_item_and_pr
|
|||||||
class PatientAppointment(Document):
|
class PatientAppointment(Document):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_overlaps()
|
self.validate_overlaps()
|
||||||
|
self.validate_service_unit()
|
||||||
self.set_appointment_datetime()
|
self.set_appointment_datetime()
|
||||||
self.validate_customer_created()
|
self.validate_customer_created()
|
||||||
self.set_status()
|
self.set_status()
|
||||||
@ -68,6 +69,19 @@ class PatientAppointment(Document):
|
|||||||
overlaps[0][1], overlaps[0][2], overlaps[0][3], overlaps[0][4])
|
overlaps[0][1], overlaps[0][2], overlaps[0][3], overlaps[0][4])
|
||||||
frappe.throw(overlapping_details, title=_('Appointments Overlapping'))
|
frappe.throw(overlapping_details, title=_('Appointments Overlapping'))
|
||||||
|
|
||||||
|
def validate_service_unit(self):
|
||||||
|
if self.inpatient_record and self.service_unit:
|
||||||
|
from erpnext.healthcare.doctype.inpatient_medication_entry.inpatient_medication_entry import get_current_healthcare_service_unit
|
||||||
|
|
||||||
|
is_inpatient_occupancy_unit = frappe.db.get_value('Healthcare Service Unit', self.service_unit,
|
||||||
|
'inpatient_occupancy')
|
||||||
|
service_unit = get_current_healthcare_service_unit(self.inpatient_record)
|
||||||
|
if is_inpatient_occupancy_unit and service_unit != self.service_unit:
|
||||||
|
msg = _('Patient {0} is not admitted in the service unit {1}').format(frappe.bold(self.patient), frappe.bold(self.service_unit)) + '<br>'
|
||||||
|
msg += _('Appointment for service units with Inpatient Occupancy can only be created against the unit where patient has been admitted.')
|
||||||
|
frappe.throw(msg, title=_('Invalid Healthcare Service Unit'))
|
||||||
|
|
||||||
|
|
||||||
def set_appointment_datetime(self):
|
def set_appointment_datetime(self):
|
||||||
self.appointment_datetime = "%s %s" % (self.appointment_date, self.appointment_time or "00:00:00")
|
self.appointment_datetime = "%s %s" % (self.appointment_date, self.appointment_time or "00:00:00")
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ from __future__ import unicode_literals
|
|||||||
import unittest
|
import unittest
|
||||||
import frappe
|
import frappe
|
||||||
from erpnext.healthcare.doctype.patient_appointment.patient_appointment import update_status, make_encounter
|
from erpnext.healthcare.doctype.patient_appointment.patient_appointment import update_status, make_encounter
|
||||||
from frappe.utils import nowdate, add_days
|
from frappe.utils import nowdate, add_days, now_datetime
|
||||||
from frappe.utils.make_random import get_random
|
from frappe.utils.make_random import get_random
|
||||||
from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
|
from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
|
||||||
|
|
||||||
@ -78,6 +78,59 @@ class TestPatientAppointment(unittest.TestCase):
|
|||||||
sales_invoice_name = frappe.db.get_value('Sales Invoice Item', {'reference_dn': appointment.name}, 'parent')
|
sales_invoice_name = frappe.db.get_value('Sales Invoice Item', {'reference_dn': appointment.name}, 'parent')
|
||||||
self.assertEqual(frappe.db.get_value('Sales Invoice', sales_invoice_name, 'status'), 'Cancelled')
|
self.assertEqual(frappe.db.get_value('Sales Invoice', sales_invoice_name, 'status'), 'Cancelled')
|
||||||
|
|
||||||
|
def test_appointment_booking_for_admission_service_unit(self):
|
||||||
|
from erpnext.healthcare.doctype.inpatient_record.inpatient_record import admit_patient, discharge_patient, schedule_discharge
|
||||||
|
from erpnext.healthcare.doctype.inpatient_record.test_inpatient_record import \
|
||||||
|
create_inpatient, get_healthcare_service_unit, mark_invoiced_inpatient_occupancy
|
||||||
|
|
||||||
|
frappe.db.sql("""delete from `tabInpatient Record`""")
|
||||||
|
patient, medical_department, practitioner = create_healthcare_docs()
|
||||||
|
patient = create_patient()
|
||||||
|
# Schedule Admission
|
||||||
|
ip_record = create_inpatient(patient)
|
||||||
|
ip_record.expected_length_of_stay = 0
|
||||||
|
ip_record.save(ignore_permissions = True)
|
||||||
|
|
||||||
|
# Admit
|
||||||
|
service_unit = get_healthcare_service_unit('Test Service Unit Ip Occupancy')
|
||||||
|
admit_patient(ip_record, service_unit, now_datetime())
|
||||||
|
|
||||||
|
appointment = create_appointment(patient, practitioner, nowdate(), service_unit=service_unit)
|
||||||
|
self.assertEqual(appointment.service_unit, service_unit)
|
||||||
|
|
||||||
|
# Discharge
|
||||||
|
schedule_discharge(frappe.as_json({'patient': patient}))
|
||||||
|
ip_record1 = frappe.get_doc("Inpatient Record", ip_record.name)
|
||||||
|
mark_invoiced_inpatient_occupancy(ip_record1)
|
||||||
|
discharge_patient(ip_record1)
|
||||||
|
|
||||||
|
def test_invalid_healthcare_service_unit_validation(self):
|
||||||
|
from erpnext.healthcare.doctype.inpatient_record.inpatient_record import admit_patient, discharge_patient, schedule_discharge
|
||||||
|
from erpnext.healthcare.doctype.inpatient_record.test_inpatient_record import \
|
||||||
|
create_inpatient, get_healthcare_service_unit, mark_invoiced_inpatient_occupancy
|
||||||
|
|
||||||
|
frappe.db.sql("""delete from `tabInpatient Record`""")
|
||||||
|
patient, medical_department, practitioner = create_healthcare_docs()
|
||||||
|
patient = create_patient()
|
||||||
|
# Schedule Admission
|
||||||
|
ip_record = create_inpatient(patient)
|
||||||
|
ip_record.expected_length_of_stay = 0
|
||||||
|
ip_record.save(ignore_permissions = True)
|
||||||
|
|
||||||
|
# Admit
|
||||||
|
service_unit = get_healthcare_service_unit('Test Service Unit Ip Occupancy')
|
||||||
|
admit_patient(ip_record, service_unit, now_datetime())
|
||||||
|
|
||||||
|
appointment_service_unit = get_healthcare_service_unit('Test Service Unit Ip Occupancy for Appointment')
|
||||||
|
appointment = create_appointment(patient, practitioner, nowdate(), service_unit=appointment_service_unit, save=0)
|
||||||
|
self.assertRaises(frappe.exceptions.ValidationError, appointment.save)
|
||||||
|
|
||||||
|
# Discharge
|
||||||
|
schedule_discharge(frappe.as_json({'patient': patient}))
|
||||||
|
ip_record1 = frappe.get_doc("Inpatient Record", ip_record.name)
|
||||||
|
mark_invoiced_inpatient_occupancy(ip_record1)
|
||||||
|
discharge_patient(ip_record1)
|
||||||
|
|
||||||
|
|
||||||
def create_healthcare_docs():
|
def create_healthcare_docs():
|
||||||
patient = create_patient()
|
patient = create_patient()
|
||||||
@ -125,7 +178,7 @@ def create_encounter(appointment):
|
|||||||
encounter.submit()
|
encounter.submit()
|
||||||
return encounter
|
return encounter
|
||||||
|
|
||||||
def create_appointment(patient, practitioner, appointment_date, invoice=0, procedure_template=0):
|
def create_appointment(patient, practitioner, appointment_date, invoice=0, procedure_template=0, service_unit=None, save=1):
|
||||||
item = create_healthcare_service_items()
|
item = create_healthcare_service_items()
|
||||||
frappe.db.set_value('Healthcare Settings', None, 'inpatient_visit_charge_item', item)
|
frappe.db.set_value('Healthcare Settings', None, 'inpatient_visit_charge_item', item)
|
||||||
frappe.db.set_value('Healthcare Settings', None, 'op_consulting_charge_item', item)
|
frappe.db.set_value('Healthcare Settings', None, 'op_consulting_charge_item', item)
|
||||||
@ -136,11 +189,14 @@ def create_appointment(patient, practitioner, appointment_date, invoice=0, proce
|
|||||||
appointment.appointment_date = appointment_date
|
appointment.appointment_date = appointment_date
|
||||||
appointment.company = '_Test Company'
|
appointment.company = '_Test Company'
|
||||||
appointment.duration = 15
|
appointment.duration = 15
|
||||||
|
if service_unit:
|
||||||
|
appointment.service_unit = service_unit
|
||||||
if invoice:
|
if invoice:
|
||||||
appointment.mode_of_payment = 'Cash'
|
appointment.mode_of_payment = 'Cash'
|
||||||
appointment.paid_amount = 500
|
appointment.paid_amount = 500
|
||||||
if procedure_template:
|
if procedure_template:
|
||||||
appointment.procedure_template = create_clinical_procedure_template().get('name')
|
appointment.procedure_template = create_clinical_procedure_template().get('name')
|
||||||
|
if save:
|
||||||
appointment.save(ignore_permissions=True)
|
appointment.save(ignore_permissions=True)
|
||||||
return appointment
|
return appointment
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user