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,
|
"hidden": 0,
|
||||||
"label": "Reports",
|
"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",
|
"category": "Domains",
|
||||||
@ -64,7 +64,7 @@
|
|||||||
"idx": 0,
|
"idx": 0,
|
||||||
"is_standard": 1,
|
"is_standard": 1,
|
||||||
"label": "Healthcare",
|
"label": "Healthcare",
|
||||||
"modified": "2020-06-25 23:50:56.951698",
|
"modified": "2020-11-23 23:00:48.764377",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Healthcare",
|
"module": "Healthcare",
|
||||||
"name": "Healthcare",
|
"name": "Healthcare",
|
||||||
|
@ -274,4 +274,6 @@ 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:
|
||||||
return ip_record.inpatient_occupancies[-1].service_unit
|
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