feat: Inpatient Medication Orders Script Report (#23984)
* feat: Inpatient Medication Orders Script Report * feat: add chart for Inpatient Medication Order Report * feat: add report to Desk Page * feat: added filters for dates and healthcare service unit * test: Inpatient Medication Orders report
This commit is contained in:
parent
a339752ba4
commit
c66bd45ba4
@ -43,7 +43,7 @@
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Reports",
|
||||
"links": "[\n\t{\n\t\t\"type\": \"report\",\n\t\t\"is_query_report\": true,\n\t\t\"name\": \"Patient Appointment Analytics\",\n\t\t\"doctype\": \"Patient Appointment\"\n\t},\n\t{\n\t\t\"type\": \"report\",\n\t\t\"is_query_report\": true,\n\t\t\"name\": \"Lab Test Report\",\n\t\t\"doctype\": \"Lab Test\",\n\t\t\"label\": \"Lab Test Report\"\n\t}\n]"
|
||||
"links": "[\n\t{\n\t\t\"type\": \"report\",\n\t\t\"is_query_report\": true,\n\t\t\"name\": \"Patient Appointment Analytics\",\n\t\t\"doctype\": \"Patient Appointment\"\n\t},\n\t{\n\t\t\"type\": \"report\",\n\t\t\"is_query_report\": true,\n\t\t\"name\": \"Lab Test Report\",\n\t\t\"doctype\": \"Lab Test\",\n\t\t\"label\": \"Lab Test Report\"\n\t},\n\t{\n\t\t\"type\": \"report\",\n\t\t\"is_query_report\": true,\n\t\t\"name\": \"Inpatient Medication Orders\",\n\t\t\"doctype\": \"Inpatient Medication Order\",\n\t\t\"label\": \"Inpatient Medication Orders\"\n\t}\n]"
|
||||
}
|
||||
],
|
||||
"category": "Domains",
|
||||
@ -64,7 +64,7 @@
|
||||
"idx": 0,
|
||||
"is_standard": 1,
|
||||
"label": "Healthcare",
|
||||
"modified": "2020-06-25 23:50:56.951698",
|
||||
"modified": "2020-11-23 23:00:48.764377",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Healthcare",
|
||||
|
@ -274,4 +274,6 @@ def get_filters(entry):
|
||||
|
||||
def get_current_healthcare_service_unit(inpatient_record):
|
||||
ip_record = frappe.get_doc('Inpatient Record', inpatient_record)
|
||||
return ip_record.inpatient_occupancies[-1].service_unit
|
||||
if ip_record.inpatient_occupancies:
|
||||
return ip_record.inpatient_occupancies[-1].service_unit
|
||||
return
|
@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
/* eslint-disable */
|
||||
|
||||
frappe.query_reports["Inpatient Medication Orders"] = {
|
||||
"filters": [
|
||||
{
|
||||
fieldname: "company",
|
||||
label: __("Company"),
|
||||
fieldtype: "Link",
|
||||
options: "Company",
|
||||
default: frappe.defaults.get_user_default("Company"),
|
||||
reqd: 1
|
||||
},
|
||||
{
|
||||
fieldname: "from_date",
|
||||
label: __("From Date"),
|
||||
fieldtype: "Date",
|
||||
default: frappe.datetime.add_months(frappe.datetime.get_today(), -1),
|
||||
reqd: 1
|
||||
},
|
||||
{
|
||||
fieldname: "to_date",
|
||||
label: __("To Date"),
|
||||
fieldtype: "Date",
|
||||
default: frappe.datetime.now_date(),
|
||||
reqd: 1
|
||||
},
|
||||
{
|
||||
fieldname: "patient",
|
||||
label: __("Patient"),
|
||||
fieldtype: "Link",
|
||||
options: "Patient"
|
||||
},
|
||||
{
|
||||
fieldname: "service_unit",
|
||||
label: __("Healthcare Service Unit"),
|
||||
fieldtype: "Link",
|
||||
options: "Healthcare Service Unit",
|
||||
get_query: () => {
|
||||
var company = frappe.query_report.get_filter_value('company');
|
||||
return {
|
||||
filters: {
|
||||
'company': company,
|
||||
'is_group': 0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
fieldname: "show_completed_orders",
|
||||
label: __("Show Completed Orders"),
|
||||
fieldtype: "Check",
|
||||
default: 1
|
||||
}
|
||||
]
|
||||
};
|
@ -0,0 +1,36 @@
|
||||
{
|
||||
"add_total_row": 0,
|
||||
"columns": [],
|
||||
"creation": "2020-11-23 17:25:58.802949",
|
||||
"disable_prepared_report": 0,
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"filters": [],
|
||||
"idx": 0,
|
||||
"is_standard": "Yes",
|
||||
"json": "{}",
|
||||
"modified": "2020-11-23 19:40:20.227591",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Inpatient Medication Orders",
|
||||
"owner": "Administrator",
|
||||
"prepared_report": 0,
|
||||
"ref_doctype": "Inpatient Medication Order",
|
||||
"report_name": "Inpatient Medication Orders",
|
||||
"report_type": "Script Report",
|
||||
"roles": [
|
||||
{
|
||||
"role": "System Manager"
|
||||
},
|
||||
{
|
||||
"role": "Healthcare Administrator"
|
||||
},
|
||||
{
|
||||
"role": "Nursing User"
|
||||
},
|
||||
{
|
||||
"role": "Physician"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,198 @@
|
||||
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from erpnext.healthcare.doctype.inpatient_medication_entry.inpatient_medication_entry import get_current_healthcare_service_unit
|
||||
|
||||
def execute(filters=None):
|
||||
columns = get_columns()
|
||||
data = get_data(filters)
|
||||
chart = get_chart_data(data)
|
||||
|
||||
return columns, data, None, chart
|
||||
|
||||
def get_columns():
|
||||
return [
|
||||
{
|
||||
"fieldname": "patient",
|
||||
"fieldtype": "Link",
|
||||
"label": "Patient",
|
||||
"options": "Patient",
|
||||
"width": 200
|
||||
},
|
||||
{
|
||||
"fieldname": "healthcare_service_unit",
|
||||
"fieldtype": "Link",
|
||||
"label": "Healthcare Service Unit",
|
||||
"options": "Healthcare Service Unit",
|
||||
"width": 150
|
||||
},
|
||||
{
|
||||
"fieldname": "drug",
|
||||
"fieldtype": "Link",
|
||||
"label": "Drug Code",
|
||||
"options": "Item",
|
||||
"width": 150
|
||||
},
|
||||
{
|
||||
"fieldname": "drug_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "Drug Name",
|
||||
"width": 150
|
||||
},
|
||||
{
|
||||
"fieldname": "dosage",
|
||||
"fieldtype": "Link",
|
||||
"label": "Dosage",
|
||||
"options": "Prescription Dosage",
|
||||
"width": 80
|
||||
},
|
||||
{
|
||||
"fieldname": "dosage_form",
|
||||
"fieldtype": "Link",
|
||||
"label": "Dosage Form",
|
||||
"options": "Dosage Form",
|
||||
"width": 100
|
||||
},
|
||||
{
|
||||
"fieldname": "date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Date",
|
||||
"width": 100
|
||||
},
|
||||
{
|
||||
"fieldname": "time",
|
||||
"fieldtype": "Time",
|
||||
"label": "Time",
|
||||
"width": 100
|
||||
},
|
||||
{
|
||||
"fieldname": "is_completed",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is Order Completed",
|
||||
"width": 100
|
||||
},
|
||||
{
|
||||
"fieldname": "healthcare_practitioner",
|
||||
"fieldtype": "Link",
|
||||
"label": "Healthcare Practitioner",
|
||||
"options": "Healthcare Practitioner",
|
||||
"width": 200
|
||||
},
|
||||
{
|
||||
"fieldname": "inpatient_medication_entry",
|
||||
"fieldtype": "Link",
|
||||
"label": "Inpatient Medication Entry",
|
||||
"options": "Inpatient Medication Entry",
|
||||
"width": 200
|
||||
},
|
||||
{
|
||||
"fieldname": "inpatient_record",
|
||||
"fieldtype": "Link",
|
||||
"label": "Inpatient Record",
|
||||
"options": "Inpatient Record",
|
||||
"width": 200
|
||||
}
|
||||
]
|
||||
|
||||
def get_data(filters):
|
||||
conditions, values = get_conditions(filters)
|
||||
|
||||
data = frappe.db.sql("""
|
||||
SELECT
|
||||
parent.patient, parent.inpatient_record, parent.practitioner,
|
||||
child.drug, child.drug_name, child.dosage, child.dosage_form,
|
||||
child.date, child.time, child.is_completed, child.name
|
||||
FROM `tabInpatient Medication Order` parent
|
||||
INNER JOIN `tabInpatient Medication Order Entry` child
|
||||
ON child.parent = parent.name
|
||||
WHERE
|
||||
parent.docstatus = 1
|
||||
{conditions}
|
||||
ORDER BY date, time
|
||||
""".format(conditions=conditions), values, as_dict=1)
|
||||
|
||||
data = get_inpatient_details(data, filters.get("service_unit"))
|
||||
|
||||
return data
|
||||
|
||||
def get_conditions(filters):
|
||||
conditions = ""
|
||||
values = dict()
|
||||
|
||||
if filters.get("company"):
|
||||
conditions += " AND parent.company = %(company)s"
|
||||
values["company"] = filters.get("company")
|
||||
|
||||
if filters.get("from_date") and filters.get("to_date"):
|
||||
conditions += " AND child.date BETWEEN %(from_date)s and %(to_date)s"
|
||||
values["from_date"] = filters.get("from_date")
|
||||
values["to_date"] = filters.get("to_date")
|
||||
|
||||
if filters.get("patient"):
|
||||
conditions += " AND parent.patient = %(patient)s"
|
||||
values["patient"] = filters.get("patient")
|
||||
|
||||
if not filters.get("show_completed_orders"):
|
||||
conditions += " AND child.is_completed = 0"
|
||||
|
||||
return conditions, values
|
||||
|
||||
|
||||
def get_inpatient_details(data, service_unit):
|
||||
service_unit_filtered_data = []
|
||||
|
||||
for entry in data:
|
||||
entry["healthcare_service_unit"] = get_current_healthcare_service_unit(entry.inpatient_record)
|
||||
if entry.is_completed:
|
||||
entry["inpatient_medication_entry"] = get_inpatient_medication_entry(entry.name)
|
||||
|
||||
if service_unit and entry.healthcare_service_unit and service_unit != entry.healthcare_service_unit:
|
||||
service_unit_filtered_data.append(entry)
|
||||
|
||||
entry.pop("name", None)
|
||||
|
||||
for entry in service_unit_filtered_data:
|
||||
data.remove(entry)
|
||||
|
||||
return data
|
||||
|
||||
def get_inpatient_medication_entry(order_entry):
|
||||
return frappe.db.get_value("Inpatient Medication Entry Detail", {"against_imoe": order_entry}, "parent")
|
||||
|
||||
def get_chart_data(data):
|
||||
if not data:
|
||||
return None
|
||||
|
||||
labels = ["Pending", "Completed"]
|
||||
datasets = []
|
||||
|
||||
status_wise_data = {
|
||||
"Pending": 0,
|
||||
"Completed": 0
|
||||
}
|
||||
|
||||
for d in data:
|
||||
if d.is_completed:
|
||||
status_wise_data["Completed"] += 1
|
||||
else:
|
||||
status_wise_data["Pending"] += 1
|
||||
|
||||
datasets.append({
|
||||
"name": "Inpatient Medication Order Status",
|
||||
"values": [status_wise_data.get("Pending"), status_wise_data.get("Completed")]
|
||||
})
|
||||
|
||||
chart = {
|
||||
"data": {
|
||||
"labels": labels,
|
||||
"datasets": datasets
|
||||
},
|
||||
"type": "donut",
|
||||
"height": 300
|
||||
}
|
||||
|
||||
chart["fieldtype"] = "Data"
|
||||
|
||||
return chart
|
@ -0,0 +1,128 @@
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import unittest
|
||||
import frappe
|
||||
import datetime
|
||||
from frappe.utils import getdate, now_datetime
|
||||
from erpnext.healthcare.doctype.inpatient_record.test_inpatient_record import create_patient, create_inpatient, get_healthcare_service_unit, mark_invoiced_inpatient_occupancy
|
||||
from erpnext.healthcare.doctype.inpatient_record.inpatient_record import admit_patient, discharge_patient, schedule_discharge
|
||||
from erpnext.healthcare.doctype.inpatient_medication_order.test_inpatient_medication_order import create_ipmo, create_ipme
|
||||
from erpnext.healthcare.report.inpatient_medication_orders.inpatient_medication_orders import execute
|
||||
|
||||
class TestInpatientMedicationOrders(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(self):
|
||||
frappe.db.sql("delete from `tabInpatient Medication Order` where company='_Test Company'")
|
||||
frappe.db.sql("delete from `tabInpatient Medication Entry` where company='_Test Company'")
|
||||
self.patient = create_patient()
|
||||
self.ip_record = create_records(self.patient)
|
||||
|
||||
def test_inpatient_medication_orders_report(self):
|
||||
filters = {
|
||||
'company': '_Test Company',
|
||||
'from_date': getdate(),
|
||||
'to_date': getdate(),
|
||||
'patient': '_Test IPD Patient',
|
||||
'service_unit': 'Test Service Unit Ip Occupancy - _TC'
|
||||
}
|
||||
|
||||
report = execute(filters)
|
||||
|
||||
expected_data = [
|
||||
{
|
||||
'patient': '_Test IPD Patient',
|
||||
'inpatient_record': self.ip_record.name,
|
||||
'practitioner': None,
|
||||
'drug': 'Dextromethorphan',
|
||||
'drug_name': 'Dextromethorphan',
|
||||
'dosage': 1.0,
|
||||
'dosage_form': 'Tablet',
|
||||
'date': getdate(),
|
||||
'time': datetime.timedelta(seconds=32400),
|
||||
'is_completed': 0,
|
||||
'healthcare_service_unit': 'Test Service Unit Ip Occupancy - _TC'
|
||||
},
|
||||
{
|
||||
'patient': '_Test IPD Patient',
|
||||
'inpatient_record': self.ip_record.name,
|
||||
'practitioner': None,
|
||||
'drug': 'Dextromethorphan',
|
||||
'drug_name': 'Dextromethorphan',
|
||||
'dosage': 1.0,
|
||||
'dosage_form': 'Tablet',
|
||||
'date': getdate(),
|
||||
'time': datetime.timedelta(seconds=50400),
|
||||
'is_completed': 0,
|
||||
'healthcare_service_unit': 'Test Service Unit Ip Occupancy - _TC'
|
||||
},
|
||||
{
|
||||
'patient': '_Test IPD Patient',
|
||||
'inpatient_record': self.ip_record.name,
|
||||
'practitioner': None,
|
||||
'drug': 'Dextromethorphan',
|
||||
'drug_name': 'Dextromethorphan',
|
||||
'dosage': 1.0,
|
||||
'dosage_form': 'Tablet',
|
||||
'date': getdate(),
|
||||
'time': datetime.timedelta(seconds=75600),
|
||||
'is_completed': 0,
|
||||
'healthcare_service_unit': 'Test Service Unit Ip Occupancy - _TC'
|
||||
}
|
||||
]
|
||||
|
||||
self.assertEqual(expected_data, report[1])
|
||||
|
||||
filters = frappe._dict(from_date=getdate(), to_date=getdate(), from_time='', to_time='')
|
||||
ipme = create_ipme(filters)
|
||||
ipme.submit()
|
||||
|
||||
filters = {
|
||||
'company': '_Test Company',
|
||||
'from_date': getdate(),
|
||||
'to_date': getdate(),
|
||||
'patient': '_Test IPD Patient',
|
||||
'service_unit': 'Test Service Unit Ip Occupancy - _TC',
|
||||
'show_completed_orders': 0
|
||||
}
|
||||
|
||||
report = execute(filters)
|
||||
self.assertEqual(len(report[1]), 0)
|
||||
|
||||
def tearDown(self):
|
||||
if frappe.db.get_value('Patient', self.patient, 'inpatient_record'):
|
||||
# cleanup - Discharge
|
||||
schedule_discharge(frappe.as_json({'patient': self.patient}))
|
||||
self.ip_record.reload()
|
||||
mark_invoiced_inpatient_occupancy(self.ip_record)
|
||||
|
||||
self.ip_record.reload()
|
||||
discharge_patient(self.ip_record)
|
||||
|
||||
for entry in frappe.get_all('Inpatient Medication Entry'):
|
||||
doc = frappe.get_doc('Inpatient Medication Entry', entry.name)
|
||||
doc.cancel()
|
||||
doc.delete()
|
||||
|
||||
for entry in frappe.get_all('Inpatient Medication Order'):
|
||||
doc = frappe.get_doc('Inpatient Medication Order', entry.name)
|
||||
doc.cancel()
|
||||
doc.delete()
|
||||
|
||||
|
||||
def create_records(patient):
|
||||
frappe.db.sql("""delete from `tabInpatient Record`""")
|
||||
|
||||
# Admit
|
||||
ip_record = create_inpatient(patient)
|
||||
ip_record.expected_length_of_stay = 0
|
||||
ip_record.save()
|
||||
ip_record.reload()
|
||||
service_unit = get_healthcare_service_unit()
|
||||
admit_patient(ip_record, service_unit, now_datetime())
|
||||
|
||||
ipmo = create_ipmo(patient)
|
||||
ipmo.submit()
|
||||
|
||||
return ip_record
|
Loading…
x
Reference in New Issue
Block a user