mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-08 07:32:50 +00:00
style: bulk format code with black
v13 port because otherwise backports will result in conflicts always
This commit is contained in:
@@ -8,30 +8,39 @@ from frappe.utils.dashboard import cache_source
|
||||
|
||||
@frappe.whitelist()
|
||||
@cache_source
|
||||
def get(chart_name = None, chart = None, no_cache = None, filters = None, from_date = None,
|
||||
to_date = None, timespan = None, time_interval = None, heatmap_year = None):
|
||||
def get(
|
||||
chart_name=None,
|
||||
chart=None,
|
||||
no_cache=None,
|
||||
filters=None,
|
||||
from_date=None,
|
||||
to_date=None,
|
||||
timespan=None,
|
||||
time_interval=None,
|
||||
heatmap_year=None,
|
||||
):
|
||||
if chart_name:
|
||||
chart = frappe.get_doc('Dashboard Chart', chart_name)
|
||||
chart = frappe.get_doc("Dashboard Chart", chart_name)
|
||||
else:
|
||||
chart = frappe._dict(frappe.parse_json(chart))
|
||||
|
||||
filters = frappe.parse_json(filters)
|
||||
|
||||
data = frappe.db.get_list('Medical Department', fields=['name'])
|
||||
data = frappe.db.get_list("Medical Department", fields=["name"])
|
||||
if not filters:
|
||||
filters = {}
|
||||
|
||||
status = ['Open', 'Scheduled', 'Closed', 'Cancelled']
|
||||
status = ["Open", "Scheduled", "Closed", "Cancelled"]
|
||||
for department in data:
|
||||
filters['department'] = department.name
|
||||
department['total_appointments'] = frappe.db.count('Patient Appointment', filters=filters)
|
||||
filters["department"] = department.name
|
||||
department["total_appointments"] = frappe.db.count("Patient Appointment", filters=filters)
|
||||
|
||||
for entry in status:
|
||||
filters['status'] = entry
|
||||
department[frappe.scrub(entry)] = frappe.db.count('Patient Appointment', filters=filters)
|
||||
filters.pop('status')
|
||||
filters["status"] = entry
|
||||
department[frappe.scrub(entry)] = frappe.db.count("Patient Appointment", filters=filters)
|
||||
filters.pop("status")
|
||||
|
||||
sorted_department_map = sorted(data, key = lambda i: i['total_appointments'], reverse=True)
|
||||
sorted_department_map = sorted(data, key=lambda i: i["total_appointments"], reverse=True)
|
||||
|
||||
if len(sorted_department_map) > 10:
|
||||
sorted_department_map = sorted_department_map[:10]
|
||||
@@ -50,24 +59,12 @@ def get(chart_name = None, chart = None, no_cache = None, filters = None, from_d
|
||||
cancelled.append(department.cancelled)
|
||||
|
||||
return {
|
||||
'labels': labels,
|
||||
'datasets': [
|
||||
{
|
||||
'name': 'Open',
|
||||
'values': open_appointments
|
||||
},
|
||||
{
|
||||
'name': 'Scheduled',
|
||||
'values': scheduled
|
||||
},
|
||||
{
|
||||
'name': 'Closed',
|
||||
'values': closed
|
||||
},
|
||||
{
|
||||
'name': 'Cancelled',
|
||||
'values': cancelled
|
||||
}
|
||||
"labels": labels,
|
||||
"datasets": [
|
||||
{"name": "Open", "values": open_appointments},
|
||||
{"name": "Scheduled", "values": scheduled},
|
||||
{"name": "Closed", "values": closed},
|
||||
{"name": "Cancelled", "values": cancelled},
|
||||
],
|
||||
'type': 'bar'
|
||||
"type": "bar",
|
||||
}
|
||||
|
||||
@@ -10,47 +10,65 @@ class AppointmentType(Document):
|
||||
def validate(self):
|
||||
if self.items and self.price_list:
|
||||
for item in self.items:
|
||||
existing_op_item_price = frappe.db.exists('Item Price', {
|
||||
'item_code': item.op_consulting_charge_item,
|
||||
'price_list': self.price_list
|
||||
})
|
||||
existing_op_item_price = frappe.db.exists(
|
||||
"Item Price", {"item_code": item.op_consulting_charge_item, "price_list": self.price_list}
|
||||
)
|
||||
|
||||
if not existing_op_item_price and item.op_consulting_charge_item and item.op_consulting_charge:
|
||||
make_item_price(self.price_list, item.op_consulting_charge_item, item.op_consulting_charge)
|
||||
|
||||
existing_ip_item_price = frappe.db.exists('Item Price', {
|
||||
'item_code': item.inpatient_visit_charge_item,
|
||||
'price_list': self.price_list
|
||||
})
|
||||
existing_ip_item_price = frappe.db.exists(
|
||||
"Item Price", {"item_code": item.inpatient_visit_charge_item, "price_list": self.price_list}
|
||||
)
|
||||
|
||||
if (
|
||||
not existing_ip_item_price
|
||||
and item.inpatient_visit_charge_item
|
||||
and item.inpatient_visit_charge
|
||||
):
|
||||
make_item_price(
|
||||
self.price_list, item.inpatient_visit_charge_item, item.inpatient_visit_charge
|
||||
)
|
||||
|
||||
if not existing_ip_item_price and item.inpatient_visit_charge_item and item.inpatient_visit_charge:
|
||||
make_item_price(self.price_list, item.inpatient_visit_charge_item, item.inpatient_visit_charge)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_service_item_based_on_department(appointment_type, department):
|
||||
item_list = frappe.db.get_value('Appointment Type Service Item',
|
||||
filters = {'medical_department': department, 'parent': appointment_type},
|
||||
fieldname = ['op_consulting_charge_item',
|
||||
'inpatient_visit_charge_item', 'op_consulting_charge', 'inpatient_visit_charge'],
|
||||
as_dict = 1
|
||||
item_list = frappe.db.get_value(
|
||||
"Appointment Type Service Item",
|
||||
filters={"medical_department": department, "parent": appointment_type},
|
||||
fieldname=[
|
||||
"op_consulting_charge_item",
|
||||
"inpatient_visit_charge_item",
|
||||
"op_consulting_charge",
|
||||
"inpatient_visit_charge",
|
||||
],
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
# if department wise items are not set up
|
||||
# use the generic items
|
||||
if not item_list:
|
||||
item_list = frappe.db.get_value('Appointment Type Service Item',
|
||||
filters = {'parent': appointment_type},
|
||||
fieldname = ['op_consulting_charge_item',
|
||||
'inpatient_visit_charge_item', 'op_consulting_charge', 'inpatient_visit_charge'],
|
||||
as_dict = 1
|
||||
item_list = frappe.db.get_value(
|
||||
"Appointment Type Service Item",
|
||||
filters={"parent": appointment_type},
|
||||
fieldname=[
|
||||
"op_consulting_charge_item",
|
||||
"inpatient_visit_charge_item",
|
||||
"op_consulting_charge",
|
||||
"inpatient_visit_charge",
|
||||
],
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
return item_list
|
||||
|
||||
|
||||
def make_item_price(price_list, item, item_price):
|
||||
frappe.get_doc({
|
||||
'doctype': 'Item Price',
|
||||
'price_list': price_list,
|
||||
'item_code': item,
|
||||
'price_list_rate': item_price
|
||||
}).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
frappe.get_doc(
|
||||
{
|
||||
"doctype": "Item Price",
|
||||
"price_list": price_list,
|
||||
"item_code": item,
|
||||
"price_list_rate": item_price,
|
||||
}
|
||||
).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
|
||||
from frappe import _
|
||||
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'appointment_type',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Patient Appointments'),
|
||||
'items': ['Patient Appointment']
|
||||
},
|
||||
]
|
||||
"fieldname": "appointment_type",
|
||||
"transactions": [
|
||||
{"label": _("Patient Appointments"), "items": ["Patient Appointment"]},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@ import unittest
|
||||
|
||||
# test_records = frappe.get_test_records('Appointment Type')
|
||||
|
||||
|
||||
class TestAppointmentType(unittest.TestCase):
|
||||
pass
|
||||
|
||||
@@ -33,27 +33,29 @@ class ClinicalProcedure(Document):
|
||||
|
||||
def after_insert(self):
|
||||
if self.prescription:
|
||||
frappe.db.set_value('Procedure Prescription', self.prescription, 'procedure_created', 1)
|
||||
frappe.db.set_value("Procedure Prescription", self.prescription, "procedure_created", 1)
|
||||
if self.appointment:
|
||||
frappe.db.set_value('Patient Appointment', self.appointment, 'status', 'Closed')
|
||||
template = frappe.get_doc('Clinical Procedure Template', self.procedure_template)
|
||||
frappe.db.set_value("Patient Appointment", self.appointment, "status", "Closed")
|
||||
template = frappe.get_doc("Clinical Procedure Template", self.procedure_template)
|
||||
if template.sample:
|
||||
patient = frappe.get_doc('Patient', self.patient)
|
||||
patient = frappe.get_doc("Patient", self.patient)
|
||||
sample_collection = create_sample_doc(template, patient, None, self.company)
|
||||
frappe.db.set_value('Clinical Procedure', self.name, 'sample', sample_collection.name)
|
||||
frappe.db.set_value("Clinical Procedure", self.name, "sample", sample_collection.name)
|
||||
self.reload()
|
||||
|
||||
def set_status(self):
|
||||
if self.docstatus == 0:
|
||||
self.status = 'Draft'
|
||||
self.status = "Draft"
|
||||
elif self.docstatus == 1:
|
||||
if self.status not in ['In Progress', 'Completed']:
|
||||
self.status = 'Pending'
|
||||
if self.status not in ["In Progress", "Completed"]:
|
||||
self.status = "Pending"
|
||||
elif self.docstatus == 2:
|
||||
self.status = 'Cancelled'
|
||||
self.status = "Cancelled"
|
||||
|
||||
def set_title(self):
|
||||
self.title = _('{0} - {1}').format(self.patient_name or self.patient, self.procedure_template)[:100]
|
||||
self.title = _("{0} - {1}").format(self.patient_name or self.patient, self.procedure_template)[
|
||||
:100
|
||||
]
|
||||
|
||||
@frappe.whitelist()
|
||||
def complete_procedure(self):
|
||||
@@ -63,37 +65,48 @@ class ClinicalProcedure(Document):
|
||||
if self.items:
|
||||
consumable_total_amount = 0
|
||||
consumption_details = False
|
||||
customer = frappe.db.get_value('Patient', self.patient, 'customer')
|
||||
customer = frappe.db.get_value("Patient", self.patient, "customer")
|
||||
if customer:
|
||||
for item in self.items:
|
||||
if item.invoice_separately_as_consumables:
|
||||
price_list, price_list_currency = frappe.db.get_values('Price List', {'selling': 1}, ['name', 'currency'])[0]
|
||||
price_list, price_list_currency = frappe.db.get_values(
|
||||
"Price List", {"selling": 1}, ["name", "currency"]
|
||||
)[0]
|
||||
args = {
|
||||
'doctype': 'Sales Invoice',
|
||||
'item_code': item.item_code,
|
||||
'company': self.company,
|
||||
'warehouse': self.warehouse,
|
||||
'customer': customer,
|
||||
'selling_price_list': price_list,
|
||||
'price_list_currency': price_list_currency,
|
||||
'plc_conversion_rate': 1.0,
|
||||
'conversion_rate': 1.0
|
||||
"doctype": "Sales Invoice",
|
||||
"item_code": item.item_code,
|
||||
"company": self.company,
|
||||
"warehouse": self.warehouse,
|
||||
"customer": customer,
|
||||
"selling_price_list": price_list,
|
||||
"price_list_currency": price_list_currency,
|
||||
"plc_conversion_rate": 1.0,
|
||||
"conversion_rate": 1.0,
|
||||
}
|
||||
item_details = get_item_details(args)
|
||||
item_price = item_details.price_list_rate * item.qty
|
||||
item_consumption_details = item_details.item_name + ' ' + str(item.qty) + ' ' + item.uom + ' ' + str(item_price)
|
||||
item_consumption_details = (
|
||||
item_details.item_name + " " + str(item.qty) + " " + item.uom + " " + str(item_price)
|
||||
)
|
||||
consumable_total_amount += item_price
|
||||
if not consumption_details:
|
||||
consumption_details = _('Clinical Procedure ({0}):').format(self.name)
|
||||
consumption_details += '\n\t' + item_consumption_details
|
||||
consumption_details = _("Clinical Procedure ({0}):").format(self.name)
|
||||
consumption_details += "\n\t" + item_consumption_details
|
||||
|
||||
if consumable_total_amount > 0:
|
||||
frappe.db.set_value('Clinical Procedure', self.name, 'consumable_total_amount', consumable_total_amount)
|
||||
frappe.db.set_value('Clinical Procedure', self.name, 'consumption_details', consumption_details)
|
||||
frappe.db.set_value(
|
||||
"Clinical Procedure", self.name, "consumable_total_amount", consumable_total_amount
|
||||
)
|
||||
frappe.db.set_value(
|
||||
"Clinical Procedure", self.name, "consumption_details", consumption_details
|
||||
)
|
||||
else:
|
||||
frappe.throw(_('Please set Customer in Patient {0}').format(frappe.bold(self.patient)), title=_('Customer Not Found'))
|
||||
frappe.throw(
|
||||
_("Please set Customer in Patient {0}").format(frappe.bold(self.patient)),
|
||||
title=_("Customer Not Found"),
|
||||
)
|
||||
|
||||
self.db_set('status', 'Completed')
|
||||
self.db_set("status", "Completed")
|
||||
|
||||
if self.consume_stock and self.items:
|
||||
return stock_entry
|
||||
@@ -102,15 +115,15 @@ class ClinicalProcedure(Document):
|
||||
def start_procedure(self):
|
||||
allow_start = self.set_actual_qty()
|
||||
if allow_start:
|
||||
self.db_set('status', 'In Progress')
|
||||
return 'success'
|
||||
return 'insufficient stock'
|
||||
self.db_set("status", "In Progress")
|
||||
return "success"
|
||||
return "insufficient stock"
|
||||
|
||||
def set_actual_qty(self):
|
||||
allow_negative_stock = frappe.db.get_single_value('Stock Settings', 'allow_negative_stock')
|
||||
allow_negative_stock = frappe.db.get_single_value("Stock Settings", "allow_negative_stock")
|
||||
|
||||
allow_start = True
|
||||
for d in self.get('items'):
|
||||
for d in self.get("items"):
|
||||
d.actual_qty = get_stock_qty(d.item_code, self.warehouse)
|
||||
# validate qty
|
||||
if not allow_negative_stock and d.actual_qty < d.qty:
|
||||
@@ -121,15 +134,15 @@ class ClinicalProcedure(Document):
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_material_receipt(self, submit=False):
|
||||
stock_entry = frappe.new_doc('Stock Entry')
|
||||
stock_entry = frappe.new_doc("Stock Entry")
|
||||
|
||||
stock_entry.stock_entry_type = 'Material Receipt'
|
||||
stock_entry.stock_entry_type = "Material Receipt"
|
||||
stock_entry.to_warehouse = self.warehouse
|
||||
stock_entry.company = self.company
|
||||
expense_account = get_account(None, 'expense_account', 'Healthcare Settings', self.company)
|
||||
expense_account = get_account(None, "expense_account", "Healthcare Settings", self.company)
|
||||
for item in self.items:
|
||||
if item.qty > item.actual_qty:
|
||||
se_child = stock_entry.append('items')
|
||||
se_child = stock_entry.append("items")
|
||||
se_child.item_code = item.item_code
|
||||
se_child.item_name = item.item_name
|
||||
se_child.uom = item.uom
|
||||
@@ -139,7 +152,7 @@ class ClinicalProcedure(Document):
|
||||
# in stock uom
|
||||
se_child.transfer_qty = flt(item.transfer_qty)
|
||||
se_child.conversion_factor = flt(item.conversion_factor)
|
||||
cost_center = frappe.get_cached_value('Company', self.company, 'cost_center')
|
||||
cost_center = frappe.get_cached_value("Company", self.company, "cost_center")
|
||||
se_child.cost_center = cost_center
|
||||
se_child.expense_account = expense_account
|
||||
if submit:
|
||||
@@ -149,25 +162,30 @@ class ClinicalProcedure(Document):
|
||||
|
||||
|
||||
def get_stock_qty(item_code, warehouse):
|
||||
return get_previous_sle({
|
||||
'item_code': item_code,
|
||||
'warehouse': warehouse,
|
||||
'posting_date': nowdate(),
|
||||
'posting_time': nowtime()
|
||||
}).get('qty_after_transaction') or 0
|
||||
return (
|
||||
get_previous_sle(
|
||||
{
|
||||
"item_code": item_code,
|
||||
"warehouse": warehouse,
|
||||
"posting_date": nowdate(),
|
||||
"posting_time": nowtime(),
|
||||
}
|
||||
).get("qty_after_transaction")
|
||||
or 0
|
||||
)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_procedure_consumables(procedure_template):
|
||||
return get_items('Clinical Procedure Item', procedure_template, 'Clinical Procedure Template')
|
||||
return get_items("Clinical Procedure Item", procedure_template, "Clinical Procedure Template")
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def set_stock_items(doc, stock_detail_parent, parenttype):
|
||||
items = get_items('Clinical Procedure Item', stock_detail_parent, parenttype)
|
||||
items = get_items("Clinical Procedure Item", stock_detail_parent, parenttype)
|
||||
|
||||
for item in items:
|
||||
se_child = doc.append('items')
|
||||
se_child = doc.append("items")
|
||||
se_child.item_code = item.item_code
|
||||
se_child.item_name = item.item_name
|
||||
se_child.uom = item.uom
|
||||
@@ -178,32 +196,31 @@ def set_stock_items(doc, stock_detail_parent, parenttype):
|
||||
se_child.conversion_factor = flt(item.conversion_factor)
|
||||
if item.batch_no:
|
||||
se_child.batch_no = item.batch_no
|
||||
if parenttype == 'Clinical Procedure Template':
|
||||
if parenttype == "Clinical Procedure Template":
|
||||
se_child.invoice_separately_as_consumables = item.invoice_separately_as_consumables
|
||||
|
||||
return doc
|
||||
|
||||
|
||||
def get_items(table, parent, parenttype):
|
||||
items = frappe.db.get_all(table, filters={
|
||||
'parent': parent,
|
||||
'parenttype': parenttype
|
||||
}, fields=['*'])
|
||||
items = frappe.db.get_all(
|
||||
table, filters={"parent": parent, "parenttype": parenttype}, fields=["*"]
|
||||
)
|
||||
|
||||
return items
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_stock_entry(doc):
|
||||
stock_entry = frappe.new_doc('Stock Entry')
|
||||
stock_entry = set_stock_items(stock_entry, doc.name, 'Clinical Procedure')
|
||||
stock_entry.stock_entry_type = 'Material Issue'
|
||||
stock_entry = frappe.new_doc("Stock Entry")
|
||||
stock_entry = set_stock_items(stock_entry, doc.name, "Clinical Procedure")
|
||||
stock_entry.stock_entry_type = "Material Issue"
|
||||
stock_entry.from_warehouse = doc.warehouse
|
||||
stock_entry.company = doc.company
|
||||
expense_account = get_account(None, 'expense_account', 'Healthcare Settings', doc.company)
|
||||
expense_account = get_account(None, "expense_account", "Healthcare Settings", doc.company)
|
||||
|
||||
for item_line in stock_entry.items:
|
||||
cost_center = frappe.get_cached_value('Company', doc.company, 'cost_center')
|
||||
cost_center = frappe.get_cached_value("Company", doc.company, "cost_center")
|
||||
item_line.cost_center = cost_center
|
||||
item_line.expense_account = expense_account
|
||||
|
||||
@@ -215,39 +232,47 @@ def make_stock_entry(doc):
|
||||
@frappe.whitelist()
|
||||
def make_procedure(source_name, target_doc=None):
|
||||
def set_missing_values(source, target):
|
||||
consume_stock = frappe.db.get_value('Clinical Procedure Template', source.procedure_template, 'consume_stock')
|
||||
consume_stock = frappe.db.get_value(
|
||||
"Clinical Procedure Template", source.procedure_template, "consume_stock"
|
||||
)
|
||||
if consume_stock:
|
||||
target.consume_stock = 1
|
||||
warehouse = None
|
||||
if source.service_unit:
|
||||
warehouse = frappe.db.get_value('Healthcare Service Unit', source.service_unit, 'warehouse')
|
||||
warehouse = frappe.db.get_value("Healthcare Service Unit", source.service_unit, "warehouse")
|
||||
if not warehouse:
|
||||
warehouse = frappe.db.get_value('Stock Settings', None, 'default_warehouse')
|
||||
warehouse = frappe.db.get_value("Stock Settings", None, "default_warehouse")
|
||||
if warehouse:
|
||||
target.warehouse = warehouse
|
||||
|
||||
set_stock_items(target, source.procedure_template, 'Clinical Procedure Template')
|
||||
set_stock_items(target, source.procedure_template, "Clinical Procedure Template")
|
||||
|
||||
doc = get_mapped_doc('Patient Appointment', source_name, {
|
||||
'Patient Appointment': {
|
||||
'doctype': 'Clinical Procedure',
|
||||
'field_map': [
|
||||
['appointment', 'name'],
|
||||
['patient', 'patient'],
|
||||
['patient_age', 'patient_age'],
|
||||
['patient_sex', 'patient_sex'],
|
||||
['procedure_template', 'procedure_template'],
|
||||
['prescription', 'procedure_prescription'],
|
||||
['practitioner', 'practitioner'],
|
||||
['medical_department', 'department'],
|
||||
['start_date', 'appointment_date'],
|
||||
['start_time', 'appointment_time'],
|
||||
['notes', 'notes'],
|
||||
['service_unit', 'service_unit'],
|
||||
['company', 'company'],
|
||||
['invoiced', 'invoiced']
|
||||
]
|
||||
doc = get_mapped_doc(
|
||||
"Patient Appointment",
|
||||
source_name,
|
||||
{
|
||||
"Patient Appointment": {
|
||||
"doctype": "Clinical Procedure",
|
||||
"field_map": [
|
||||
["appointment", "name"],
|
||||
["patient", "patient"],
|
||||
["patient_age", "patient_age"],
|
||||
["patient_sex", "patient_sex"],
|
||||
["procedure_template", "procedure_template"],
|
||||
["prescription", "procedure_prescription"],
|
||||
["practitioner", "practitioner"],
|
||||
["medical_department", "department"],
|
||||
["start_date", "appointment_date"],
|
||||
["start_time", "appointment_time"],
|
||||
["notes", "notes"],
|
||||
["service_unit", "service_unit"],
|
||||
["company", "company"],
|
||||
["invoiced", "invoiced"],
|
||||
],
|
||||
}
|
||||
}, target_doc, set_missing_values)
|
||||
},
|
||||
target_doc,
|
||||
set_missing_values,
|
||||
)
|
||||
|
||||
return doc
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2017, ESS LLP and Contributors
|
||||
# See license.txt
|
||||
|
||||
@@ -11,54 +11,59 @@ from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment imp
|
||||
create_healthcare_docs,
|
||||
)
|
||||
|
||||
test_dependencies = ['Item']
|
||||
test_dependencies = ["Item"]
|
||||
|
||||
|
||||
class TestClinicalProcedure(unittest.TestCase):
|
||||
def test_procedure_template_item(self):
|
||||
patient, practitioner = create_healthcare_docs()
|
||||
procedure_template = create_clinical_procedure_template()
|
||||
self.assertTrue(frappe.db.exists('Item', procedure_template.item))
|
||||
self.assertTrue(frappe.db.exists("Item", procedure_template.item))
|
||||
|
||||
procedure_template.disabled = 1
|
||||
procedure_template.save()
|
||||
self.assertEqual(frappe.db.get_value('Item', procedure_template.item, 'disabled'), 1)
|
||||
self.assertEqual(frappe.db.get_value("Item", procedure_template.item, "disabled"), 1)
|
||||
|
||||
def test_consumables(self):
|
||||
patient, practitioner = create_healthcare_docs()
|
||||
procedure_template = create_clinical_procedure_template()
|
||||
procedure_template.allow_stock_consumption = 1
|
||||
consumable = create_consumable()
|
||||
procedure_template.append('items', {
|
||||
'item_code': consumable.item_code,
|
||||
'qty': 1,
|
||||
'uom': consumable.stock_uom,
|
||||
'stock_uom': consumable.stock_uom
|
||||
})
|
||||
procedure_template.append(
|
||||
"items",
|
||||
{
|
||||
"item_code": consumable.item_code,
|
||||
"qty": 1,
|
||||
"uom": consumable.stock_uom,
|
||||
"stock_uom": consumable.stock_uom,
|
||||
},
|
||||
)
|
||||
procedure_template.save()
|
||||
procedure = create_procedure(procedure_template, patient, practitioner)
|
||||
result = procedure.start_procedure()
|
||||
if result == 'insufficient stock':
|
||||
if result == "insufficient stock":
|
||||
procedure.make_material_receipt(submit=True)
|
||||
result = procedure.start_procedure()
|
||||
self.assertEqual(procedure.status, 'In Progress')
|
||||
self.assertEqual(procedure.status, "In Progress")
|
||||
result = procedure.complete_procedure()
|
||||
# check consumption
|
||||
self.assertTrue(frappe.db.exists('Stock Entry', result))
|
||||
self.assertTrue(frappe.db.exists("Stock Entry", result))
|
||||
|
||||
|
||||
def create_consumable():
|
||||
if frappe.db.exists('Item', 'Syringe'):
|
||||
return frappe.get_doc('Item', 'Syringe')
|
||||
consumable = frappe.new_doc('Item')
|
||||
consumable.item_code = 'Syringe'
|
||||
consumable.item_group = '_Test Item Group'
|
||||
consumable.stock_uom = 'Nos'
|
||||
if frappe.db.exists("Item", "Syringe"):
|
||||
return frappe.get_doc("Item", "Syringe")
|
||||
consumable = frappe.new_doc("Item")
|
||||
consumable.item_code = "Syringe"
|
||||
consumable.item_group = "_Test Item Group"
|
||||
consumable.stock_uom = "Nos"
|
||||
consumable.valuation_rate = 5.00
|
||||
consumable.save()
|
||||
return consumable
|
||||
|
||||
|
||||
def create_procedure(procedure_template, patient, practitioner):
|
||||
procedure = frappe.new_doc('Clinical Procedure')
|
||||
procedure = frappe.new_doc("Clinical Procedure")
|
||||
procedure.procedure_template = procedure_template.name
|
||||
procedure.patient = patient
|
||||
procedure.practitioner = practitioner
|
||||
|
||||
@@ -24,13 +24,13 @@ class ClinicalProcedureTemplate(Document):
|
||||
def enable_disable_item(self):
|
||||
if self.is_billable:
|
||||
if self.disabled:
|
||||
frappe.db.set_value('Item', self.item, 'disabled', 1)
|
||||
frappe.db.set_value("Item", self.item, "disabled", 1)
|
||||
else:
|
||||
frappe.db.set_value('Item', self.item, 'disabled', 0)
|
||||
frappe.db.set_value("Item", self.item, "disabled", 0)
|
||||
|
||||
def update_item_and_item_price(self):
|
||||
if self.is_billable and self.item:
|
||||
item_doc = frappe.get_doc('Item', {'item_code': self.item})
|
||||
item_doc = frappe.get_doc("Item", {"item_code": self.item})
|
||||
item_doc.item_name = self.template
|
||||
item_doc.item_group = self.item_group
|
||||
item_doc.description = self.description
|
||||
@@ -38,15 +38,15 @@ class ClinicalProcedureTemplate(Document):
|
||||
item_doc.save(ignore_permissions=True)
|
||||
|
||||
if self.rate:
|
||||
item_price = frappe.get_doc('Item Price', {'item_code': self.item})
|
||||
item_price = frappe.get_doc("Item Price", {"item_code": self.item})
|
||||
item_price.item_name = self.template
|
||||
item_price.price_list_rate = self.rate
|
||||
item_price.save()
|
||||
|
||||
elif not self.is_billable and self.item:
|
||||
frappe.db.set_value('Item', self.item, 'disabled', 1)
|
||||
frappe.db.set_value("Item", self.item, "disabled", 1)
|
||||
|
||||
self.db_set('change_in_item', 0)
|
||||
self.db_set("change_in_item", 0)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@@ -54,69 +54,72 @@ def get_item_details(args=None):
|
||||
if not isinstance(args, dict):
|
||||
args = json.loads(args)
|
||||
|
||||
item = frappe.db.get_all('Item',
|
||||
filters={
|
||||
'disabled': 0,
|
||||
'name': args.get('item_code')
|
||||
},
|
||||
fields=['stock_uom', 'item_name']
|
||||
item = frappe.db.get_all(
|
||||
"Item", filters={"disabled": 0, "name": args.get("item_code")}, fields=["stock_uom", "item_name"]
|
||||
)
|
||||
|
||||
if not item:
|
||||
frappe.throw(_('Item {0} is not active').format(args.get('item_code')))
|
||||
frappe.throw(_("Item {0} is not active").format(args.get("item_code")))
|
||||
|
||||
item = item[0]
|
||||
ret = {
|
||||
'uom': item.stock_uom,
|
||||
'stock_uom': item.stock_uom,
|
||||
'item_name': item.item_name,
|
||||
'qty': 1,
|
||||
'transfer_qty': 0,
|
||||
'conversion_factor': 1
|
||||
"uom": item.stock_uom,
|
||||
"stock_uom": item.stock_uom,
|
||||
"item_name": item.item_name,
|
||||
"qty": 1,
|
||||
"transfer_qty": 0,
|
||||
"conversion_factor": 1,
|
||||
}
|
||||
return ret
|
||||
|
||||
|
||||
def create_item_from_template(doc):
|
||||
disabled = doc.disabled
|
||||
if doc.is_billable and not doc.disabled:
|
||||
disabled = 0
|
||||
|
||||
uom = frappe.db.exists('UOM', 'Unit') or frappe.db.get_single_value('Stock Settings', 'stock_uom')
|
||||
item = frappe.get_doc({
|
||||
'doctype': 'Item',
|
||||
'item_code': doc.template,
|
||||
'item_name':doc.template,
|
||||
'item_group': doc.item_group,
|
||||
'description':doc.description,
|
||||
'is_sales_item': 1,
|
||||
'is_service_item': 1,
|
||||
'is_purchase_item': 0,
|
||||
'is_stock_item': 0,
|
||||
'show_in_website': 0,
|
||||
'is_pro_applicable': 0,
|
||||
'disabled': disabled,
|
||||
'stock_uom': uom
|
||||
}).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
uom = frappe.db.exists("UOM", "Unit") or frappe.db.get_single_value("Stock Settings", "stock_uom")
|
||||
item = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Item",
|
||||
"item_code": doc.template,
|
||||
"item_name": doc.template,
|
||||
"item_group": doc.item_group,
|
||||
"description": doc.description,
|
||||
"is_sales_item": 1,
|
||||
"is_service_item": 1,
|
||||
"is_purchase_item": 0,
|
||||
"is_stock_item": 0,
|
||||
"show_in_website": 0,
|
||||
"is_pro_applicable": 0,
|
||||
"disabled": disabled,
|
||||
"stock_uom": uom,
|
||||
}
|
||||
).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
|
||||
make_item_price(item.name, doc.rate)
|
||||
doc.db_set('item', item.name)
|
||||
doc.db_set("item", item.name)
|
||||
|
||||
|
||||
def make_item_price(item, item_price):
|
||||
price_list_name = frappe.db.get_value('Price List', {'selling': 1})
|
||||
frappe.get_doc({
|
||||
'doctype': 'Item Price',
|
||||
'price_list': price_list_name,
|
||||
'item_code': item,
|
||||
'price_list_rate': item_price
|
||||
}).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
price_list_name = frappe.db.get_value("Price List", {"selling": 1})
|
||||
frappe.get_doc(
|
||||
{
|
||||
"doctype": "Item Price",
|
||||
"price_list": price_list_name,
|
||||
"item_code": item,
|
||||
"price_list_rate": item_price,
|
||||
}
|
||||
).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def change_item_code_from_template(item_code, doc):
|
||||
doc = frappe._dict(json.loads(doc))
|
||||
|
||||
if frappe.db.exists('Item', {'item_code': item_code}):
|
||||
frappe.throw(_('Item with Item Code {0} already exists').format(item_code))
|
||||
if frappe.db.exists("Item", {"item_code": item_code}):
|
||||
frappe.throw(_("Item with Item Code {0} already exists").format(item_code))
|
||||
else:
|
||||
rename_doc('Item', doc.item_code, item_code, ignore_permissions=True)
|
||||
frappe.db.set_value('Clinical Procedure Template', doc.name, 'item_code', item_code)
|
||||
rename_doc("Item", doc.item_code, item_code, ignore_permissions=True)
|
||||
frappe.db.set_value("Clinical Procedure Template", doc.name, "item_code", item_code)
|
||||
return
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
|
||||
from frappe import _
|
||||
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'procedure_template',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Consultations'),
|
||||
'items': ['Clinical Procedure']
|
||||
}
|
||||
]
|
||||
"fieldname": "procedure_template",
|
||||
"transactions": [{"label": _("Consultations"), "items": ["Clinical Procedure"]}],
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@ import unittest
|
||||
|
||||
# test_records = frappe.get_test_records('Diagnosis')
|
||||
|
||||
|
||||
class TestDiagnosis(unittest.TestCase):
|
||||
pass
|
||||
|
||||
@@ -13,21 +13,21 @@ class DrugPrescription(Document):
|
||||
period = None
|
||||
|
||||
if self.dosage:
|
||||
dosage = frappe.get_doc('Prescription Dosage', self.dosage)
|
||||
dosage = frappe.get_doc("Prescription Dosage", self.dosage)
|
||||
for item in dosage.dosage_strength:
|
||||
quantity += item.strength
|
||||
if self.period and self.interval:
|
||||
period = frappe.get_doc('Prescription Duration', self.period)
|
||||
period = frappe.get_doc("Prescription Duration", self.period)
|
||||
if self.interval < period.get_days():
|
||||
quantity = quantity * (period.get_days()/self.interval)
|
||||
quantity = quantity * (period.get_days() / self.interval)
|
||||
|
||||
elif self.interval and self.interval_uom and self.period:
|
||||
period = frappe.get_doc('Prescription Duration', self.period)
|
||||
period = frappe.get_doc("Prescription Duration", self.period)
|
||||
interval_in = self.interval_uom
|
||||
if interval_in == 'Day' and self.interval < period.get_days():
|
||||
quantity = period.get_days()/self.interval
|
||||
elif interval_in == 'Hour' and self.interval < period.get_hours():
|
||||
quantity = period.get_hours()/self.interval
|
||||
if interval_in == "Day" and self.interval < period.get_days():
|
||||
quantity = period.get_days() / self.interval
|
||||
elif interval_in == "Hour" and self.interval < period.get_hours():
|
||||
quantity = period.get_hours() / self.interval
|
||||
if quantity > 0:
|
||||
return quantity
|
||||
else:
|
||||
|
||||
@@ -9,6 +9,6 @@ from frappe.model.document import Document
|
||||
class ExerciseType(Document):
|
||||
def autoname(self):
|
||||
if self.difficulty_level:
|
||||
self.name = ' - '.join(filter(None, [self.exercise_name, self.difficulty_level]))
|
||||
self.name = " - ".join(filter(None, [self.exercise_name, self.difficulty_level]))
|
||||
else:
|
||||
self.name = self.exercise_name
|
||||
|
||||
@@ -15,40 +15,45 @@ class FeeValidity(Document):
|
||||
|
||||
def update_status(self):
|
||||
if self.visited >= self.max_visits:
|
||||
self.status = 'Completed'
|
||||
self.status = "Completed"
|
||||
else:
|
||||
self.status = 'Pending'
|
||||
self.status = "Pending"
|
||||
|
||||
|
||||
def create_fee_validity(appointment):
|
||||
if not check_is_new_patient(appointment):
|
||||
return
|
||||
|
||||
fee_validity = frappe.new_doc('Fee Validity')
|
||||
fee_validity = frappe.new_doc("Fee Validity")
|
||||
fee_validity.practitioner = appointment.practitioner
|
||||
fee_validity.patient = appointment.patient
|
||||
fee_validity.max_visits = frappe.db.get_single_value('Healthcare Settings', 'max_visits') or 1
|
||||
valid_days = frappe.db.get_single_value('Healthcare Settings', 'valid_days') or 1
|
||||
fee_validity.max_visits = frappe.db.get_single_value("Healthcare Settings", "max_visits") or 1
|
||||
valid_days = frappe.db.get_single_value("Healthcare Settings", "valid_days") or 1
|
||||
fee_validity.visited = 0
|
||||
fee_validity.start_date = getdate(appointment.appointment_date)
|
||||
fee_validity.valid_till = getdate(appointment.appointment_date) + datetime.timedelta(days=int(valid_days))
|
||||
fee_validity.valid_till = getdate(appointment.appointment_date) + datetime.timedelta(
|
||||
days=int(valid_days)
|
||||
)
|
||||
fee_validity.save(ignore_permissions=True)
|
||||
return fee_validity
|
||||
|
||||
|
||||
def check_is_new_patient(appointment):
|
||||
validity_exists = frappe.db.exists('Fee Validity', {
|
||||
'practitioner': appointment.practitioner,
|
||||
'patient': appointment.patient
|
||||
})
|
||||
validity_exists = frappe.db.exists(
|
||||
"Fee Validity", {"practitioner": appointment.practitioner, "patient": appointment.patient}
|
||||
)
|
||||
if validity_exists:
|
||||
return False
|
||||
|
||||
appointment_exists = frappe.db.get_all('Patient Appointment', {
|
||||
'name': ('!=', appointment.name),
|
||||
'status': ('!=', 'Cancelled'),
|
||||
'patient': appointment.patient,
|
||||
'practitioner': appointment.practitioner
|
||||
})
|
||||
appointment_exists = frappe.db.get_all(
|
||||
"Patient Appointment",
|
||||
{
|
||||
"name": ("!=", appointment.name),
|
||||
"status": ("!=", "Cancelled"),
|
||||
"patient": appointment.patient,
|
||||
"practitioner": appointment.practitioner,
|
||||
},
|
||||
)
|
||||
if len(appointment_exists) and appointment_exists[0]:
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -15,6 +15,7 @@ from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment imp
|
||||
|
||||
test_dependencies = ["Company"]
|
||||
|
||||
|
||||
class TestFeeValidity(unittest.TestCase):
|
||||
def setUp(self):
|
||||
frappe.db.sql("""delete from `tabPatient Appointment`""")
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
def get_data():
|
||||
|
||||
return []
|
||||
|
||||
@@ -22,71 +22,87 @@ class HealthcarePractitioner(Document):
|
||||
# concat first and last name
|
||||
self.name = self.practitioner_name
|
||||
|
||||
if frappe.db.exists('Healthcare Practitioner', self.name):
|
||||
self.name = append_number_if_name_exists('Contact', self.name)
|
||||
if frappe.db.exists("Healthcare Practitioner", self.name):
|
||||
self.name = append_number_if_name_exists("Contact", self.name)
|
||||
|
||||
def validate(self):
|
||||
self.set_full_name()
|
||||
validate_party_accounts(self)
|
||||
if self.inpatient_visit_charge_item:
|
||||
validate_service_item(self.inpatient_visit_charge_item, 'Configure a service Item for Inpatient Consulting Charge Item')
|
||||
validate_service_item(
|
||||
self.inpatient_visit_charge_item,
|
||||
"Configure a service Item for Inpatient Consulting Charge Item",
|
||||
)
|
||||
if self.op_consulting_charge_item:
|
||||
validate_service_item(self.op_consulting_charge_item, 'Configure a service Item for Out Patient Consulting Charge Item')
|
||||
validate_service_item(
|
||||
self.op_consulting_charge_item,
|
||||
"Configure a service Item for Out Patient Consulting Charge Item",
|
||||
)
|
||||
|
||||
if self.user_id:
|
||||
self.validate_user_id()
|
||||
else:
|
||||
existing_user_id = frappe.db.get_value('Healthcare Practitioner', self.name, 'user_id')
|
||||
existing_user_id = frappe.db.get_value("Healthcare Practitioner", self.name, "user_id")
|
||||
if existing_user_id:
|
||||
frappe.permissions.remove_user_permission(
|
||||
'Healthcare Practitioner', self.name, existing_user_id)
|
||||
"Healthcare Practitioner", self.name, existing_user_id
|
||||
)
|
||||
|
||||
def on_update(self):
|
||||
if self.user_id:
|
||||
frappe.permissions.add_user_permission('Healthcare Practitioner', self.name, self.user_id)
|
||||
frappe.permissions.add_user_permission("Healthcare Practitioner", self.name, self.user_id)
|
||||
|
||||
def set_full_name(self):
|
||||
if self.last_name:
|
||||
self.practitioner_name = ' '.join(filter(None, [self.first_name, self.last_name]))
|
||||
self.practitioner_name = " ".join(filter(None, [self.first_name, self.last_name]))
|
||||
else:
|
||||
self.practitioner_name = self.first_name
|
||||
|
||||
def validate_user_id(self):
|
||||
if not frappe.db.exists('User', self.user_id):
|
||||
frappe.throw(_('User {0} does not exist').format(self.user_id))
|
||||
elif not frappe.db.exists('User', self.user_id, 'enabled'):
|
||||
frappe.throw(_('User {0} is disabled').format(self.user_id))
|
||||
if not frappe.db.exists("User", self.user_id):
|
||||
frappe.throw(_("User {0} does not exist").format(self.user_id))
|
||||
elif not frappe.db.exists("User", self.user_id, "enabled"):
|
||||
frappe.throw(_("User {0} is disabled").format(self.user_id))
|
||||
|
||||
# check duplicate
|
||||
practitioner = frappe.db.exists('Healthcare Practitioner', {
|
||||
'user_id': self.user_id,
|
||||
'name': ('!=', self.name)
|
||||
})
|
||||
practitioner = frappe.db.exists(
|
||||
"Healthcare Practitioner", {"user_id": self.user_id, "name": ("!=", self.name)}
|
||||
)
|
||||
if practitioner:
|
||||
frappe.throw(_('User {0} is already assigned to Healthcare Practitioner {1}').format(
|
||||
self.user_id, practitioner))
|
||||
frappe.throw(
|
||||
_("User {0} is already assigned to Healthcare Practitioner {1}").format(
|
||||
self.user_id, practitioner
|
||||
)
|
||||
)
|
||||
|
||||
def on_trash(self):
|
||||
delete_contact_and_address('Healthcare Practitioner', self.name)
|
||||
delete_contact_and_address("Healthcare Practitioner", self.name)
|
||||
|
||||
|
||||
def validate_service_item(item, msg):
|
||||
if frappe.db.get_value('Item', item, 'is_stock_item'):
|
||||
if frappe.db.get_value("Item", item, "is_stock_item"):
|
||||
frappe.throw(_(msg))
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_practitioner_list(doctype, txt, searchfield, start, page_len, filters=None):
|
||||
|
||||
active_filter = {'status': 'Active'}
|
||||
active_filter = {"status": "Active"}
|
||||
|
||||
filters = {**active_filter, **filters} if filters else active_filter
|
||||
|
||||
fields = ['name', 'practitioner_name', 'mobile_phone']
|
||||
fields = ["name", "practitioner_name", "mobile_phone"]
|
||||
|
||||
text_in = {
|
||||
'name': ('like', '%%%s%%' % txt),
|
||||
'practitioner_name': ('like', '%%%s%%' % txt)
|
||||
}
|
||||
text_in = {"name": ("like", "%%%s%%" % txt), "practitioner_name": ("like", "%%%s%%" % txt)}
|
||||
|
||||
return frappe.get_all('Healthcare Practitioner', fields = fields,
|
||||
filters = filters, or_filters = text_in, start=start, page_length=page_len, order_by='name, practitioner_name', as_list=1)
|
||||
return frappe.get_all(
|
||||
"Healthcare Practitioner",
|
||||
fields=fields,
|
||||
filters=filters,
|
||||
or_filters=text_in,
|
||||
start=start,
|
||||
page_length=page_len,
|
||||
order_by="name, practitioner_name",
|
||||
as_list=1,
|
||||
)
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
|
||||
from frappe import _
|
||||
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'heatmap': True,
|
||||
'heatmap_message': _('This is based on transactions against this Healthcare Practitioner.'),
|
||||
'fieldname': 'practitioner',
|
||||
'transactions': [
|
||||
"heatmap": True,
|
||||
"heatmap_message": _("This is based on transactions against this Healthcare Practitioner."),
|
||||
"fieldname": "practitioner",
|
||||
"transactions": [
|
||||
{
|
||||
'label': _('Appointments and Patient Encounters'),
|
||||
'items': ['Patient Appointment', 'Patient Encounter', 'Fee Validity']
|
||||
"label": _("Appointments and Patient Encounters"),
|
||||
"items": ["Patient Appointment", "Patient Encounter", "Fee Validity"],
|
||||
},
|
||||
{
|
||||
'label': _('Consultation'),
|
||||
'items': ['Clinical Procedure', 'Lab Test']
|
||||
}
|
||||
]
|
||||
{"label": _("Consultation"), "items": ["Clinical Procedure", "Lab Test"]},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -11,14 +11,14 @@ from frappe.utils.nestedset import NestedSet
|
||||
|
||||
|
||||
class HealthcareServiceUnit(NestedSet):
|
||||
nsm_parent_field = 'parent_healthcare_service_unit'
|
||||
nsm_parent_field = "parent_healthcare_service_unit"
|
||||
|
||||
def validate(self):
|
||||
self.set_service_unit_properties()
|
||||
|
||||
def autoname(self):
|
||||
if self.company:
|
||||
suffix = " - " + frappe.get_cached_value('Company', self.company, 'abbr')
|
||||
suffix = " - " + frappe.get_cached_value("Company", self.company, "abbr")
|
||||
if not self.healthcare_service_unit_name.endswith(suffix):
|
||||
self.name = self.healthcare_service_unit_name + suffix
|
||||
else:
|
||||
@@ -34,15 +34,15 @@ class HealthcareServiceUnit(NestedSet):
|
||||
self.overlap_appointments = False
|
||||
self.inpatient_occupancy = False
|
||||
self.service_unit_capacity = 0
|
||||
self.occupancy_status = ''
|
||||
self.service_unit_type = ''
|
||||
elif self.service_unit_type != '':
|
||||
service_unit_type = frappe.get_doc('Healthcare Service Unit Type', self.service_unit_type)
|
||||
self.occupancy_status = ""
|
||||
self.service_unit_type = ""
|
||||
elif self.service_unit_type != "":
|
||||
service_unit_type = frappe.get_doc("Healthcare Service Unit Type", self.service_unit_type)
|
||||
self.allow_appointments = service_unit_type.allow_appointments
|
||||
self.inpatient_occupancy = service_unit_type.inpatient_occupancy
|
||||
|
||||
if self.inpatient_occupancy and self.occupancy_status != '':
|
||||
self.occupancy_status = 'Vacant'
|
||||
if self.inpatient_occupancy and self.occupancy_status != "":
|
||||
self.occupancy_status = "Vacant"
|
||||
|
||||
if service_unit_type.overlap_appointments:
|
||||
self.overlap_appointments = True
|
||||
@@ -52,62 +52,78 @@ class HealthcareServiceUnit(NestedSet):
|
||||
|
||||
if self.overlap_appointments:
|
||||
if not self.service_unit_capacity:
|
||||
frappe.throw(_('Please set a valid Service Unit Capacity to enable Overlapping Appointments'),
|
||||
title=_('Mandatory'))
|
||||
frappe.throw(
|
||||
_("Please set a valid Service Unit Capacity to enable Overlapping Appointments"),
|
||||
title=_("Mandatory"),
|
||||
)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def add_multiple_service_units(parent, data):
|
||||
'''
|
||||
"""
|
||||
parent - parent service unit under which the service units are to be created
|
||||
data (dict) - company, healthcare_service_unit_name, count, service_unit_type, warehouse, service_unit_capacity
|
||||
'''
|
||||
"""
|
||||
if not parent or not data:
|
||||
return
|
||||
|
||||
data = json.loads(data)
|
||||
company = data.get('company') or \
|
||||
frappe.defaults.get_defaults().get('company') or \
|
||||
frappe.db.get_single_value('Global Defaults', 'default_company')
|
||||
company = (
|
||||
data.get("company")
|
||||
or frappe.defaults.get_defaults().get("company")
|
||||
or frappe.db.get_single_value("Global Defaults", "default_company")
|
||||
)
|
||||
|
||||
if not data.get('healthcare_service_unit_name') or not company:
|
||||
frappe.throw(_('Service Unit Name and Company are mandatory to create Healthcare Service Units'),
|
||||
title=_('Missing Required Fields'))
|
||||
if not data.get("healthcare_service_unit_name") or not company:
|
||||
frappe.throw(
|
||||
_("Service Unit Name and Company are mandatory to create Healthcare Service Units"),
|
||||
title=_("Missing Required Fields"),
|
||||
)
|
||||
|
||||
count = cint(data.get('count') or 0)
|
||||
count = cint(data.get("count") or 0)
|
||||
if count <= 0:
|
||||
frappe.throw(_('Number of Service Units to be created should at least be 1'),
|
||||
title=_('Invalid Number of Service Units'))
|
||||
frappe.throw(
|
||||
_("Number of Service Units to be created should at least be 1"),
|
||||
title=_("Invalid Number of Service Units"),
|
||||
)
|
||||
|
||||
capacity = cint(data.get('service_unit_capacity') or 1)
|
||||
capacity = cint(data.get("service_unit_capacity") or 1)
|
||||
|
||||
service_unit = {
|
||||
'doctype': 'Healthcare Service Unit',
|
||||
'parent_healthcare_service_unit': parent,
|
||||
'service_unit_type': data.get('service_unit_type') or None,
|
||||
'service_unit_capacity': capacity if capacity > 0 else 1,
|
||||
'warehouse': data.get('warehouse') or None,
|
||||
'company': company
|
||||
"doctype": "Healthcare Service Unit",
|
||||
"parent_healthcare_service_unit": parent,
|
||||
"service_unit_type": data.get("service_unit_type") or None,
|
||||
"service_unit_capacity": capacity if capacity > 0 else 1,
|
||||
"warehouse": data.get("warehouse") or None,
|
||||
"company": company,
|
||||
}
|
||||
|
||||
service_unit_name = '{}'.format(data.get('healthcare_service_unit_name').strip(' -'))
|
||||
service_unit_name = "{}".format(data.get("healthcare_service_unit_name").strip(" -"))
|
||||
|
||||
last_suffix = frappe.db.sql("""SELECT
|
||||
last_suffix = frappe.db.sql(
|
||||
"""SELECT
|
||||
IFNULL(MAX(CAST(SUBSTRING(name FROM %(start)s FOR 4) AS UNSIGNED)), 0)
|
||||
FROM `tabHealthcare Service Unit`
|
||||
WHERE name like %(prefix)s AND company=%(company)s""",
|
||||
{'start': len(service_unit_name)+2, 'prefix': '{}-%'.format(service_unit_name), 'company': company},
|
||||
as_list=1)[0][0]
|
||||
{
|
||||
"start": len(service_unit_name) + 2,
|
||||
"prefix": "{}-%".format(service_unit_name),
|
||||
"company": company,
|
||||
},
|
||||
as_list=1,
|
||||
)[0][0]
|
||||
start_suffix = cint(last_suffix) + 1
|
||||
|
||||
failed_list = []
|
||||
for i in range(start_suffix, count + start_suffix):
|
||||
# name to be in the form WARD-####
|
||||
service_unit['healthcare_service_unit_name'] = '{}-{}'.format(service_unit_name, cstr('%0*d' % (4, i)))
|
||||
service_unit["healthcare_service_unit_name"] = "{}-{}".format(
|
||||
service_unit_name, cstr("%0*d" % (4, i))
|
||||
)
|
||||
service_unit_doc = frappe.get_doc(service_unit)
|
||||
try:
|
||||
service_unit_doc.insert()
|
||||
except Exception:
|
||||
failed_list.append(service_unit['healthcare_service_unit_name'])
|
||||
failed_list.append(service_unit["healthcare_service_unit_name"])
|
||||
|
||||
return failed_list
|
||||
|
||||
@@ -12,15 +12,21 @@ class HealthcareServiceUnitType(Document):
|
||||
def validate(self):
|
||||
if self.allow_appointments and self.inpatient_occupancy:
|
||||
frappe.msgprint(
|
||||
_('Healthcare Service Unit Type cannot have both {0} and {1}').format(
|
||||
frappe.bold('Allow Appointments'), frappe.bold('Inpatient Occupancy')),
|
||||
raise_exception=1, title=_('Validation Error'), indicator='red'
|
||||
_("Healthcare Service Unit Type cannot have both {0} and {1}").format(
|
||||
frappe.bold("Allow Appointments"), frappe.bold("Inpatient Occupancy")
|
||||
),
|
||||
raise_exception=1,
|
||||
title=_("Validation Error"),
|
||||
indicator="red",
|
||||
)
|
||||
elif not self.allow_appointments and not self.inpatient_occupancy:
|
||||
frappe.msgprint(
|
||||
_('Healthcare Service Unit Type must allow atleast one among {0} and {1}').format(
|
||||
frappe.bold('Allow Appointments'), frappe.bold('Inpatient Occupancy')),
|
||||
raise_exception=1, title=_('Validation Error'), indicator='red'
|
||||
_("Healthcare Service Unit Type must allow atleast one among {0} and {1}").format(
|
||||
frappe.bold("Allow Appointments"), frappe.bold("Inpatient Occupancy")
|
||||
),
|
||||
raise_exception=1,
|
||||
title=_("Validation Error"),
|
||||
indicator="red",
|
||||
)
|
||||
|
||||
if not self.allow_appointments:
|
||||
@@ -28,9 +34,9 @@ class HealthcareServiceUnitType(Document):
|
||||
|
||||
if self.is_billable:
|
||||
if self.disabled:
|
||||
frappe.db.set_value('Item', self.item, 'disabled', 1)
|
||||
frappe.db.set_value("Item", self.item, "disabled", 1)
|
||||
else:
|
||||
frappe.db.set_value('Item', self.item, 'disabled', 0)
|
||||
frappe.db.set_value("Item", self.item, "disabled", 0)
|
||||
|
||||
def after_insert(self):
|
||||
if self.inpatient_occupancy and self.is_billable:
|
||||
@@ -40,10 +46,10 @@ class HealthcareServiceUnitType(Document):
|
||||
if self.item:
|
||||
try:
|
||||
item = self.item
|
||||
self.db_set('item', '')
|
||||
frappe.delete_doc('Item', item)
|
||||
self.db_set("item", "")
|
||||
frappe.delete_doc("Item", item)
|
||||
except Exception:
|
||||
frappe.throw(_('Not permitted. Please disable the Service Unit Type'))
|
||||
frappe.throw(_("Not permitted. Please disable the Service Unit Type"))
|
||||
|
||||
def on_update(self):
|
||||
if self.change_in_item and self.is_billable and self.item:
|
||||
@@ -52,47 +58,50 @@ class HealthcareServiceUnitType(Document):
|
||||
item_price = item_price_exists(self)
|
||||
|
||||
if not item_price:
|
||||
price_list_name = frappe.db.get_value('Price List', {'selling': 1})
|
||||
price_list_name = frappe.db.get_value("Price List", {"selling": 1})
|
||||
if self.rate:
|
||||
make_item_price(self.item_code, price_list_name, self.rate)
|
||||
else:
|
||||
make_item_price(self.item_code, price_list_name, 0.0)
|
||||
else:
|
||||
frappe.db.set_value('Item Price', item_price, 'price_list_rate', self.rate)
|
||||
frappe.db.set_value("Item Price", item_price, "price_list_rate", self.rate)
|
||||
|
||||
frappe.db.set_value(self.doctype, self.name, 'change_in_item',0)
|
||||
frappe.db.set_value(self.doctype, self.name, "change_in_item", 0)
|
||||
elif not self.is_billable and self.item:
|
||||
frappe.db.set_value('Item', self.item, 'disabled', 1)
|
||||
frappe.db.set_value("Item", self.item, "disabled", 1)
|
||||
self.reload()
|
||||
|
||||
|
||||
def item_price_exists(doc):
|
||||
item_price = frappe.db.exists({'doctype': 'Item Price', 'item_code': doc.item_code})
|
||||
item_price = frappe.db.exists({"doctype": "Item Price", "item_code": doc.item_code})
|
||||
if len(item_price):
|
||||
return item_price[0][0]
|
||||
return False
|
||||
|
||||
|
||||
def create_item(doc):
|
||||
# insert item
|
||||
item = frappe.get_doc({
|
||||
'doctype': 'Item',
|
||||
'item_code': doc.item_code,
|
||||
'item_name': doc.service_unit_type,
|
||||
'item_group': doc.item_group,
|
||||
'description': doc.description or doc.item_code,
|
||||
'is_sales_item': 1,
|
||||
'is_service_item': 1,
|
||||
'is_purchase_item': 0,
|
||||
'is_stock_item': 0,
|
||||
'show_in_website': 0,
|
||||
'is_pro_applicable': 0,
|
||||
'disabled': 0,
|
||||
'stock_uom': doc.uom
|
||||
}).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
item = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Item",
|
||||
"item_code": doc.item_code,
|
||||
"item_name": doc.service_unit_type,
|
||||
"item_group": doc.item_group,
|
||||
"description": doc.description or doc.item_code,
|
||||
"is_sales_item": 1,
|
||||
"is_service_item": 1,
|
||||
"is_purchase_item": 0,
|
||||
"is_stock_item": 0,
|
||||
"show_in_website": 0,
|
||||
"is_pro_applicable": 0,
|
||||
"disabled": 0,
|
||||
"stock_uom": doc.uom,
|
||||
}
|
||||
).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
|
||||
# insert item price
|
||||
# get item price list to insert item price
|
||||
price_list_name = frappe.db.get_value('Price List', {'selling': 1})
|
||||
price_list_name = frappe.db.get_value("Price List", {"selling": 1})
|
||||
if doc.rate:
|
||||
make_item_price(item.name, price_list_name, doc.rate)
|
||||
item.standard_rate = doc.rate
|
||||
@@ -103,32 +112,39 @@ def create_item(doc):
|
||||
item.save(ignore_permissions=True)
|
||||
|
||||
# Set item in the doc
|
||||
doc.db_set('item', item.name)
|
||||
doc.db_set("item", item.name)
|
||||
|
||||
|
||||
def make_item_price(item, price_list_name, item_price):
|
||||
frappe.get_doc({
|
||||
'doctype': 'Item Price',
|
||||
'price_list': price_list_name,
|
||||
'item_code': item,
|
||||
'price_list_rate': item_price
|
||||
}).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
frappe.get_doc(
|
||||
{
|
||||
"doctype": "Item Price",
|
||||
"price_list": price_list_name,
|
||||
"item_code": item,
|
||||
"price_list_rate": item_price,
|
||||
}
|
||||
).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
|
||||
|
||||
def update_item(doc):
|
||||
item = frappe.get_doc("Item", doc.item)
|
||||
if item:
|
||||
item.update({
|
||||
"item_name": doc.service_unit_type,
|
||||
"item_group": doc.item_group,
|
||||
"disabled": 0,
|
||||
"standard_rate": doc.rate,
|
||||
"description": doc.description
|
||||
})
|
||||
item.update(
|
||||
{
|
||||
"item_name": doc.service_unit_type,
|
||||
"item_group": doc.item_group,
|
||||
"disabled": 0,
|
||||
"standard_rate": doc.rate,
|
||||
"description": doc.description,
|
||||
}
|
||||
)
|
||||
item.db_update()
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def change_item_code(item, item_code, doc_name):
|
||||
if frappe.db.exists({'doctype': 'Item', 'item_code': item_code}):
|
||||
frappe.throw(_('Item with Item Code {0} already exists').format(item_code))
|
||||
if frappe.db.exists({"doctype": "Item", "item_code": item_code}):
|
||||
frappe.throw(_("Item with Item Code {0} already exists").format(item_code))
|
||||
else:
|
||||
rename_doc('Item', item, item_code, ignore_permissions=True)
|
||||
frappe.db.set_value('Healthcare Service Unit Type', doc_name, 'item_code', item_code)
|
||||
rename_doc("Item", item, item_code, ignore_permissions=True)
|
||||
frappe.db.set_value("Healthcare Service Unit Type", doc_name, "item_code", item_code)
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
|
||||
from frappe import _
|
||||
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'service_unit_type',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Healthcare Service Units'),
|
||||
'items': ['Healthcare Service Unit']
|
||||
},
|
||||
]
|
||||
"fieldname": "service_unit_type",
|
||||
"transactions": [
|
||||
{"label": _("Healthcare Service Units"), "items": ["Healthcare Service Unit"]},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -9,25 +9,25 @@ import frappe
|
||||
class TestHealthcareServiceUnitType(unittest.TestCase):
|
||||
def test_item_creation(self):
|
||||
unit_type = get_unit_type()
|
||||
self.assertTrue(frappe.db.exists('Item', unit_type.item))
|
||||
self.assertTrue(frappe.db.exists("Item", unit_type.item))
|
||||
|
||||
# check item disabled
|
||||
unit_type.disabled = 1
|
||||
unit_type.save()
|
||||
self.assertEqual(frappe.db.get_value('Item', unit_type.item, 'disabled'), 1)
|
||||
self.assertEqual(frappe.db.get_value("Item", unit_type.item, "disabled"), 1)
|
||||
|
||||
|
||||
def get_unit_type():
|
||||
if frappe.db.exists('Healthcare Service Unit Type', 'Inpatient Rooms'):
|
||||
return frappe.get_doc('Healthcare Service Unit Type', 'Inpatient Rooms')
|
||||
if frappe.db.exists("Healthcare Service Unit Type", "Inpatient Rooms"):
|
||||
return frappe.get_doc("Healthcare Service Unit Type", "Inpatient Rooms")
|
||||
|
||||
unit_type = frappe.new_doc('Healthcare Service Unit Type')
|
||||
unit_type.service_unit_type = 'Inpatient Rooms'
|
||||
unit_type = frappe.new_doc("Healthcare Service Unit Type")
|
||||
unit_type.service_unit_type = "Inpatient Rooms"
|
||||
unit_type.inpatient_occupancy = 1
|
||||
unit_type.is_billable = 1
|
||||
unit_type.item_code = 'Inpatient Rooms'
|
||||
unit_type.item_group = 'Services'
|
||||
unit_type.uom = 'Hour'
|
||||
unit_type.item_code = "Inpatient Rooms"
|
||||
unit_type.item_group = "Services"
|
||||
unit_type.uom = "Hour"
|
||||
unit_type.no_of_hours = 1
|
||||
unit_type.rate = 4000
|
||||
unit_type.save()
|
||||
|
||||
@@ -12,13 +12,19 @@ from frappe.model.document import Document
|
||||
|
||||
class HealthcareSettings(Document):
|
||||
def validate(self):
|
||||
for key in ['collect_registration_fee', 'link_customer_to_patient', 'patient_name_by',
|
||||
'lab_test_approval_required', 'create_sample_collection_for_lab_test', 'default_medical_code_standard']:
|
||||
for key in [
|
||||
"collect_registration_fee",
|
||||
"link_customer_to_patient",
|
||||
"patient_name_by",
|
||||
"lab_test_approval_required",
|
||||
"create_sample_collection_for_lab_test",
|
||||
"default_medical_code_standard",
|
||||
]:
|
||||
frappe.db.set_default(key, self.get(key, ""))
|
||||
|
||||
if self.collect_registration_fee:
|
||||
if self.registration_fee <= 0:
|
||||
frappe.throw(_('Registration Fee cannot be negative or zero'))
|
||||
frappe.throw(_("Registration Fee cannot be negative or zero"))
|
||||
|
||||
if self.inpatient_visit_charge_item:
|
||||
validate_service_item(self.inpatient_visit_charge_item)
|
||||
@@ -29,63 +35,70 @@ class HealthcareSettings(Document):
|
||||
|
||||
|
||||
def validate_service_item(item):
|
||||
if frappe.db.get_value('Item', item, 'is_stock_item'):
|
||||
frappe.throw(_('Configure a service Item for {0}').format(item))
|
||||
if frappe.db.get_value("Item", item, "is_stock_item"):
|
||||
frappe.throw(_("Configure a service Item for {0}").format(item))
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_sms_text(doc):
|
||||
sms_text = {}
|
||||
doc = frappe.get_doc('Lab Test', doc)
|
||||
context = {'doc': doc, 'alert': doc, 'comments': None}
|
||||
doc = frappe.get_doc("Lab Test", doc)
|
||||
context = {"doc": doc, "alert": doc, "comments": None}
|
||||
|
||||
emailed = frappe.db.get_value('Healthcare Settings', None, 'sms_emailed')
|
||||
sms_text['emailed'] = frappe.render_template(emailed, context)
|
||||
emailed = frappe.db.get_value("Healthcare Settings", None, "sms_emailed")
|
||||
sms_text["emailed"] = frappe.render_template(emailed, context)
|
||||
|
||||
printed = frappe.db.get_value('Healthcare Settings', None, 'sms_printed')
|
||||
sms_text['printed'] = frappe.render_template(printed, context)
|
||||
printed = frappe.db.get_value("Healthcare Settings", None, "sms_printed")
|
||||
sms_text["printed"] = frappe.render_template(printed, context)
|
||||
|
||||
return sms_text
|
||||
|
||||
|
||||
def send_registration_sms(doc):
|
||||
if frappe.db.get_single_value('Healthcare Settings', 'send_registration_msg'):
|
||||
if frappe.db.get_single_value("Healthcare Settings", "send_registration_msg"):
|
||||
if doc.mobile:
|
||||
context = {'doc': doc, 'alert': doc, 'comments': None}
|
||||
if doc.get('_comments'):
|
||||
context['comments'] = json.loads(doc.get('_comments'))
|
||||
messages = frappe.db.get_single_value('Healthcare Settings', 'registration_msg')
|
||||
context = {"doc": doc, "alert": doc, "comments": None}
|
||||
if doc.get("_comments"):
|
||||
context["comments"] = json.loads(doc.get("_comments"))
|
||||
messages = frappe.db.get_single_value("Healthcare Settings", "registration_msg")
|
||||
messages = frappe.render_template(messages, context)
|
||||
number = [doc.mobile]
|
||||
send_sms(number,messages)
|
||||
send_sms(number, messages)
|
||||
else:
|
||||
frappe.msgprint(doc.name + ' has no mobile number to send registration SMS', alert=True)
|
||||
frappe.msgprint(doc.name + " has no mobile number to send registration SMS", alert=True)
|
||||
|
||||
|
||||
def get_receivable_account(company):
|
||||
receivable_account = get_account(None, 'receivable_account', 'Healthcare Settings', company)
|
||||
receivable_account = get_account(None, "receivable_account", "Healthcare Settings", company)
|
||||
if receivable_account:
|
||||
return receivable_account
|
||||
|
||||
return frappe.get_cached_value('Company', company, 'default_receivable_account')
|
||||
return frappe.get_cached_value("Company", company, "default_receivable_account")
|
||||
|
||||
|
||||
def get_income_account(practitioner, company):
|
||||
# check income account in Healthcare Practitioner
|
||||
if practitioner:
|
||||
income_account = get_account('Healthcare Practitioner', None, practitioner, company)
|
||||
income_account = get_account("Healthcare Practitioner", None, practitioner, company)
|
||||
if income_account:
|
||||
return income_account
|
||||
|
||||
# else check income account in Healthcare Settings
|
||||
income_account = get_account(None, 'income_account', 'Healthcare Settings', company)
|
||||
income_account = get_account(None, "income_account", "Healthcare Settings", company)
|
||||
if income_account:
|
||||
return income_account
|
||||
|
||||
# else return default income account of company
|
||||
return frappe.get_cached_value('Company', company, 'default_income_account')
|
||||
return frappe.get_cached_value("Company", company, "default_income_account")
|
||||
|
||||
|
||||
def get_account(parent_type, parent_field, parent, company):
|
||||
if parent_type:
|
||||
return frappe.db.get_value('Party Account',
|
||||
{'parenttype': parent_type, 'parent': parent, 'company': company}, 'account')
|
||||
return frappe.db.get_value(
|
||||
"Party Account", {"parenttype": parent_type, "parent": parent, "company": company}, "account"
|
||||
)
|
||||
|
||||
if parent_field:
|
||||
return frappe.db.get_value('Party Account',
|
||||
{'parentfield': parent_field, 'parent': parent, 'company': company}, 'account')
|
||||
return frappe.db.get_value(
|
||||
"Party Account", {"parentfield": parent_field, "parent": parent, "company": company}, "account"
|
||||
)
|
||||
|
||||
@@ -24,59 +24,68 @@ class InpatientMedicationEntry(Document):
|
||||
self.add_mo_to_table(orders)
|
||||
return self
|
||||
else:
|
||||
self.set('medication_orders', [])
|
||||
frappe.msgprint(_('No pending medication orders found for selected criteria'))
|
||||
self.set("medication_orders", [])
|
||||
frappe.msgprint(_("No pending medication orders found for selected criteria"))
|
||||
|
||||
def add_mo_to_table(self, orders):
|
||||
# Add medication orders in the child table
|
||||
self.set('medication_orders', [])
|
||||
self.set("medication_orders", [])
|
||||
|
||||
for data in orders:
|
||||
self.append('medication_orders', {
|
||||
'patient': data.patient,
|
||||
'patient_name': data.patient_name,
|
||||
'inpatient_record': data.inpatient_record,
|
||||
'service_unit': data.service_unit,
|
||||
'datetime': "%s %s" % (data.date, data.time or "00:00:00"),
|
||||
'drug_code': data.drug,
|
||||
'drug_name': data.drug_name,
|
||||
'dosage': data.dosage,
|
||||
'dosage_form': data.dosage_form,
|
||||
'against_imo': data.parent,
|
||||
'against_imoe': data.name
|
||||
})
|
||||
self.append(
|
||||
"medication_orders",
|
||||
{
|
||||
"patient": data.patient,
|
||||
"patient_name": data.patient_name,
|
||||
"inpatient_record": data.inpatient_record,
|
||||
"service_unit": data.service_unit,
|
||||
"datetime": "%s %s" % (data.date, data.time or "00:00:00"),
|
||||
"drug_code": data.drug,
|
||||
"drug_name": data.drug_name,
|
||||
"dosage": data.dosage,
|
||||
"dosage_form": data.dosage_form,
|
||||
"against_imo": data.parent,
|
||||
"against_imoe": data.name,
|
||||
},
|
||||
)
|
||||
|
||||
def on_submit(self):
|
||||
self.validate_medication_orders()
|
||||
success_msg = ""
|
||||
if self.update_stock:
|
||||
stock_entry = self.process_stock()
|
||||
success_msg += _('Stock Entry {0} created and ').format(
|
||||
frappe.bold(get_link_to_form('Stock Entry', stock_entry)))
|
||||
success_msg += _("Stock Entry {0} created and ").format(
|
||||
frappe.bold(get_link_to_form("Stock Entry", stock_entry))
|
||||
)
|
||||
|
||||
self.update_medication_orders()
|
||||
success_msg += _('Inpatient Medication Orders updated successfully')
|
||||
frappe.msgprint(success_msg, title=_('Success'), indicator='green')
|
||||
success_msg += _("Inpatient Medication Orders updated successfully")
|
||||
frappe.msgprint(success_msg, title=_("Success"), indicator="green")
|
||||
|
||||
def validate_medication_orders(self):
|
||||
for entry in self.medication_orders:
|
||||
docstatus, is_completed = frappe.db.get_value('Inpatient Medication Order Entry', entry.against_imoe,
|
||||
['docstatus', 'is_completed'])
|
||||
docstatus, is_completed = frappe.db.get_value(
|
||||
"Inpatient Medication Order Entry", entry.against_imoe, ["docstatus", "is_completed"]
|
||||
)
|
||||
|
||||
if docstatus == 2:
|
||||
frappe.throw(_('Row {0}: Cannot create Inpatient Medication Entry against cancelled Inpatient Medication Order {1}').format(
|
||||
entry.idx, get_link_to_form(entry.against_imo)))
|
||||
frappe.throw(
|
||||
_(
|
||||
"Row {0}: Cannot create Inpatient Medication Entry against cancelled Inpatient Medication Order {1}"
|
||||
).format(entry.idx, get_link_to_form(entry.against_imo))
|
||||
)
|
||||
|
||||
if is_completed:
|
||||
frappe.throw(_('Row {0}: This Medication Order is already marked as completed').format(
|
||||
entry.idx))
|
||||
frappe.throw(
|
||||
_("Row {0}: This Medication Order is already marked as completed").format(entry.idx)
|
||||
)
|
||||
|
||||
def on_cancel(self):
|
||||
self.cancel_stock_entries()
|
||||
self.update_medication_orders(on_cancel=True)
|
||||
|
||||
def process_stock(self):
|
||||
allow_negative_stock = frappe.db.get_single_value('Stock Settings', 'allow_negative_stock')
|
||||
allow_negative_stock = frappe.db.get_single_value("Stock Settings", "allow_negative_stock")
|
||||
if not allow_negative_stock:
|
||||
self.check_stock_qty()
|
||||
|
||||
@@ -89,24 +98,27 @@ class InpatientMedicationEntry(Document):
|
||||
if on_cancel:
|
||||
is_completed = 0
|
||||
|
||||
frappe.db.sql("""
|
||||
frappe.db.sql(
|
||||
"""
|
||||
UPDATE `tabInpatient Medication Order Entry`
|
||||
SET is_completed = %(is_completed)s
|
||||
WHERE name IN %(orders)s
|
||||
""", {'orders': orders, 'is_completed': is_completed})
|
||||
""",
|
||||
{"orders": orders, "is_completed": is_completed},
|
||||
)
|
||||
|
||||
# update status and completed orders count
|
||||
for order, count in order_entry_map.items():
|
||||
medication_order = frappe.get_doc('Inpatient Medication Order', order)
|
||||
medication_order = frappe.get_doc("Inpatient Medication Order", order)
|
||||
completed_orders = flt(count)
|
||||
current_value = frappe.db.get_value('Inpatient Medication Order', order, 'completed_orders')
|
||||
current_value = frappe.db.get_value("Inpatient Medication Order", order, "completed_orders")
|
||||
|
||||
if on_cancel:
|
||||
completed_orders = flt(current_value) - flt(count)
|
||||
else:
|
||||
completed_orders = flt(current_value) + flt(count)
|
||||
|
||||
medication_order.db_set('completed_orders', completed_orders)
|
||||
medication_order.db_set("completed_orders", completed_orders)
|
||||
medication_order.set_status()
|
||||
|
||||
def get_order_entry_map(self):
|
||||
@@ -129,17 +141,23 @@ class InpatientMedicationEntry(Document):
|
||||
drug_shortage = get_drug_shortage_map(self.medication_orders, self.warehouse)
|
||||
|
||||
if drug_shortage:
|
||||
message = _('Quantity not available for the following items in warehouse {0}. ').format(frappe.bold(self.warehouse))
|
||||
message += _('Please enable Allow Negative Stock in Stock Settings or create Stock Entry to proceed.')
|
||||
message = _("Quantity not available for the following items in warehouse {0}. ").format(
|
||||
frappe.bold(self.warehouse)
|
||||
)
|
||||
message += _(
|
||||
"Please enable Allow Negative Stock in Stock Settings or create Stock Entry to proceed."
|
||||
)
|
||||
|
||||
formatted_item_rows = ''
|
||||
formatted_item_rows = ""
|
||||
|
||||
for drug, shortage_qty in drug_shortage.items():
|
||||
item_link = get_link_to_form('Item', drug)
|
||||
item_link = get_link_to_form("Item", drug)
|
||||
formatted_item_rows += """
|
||||
<td>{0}</td>
|
||||
<td>{1}</td>
|
||||
</tr>""".format(item_link, frappe.bold(shortage_qty))
|
||||
</tr>""".format(
|
||||
item_link, frappe.bold(shortage_qty)
|
||||
)
|
||||
|
||||
message += """
|
||||
<table class='table'>
|
||||
@@ -149,25 +167,27 @@ class InpatientMedicationEntry(Document):
|
||||
</thead>
|
||||
{2}
|
||||
</table>
|
||||
""".format(_('Drug Code'), _('Shortage Qty'), formatted_item_rows)
|
||||
""".format(
|
||||
_("Drug Code"), _("Shortage Qty"), formatted_item_rows
|
||||
)
|
||||
|
||||
frappe.throw(message, title=_('Insufficient Stock'), is_minimizable=True, wide=True)
|
||||
frappe.throw(message, title=_("Insufficient Stock"), is_minimizable=True, wide=True)
|
||||
|
||||
def make_stock_entry(self):
|
||||
stock_entry = frappe.new_doc('Stock Entry')
|
||||
stock_entry.purpose = 'Material Issue'
|
||||
stock_entry = frappe.new_doc("Stock Entry")
|
||||
stock_entry.purpose = "Material Issue"
|
||||
stock_entry.set_stock_entry_type()
|
||||
stock_entry.from_warehouse = self.warehouse
|
||||
stock_entry.company = self.company
|
||||
stock_entry.inpatient_medication_entry = self.name
|
||||
cost_center = frappe.get_cached_value('Company', self.company, 'cost_center')
|
||||
expense_account = get_account(None, 'expense_account', 'Healthcare Settings', self.company)
|
||||
cost_center = frappe.get_cached_value("Company", self.company, "cost_center")
|
||||
expense_account = get_account(None, "expense_account", "Healthcare Settings", self.company)
|
||||
|
||||
for entry in self.medication_orders:
|
||||
se_child = stock_entry.append('items')
|
||||
se_child = stock_entry.append("items")
|
||||
se_child.item_code = entry.drug_code
|
||||
se_child.item_name = entry.drug_name
|
||||
se_child.uom = frappe.db.get_value('Item', entry.drug_code, 'stock_uom')
|
||||
se_child.uom = frappe.db.get_value("Item", entry.drug_code, "stock_uom")
|
||||
se_child.stock_uom = se_child.uom
|
||||
se_child.qty = flt(entry.dosage)
|
||||
# in stock uom
|
||||
@@ -182,9 +202,9 @@ class InpatientMedicationEntry(Document):
|
||||
return stock_entry.name
|
||||
|
||||
def cancel_stock_entries(self):
|
||||
stock_entries = frappe.get_all('Stock Entry', {'inpatient_medication_entry': self.name})
|
||||
stock_entries = frappe.get_all("Stock Entry", {"inpatient_medication_entry": self.name})
|
||||
for entry in stock_entries:
|
||||
doc = frappe.get_doc('Stock Entry', entry.name)
|
||||
doc = frappe.get_doc("Stock Entry", entry.name)
|
||||
doc.cancel()
|
||||
|
||||
|
||||
@@ -192,7 +212,8 @@ def get_pending_medication_orders(entry):
|
||||
filters, values = get_filters(entry)
|
||||
to_remove = []
|
||||
|
||||
data = frappe.db.sql("""
|
||||
data = frappe.db.sql(
|
||||
"""
|
||||
SELECT
|
||||
ip.inpatient_record, ip.patient, ip.patient_name,
|
||||
entry.name, entry.parent, entry.drug, entry.drug_name,
|
||||
@@ -210,12 +231,17 @@ def get_pending_medication_orders(entry):
|
||||
{0}
|
||||
ORDER BY
|
||||
entry.date, entry.time
|
||||
""".format(filters), values, as_dict=1)
|
||||
""".format(
|
||||
filters
|
||||
),
|
||||
values,
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
for doc in data:
|
||||
inpatient_record = doc.inpatient_record
|
||||
if inpatient_record:
|
||||
doc['service_unit'] = get_current_healthcare_service_unit(inpatient_record)
|
||||
doc["service_unit"] = get_current_healthcare_service_unit(inpatient_record)
|
||||
|
||||
if entry.service_unit and doc.service_unit != entry.service_unit:
|
||||
to_remove.append(doc)
|
||||
@@ -227,53 +253,53 @@ def get_pending_medication_orders(entry):
|
||||
|
||||
|
||||
def get_filters(entry):
|
||||
filters = ''
|
||||
filters = ""
|
||||
values = dict(company=entry.company)
|
||||
if entry.from_date:
|
||||
filters += ' and entry.date >= %(from_date)s'
|
||||
values['from_date'] = entry.from_date
|
||||
filters += " and entry.date >= %(from_date)s"
|
||||
values["from_date"] = entry.from_date
|
||||
|
||||
if entry.to_date:
|
||||
filters += ' and entry.date <= %(to_date)s'
|
||||
values['to_date'] = entry.to_date
|
||||
filters += " and entry.date <= %(to_date)s"
|
||||
values["to_date"] = entry.to_date
|
||||
|
||||
if entry.from_time:
|
||||
filters += ' and entry.time >= %(from_time)s'
|
||||
values['from_time'] = entry.from_time
|
||||
filters += " and entry.time >= %(from_time)s"
|
||||
values["from_time"] = entry.from_time
|
||||
|
||||
if entry.to_time:
|
||||
filters += ' and entry.time <= %(to_time)s'
|
||||
values['to_time'] = entry.to_time
|
||||
filters += " and entry.time <= %(to_time)s"
|
||||
values["to_time"] = entry.to_time
|
||||
|
||||
if entry.patient:
|
||||
filters += ' and ip.patient = %(patient)s'
|
||||
values['patient'] = entry.patient
|
||||
filters += " and ip.patient = %(patient)s"
|
||||
values["patient"] = entry.patient
|
||||
|
||||
if entry.practitioner:
|
||||
filters += ' and ip.practitioner = %(practitioner)s'
|
||||
values['practitioner'] = entry.practitioner
|
||||
filters += " and ip.practitioner = %(practitioner)s"
|
||||
values["practitioner"] = entry.practitioner
|
||||
|
||||
if entry.item_code:
|
||||
filters += ' and entry.drug = %(item_code)s'
|
||||
values['item_code'] = entry.item_code
|
||||
filters += " and entry.drug = %(item_code)s"
|
||||
values["item_code"] = entry.item_code
|
||||
|
||||
if entry.assigned_to_practitioner:
|
||||
filters += ' and ip._assign LIKE %(assigned_to)s'
|
||||
values['assigned_to'] = '%' + entry.assigned_to_practitioner + '%'
|
||||
filters += " and ip._assign LIKE %(assigned_to)s"
|
||||
values["assigned_to"] = "%" + entry.assigned_to_practitioner + "%"
|
||||
|
||||
return filters, values
|
||||
|
||||
|
||||
def get_current_healthcare_service_unit(inpatient_record):
|
||||
ip_record = frappe.get_doc('Inpatient Record', inpatient_record)
|
||||
if ip_record.status in ['Admitted', 'Discharge Scheduled'] and ip_record.inpatient_occupancies:
|
||||
ip_record = frappe.get_doc("Inpatient Record", inpatient_record)
|
||||
if ip_record.status in ["Admitted", "Discharge Scheduled"] and ip_record.inpatient_occupancies:
|
||||
return ip_record.inpatient_occupancies[-1].service_unit
|
||||
return
|
||||
|
||||
|
||||
def get_drug_shortage_map(medication_orders, warehouse):
|
||||
"""
|
||||
Returns a dict like { drug_code: shortage_qty }
|
||||
Returns a dict like { drug_code: shortage_qty }
|
||||
"""
|
||||
drug_requirement = dict()
|
||||
for d in medication_orders:
|
||||
@@ -292,25 +318,25 @@ def get_drug_shortage_map(medication_orders, warehouse):
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_difference_stock_entry(docname):
|
||||
doc = frappe.get_doc('Inpatient Medication Entry', docname)
|
||||
doc = frappe.get_doc("Inpatient Medication Entry", docname)
|
||||
drug_shortage = get_drug_shortage_map(doc.medication_orders, doc.warehouse)
|
||||
|
||||
if not drug_shortage:
|
||||
return None
|
||||
|
||||
stock_entry = frappe.new_doc('Stock Entry')
|
||||
stock_entry.purpose = 'Material Transfer'
|
||||
stock_entry = frappe.new_doc("Stock Entry")
|
||||
stock_entry.purpose = "Material Transfer"
|
||||
stock_entry.set_stock_entry_type()
|
||||
stock_entry.to_warehouse = doc.warehouse
|
||||
stock_entry.company = doc.company
|
||||
cost_center = frappe.get_cached_value('Company', doc.company, 'cost_center')
|
||||
expense_account = get_account(None, 'expense_account', 'Healthcare Settings', doc.company)
|
||||
cost_center = frappe.get_cached_value("Company", doc.company, "cost_center")
|
||||
expense_account = get_account(None, "expense_account", "Healthcare Settings", doc.company)
|
||||
|
||||
for drug, shortage_qty in drug_shortage.items():
|
||||
se_child = stock_entry.append('items')
|
||||
se_child = stock_entry.append("items")
|
||||
se_child.item_code = drug
|
||||
se_child.item_name = frappe.db.get_value('Item', drug, 'stock_uom')
|
||||
se_child.uom = frappe.db.get_value('Item', drug, 'stock_uom')
|
||||
se_child.item_name = frappe.db.get_value("Item", drug, "stock_uom")
|
||||
se_child.uom = frappe.db.get_value("Item", drug, "stock_uom")
|
||||
se_child.stock_uom = se_child.uom
|
||||
se_child.qty = flt(shortage_qty)
|
||||
se_child.t_warehouse = doc.warehouse
|
||||
|
||||
@@ -1,17 +1,9 @@
|
||||
|
||||
from frappe import _
|
||||
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'against_imoe',
|
||||
'internal_links': {
|
||||
'Inpatient Medication Order': ['medication_orders', 'against_imo']
|
||||
},
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Reference'),
|
||||
'items': ['Inpatient Medication Order']
|
||||
}
|
||||
]
|
||||
"fieldname": "against_imoe",
|
||||
"internal_links": {"Inpatient Medication Order": ["medication_orders", "against_imo"]},
|
||||
"transactions": [{"label": _("Reference"), "items": ["Inpatient Medication Order"]}],
|
||||
}
|
||||
|
||||
@@ -53,10 +53,10 @@ class TestInpatientMedicationEntry(unittest.TestCase):
|
||||
filters = frappe._dict(
|
||||
from_date=date,
|
||||
to_date=date,
|
||||
from_time='',
|
||||
to_time='',
|
||||
item_code='Dextromethorphan',
|
||||
patient=self.patient
|
||||
from_time="",
|
||||
to_time="",
|
||||
item_code="Dextromethorphan",
|
||||
patient=self.patient,
|
||||
)
|
||||
|
||||
ipme = create_ipme(filters, update_stock=0)
|
||||
@@ -74,10 +74,10 @@ class TestInpatientMedicationEntry(unittest.TestCase):
|
||||
filters = frappe._dict(
|
||||
from_date=date,
|
||||
to_date=date,
|
||||
from_time='',
|
||||
to_time='',
|
||||
item_code='Dextromethorphan',
|
||||
patient=self.patient
|
||||
from_time="",
|
||||
to_time="",
|
||||
item_code="Dextromethorphan",
|
||||
patient=self.patient,
|
||||
)
|
||||
|
||||
make_stock_entry()
|
||||
@@ -86,18 +86,21 @@ class TestInpatientMedicationEntry(unittest.TestCase):
|
||||
ipme.reload()
|
||||
|
||||
# test order completed
|
||||
is_order_completed = frappe.db.get_value('Inpatient Medication Order Entry',
|
||||
ipme.medication_orders[0].against_imoe, 'is_completed')
|
||||
is_order_completed = frappe.db.get_value(
|
||||
"Inpatient Medication Order Entry", ipme.medication_orders[0].against_imoe, "is_completed"
|
||||
)
|
||||
self.assertEqual(is_order_completed, 1)
|
||||
|
||||
# test stock entry
|
||||
stock_entry = frappe.db.exists('Stock Entry', {'inpatient_medication_entry': ipme.name})
|
||||
stock_entry = frappe.db.exists("Stock Entry", {"inpatient_medication_entry": ipme.name})
|
||||
self.assertTrue(stock_entry)
|
||||
|
||||
# check references
|
||||
stock_entry = frappe.get_doc('Stock Entry', stock_entry)
|
||||
stock_entry = frappe.get_doc("Stock Entry", stock_entry)
|
||||
self.assertEqual(stock_entry.items[0].patient, self.patient)
|
||||
self.assertEqual(stock_entry.items[0].inpatient_medication_entry_child, ipme.medication_orders[0].name)
|
||||
self.assertEqual(
|
||||
stock_entry.items[0].inpatient_medication_entry_child, ipme.medication_orders[0].name
|
||||
)
|
||||
|
||||
def test_drug_shortage_stock_entry(self):
|
||||
ipmo = create_ipmo(self.patient)
|
||||
@@ -108,25 +111,25 @@ class TestInpatientMedicationEntry(unittest.TestCase):
|
||||
filters = frappe._dict(
|
||||
from_date=date,
|
||||
to_date=date,
|
||||
from_time='',
|
||||
to_time='',
|
||||
item_code='Dextromethorphan',
|
||||
patient=self.patient
|
||||
from_time="",
|
||||
to_time="",
|
||||
item_code="Dextromethorphan",
|
||||
patient=self.patient,
|
||||
)
|
||||
|
||||
# check drug shortage
|
||||
ipme = create_ipme(filters, update_stock=1)
|
||||
ipme.warehouse = 'Finished Goods - _TC'
|
||||
ipme.warehouse = "Finished Goods - _TC"
|
||||
ipme.save()
|
||||
drug_shortage = get_drug_shortage_map(ipme.medication_orders, ipme.warehouse)
|
||||
self.assertEqual(drug_shortage.get('Dextromethorphan'), 3)
|
||||
self.assertEqual(drug_shortage.get("Dextromethorphan"), 3)
|
||||
|
||||
# check material transfer for drug shortage
|
||||
make_stock_entry()
|
||||
stock_entry = make_difference_stock_entry(ipme.name)
|
||||
self.assertEqual(stock_entry.items[0].item_code, 'Dextromethorphan')
|
||||
self.assertEqual(stock_entry.items[0].item_code, "Dextromethorphan")
|
||||
self.assertEqual(stock_entry.items[0].qty, 3)
|
||||
stock_entry.from_warehouse = 'Stores - _TC'
|
||||
stock_entry.from_warehouse = "Stores - _TC"
|
||||
stock_entry.submit()
|
||||
|
||||
ipme.reload()
|
||||
@@ -134,38 +137,45 @@ class TestInpatientMedicationEntry(unittest.TestCase):
|
||||
|
||||
def tearDown(self):
|
||||
# cleanup - Discharge
|
||||
schedule_discharge(frappe.as_json({'patient': self.patient, 'discharge_ordered_datetime': now_datetime()}))
|
||||
schedule_discharge(
|
||||
frappe.as_json({"patient": self.patient, "discharge_ordered_datetime": now_datetime()})
|
||||
)
|
||||
self.ip_record.reload()
|
||||
mark_invoiced_inpatient_occupancy(self.ip_record)
|
||||
|
||||
self.ip_record.reload()
|
||||
discharge_patient(self.ip_record, now_datetime())
|
||||
|
||||
for entry in frappe.get_all('Inpatient Medication Entry'):
|
||||
doc = frappe.get_doc('Inpatient Medication Entry', entry.name)
|
||||
for entry in frappe.get_all("Inpatient Medication Entry"):
|
||||
doc = frappe.get_doc("Inpatient Medication Entry", entry.name)
|
||||
doc.cancel()
|
||||
|
||||
for entry in frappe.get_all('Inpatient Medication Order'):
|
||||
doc = frappe.get_doc('Inpatient Medication Order', entry.name)
|
||||
for entry in frappe.get_all("Inpatient Medication Order"):
|
||||
doc = frappe.get_doc("Inpatient Medication Order", entry.name)
|
||||
doc.cancel()
|
||||
|
||||
|
||||
def make_stock_entry(warehouse=None):
|
||||
frappe.db.set_value('Company', '_Test Company', {
|
||||
'stock_adjustment_account': 'Stock Adjustment - _TC',
|
||||
'default_inventory_account': 'Stock In Hand - _TC'
|
||||
})
|
||||
stock_entry = frappe.new_doc('Stock Entry')
|
||||
stock_entry.stock_entry_type = 'Material Receipt'
|
||||
stock_entry.company = '_Test Company'
|
||||
stock_entry.to_warehouse = warehouse or 'Stores - _TC'
|
||||
expense_account = get_account(None, 'expense_account', 'Healthcare Settings', '_Test Company')
|
||||
se_child = stock_entry.append('items')
|
||||
se_child.item_code = 'Dextromethorphan'
|
||||
se_child.item_name = 'Dextromethorphan'
|
||||
se_child.uom = 'Nos'
|
||||
se_child.stock_uom = 'Nos'
|
||||
frappe.db.set_value(
|
||||
"Company",
|
||||
"_Test Company",
|
||||
{
|
||||
"stock_adjustment_account": "Stock Adjustment - _TC",
|
||||
"default_inventory_account": "Stock In Hand - _TC",
|
||||
},
|
||||
)
|
||||
stock_entry = frappe.new_doc("Stock Entry")
|
||||
stock_entry.stock_entry_type = "Material Receipt"
|
||||
stock_entry.company = "_Test Company"
|
||||
stock_entry.to_warehouse = warehouse or "Stores - _TC"
|
||||
expense_account = get_account(None, "expense_account", "Healthcare Settings", "_Test Company")
|
||||
se_child = stock_entry.append("items")
|
||||
se_child.item_code = "Dextromethorphan"
|
||||
se_child.item_name = "Dextromethorphan"
|
||||
se_child.uom = "Nos"
|
||||
se_child.stock_uom = "Nos"
|
||||
se_child.qty = 6
|
||||
se_child.t_warehouse = 'Stores - _TC'
|
||||
se_child.t_warehouse = "Stores - _TC"
|
||||
# in stock uom
|
||||
se_child.conversion_factor = 1.0
|
||||
se_child.expense_account = expense_account
|
||||
|
||||
@@ -26,50 +26,53 @@ class InpatientMedicationOrder(Document):
|
||||
|
||||
def validate_inpatient(self):
|
||||
if not self.inpatient_record:
|
||||
frappe.throw(_('No Inpatient Record found against patient {0}').format(self.patient))
|
||||
frappe.throw(_("No Inpatient Record found against patient {0}").format(self.patient))
|
||||
|
||||
def validate_duplicate(self):
|
||||
existing_mo = frappe.db.exists('Inpatient Medication Order', {
|
||||
'patient_encounter': self.patient_encounter,
|
||||
'docstatus': ('!=', 2),
|
||||
'name': ('!=', self.name)
|
||||
})
|
||||
existing_mo = frappe.db.exists(
|
||||
"Inpatient Medication Order",
|
||||
{
|
||||
"patient_encounter": self.patient_encounter,
|
||||
"docstatus": ("!=", 2),
|
||||
"name": ("!=", self.name),
|
||||
},
|
||||
)
|
||||
if existing_mo:
|
||||
frappe.throw(_('An Inpatient Medication Order {0} against Patient Encounter {1} already exists.').format(
|
||||
existing_mo, self.patient_encounter), frappe.DuplicateEntryError)
|
||||
frappe.throw(
|
||||
_("An Inpatient Medication Order {0} against Patient Encounter {1} already exists.").format(
|
||||
existing_mo, self.patient_encounter
|
||||
),
|
||||
frappe.DuplicateEntryError,
|
||||
)
|
||||
|
||||
def set_total_orders(self):
|
||||
self.db_set('total_orders', len(self.medication_orders))
|
||||
self.db_set("total_orders", len(self.medication_orders))
|
||||
|
||||
def set_status(self):
|
||||
status = {
|
||||
"0": "Draft",
|
||||
"1": "Submitted",
|
||||
"2": "Cancelled"
|
||||
}[cstr(self.docstatus or 0)]
|
||||
status = {"0": "Draft", "1": "Submitted", "2": "Cancelled"}[cstr(self.docstatus or 0)]
|
||||
|
||||
if self.docstatus == 1:
|
||||
if not self.completed_orders:
|
||||
status = 'Pending'
|
||||
status = "Pending"
|
||||
elif self.completed_orders < self.total_orders:
|
||||
status = 'In Process'
|
||||
status = "In Process"
|
||||
else:
|
||||
status = 'Completed'
|
||||
status = "Completed"
|
||||
|
||||
self.db_set('status', status)
|
||||
self.db_set("status", status)
|
||||
|
||||
@frappe.whitelist()
|
||||
def add_order_entries(self, order):
|
||||
if order.get('drug_code'):
|
||||
dosage = frappe.get_doc('Prescription Dosage', order.get('dosage'))
|
||||
dates = get_prescription_dates(order.get('period'), self.start_date)
|
||||
if order.get("drug_code"):
|
||||
dosage = frappe.get_doc("Prescription Dosage", order.get("dosage"))
|
||||
dates = get_prescription_dates(order.get("period"), self.start_date)
|
||||
for date in dates:
|
||||
for dose in dosage.dosage_strength:
|
||||
entry = self.append('medication_orders')
|
||||
entry.drug = order.get('drug_code')
|
||||
entry.drug_name = frappe.db.get_value('Item', order.get('drug_code'), 'item_name')
|
||||
entry = self.append("medication_orders")
|
||||
entry.drug = order.get("drug_code")
|
||||
entry.drug_name = frappe.db.get_value("Item", order.get("drug_code"), "item_name")
|
||||
entry.dosage = dose.strength
|
||||
entry.dosage_form = order.get('dosage_form')
|
||||
entry.dosage_form = order.get("dosage_form")
|
||||
entry.date = date
|
||||
entry.time = dose.strength_time
|
||||
self.end_date = dates[-1]
|
||||
|
||||
@@ -42,15 +42,19 @@ class TestInpatientMedicationOrder(unittest.TestCase):
|
||||
self.assertEqual(len(ipmo.medication_orders), 6)
|
||||
self.assertEqual(ipmo.medication_orders[0].date, add_days(getdate(), -1))
|
||||
|
||||
prescription_dosage = frappe.get_doc('Prescription Dosage', '1-1-1')
|
||||
prescription_dosage = frappe.get_doc("Prescription Dosage", "1-1-1")
|
||||
for i in range(len(prescription_dosage.dosage_strength)):
|
||||
self.assertEqual(ipmo.medication_orders[i].time, prescription_dosage.dosage_strength[i].strength_time)
|
||||
self.assertEqual(
|
||||
ipmo.medication_orders[i].time, prescription_dosage.dosage_strength[i].strength_time
|
||||
)
|
||||
|
||||
self.assertEqual(ipmo.medication_orders[3].date, getdate())
|
||||
|
||||
def test_inpatient_validation(self):
|
||||
# Discharge
|
||||
schedule_discharge(frappe.as_json({'patient': self.patient, 'discharge_ordered_datetime': now_datetime()}))
|
||||
schedule_discharge(
|
||||
frappe.as_json({"patient": self.patient, "discharge_ordered_datetime": now_datetime()})
|
||||
)
|
||||
|
||||
self.ip_record.reload()
|
||||
mark_invoiced_inpatient_occupancy(self.ip_record)
|
||||
@@ -67,24 +71,28 @@ class TestInpatientMedicationOrder(unittest.TestCase):
|
||||
ipmo.submit()
|
||||
ipmo.reload()
|
||||
|
||||
self.assertEqual(ipmo.status, 'Pending')
|
||||
self.assertEqual(ipmo.status, "Pending")
|
||||
|
||||
filters = frappe._dict(from_date=add_days(getdate(), -1), to_date=add_days(getdate(), -1), from_time='', to_time='')
|
||||
filters = frappe._dict(
|
||||
from_date=add_days(getdate(), -1), to_date=add_days(getdate(), -1), from_time="", to_time=""
|
||||
)
|
||||
ipme = create_ipme(filters)
|
||||
ipme.submit()
|
||||
ipmo.reload()
|
||||
self.assertEqual(ipmo.status, 'In Process')
|
||||
self.assertEqual(ipmo.status, "In Process")
|
||||
|
||||
filters = frappe._dict(from_date=getdate(), to_date=getdate(), from_time='', to_time='')
|
||||
filters = frappe._dict(from_date=getdate(), to_date=getdate(), from_time="", to_time="")
|
||||
ipme = create_ipme(filters)
|
||||
ipme.submit()
|
||||
ipmo.reload()
|
||||
self.assertEqual(ipmo.status, 'Completed')
|
||||
self.assertEqual(ipmo.status, "Completed")
|
||||
|
||||
def tearDown(self):
|
||||
if frappe.db.get_value('Patient', self.patient, 'inpatient_record'):
|
||||
if frappe.db.get_value("Patient", self.patient, "inpatient_record"):
|
||||
# cleanup - Discharge
|
||||
schedule_discharge(frappe.as_json({'patient': self.patient, 'discharge_ordered_datetime': now_datetime()}))
|
||||
schedule_discharge(
|
||||
frappe.as_json({"patient": self.patient, "discharge_ordered_datetime": now_datetime()})
|
||||
)
|
||||
self.ip_record.reload()
|
||||
mark_invoiced_inpatient_occupancy(self.ip_record)
|
||||
|
||||
@@ -94,57 +102,61 @@ class TestInpatientMedicationOrder(unittest.TestCase):
|
||||
for doctype in ["Inpatient Medication Entry", "Inpatient Medication Order"]:
|
||||
frappe.db.sql("delete from `tab{doctype}`".format(doctype=doctype))
|
||||
|
||||
|
||||
def create_dosage_form():
|
||||
if not frappe.db.exists('Dosage Form', 'Tablet'):
|
||||
frappe.get_doc({
|
||||
'doctype': 'Dosage Form',
|
||||
'dosage_form': 'Tablet'
|
||||
}).insert()
|
||||
if not frappe.db.exists("Dosage Form", "Tablet"):
|
||||
frappe.get_doc({"doctype": "Dosage Form", "dosage_form": "Tablet"}).insert()
|
||||
|
||||
|
||||
def create_drug(item=None):
|
||||
if not item:
|
||||
item = 'Dextromethorphan'
|
||||
drug = frappe.db.exists('Item', {'item_code': 'Dextromethorphan'})
|
||||
item = "Dextromethorphan"
|
||||
drug = frappe.db.exists("Item", {"item_code": "Dextromethorphan"})
|
||||
if not drug:
|
||||
drug = frappe.get_doc({
|
||||
'doctype': 'Item',
|
||||
'item_code': 'Dextromethorphan',
|
||||
'item_name': 'Dextromethorphan',
|
||||
'item_group': 'Products',
|
||||
'stock_uom': 'Nos',
|
||||
'is_stock_item': 1,
|
||||
'valuation_rate': 50,
|
||||
'opening_stock': 20
|
||||
}).insert()
|
||||
drug = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Item",
|
||||
"item_code": "Dextromethorphan",
|
||||
"item_name": "Dextromethorphan",
|
||||
"item_group": "Products",
|
||||
"stock_uom": "Nos",
|
||||
"is_stock_item": 1,
|
||||
"valuation_rate": 50,
|
||||
"opening_stock": 20,
|
||||
}
|
||||
).insert()
|
||||
|
||||
|
||||
def get_orders():
|
||||
create_dosage_form()
|
||||
create_drug()
|
||||
return {
|
||||
'drug_code': 'Dextromethorphan',
|
||||
'drug_name': 'Dextromethorphan',
|
||||
'dosage': '1-1-1',
|
||||
'dosage_form': 'Tablet',
|
||||
'period': '2 Day'
|
||||
"drug_code": "Dextromethorphan",
|
||||
"drug_name": "Dextromethorphan",
|
||||
"dosage": "1-1-1",
|
||||
"dosage_form": "Tablet",
|
||||
"period": "2 Day",
|
||||
}
|
||||
|
||||
|
||||
def create_ipmo(patient):
|
||||
orders = get_orders()
|
||||
ipmo = frappe.new_doc('Inpatient Medication Order')
|
||||
ipmo = frappe.new_doc("Inpatient Medication Order")
|
||||
ipmo.patient = patient
|
||||
ipmo.company = '_Test Company'
|
||||
ipmo.company = "_Test Company"
|
||||
ipmo.start_date = add_days(getdate(), -1)
|
||||
ipmo.add_order_entries(orders)
|
||||
|
||||
return ipmo
|
||||
|
||||
|
||||
def create_ipme(filters, update_stock=0):
|
||||
ipme = frappe.new_doc('Inpatient Medication Entry')
|
||||
ipme.company = '_Test Company'
|
||||
ipme = frappe.new_doc("Inpatient Medication Entry")
|
||||
ipme.company = "_Test Company"
|
||||
ipme.posting_date = getdate()
|
||||
ipme.update_stock = update_stock
|
||||
if update_stock:
|
||||
ipme.warehouse = 'Stores - _TC'
|
||||
ipme.warehouse = "Stores - _TC"
|
||||
for key, value in filters.items():
|
||||
ipme.set(key, value)
|
||||
ipme = ipme.get_medication_orders()
|
||||
|
||||
@@ -13,12 +13,16 @@ from frappe.utils import get_datetime, get_link_to_form, getdate, now_datetime,
|
||||
|
||||
class InpatientRecord(Document):
|
||||
def after_insert(self):
|
||||
frappe.db.set_value('Patient', self.patient, 'inpatient_record', self.name)
|
||||
frappe.db.set_value('Patient', self.patient, 'inpatient_status', self.status)
|
||||
frappe.db.set_value("Patient", self.patient, "inpatient_record", self.name)
|
||||
frappe.db.set_value("Patient", self.patient, "inpatient_status", self.status)
|
||||
|
||||
if self.admission_encounter: # Update encounter
|
||||
frappe.db.set_value('Patient Encounter', self.admission_encounter, 'inpatient_record', self.name)
|
||||
frappe.db.set_value('Patient Encounter', self.admission_encounter, 'inpatient_status', self.status)
|
||||
if self.admission_encounter: # Update encounter
|
||||
frappe.db.set_value(
|
||||
"Patient Encounter", self.admission_encounter, "inpatient_record", self.name
|
||||
)
|
||||
frappe.db.set_value(
|
||||
"Patient Encounter", self.admission_encounter, "inpatient_status", self.status
|
||||
)
|
||||
|
||||
def validate(self):
|
||||
self.validate_dates()
|
||||
@@ -28,14 +32,20 @@ class InpatientRecord(Document):
|
||||
frappe.db.set_value("Patient", self.patient, "inpatient_record", None)
|
||||
|
||||
def validate_dates(self):
|
||||
if (getdate(self.expected_discharge) < getdate(self.scheduled_date)) or \
|
||||
(getdate(self.discharge_ordered_datetime) < getdate(self.scheduled_date)):
|
||||
frappe.throw(_('Expected and Discharge dates cannot be less than Admission Schedule date'))
|
||||
if (getdate(self.expected_discharge) < getdate(self.scheduled_date)) or (
|
||||
getdate(self.discharge_ordered_datetime) < getdate(self.scheduled_date)
|
||||
):
|
||||
frappe.throw(_("Expected and Discharge dates cannot be less than Admission Schedule date"))
|
||||
|
||||
for entry in self.inpatient_occupancies:
|
||||
if entry.check_in and entry.check_out and \
|
||||
get_datetime(entry.check_in) > get_datetime(entry.check_out):
|
||||
frappe.throw(_('Row #{0}: Check Out datetime cannot be less than Check In datetime').format(entry.idx))
|
||||
if (
|
||||
entry.check_in
|
||||
and entry.check_out
|
||||
and get_datetime(entry.check_in) > get_datetime(entry.check_out)
|
||||
):
|
||||
frappe.throw(
|
||||
_("Row #{0}: Check Out datetime cannot be less than Check In datetime").format(entry.idx)
|
||||
)
|
||||
|
||||
def validate_already_scheduled_or_admitted(self):
|
||||
query = """
|
||||
@@ -45,14 +55,13 @@ class InpatientRecord(Document):
|
||||
and name != %(name)s and patient = %(patient)s
|
||||
"""
|
||||
|
||||
ip_record = frappe.db.sql(query,{
|
||||
"name": self.name,
|
||||
"patient": self.patient
|
||||
}, as_dict = 1)
|
||||
ip_record = frappe.db.sql(query, {"name": self.name, "patient": self.patient}, as_dict=1)
|
||||
|
||||
if ip_record:
|
||||
msg = _(("Already {0} Patient {1} with Inpatient Record ").format(ip_record[0].status, self.patient) \
|
||||
+ """ <b><a href="/app/Form/Inpatient Record/{0}">{0}</a></b>""".format(ip_record[0].name))
|
||||
msg = _(
|
||||
("Already {0} Patient {1} with Inpatient Record ").format(ip_record[0].status, self.patient)
|
||||
+ """ <b><a href="/app/Form/Inpatient Record/{0}">{0}</a></b>""".format(ip_record[0].name)
|
||||
)
|
||||
frappe.throw(msg)
|
||||
|
||||
@frappe.whitelist()
|
||||
@@ -63,8 +72,8 @@ class InpatientRecord(Document):
|
||||
def discharge(self, check_out=None):
|
||||
if not check_out:
|
||||
check_out = now_datetime()
|
||||
if (getdate(check_out) < getdate(self.admitted_datetime)):
|
||||
frappe.throw(_('Discharge date cannot be less than Admission date'))
|
||||
if getdate(check_out) < getdate(self.admitted_datetime):
|
||||
frappe.throw(_("Discharge date cannot be less than Admission date"))
|
||||
discharge_patient(self, check_out)
|
||||
|
||||
@frappe.whitelist()
|
||||
@@ -77,17 +86,21 @@ class InpatientRecord(Document):
|
||||
|
||||
@frappe.whitelist()
|
||||
def schedule_inpatient(args):
|
||||
admission_order = json.loads(args) # admission order via Encounter
|
||||
if not admission_order or not admission_order['patient'] or not admission_order['admission_encounter']:
|
||||
frappe.throw(_('Missing required details, did not create Inpatient Record'))
|
||||
admission_order = json.loads(args) # admission order via Encounter
|
||||
if (
|
||||
not admission_order
|
||||
or not admission_order["patient"]
|
||||
or not admission_order["admission_encounter"]
|
||||
):
|
||||
frappe.throw(_("Missing required details, did not create Inpatient Record"))
|
||||
|
||||
inpatient_record = frappe.new_doc('Inpatient Record')
|
||||
inpatient_record = frappe.new_doc("Inpatient Record")
|
||||
|
||||
# Admission order details
|
||||
set_details_from_ip_order(inpatient_record, admission_order)
|
||||
|
||||
# Patient details
|
||||
patient = frappe.get_doc('Patient', admission_order['patient'])
|
||||
patient = frappe.get_doc("Patient", admission_order["patient"])
|
||||
inpatient_record.patient = patient.name
|
||||
inpatient_record.patient_name = patient.patient_name
|
||||
inpatient_record.gender = patient.sex
|
||||
@@ -99,45 +112,60 @@ def schedule_inpatient(args):
|
||||
inpatient_record.scheduled_date = today()
|
||||
|
||||
# Set encounter detials
|
||||
encounter = frappe.get_doc('Patient Encounter', admission_order['admission_encounter'])
|
||||
if encounter and encounter.symptoms: # Symptoms
|
||||
set_ip_child_records(inpatient_record, 'chief_complaint', encounter.symptoms)
|
||||
encounter = frappe.get_doc("Patient Encounter", admission_order["admission_encounter"])
|
||||
if encounter and encounter.symptoms: # Symptoms
|
||||
set_ip_child_records(inpatient_record, "chief_complaint", encounter.symptoms)
|
||||
|
||||
if encounter and encounter.diagnosis: # Diagnosis
|
||||
set_ip_child_records(inpatient_record, 'diagnosis', encounter.diagnosis)
|
||||
if encounter and encounter.diagnosis: # Diagnosis
|
||||
set_ip_child_records(inpatient_record, "diagnosis", encounter.diagnosis)
|
||||
|
||||
if encounter and encounter.drug_prescription: # Medication
|
||||
set_ip_child_records(inpatient_record, 'drug_prescription', encounter.drug_prescription)
|
||||
if encounter and encounter.drug_prescription: # Medication
|
||||
set_ip_child_records(inpatient_record, "drug_prescription", encounter.drug_prescription)
|
||||
|
||||
if encounter and encounter.lab_test_prescription: # Lab Tests
|
||||
set_ip_child_records(inpatient_record, 'lab_test_prescription', encounter.lab_test_prescription)
|
||||
if encounter and encounter.lab_test_prescription: # Lab Tests
|
||||
set_ip_child_records(inpatient_record, "lab_test_prescription", encounter.lab_test_prescription)
|
||||
|
||||
if encounter and encounter.procedure_prescription: # Procedure Prescription
|
||||
set_ip_child_records(inpatient_record, 'procedure_prescription', encounter.procedure_prescription)
|
||||
if encounter and encounter.procedure_prescription: # Procedure Prescription
|
||||
set_ip_child_records(
|
||||
inpatient_record, "procedure_prescription", encounter.procedure_prescription
|
||||
)
|
||||
|
||||
if encounter and encounter.therapies: # Therapies
|
||||
if encounter and encounter.therapies: # Therapies
|
||||
inpatient_record.therapy_plan = encounter.therapy_plan
|
||||
set_ip_child_records(inpatient_record, 'therapies', encounter.therapies)
|
||||
set_ip_child_records(inpatient_record, "therapies", encounter.therapies)
|
||||
|
||||
inpatient_record.status = 'Admission Scheduled'
|
||||
inpatient_record.save(ignore_permissions = True)
|
||||
inpatient_record.status = "Admission Scheduled"
|
||||
inpatient_record.save(ignore_permissions=True)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def schedule_discharge(args):
|
||||
discharge_order = json.loads(args)
|
||||
if not discharge_order or not discharge_order['patient'] or not discharge_order['discharge_ordered_datetime']:
|
||||
frappe.throw(_('Missing required details, did not create schedule discharge'))
|
||||
if (
|
||||
not discharge_order
|
||||
or not discharge_order["patient"]
|
||||
or not discharge_order["discharge_ordered_datetime"]
|
||||
):
|
||||
frappe.throw(_("Missing required details, did not create schedule discharge"))
|
||||
|
||||
inpatient_record_id = frappe.db.get_value('Patient', discharge_order['patient'], 'inpatient_record')
|
||||
inpatient_record_id = frappe.db.get_value(
|
||||
"Patient", discharge_order["patient"], "inpatient_record"
|
||||
)
|
||||
if inpatient_record_id:
|
||||
inpatient_record = frappe.get_doc('Inpatient Record', inpatient_record_id)
|
||||
check_out_inpatient(inpatient_record, discharge_order['discharge_ordered_datetime'])
|
||||
inpatient_record = frappe.get_doc("Inpatient Record", inpatient_record_id)
|
||||
check_out_inpatient(inpatient_record, discharge_order["discharge_ordered_datetime"])
|
||||
set_details_from_ip_order(inpatient_record, discharge_order)
|
||||
inpatient_record.status = 'Discharge Scheduled'
|
||||
inpatient_record.save(ignore_permissions = True)
|
||||
frappe.db.set_value('Patient', discharge_order['patient'], 'inpatient_status', inpatient_record.status)
|
||||
frappe.db.set_value('Patient Encounter', inpatient_record.discharge_encounter, 'inpatient_status', inpatient_record.status)
|
||||
inpatient_record.status = "Discharge Scheduled"
|
||||
inpatient_record.save(ignore_permissions=True)
|
||||
frappe.db.set_value(
|
||||
"Patient", discharge_order["patient"], "inpatient_status", inpatient_record.status
|
||||
)
|
||||
frappe.db.set_value(
|
||||
"Patient Encounter",
|
||||
inpatient_record.discharge_encounter,
|
||||
"inpatient_status",
|
||||
inpatient_record.status,
|
||||
)
|
||||
|
||||
|
||||
def set_details_from_ip_order(inpatient_record, ip_order):
|
||||
@@ -148,7 +176,7 @@ def set_details_from_ip_order(inpatient_record, ip_order):
|
||||
def set_ip_child_records(inpatient_record, inpatient_record_child, encounter_child):
|
||||
for item in encounter_child:
|
||||
table = inpatient_record.append(inpatient_record_child)
|
||||
for df in table.meta.get('fields'):
|
||||
for df in table.meta.get("fields"):
|
||||
table.set(df.fieldname, item.get(df.fieldname))
|
||||
|
||||
|
||||
@@ -158,7 +186,9 @@ def check_out_inpatient(inpatient_record, discharge_ordered_datetime):
|
||||
if inpatient_occupancy.left != 1:
|
||||
inpatient_occupancy.left = True
|
||||
inpatient_occupancy.check_out = discharge_ordered_datetime
|
||||
frappe.db.set_value("Healthcare Service Unit", inpatient_occupancy.service_unit, "occupancy_status", "Vacant")
|
||||
frappe.db.set_value(
|
||||
"Healthcare Service Unit", inpatient_occupancy.service_unit, "occupancy_status", "Vacant"
|
||||
)
|
||||
|
||||
|
||||
def discharge_patient(inpatient_record, check_out):
|
||||
@@ -166,7 +196,7 @@ def discharge_patient(inpatient_record, check_out):
|
||||
inpatient_record.discharge_datetime = check_out
|
||||
inpatient_record.status = "Discharged"
|
||||
|
||||
inpatient_record.save(ignore_permissions = True)
|
||||
inpatient_record.save(ignore_permissions=True)
|
||||
|
||||
|
||||
def validate_inpatient_invoicing(inpatient_record):
|
||||
@@ -178,13 +208,15 @@ def validate_inpatient_invoicing(inpatient_record):
|
||||
if pending_invoices:
|
||||
message = _("Cannot mark Inpatient Record as Discharged since there are unbilled services. ")
|
||||
|
||||
formatted_doc_rows = ''
|
||||
formatted_doc_rows = ""
|
||||
|
||||
for doctype, docnames in pending_invoices.items():
|
||||
formatted_doc_rows += """
|
||||
<td>{0}</td>
|
||||
<td>{1}</td>
|
||||
</tr>""".format(doctype, docnames)
|
||||
</tr>""".format(
|
||||
doctype, docnames
|
||||
)
|
||||
|
||||
message += """
|
||||
<table class='table'>
|
||||
@@ -194,7 +226,9 @@ def validate_inpatient_invoicing(inpatient_record):
|
||||
</thead>
|
||||
{2}
|
||||
</table>
|
||||
""".format(_("Healthcare Service"), _("Documents"), formatted_doc_rows)
|
||||
""".format(
|
||||
_("Healthcare Service"), _("Documents"), formatted_doc_rows
|
||||
)
|
||||
|
||||
frappe.throw(message, title=_("Unbilled Services"), is_minimizable=True, wide=True)
|
||||
|
||||
@@ -232,34 +266,43 @@ def get_pending_doc(doc, doc_name_list, pending_invoices):
|
||||
else:
|
||||
doc_ids = doc_link
|
||||
if doc_ids:
|
||||
pending_invoices[doc] = doc_ids
|
||||
pending_invoices[doc] = doc_ids
|
||||
|
||||
return pending_invoices
|
||||
|
||||
|
||||
def get_unbilled_inpatient_docs(doc, inpatient_record):
|
||||
return frappe.db.get_list(doc, filters = {'patient': inpatient_record.patient,
|
||||
'inpatient_record': inpatient_record.name, 'docstatus': 1, 'invoiced': 0})
|
||||
return frappe.db.get_list(
|
||||
doc,
|
||||
filters={
|
||||
"patient": inpatient_record.patient,
|
||||
"inpatient_record": inpatient_record.name,
|
||||
"docstatus": 1,
|
||||
"invoiced": 0,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def admit_patient(inpatient_record, service_unit, check_in, expected_discharge=None):
|
||||
inpatient_record.admitted_datetime = check_in
|
||||
inpatient_record.status = 'Admitted'
|
||||
inpatient_record.status = "Admitted"
|
||||
inpatient_record.expected_discharge = expected_discharge
|
||||
|
||||
inpatient_record.set('inpatient_occupancies', [])
|
||||
inpatient_record.set("inpatient_occupancies", [])
|
||||
transfer_patient(inpatient_record, service_unit, check_in)
|
||||
|
||||
frappe.db.set_value('Patient', inpatient_record.patient, 'inpatient_status', 'Admitted')
|
||||
frappe.db.set_value('Patient', inpatient_record.patient, 'inpatient_record', inpatient_record.name)
|
||||
frappe.db.set_value("Patient", inpatient_record.patient, "inpatient_status", "Admitted")
|
||||
frappe.db.set_value(
|
||||
"Patient", inpatient_record.patient, "inpatient_record", inpatient_record.name
|
||||
)
|
||||
|
||||
|
||||
def transfer_patient(inpatient_record, service_unit, check_in):
|
||||
item_line = inpatient_record.append('inpatient_occupancies', {})
|
||||
item_line = inpatient_record.append("inpatient_occupancies", {})
|
||||
item_line.service_unit = service_unit
|
||||
item_line.check_in = check_in
|
||||
|
||||
inpatient_record.save(ignore_permissions = True)
|
||||
inpatient_record.save(ignore_permissions=True)
|
||||
|
||||
frappe.db.set_value("Healthcare Service Unit", service_unit, "occupancy_status", "Occupied")
|
||||
|
||||
@@ -270,27 +313,25 @@ def patient_leave_service_unit(inpatient_record, check_out, leave_from):
|
||||
if inpatient_occupancy.left != 1 and inpatient_occupancy.service_unit == leave_from:
|
||||
inpatient_occupancy.left = True
|
||||
inpatient_occupancy.check_out = check_out
|
||||
frappe.db.set_value("Healthcare Service Unit", inpatient_occupancy.service_unit, "occupancy_status", "Vacant")
|
||||
inpatient_record.save(ignore_permissions = True)
|
||||
frappe.db.set_value(
|
||||
"Healthcare Service Unit", inpatient_occupancy.service_unit, "occupancy_status", "Vacant"
|
||||
)
|
||||
inpatient_record.save(ignore_permissions=True)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_leave_from(doctype, txt, searchfield, start, page_len, filters):
|
||||
docname = filters['docname']
|
||||
docname = filters["docname"]
|
||||
|
||||
query = '''select io.service_unit
|
||||
query = """select io.service_unit
|
||||
from `tabInpatient Occupancy` io, `tabInpatient Record` ir
|
||||
where io.parent = '{docname}' and io.parentfield = 'inpatient_occupancies'
|
||||
and io.left!=1 and io.parent = ir.name'''
|
||||
and io.left!=1 and io.parent = ir.name"""
|
||||
|
||||
return frappe.db.sql(query.format(**{
|
||||
"docname": docname,
|
||||
"searchfield": searchfield,
|
||||
"mcond": get_match_cond(doctype)
|
||||
}), {
|
||||
'txt': "%%%s%%" % txt,
|
||||
'_txt': txt.replace("%", ""),
|
||||
'start': start,
|
||||
'page_len': page_len
|
||||
})
|
||||
return frappe.db.sql(
|
||||
query.format(
|
||||
**{"docname": docname, "searchfield": searchfield, "mcond": get_match_cond(doctype)}
|
||||
),
|
||||
{"txt": "%%%s%%" % txt, "_txt": txt.replace("%", ""), "start": start, "page_len": page_len},
|
||||
)
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
|
||||
from frappe import _
|
||||
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'inpatient_record',
|
||||
'transactions': [
|
||||
"fieldname": "inpatient_record",
|
||||
"transactions": [
|
||||
{
|
||||
'label': _('Appointments and Encounters'),
|
||||
'items': ['Patient Appointment', 'Patient Encounter']
|
||||
"label": _("Appointments and Encounters"),
|
||||
"items": ["Patient Appointment", "Patient Encounter"],
|
||||
},
|
||||
{
|
||||
'label': _('Lab Tests and Vital Signs'),
|
||||
'items': ['Lab Test', 'Clinical Procedure', 'Sample Collection', 'Vital Signs']
|
||||
}
|
||||
]
|
||||
"label": _("Lab Tests and Vital Signs"),
|
||||
"items": ["Lab Test", "Clinical Procedure", "Sample Collection", "Vital Signs"],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ class TestInpatientRecord(unittest.TestCase):
|
||||
# Schedule Admission
|
||||
ip_record = create_inpatient(patient)
|
||||
ip_record.expected_length_of_stay = 0
|
||||
ip_record.save(ignore_permissions = True)
|
||||
ip_record.save(ignore_permissions=True)
|
||||
self.assertEqual(ip_record.name, frappe.db.get_value("Patient", patient, "inpatient_record"))
|
||||
self.assertEqual(ip_record.status, frappe.db.get_value("Patient", patient, "inpatient_status"))
|
||||
|
||||
@@ -31,11 +31,17 @@ class TestInpatientRecord(unittest.TestCase):
|
||||
service_unit = get_healthcare_service_unit()
|
||||
admit_patient(ip_record, service_unit, now_datetime())
|
||||
self.assertEqual("Admitted", frappe.db.get_value("Patient", patient, "inpatient_status"))
|
||||
self.assertEqual("Occupied", frappe.db.get_value("Healthcare Service Unit", service_unit, "occupancy_status"))
|
||||
self.assertEqual(
|
||||
"Occupied", frappe.db.get_value("Healthcare Service Unit", service_unit, "occupancy_status")
|
||||
)
|
||||
|
||||
# Discharge
|
||||
schedule_discharge(frappe.as_json({'patient': patient, 'discharge_ordered_datetime': now_datetime()}))
|
||||
self.assertEqual("Vacant", frappe.db.get_value("Healthcare Service Unit", service_unit, "occupancy_status"))
|
||||
schedule_discharge(
|
||||
frappe.as_json({"patient": patient, "discharge_ordered_datetime": now_datetime()})
|
||||
)
|
||||
self.assertEqual(
|
||||
"Vacant", frappe.db.get_value("Healthcare Service Unit", service_unit, "occupancy_status")
|
||||
)
|
||||
|
||||
ip_record1 = frappe.get_doc("Inpatient Record", ip_record.name)
|
||||
# Validate Pending Invoices
|
||||
@@ -54,15 +60,19 @@ class TestInpatientRecord(unittest.TestCase):
|
||||
# Schedule Admission
|
||||
ip_record = create_inpatient(patient)
|
||||
ip_record.expected_length_of_stay = 0
|
||||
ip_record.save(ignore_permissions = True)
|
||||
ip_record.save(ignore_permissions=True)
|
||||
|
||||
# Admit
|
||||
service_unit = get_healthcare_service_unit()
|
||||
admit_patient(ip_record, service_unit, now_datetime())
|
||||
|
||||
# Discharge
|
||||
schedule_discharge(frappe.as_json({"patient": patient, 'discharge_ordered_datetime': now_datetime()}))
|
||||
self.assertEqual("Vacant", frappe.db.get_value("Healthcare Service Unit", service_unit, "occupancy_status"))
|
||||
schedule_discharge(
|
||||
frappe.as_json({"patient": patient, "discharge_ordered_datetime": now_datetime()})
|
||||
)
|
||||
self.assertEqual(
|
||||
"Vacant", frappe.db.get_value("Healthcare Service Unit", service_unit, "occupancy_status")
|
||||
)
|
||||
|
||||
ip_record = frappe.get_doc("Inpatient Record", ip_record.name)
|
||||
# Should not validate Pending Invoices
|
||||
@@ -80,7 +90,7 @@ class TestInpatientRecord(unittest.TestCase):
|
||||
# Schedule Admission
|
||||
ip_record = create_inpatient(patient)
|
||||
ip_record.expected_length_of_stay = 0
|
||||
ip_record.save(ignore_permissions = True)
|
||||
ip_record.save(ignore_permissions=True)
|
||||
|
||||
# Admit
|
||||
service_unit = get_healthcare_service_unit()
|
||||
@@ -93,8 +103,12 @@ class TestInpatientRecord(unittest.TestCase):
|
||||
self.assertFalse(patient_encounter.name in encounter_ids)
|
||||
|
||||
# Discharge
|
||||
schedule_discharge(frappe.as_json({"patient": patient, 'discharge_ordered_datetime': now_datetime()}))
|
||||
self.assertEqual("Vacant", frappe.db.get_value("Healthcare Service Unit", service_unit, "occupancy_status"))
|
||||
schedule_discharge(
|
||||
frappe.as_json({"patient": patient, "discharge_ordered_datetime": now_datetime()})
|
||||
)
|
||||
self.assertEqual(
|
||||
"Vacant", frappe.db.get_value("Healthcare Service Unit", service_unit, "occupancy_status")
|
||||
)
|
||||
|
||||
ip_record = frappe.get_doc("Inpatient Record", ip_record.name)
|
||||
mark_invoiced_inpatient_occupancy(ip_record)
|
||||
@@ -107,7 +121,7 @@ class TestInpatientRecord(unittest.TestCase):
|
||||
|
||||
ip_record = create_inpatient(patient)
|
||||
ip_record.expected_length_of_stay = 0
|
||||
ip_record.save(ignore_permissions = True)
|
||||
ip_record.save(ignore_permissions=True)
|
||||
ip_record_new = create_inpatient(patient)
|
||||
ip_record_new.expected_length_of_stay = 0
|
||||
self.assertRaises(frappe.ValidationError, ip_record_new.save)
|
||||
@@ -118,11 +132,12 @@ class TestInpatientRecord(unittest.TestCase):
|
||||
self.assertRaises(frappe.ValidationError, ip_record_new.save)
|
||||
frappe.db.sql("""delete from `tabInpatient Record`""")
|
||||
|
||||
|
||||
def mark_invoiced_inpatient_occupancy(ip_record):
|
||||
if ip_record.inpatient_occupancies:
|
||||
for inpatient_occupancy in ip_record.inpatient_occupancies:
|
||||
inpatient_occupancy.invoiced = 1
|
||||
ip_record.save(ignore_permissions = True)
|
||||
ip_record.save(ignore_permissions=True)
|
||||
|
||||
|
||||
def setup_inpatient_settings(key, value):
|
||||
@@ -132,8 +147,8 @@ def setup_inpatient_settings(key, value):
|
||||
|
||||
|
||||
def create_inpatient(patient):
|
||||
patient_obj = frappe.get_doc('Patient', patient)
|
||||
inpatient_record = frappe.new_doc('Inpatient Record')
|
||||
patient_obj = frappe.get_doc("Patient", patient)
|
||||
inpatient_record = frappe.new_doc("Inpatient Record")
|
||||
inpatient_record.patient = patient
|
||||
inpatient_record.patient_name = patient_obj.patient_name
|
||||
inpatient_record.gender = patient_obj.sex
|
||||
@@ -150,9 +165,13 @@ def create_inpatient(patient):
|
||||
|
||||
def get_healthcare_service_unit(unit_name=None):
|
||||
if not unit_name:
|
||||
service_unit = get_random("Healthcare Service Unit", filters={"inpatient_occupancy": 1, "company": "_Test Company"})
|
||||
service_unit = get_random(
|
||||
"Healthcare Service Unit", filters={"inpatient_occupancy": 1, "company": "_Test Company"}
|
||||
)
|
||||
else:
|
||||
service_unit = frappe.db.exists("Healthcare Service Unit", {"healthcare_service_unit_name": unit_name})
|
||||
service_unit = frappe.db.exists(
|
||||
"Healthcare Service Unit", {"healthcare_service_unit_name": unit_name}
|
||||
)
|
||||
|
||||
if not service_unit:
|
||||
service_unit = frappe.new_doc("Healthcare Service Unit")
|
||||
@@ -162,20 +181,22 @@ def get_healthcare_service_unit(unit_name=None):
|
||||
service_unit.inpatient_occupancy = 1
|
||||
service_unit.occupancy_status = "Vacant"
|
||||
service_unit.is_group = 0
|
||||
service_unit_parent_name = frappe.db.exists({
|
||||
service_unit_parent_name = frappe.db.exists(
|
||||
{
|
||||
"doctype": "Healthcare Service Unit",
|
||||
"healthcare_service_unit_name": "_Test All Healthcare Service Units",
|
||||
"is_group": 1
|
||||
})
|
||||
"is_group": 1,
|
||||
}
|
||||
)
|
||||
if not service_unit_parent_name:
|
||||
parent_service_unit = frappe.new_doc("Healthcare Service Unit")
|
||||
parent_service_unit.healthcare_service_unit_name = "_Test All Healthcare Service Units"
|
||||
parent_service_unit.is_group = 1
|
||||
parent_service_unit.save(ignore_permissions = True)
|
||||
parent_service_unit.save(ignore_permissions=True)
|
||||
service_unit.parent_healthcare_service_unit = parent_service_unit.name
|
||||
else:
|
||||
service_unit.parent_healthcare_service_unit = service_unit_parent_name[0][0]
|
||||
service_unit.save(ignore_permissions = True)
|
||||
service_unit.save(ignore_permissions=True)
|
||||
return service_unit.name
|
||||
return service_unit
|
||||
|
||||
@@ -187,17 +208,17 @@ def get_service_unit_type():
|
||||
service_unit_type = frappe.new_doc("Healthcare Service Unit Type")
|
||||
service_unit_type.service_unit_type = "_Test Service Unit Type Ip Occupancy"
|
||||
service_unit_type.inpatient_occupancy = 1
|
||||
service_unit_type.save(ignore_permissions = True)
|
||||
service_unit_type.save(ignore_permissions=True)
|
||||
return service_unit_type.name
|
||||
return service_unit_type
|
||||
|
||||
|
||||
def create_patient():
|
||||
patient = frappe.db.exists('Patient', '_Test IPD Patient')
|
||||
patient = frappe.db.exists("Patient", "_Test IPD Patient")
|
||||
if not patient:
|
||||
patient = frappe.new_doc('Patient')
|
||||
patient.first_name = '_Test IPD Patient'
|
||||
patient.sex = 'Female'
|
||||
patient = frappe.new_doc("Patient")
|
||||
patient.first_name = "_Test IPD Patient"
|
||||
patient.sex = "Female"
|
||||
patient.save(ignore_permissions=True)
|
||||
patient = patient.name
|
||||
return patient
|
||||
|
||||
@@ -15,11 +15,11 @@ class LabTest(Document):
|
||||
|
||||
def on_submit(self):
|
||||
self.validate_result_values()
|
||||
self.db_set('submitted_date', getdate())
|
||||
self.db_set('status', 'Completed')
|
||||
self.db_set("submitted_date", getdate())
|
||||
self.db_set("status", "Completed")
|
||||
|
||||
def on_cancel(self):
|
||||
self.db_set('status', 'Cancelled')
|
||||
self.db_set("status", "Cancelled")
|
||||
self.reload()
|
||||
|
||||
def on_update(self):
|
||||
@@ -31,8 +31,8 @@ class LabTest(Document):
|
||||
|
||||
def after_insert(self):
|
||||
if self.prescription:
|
||||
frappe.db.set_value('Lab Prescription', self.prescription, 'lab_test_created', 1)
|
||||
if frappe.db.get_value('Lab Prescription', self.prescription, 'invoiced'):
|
||||
frappe.db.set_value("Lab Prescription", self.prescription, "lab_test_created", 1)
|
||||
if frappe.db.get_value("Lab Prescription", self.prescription, "invoiced"):
|
||||
self.invoiced = True
|
||||
if self.template:
|
||||
self.load_test_from_template()
|
||||
@@ -49,26 +49,36 @@ class LabTest(Document):
|
||||
try:
|
||||
item.secondary_uom_result = float(item.result_value) * float(item.conversion_factor)
|
||||
except Exception:
|
||||
item.secondary_uom_result = ''
|
||||
frappe.msgprint(_('Row #{0}: Result for Secondary UOM not calculated').format(item.idx), title = _('Warning'))
|
||||
item.secondary_uom_result = ""
|
||||
frappe.msgprint(
|
||||
_("Row #{0}: Result for Secondary UOM not calculated").format(item.idx), title=_("Warning")
|
||||
)
|
||||
|
||||
def validate_result_values(self):
|
||||
if self.normal_test_items:
|
||||
for item in self.normal_test_items:
|
||||
if not item.result_value and not item.allow_blank and item.require_result_value:
|
||||
frappe.throw(_('Row #{0}: Please enter the result value for {1}').format(
|
||||
item.idx, frappe.bold(item.lab_test_name)), title=_('Mandatory Results'))
|
||||
frappe.throw(
|
||||
_("Row #{0}: Please enter the result value for {1}").format(
|
||||
item.idx, frappe.bold(item.lab_test_name)
|
||||
),
|
||||
title=_("Mandatory Results"),
|
||||
)
|
||||
|
||||
if self.descriptive_test_items:
|
||||
for item in self.descriptive_test_items:
|
||||
if not item.result_value and not item.allow_blank and item.require_result_value:
|
||||
frappe.throw(_('Row #{0}: Please enter the result value for {1}').format(
|
||||
item.idx, frappe.bold(item.lab_test_particulars)), title=_('Mandatory Results'))
|
||||
frappe.throw(
|
||||
_("Row #{0}: Please enter the result value for {1}").format(
|
||||
item.idx, frappe.bold(item.lab_test_particulars)
|
||||
),
|
||||
title=_("Mandatory Results"),
|
||||
)
|
||||
|
||||
|
||||
def create_test_from_template(lab_test):
|
||||
template = frappe.get_doc('Lab Test Template', lab_test.template)
|
||||
patient = frappe.get_doc('Patient', lab_test.patient)
|
||||
template = frappe.get_doc("Lab Test Template", lab_test.template)
|
||||
patient = frappe.get_doc("Patient", lab_test.patient)
|
||||
|
||||
lab_test.lab_test_name = template.lab_test_name
|
||||
lab_test.result_date = getdate()
|
||||
@@ -81,85 +91,98 @@ def create_test_from_template(lab_test):
|
||||
lab_test = create_sample_collection(lab_test, template, patient, None)
|
||||
lab_test = load_result_format(lab_test, template, None, None)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def update_status(status, name):
|
||||
if name and status:
|
||||
frappe.db.set_value('Lab Test', name, {
|
||||
'status': status,
|
||||
'approved_date': getdate()
|
||||
})
|
||||
frappe.db.set_value("Lab Test", name, {"status": status, "approved_date": getdate()})
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_multiple(doctype, docname):
|
||||
if not doctype or not docname:
|
||||
frappe.throw(_('Sales Invoice or Patient Encounter is required to create Lab Tests'), title=_('Insufficient Data'))
|
||||
frappe.throw(
|
||||
_("Sales Invoice or Patient Encounter is required to create Lab Tests"),
|
||||
title=_("Insufficient Data"),
|
||||
)
|
||||
|
||||
lab_test_created = False
|
||||
if doctype == 'Sales Invoice':
|
||||
if doctype == "Sales Invoice":
|
||||
lab_test_created = create_lab_test_from_invoice(docname)
|
||||
elif doctype == 'Patient Encounter':
|
||||
elif doctype == "Patient Encounter":
|
||||
lab_test_created = create_lab_test_from_encounter(docname)
|
||||
|
||||
if lab_test_created:
|
||||
frappe.msgprint(_('Lab Test(s) {0} created successfully').format(lab_test_created), indicator='green')
|
||||
frappe.msgprint(
|
||||
_("Lab Test(s) {0} created successfully").format(lab_test_created), indicator="green"
|
||||
)
|
||||
else:
|
||||
frappe.msgprint(_('No Lab Tests created'))
|
||||
frappe.msgprint(_("No Lab Tests created"))
|
||||
|
||||
|
||||
def create_lab_test_from_encounter(encounter):
|
||||
lab_test_created = False
|
||||
encounter = frappe.get_doc('Patient Encounter', encounter)
|
||||
encounter = frappe.get_doc("Patient Encounter", encounter)
|
||||
|
||||
if encounter and encounter.lab_test_prescription:
|
||||
patient = frappe.get_doc('Patient', encounter.patient)
|
||||
patient = frappe.get_doc("Patient", encounter.patient)
|
||||
for item in encounter.lab_test_prescription:
|
||||
if not item.lab_test_created:
|
||||
template = get_lab_test_template(item.lab_test_code)
|
||||
if template:
|
||||
lab_test = create_lab_test_doc(item.invoiced, encounter.practitioner, patient, template, encounter.company)
|
||||
lab_test.save(ignore_permissions = True)
|
||||
frappe.db.set_value('Lab Prescription', item.name, 'lab_test_created', 1)
|
||||
lab_test = create_lab_test_doc(
|
||||
item.invoiced, encounter.practitioner, patient, template, encounter.company
|
||||
)
|
||||
lab_test.save(ignore_permissions=True)
|
||||
frappe.db.set_value("Lab Prescription", item.name, "lab_test_created", 1)
|
||||
if not lab_test_created:
|
||||
lab_test_created = lab_test.name
|
||||
else:
|
||||
lab_test_created += ', ' + lab_test.name
|
||||
lab_test_created += ", " + lab_test.name
|
||||
return lab_test_created
|
||||
|
||||
|
||||
def create_lab_test_from_invoice(sales_invoice):
|
||||
lab_tests_created = False
|
||||
invoice = frappe.get_doc('Sales Invoice', sales_invoice)
|
||||
invoice = frappe.get_doc("Sales Invoice", sales_invoice)
|
||||
if invoice and invoice.patient:
|
||||
patient = frappe.get_doc('Patient', invoice.patient)
|
||||
patient = frappe.get_doc("Patient", invoice.patient)
|
||||
for item in invoice.items:
|
||||
lab_test_created = 0
|
||||
if item.reference_dt == 'Lab Prescription':
|
||||
lab_test_created = frappe.db.get_value('Lab Prescription', item.reference_dn, 'lab_test_created')
|
||||
elif item.reference_dt == 'Lab Test':
|
||||
if item.reference_dt == "Lab Prescription":
|
||||
lab_test_created = frappe.db.get_value(
|
||||
"Lab Prescription", item.reference_dn, "lab_test_created"
|
||||
)
|
||||
elif item.reference_dt == "Lab Test":
|
||||
lab_test_created = 1
|
||||
if lab_test_created != 1:
|
||||
template = get_lab_test_template(item.item_code)
|
||||
if template:
|
||||
lab_test = create_lab_test_doc(True, invoice.ref_practitioner, patient, template, invoice.company)
|
||||
if item.reference_dt == 'Lab Prescription':
|
||||
lab_test = create_lab_test_doc(
|
||||
True, invoice.ref_practitioner, patient, template, invoice.company
|
||||
)
|
||||
if item.reference_dt == "Lab Prescription":
|
||||
lab_test.prescription = item.reference_dn
|
||||
lab_test.save(ignore_permissions = True)
|
||||
if item.reference_dt != 'Lab Prescription':
|
||||
frappe.db.set_value('Sales Invoice Item', item.name, 'reference_dt', 'Lab Test')
|
||||
frappe.db.set_value('Sales Invoice Item', item.name, 'reference_dn', lab_test.name)
|
||||
lab_test.save(ignore_permissions=True)
|
||||
if item.reference_dt != "Lab Prescription":
|
||||
frappe.db.set_value("Sales Invoice Item", item.name, "reference_dt", "Lab Test")
|
||||
frappe.db.set_value("Sales Invoice Item", item.name, "reference_dn", lab_test.name)
|
||||
if not lab_tests_created:
|
||||
lab_tests_created = lab_test.name
|
||||
else:
|
||||
lab_tests_created += ', ' + lab_test.name
|
||||
lab_tests_created += ", " + lab_test.name
|
||||
return lab_tests_created
|
||||
|
||||
|
||||
def get_lab_test_template(item):
|
||||
template_id = frappe.db.exists('Lab Test Template', {'item': item})
|
||||
template_id = frappe.db.exists("Lab Test Template", {"item": item})
|
||||
if template_id:
|
||||
return frappe.get_doc('Lab Test Template', template_id)
|
||||
return frappe.get_doc("Lab Test Template", template_id)
|
||||
return False
|
||||
|
||||
|
||||
def create_lab_test_doc(invoiced, practitioner, patient, template, company):
|
||||
lab_test = frappe.new_doc('Lab Test')
|
||||
lab_test = frappe.new_doc("Lab Test")
|
||||
lab_test.invoiced = invoiced
|
||||
lab_test.practitioner = practitioner
|
||||
lab_test.patient = patient.name
|
||||
@@ -175,9 +198,10 @@ def create_lab_test_doc(invoiced, practitioner, patient, template, company):
|
||||
lab_test.company = company
|
||||
return lab_test
|
||||
|
||||
|
||||
def create_normals(template, lab_test):
|
||||
lab_test.normal_toggle = 1
|
||||
normal = lab_test.append('normal_test_items')
|
||||
normal = lab_test.append("normal_test_items")
|
||||
normal.lab_test_name = template.lab_test_name
|
||||
normal.lab_test_uom = template.lab_test_uom
|
||||
normal.secondary_uom = template.secondary_uom
|
||||
@@ -187,10 +211,11 @@ def create_normals(template, lab_test):
|
||||
normal.allow_blank = 0
|
||||
normal.template = template.name
|
||||
|
||||
|
||||
def create_compounds(template, lab_test, is_group):
|
||||
lab_test.normal_toggle = 1
|
||||
for normal_test_template in template.normal_test_templates:
|
||||
normal = lab_test.append('normal_test_items')
|
||||
normal = lab_test.append("normal_test_items")
|
||||
if is_group:
|
||||
normal.lab_test_event = normal_test_template.lab_test_event
|
||||
else:
|
||||
@@ -204,41 +229,47 @@ def create_compounds(template, lab_test, is_group):
|
||||
normal.allow_blank = normal_test_template.allow_blank
|
||||
normal.template = template.name
|
||||
|
||||
|
||||
def create_descriptives(template, lab_test):
|
||||
lab_test.descriptive_toggle = 1
|
||||
if template.sensitivity:
|
||||
lab_test.sensitivity_toggle = 1
|
||||
for descriptive_test_template in template.descriptive_test_templates:
|
||||
descriptive = lab_test.append('descriptive_test_items')
|
||||
descriptive = lab_test.append("descriptive_test_items")
|
||||
descriptive.lab_test_particulars = descriptive_test_template.particulars
|
||||
descriptive.require_result_value = 1
|
||||
descriptive.allow_blank = descriptive_test_template.allow_blank
|
||||
descriptive.template = template.name
|
||||
|
||||
def create_sample_doc(template, patient, invoice, company = None):
|
||||
|
||||
def create_sample_doc(template, patient, invoice, company=None):
|
||||
if template.sample:
|
||||
sample_exists = frappe.db.exists({
|
||||
'doctype': 'Sample Collection',
|
||||
'patient': patient.name,
|
||||
'docstatus': 0,
|
||||
'sample': template.sample
|
||||
})
|
||||
sample_exists = frappe.db.exists(
|
||||
{
|
||||
"doctype": "Sample Collection",
|
||||
"patient": patient.name,
|
||||
"docstatus": 0,
|
||||
"sample": template.sample,
|
||||
}
|
||||
)
|
||||
|
||||
if sample_exists:
|
||||
# update sample collection by adding quantity
|
||||
sample_collection = frappe.get_doc('Sample Collection', sample_exists[0][0])
|
||||
sample_collection = frappe.get_doc("Sample Collection", sample_exists[0][0])
|
||||
quantity = int(sample_collection.sample_qty) + int(template.sample_qty)
|
||||
if template.sample_details:
|
||||
sample_details = sample_collection.sample_details + '\n-\n' + _('Test :')
|
||||
sample_details += (template.get('lab_test_name') or template.get('template')) + '\n'
|
||||
sample_details += _('Collection Details:') + '\n\t' + template.sample_details
|
||||
frappe.db.set_value('Sample Collection', sample_collection.name, 'sample_details', sample_details)
|
||||
sample_details = sample_collection.sample_details + "\n-\n" + _("Test :")
|
||||
sample_details += (template.get("lab_test_name") or template.get("template")) + "\n"
|
||||
sample_details += _("Collection Details:") + "\n\t" + template.sample_details
|
||||
frappe.db.set_value(
|
||||
"Sample Collection", sample_collection.name, "sample_details", sample_details
|
||||
)
|
||||
|
||||
frappe.db.set_value('Sample Collection', sample_collection.name, 'sample_qty', quantity)
|
||||
frappe.db.set_value("Sample Collection", sample_collection.name, "sample_qty", quantity)
|
||||
|
||||
else:
|
||||
# Create Sample Collection for template, copy vals from Invoice
|
||||
sample_collection = frappe.new_doc('Sample Collection')
|
||||
sample_collection = frappe.new_doc("Sample Collection")
|
||||
if invoice:
|
||||
sample_collection.invoiced = True
|
||||
|
||||
@@ -251,59 +282,70 @@ def create_sample_doc(template, patient, invoice, company = None):
|
||||
sample_collection.company = company
|
||||
|
||||
if template.sample_details:
|
||||
sample_collection.sample_details = _('Test :') + (template.get('lab_test_name') or template.get('template')) + '\n' + 'Collection Detials:\n\t' + template.sample_details
|
||||
sample_collection.sample_details = (
|
||||
_("Test :")
|
||||
+ (template.get("lab_test_name") or template.get("template"))
|
||||
+ "\n"
|
||||
+ "Collection Detials:\n\t"
|
||||
+ template.sample_details
|
||||
)
|
||||
sample_collection.save(ignore_permissions=True)
|
||||
|
||||
return sample_collection
|
||||
|
||||
|
||||
def create_sample_collection(lab_test, template, patient, invoice):
|
||||
if frappe.get_cached_value('Healthcare Settings', None, 'create_sample_collection_for_lab_test'):
|
||||
if frappe.get_cached_value("Healthcare Settings", None, "create_sample_collection_for_lab_test"):
|
||||
sample_collection = create_sample_doc(template, patient, invoice, lab_test.company)
|
||||
if sample_collection:
|
||||
lab_test.sample = sample_collection.name
|
||||
sample_collection_doc = get_link_to_form('Sample Collection', sample_collection.name)
|
||||
frappe.msgprint(_('Sample Collection {0} has been created').format(sample_collection_doc),
|
||||
title=_('Sample Collection'), indicator='green')
|
||||
sample_collection_doc = get_link_to_form("Sample Collection", sample_collection.name)
|
||||
frappe.msgprint(
|
||||
_("Sample Collection {0} has been created").format(sample_collection_doc),
|
||||
title=_("Sample Collection"),
|
||||
indicator="green",
|
||||
)
|
||||
return lab_test
|
||||
|
||||
|
||||
def load_result_format(lab_test, template, prescription, invoice):
|
||||
if template.lab_test_template_type == 'Single':
|
||||
if template.lab_test_template_type == "Single":
|
||||
create_normals(template, lab_test)
|
||||
|
||||
elif template.lab_test_template_type == 'Compound':
|
||||
elif template.lab_test_template_type == "Compound":
|
||||
create_compounds(template, lab_test, False)
|
||||
|
||||
elif template.lab_test_template_type == 'Descriptive':
|
||||
elif template.lab_test_template_type == "Descriptive":
|
||||
create_descriptives(template, lab_test)
|
||||
|
||||
elif template.lab_test_template_type == 'Grouped':
|
||||
elif template.lab_test_template_type == "Grouped":
|
||||
# Iterate for each template in the group and create one result for all.
|
||||
for lab_test_group in template.lab_test_groups:
|
||||
# Template_in_group = None
|
||||
if lab_test_group.lab_test_template:
|
||||
template_in_group = frappe.get_doc('Lab Test Template', lab_test_group.lab_test_template)
|
||||
template_in_group = frappe.get_doc("Lab Test Template", lab_test_group.lab_test_template)
|
||||
if template_in_group:
|
||||
if template_in_group.lab_test_template_type == 'Single':
|
||||
if template_in_group.lab_test_template_type == "Single":
|
||||
create_normals(template_in_group, lab_test)
|
||||
|
||||
elif template_in_group.lab_test_template_type == 'Compound':
|
||||
normal_heading = lab_test.append('normal_test_items')
|
||||
elif template_in_group.lab_test_template_type == "Compound":
|
||||
normal_heading = lab_test.append("normal_test_items")
|
||||
normal_heading.lab_test_name = template_in_group.lab_test_name
|
||||
normal_heading.require_result_value = 0
|
||||
normal_heading.allow_blank = 1
|
||||
normal_heading.template = template_in_group.name
|
||||
create_compounds(template_in_group, lab_test, True)
|
||||
|
||||
elif template_in_group.lab_test_template_type == 'Descriptive':
|
||||
descriptive_heading = lab_test.append('descriptive_test_items')
|
||||
elif template_in_group.lab_test_template_type == "Descriptive":
|
||||
descriptive_heading = lab_test.append("descriptive_test_items")
|
||||
descriptive_heading.lab_test_name = template_in_group.lab_test_name
|
||||
descriptive_heading.require_result_value = 0
|
||||
descriptive_heading.allow_blank = 1
|
||||
descriptive_heading.template = template_in_group.name
|
||||
create_descriptives(template_in_group, lab_test)
|
||||
|
||||
else: # Lab Test Group - Add New Line
|
||||
normal = lab_test.append('normal_test_items')
|
||||
else: # Lab Test Group - Add New Line
|
||||
normal = lab_test.append("normal_test_items")
|
||||
normal.lab_test_name = lab_test_group.group_event
|
||||
normal.lab_test_uom = lab_test_group.group_test_uom
|
||||
normal.secondary_uom = lab_test_group.secondary_uom
|
||||
@@ -313,26 +355,27 @@ def load_result_format(lab_test, template, prescription, invoice):
|
||||
normal.require_result_value = 1
|
||||
normal.template = template.name
|
||||
|
||||
if template.lab_test_template_type != 'No Result':
|
||||
if template.lab_test_template_type != "No Result":
|
||||
if prescription:
|
||||
lab_test.prescription = prescription
|
||||
if invoice:
|
||||
frappe.db.set_value('Lab Prescription', prescription, 'invoiced', True)
|
||||
lab_test.save(ignore_permissions=True) # Insert the result
|
||||
frappe.db.set_value("Lab Prescription", prescription, "invoiced", True)
|
||||
lab_test.save(ignore_permissions=True) # Insert the result
|
||||
return lab_test
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_employee_by_user_id(user_id):
|
||||
emp_id = frappe.db.exists('Employee', { 'user_id': user_id })
|
||||
emp_id = frappe.db.exists("Employee", {"user_id": user_id})
|
||||
if emp_id:
|
||||
return frappe.get_doc('Employee', emp_id)
|
||||
return frappe.get_doc("Employee", emp_id)
|
||||
return None
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_lab_test_prescribed(patient):
|
||||
return frappe.db.sql(
|
||||
'''
|
||||
"""
|
||||
select
|
||||
lp.name,
|
||||
lp.lab_test_code,
|
||||
@@ -347,4 +390,6 @@ def get_lab_test_prescribed(patient):
|
||||
pe.patient=%s
|
||||
and lp.parent=pe.name
|
||||
and lp.lab_test_created=0
|
||||
''', (patient))
|
||||
""",
|
||||
(patient),
|
||||
)
|
||||
|
||||
@@ -20,12 +20,15 @@ from erpnext.healthcare.doctype.patient_medical_record.test_patient_medical_reco
|
||||
class TestLabTest(unittest.TestCase):
|
||||
def test_lab_test_item(self):
|
||||
lab_template = create_lab_test_template()
|
||||
self.assertTrue(frappe.db.exists('Item', lab_template.item))
|
||||
self.assertEqual(frappe.db.get_value('Item Price', {'item_code':lab_template.item}, 'price_list_rate'), lab_template.lab_test_rate)
|
||||
self.assertTrue(frappe.db.exists("Item", lab_template.item))
|
||||
self.assertEqual(
|
||||
frappe.db.get_value("Item Price", {"item_code": lab_template.item}, "price_list_rate"),
|
||||
lab_template.lab_test_rate,
|
||||
)
|
||||
|
||||
lab_template.disabled = 1
|
||||
lab_template.save()
|
||||
self.assertEqual(frappe.db.get_value('Item', lab_template.item, 'disabled'), 1)
|
||||
self.assertEqual(frappe.db.get_value("Item", lab_template.item, "disabled"), 1)
|
||||
|
||||
lab_template.reload()
|
||||
|
||||
@@ -43,7 +46,9 @@ class TestLabTest(unittest.TestCase):
|
||||
self.assertRaises(frappe.ValidationError, lab_test.submit)
|
||||
|
||||
def test_sample_collection(self):
|
||||
frappe.db.set_value('Healthcare Settings', 'Healthcare Settings', 'create_sample_collection_for_lab_test', 1)
|
||||
frappe.db.set_value(
|
||||
"Healthcare Settings", "Healthcare Settings", "create_sample_collection_for_lab_test", 1
|
||||
)
|
||||
lab_template = create_lab_test_template()
|
||||
|
||||
lab_test = create_lab_test(lab_template)
|
||||
@@ -53,9 +58,11 @@ class TestLabTest(unittest.TestCase):
|
||||
lab_test.save()
|
||||
|
||||
# check sample collection created
|
||||
self.assertTrue(frappe.db.exists('Sample Collection', {'sample': lab_template.sample}))
|
||||
self.assertTrue(frappe.db.exists("Sample Collection", {"sample": lab_template.sample}))
|
||||
|
||||
frappe.db.set_value('Healthcare Settings', 'Healthcare Settings', 'create_sample_collection_for_lab_test', 0)
|
||||
frappe.db.set_value(
|
||||
"Healthcare Settings", "Healthcare Settings", "create_sample_collection_for_lab_test", 0
|
||||
)
|
||||
lab_test = create_lab_test(lab_template)
|
||||
lab_test.descriptive_test_items[0].result_value = 12
|
||||
lab_test.descriptive_test_items[1].result_value = 1
|
||||
@@ -68,14 +75,14 @@ class TestLabTest(unittest.TestCase):
|
||||
|
||||
def test_create_lab_tests_from_sales_invoice(self):
|
||||
sales_invoice = create_sales_invoice()
|
||||
create_multiple('Sales Invoice', sales_invoice.name)
|
||||
create_multiple("Sales Invoice", sales_invoice.name)
|
||||
sales_invoice.reload()
|
||||
self.assertIsNotNone(sales_invoice.items[0].reference_dn)
|
||||
self.assertIsNotNone(sales_invoice.items[1].reference_dn)
|
||||
|
||||
def test_create_lab_tests_from_patient_encounter(self):
|
||||
patient_encounter = create_patient_encounter()
|
||||
create_multiple('Patient Encounter', patient_encounter.name)
|
||||
create_multiple("Patient Encounter", patient_encounter.name)
|
||||
patient_encounter.reload()
|
||||
self.assertTrue(patient_encounter.lab_test_prescription[0].lab_test_created)
|
||||
self.assertTrue(patient_encounter.lab_test_prescription[0].lab_test_created)
|
||||
@@ -83,23 +90,22 @@ class TestLabTest(unittest.TestCase):
|
||||
|
||||
def create_lab_test_template(test_sensitivity=0, sample_collection=1):
|
||||
medical_department = create_medical_department()
|
||||
if frappe.db.exists('Lab Test Template', 'Insulin Resistance'):
|
||||
return frappe.get_doc('Lab Test Template', 'Insulin Resistance')
|
||||
template = frappe.new_doc('Lab Test Template')
|
||||
template.lab_test_name = 'Insulin Resistance'
|
||||
template.lab_test_template_type = 'Descriptive'
|
||||
template.lab_test_code = 'Insulin Resistance'
|
||||
template.lab_test_group = 'Services'
|
||||
if frappe.db.exists("Lab Test Template", "Insulin Resistance"):
|
||||
return frappe.get_doc("Lab Test Template", "Insulin Resistance")
|
||||
template = frappe.new_doc("Lab Test Template")
|
||||
template.lab_test_name = "Insulin Resistance"
|
||||
template.lab_test_template_type = "Descriptive"
|
||||
template.lab_test_code = "Insulin Resistance"
|
||||
template.lab_test_group = "Services"
|
||||
template.department = medical_department
|
||||
template.is_billable = 1
|
||||
template.lab_test_description = 'Insulin Resistance'
|
||||
template.lab_test_description = "Insulin Resistance"
|
||||
template.lab_test_rate = 2000
|
||||
|
||||
for entry in ['FBS', 'Insulin', 'IR']:
|
||||
template.append('descriptive_test_templates', {
|
||||
'particulars': entry,
|
||||
'allow_blank': 1 if entry=='IR' else 0
|
||||
})
|
||||
for entry in ["FBS", "Insulin", "IR"]:
|
||||
template.append(
|
||||
"descriptive_test_templates", {"particulars": entry, "allow_blank": 1 if entry == "IR" else 0}
|
||||
)
|
||||
|
||||
if test_sensitivity:
|
||||
template.sensitivity = 1
|
||||
@@ -111,77 +117,85 @@ def create_lab_test_template(test_sensitivity=0, sample_collection=1):
|
||||
template.save()
|
||||
return template
|
||||
|
||||
|
||||
def create_medical_department():
|
||||
medical_department = frappe.db.exists('Medical Department', '_Test Medical Department')
|
||||
medical_department = frappe.db.exists("Medical Department", "_Test Medical Department")
|
||||
if not medical_department:
|
||||
medical_department = frappe.new_doc('Medical Department')
|
||||
medical_department.department = '_Test Medical Department'
|
||||
medical_department = frappe.new_doc("Medical Department")
|
||||
medical_department.department = "_Test Medical Department"
|
||||
medical_department.save()
|
||||
medical_department = medical_department.name
|
||||
|
||||
return medical_department
|
||||
|
||||
|
||||
def create_lab_test(lab_template):
|
||||
patient = create_patient()
|
||||
lab_test = frappe.new_doc('Lab Test')
|
||||
lab_test = frappe.new_doc("Lab Test")
|
||||
lab_test.template = lab_template.name
|
||||
lab_test.patient = patient
|
||||
lab_test.patient_sex = 'Female'
|
||||
lab_test.patient_sex = "Female"
|
||||
lab_test.save()
|
||||
|
||||
return lab_test
|
||||
|
||||
|
||||
def create_lab_test_sample():
|
||||
blood_sample = frappe.db.exists('Lab Test Sample', 'Blood Sample')
|
||||
blood_sample = frappe.db.exists("Lab Test Sample", "Blood Sample")
|
||||
if blood_sample:
|
||||
return blood_sample
|
||||
|
||||
sample = frappe.new_doc('Lab Test Sample')
|
||||
sample.sample = 'Blood Sample'
|
||||
sample.sample_uom = 'U/ml'
|
||||
sample = frappe.new_doc("Lab Test Sample")
|
||||
sample.sample = "Blood Sample"
|
||||
sample.sample_uom = "U/ml"
|
||||
sample.save()
|
||||
|
||||
return sample.name
|
||||
|
||||
|
||||
def create_sales_invoice():
|
||||
patient = create_patient()
|
||||
medical_department = create_medical_department()
|
||||
insulin_resistance_template = create_lab_test_template()
|
||||
blood_test_template = create_blood_test_template(medical_department)
|
||||
|
||||
sales_invoice = frappe.new_doc('Sales Invoice')
|
||||
sales_invoice = frappe.new_doc("Sales Invoice")
|
||||
sales_invoice.patient = patient
|
||||
sales_invoice.customer = frappe.db.get_value('Patient', patient, 'customer')
|
||||
sales_invoice.customer = frappe.db.get_value("Patient", patient, "customer")
|
||||
sales_invoice.due_date = getdate()
|
||||
sales_invoice.company = '_Test Company'
|
||||
sales_invoice.debit_to = get_receivable_account('_Test Company')
|
||||
sales_invoice.company = "_Test Company"
|
||||
sales_invoice.debit_to = get_receivable_account("_Test Company")
|
||||
|
||||
tests = [insulin_resistance_template, blood_test_template]
|
||||
for entry in tests:
|
||||
sales_invoice.append('items', {
|
||||
'item_code': entry.item,
|
||||
'item_name': entry.lab_test_name,
|
||||
'description': entry.lab_test_description,
|
||||
'qty': 1,
|
||||
'uom': 'Nos',
|
||||
'conversion_factor': 1,
|
||||
'income_account': get_income_account(None, '_Test Company'),
|
||||
'rate': entry.lab_test_rate,
|
||||
'amount': entry.lab_test_rate
|
||||
})
|
||||
sales_invoice.append(
|
||||
"items",
|
||||
{
|
||||
"item_code": entry.item,
|
||||
"item_name": entry.lab_test_name,
|
||||
"description": entry.lab_test_description,
|
||||
"qty": 1,
|
||||
"uom": "Nos",
|
||||
"conversion_factor": 1,
|
||||
"income_account": get_income_account(None, "_Test Company"),
|
||||
"rate": entry.lab_test_rate,
|
||||
"amount": entry.lab_test_rate,
|
||||
},
|
||||
)
|
||||
|
||||
sales_invoice.set_missing_values()
|
||||
|
||||
sales_invoice.submit()
|
||||
return sales_invoice
|
||||
|
||||
|
||||
def create_patient_encounter():
|
||||
patient = create_patient()
|
||||
medical_department = create_medical_department()
|
||||
insulin_resistance_template = create_lab_test_template()
|
||||
blood_test_template = create_blood_test_template(medical_department)
|
||||
|
||||
patient_encounter = frappe.new_doc('Patient Encounter')
|
||||
patient_encounter = frappe.new_doc("Patient Encounter")
|
||||
patient_encounter.patient = patient
|
||||
patient_encounter.practitioner = create_practitioner()
|
||||
patient_encounter.encounter_date = getdate()
|
||||
@@ -189,22 +203,21 @@ def create_patient_encounter():
|
||||
|
||||
tests = [insulin_resistance_template, blood_test_template]
|
||||
for entry in tests:
|
||||
patient_encounter.append('lab_test_prescription', {
|
||||
'lab_test_code': entry.item,
|
||||
'lab_test_name': entry.lab_test_name
|
||||
})
|
||||
patient_encounter.append(
|
||||
"lab_test_prescription", {"lab_test_code": entry.item, "lab_test_name": entry.lab_test_name}
|
||||
)
|
||||
|
||||
patient_encounter.submit()
|
||||
return patient_encounter
|
||||
|
||||
|
||||
def create_practitioner():
|
||||
practitioner = frappe.db.exists('Healthcare Practitioner', '_Test Healthcare Practitioner')
|
||||
practitioner = frappe.db.exists("Healthcare Practitioner", "_Test Healthcare Practitioner")
|
||||
|
||||
if not practitioner:
|
||||
practitioner = frappe.new_doc('Healthcare Practitioner')
|
||||
practitioner.first_name = '_Test Healthcare Practitioner'
|
||||
practitioner.gender = 'Female'
|
||||
practitioner = frappe.new_doc("Healthcare Practitioner")
|
||||
practitioner.first_name = "_Test Healthcare Practitioner"
|
||||
practitioner.gender = "Female"
|
||||
practitioner.op_consulting_charge = 500
|
||||
practitioner.inpatient_visit_charge = 500
|
||||
practitioner.save(ignore_permissions=True)
|
||||
|
||||
@@ -17,7 +17,7 @@ class LabTestTemplate(Document):
|
||||
|
||||
def validate(self):
|
||||
if self.is_billable and (not self.lab_test_rate or self.lab_test_rate <= 0.0):
|
||||
frappe.throw(_('Standard Selling Rate should be greater than zero.'))
|
||||
frappe.throw(_("Standard Selling Rate should be greater than zero."))
|
||||
|
||||
self.validate_conversion_factor()
|
||||
self.enable_disable_item()
|
||||
@@ -29,15 +29,17 @@ class LabTestTemplate(Document):
|
||||
item_price = self.item_price_exists()
|
||||
if not item_price:
|
||||
if self.lab_test_rate and self.lab_test_rate > 0.0:
|
||||
price_list_name = frappe.db.get_value('Selling Settings', None, 'selling_price_list') or frappe.db.get_value('Price List', {'selling': 1})
|
||||
price_list_name = frappe.db.get_value(
|
||||
"Selling Settings", None, "selling_price_list"
|
||||
) or frappe.db.get_value("Price List", {"selling": 1})
|
||||
make_item_price(self.lab_test_code, price_list_name, self.lab_test_rate)
|
||||
else:
|
||||
frappe.db.set_value('Item Price', item_price, 'price_list_rate', self.lab_test_rate)
|
||||
frappe.db.set_value("Item Price", item_price, "price_list_rate", self.lab_test_rate)
|
||||
|
||||
self.db_set('change_in_item', 0)
|
||||
self.db_set("change_in_item", 0)
|
||||
|
||||
elif not self.is_billable and self.item:
|
||||
frappe.db.set_value('Item', self.item, 'disabled', 1)
|
||||
frappe.db.set_value("Item", self.item, "disabled", 1)
|
||||
|
||||
self.reload()
|
||||
|
||||
@@ -46,99 +48,113 @@ class LabTestTemplate(Document):
|
||||
if self.item:
|
||||
try:
|
||||
item = self.item
|
||||
self.db_set('item', '')
|
||||
frappe.delete_doc('Item', item)
|
||||
self.db_set("item", "")
|
||||
frappe.delete_doc("Item", item)
|
||||
except Exception:
|
||||
frappe.throw(_('Not permitted. Please disable the Lab Test Template'))
|
||||
frappe.throw(_("Not permitted. Please disable the Lab Test Template"))
|
||||
|
||||
def enable_disable_item(self):
|
||||
if self.is_billable:
|
||||
if self.disabled:
|
||||
frappe.db.set_value('Item', self.item, 'disabled', 1)
|
||||
frappe.db.set_value("Item", self.item, "disabled", 1)
|
||||
else:
|
||||
frappe.db.set_value('Item', self.item, 'disabled', 0)
|
||||
frappe.db.set_value("Item", self.item, "disabled", 0)
|
||||
|
||||
def update_item(self):
|
||||
item = frappe.get_doc('Item', self.item)
|
||||
item = frappe.get_doc("Item", self.item)
|
||||
if item:
|
||||
item.update({
|
||||
'item_name': self.lab_test_name,
|
||||
'item_group': self.lab_test_group,
|
||||
'disabled': 0,
|
||||
'standard_rate': self.lab_test_rate,
|
||||
'description': self.lab_test_description
|
||||
})
|
||||
item.update(
|
||||
{
|
||||
"item_name": self.lab_test_name,
|
||||
"item_group": self.lab_test_group,
|
||||
"disabled": 0,
|
||||
"standard_rate": self.lab_test_rate,
|
||||
"description": self.lab_test_description,
|
||||
}
|
||||
)
|
||||
item.flags.ignore_mandatory = True
|
||||
item.save(ignore_permissions=True)
|
||||
|
||||
def item_price_exists(self):
|
||||
item_price = frappe.db.exists({'doctype': 'Item Price', 'item_code': self.lab_test_code})
|
||||
item_price = frappe.db.exists({"doctype": "Item Price", "item_code": self.lab_test_code})
|
||||
if item_price:
|
||||
return item_price[0][0]
|
||||
return False
|
||||
|
||||
def validate_conversion_factor(self):
|
||||
if self.lab_test_template_type == 'Single' and self.secondary_uom and not self.conversion_factor:
|
||||
frappe.throw(_('Conversion Factor is mandatory'))
|
||||
if self.lab_test_template_type == 'Compound':
|
||||
if self.lab_test_template_type == "Single" and self.secondary_uom and not self.conversion_factor:
|
||||
frappe.throw(_("Conversion Factor is mandatory"))
|
||||
if self.lab_test_template_type == "Compound":
|
||||
for item in self.normal_test_templates:
|
||||
if item.secondary_uom and not item.conversion_factor:
|
||||
frappe.throw(_('Row #{0}: Conversion Factor is mandatory').format(item.idx))
|
||||
if self.lab_test_template_type == 'Grouped':
|
||||
frappe.throw(_("Row #{0}: Conversion Factor is mandatory").format(item.idx))
|
||||
if self.lab_test_template_type == "Grouped":
|
||||
for group in self.lab_test_groups:
|
||||
if group.template_or_new_line == 'Add New Line' and group.secondary_uom and not group.conversion_factor:
|
||||
frappe.throw(_('Row #{0}: Conversion Factor is mandatory').format(group.idx))
|
||||
if (
|
||||
group.template_or_new_line == "Add New Line"
|
||||
and group.secondary_uom
|
||||
and not group.conversion_factor
|
||||
):
|
||||
frappe.throw(_("Row #{0}: Conversion Factor is mandatory").format(group.idx))
|
||||
|
||||
|
||||
def create_item_from_template(doc):
|
||||
uom = frappe.db.exists('UOM', 'Unit') or frappe.db.get_single_value('Stock Settings', 'stock_uom')
|
||||
uom = frappe.db.exists("UOM", "Unit") or frappe.db.get_single_value("Stock Settings", "stock_uom")
|
||||
# Insert item
|
||||
item = frappe.get_doc({
|
||||
'doctype': 'Item',
|
||||
'item_code': doc.lab_test_code,
|
||||
'item_name':doc.lab_test_name,
|
||||
'item_group': doc.lab_test_group,
|
||||
'description':doc.lab_test_description,
|
||||
'is_sales_item': 1,
|
||||
'is_service_item': 1,
|
||||
'is_purchase_item': 0,
|
||||
'is_stock_item': 0,
|
||||
'include_item_in_manufacturing': 0,
|
||||
'show_in_website': 0,
|
||||
'is_pro_applicable': 0,
|
||||
'disabled': 0 if doc.is_billable and not doc.disabled else doc.disabled,
|
||||
'stock_uom': uom
|
||||
}).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
item = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Item",
|
||||
"item_code": doc.lab_test_code,
|
||||
"item_name": doc.lab_test_name,
|
||||
"item_group": doc.lab_test_group,
|
||||
"description": doc.lab_test_description,
|
||||
"is_sales_item": 1,
|
||||
"is_service_item": 1,
|
||||
"is_purchase_item": 0,
|
||||
"is_stock_item": 0,
|
||||
"include_item_in_manufacturing": 0,
|
||||
"show_in_website": 0,
|
||||
"is_pro_applicable": 0,
|
||||
"disabled": 0 if doc.is_billable and not doc.disabled else doc.disabled,
|
||||
"stock_uom": uom,
|
||||
}
|
||||
).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
|
||||
# Insert item price
|
||||
if doc.is_billable and doc.lab_test_rate != 0.0:
|
||||
price_list_name = frappe.db.get_value('Selling Settings', None, 'selling_price_list') or frappe.db.get_value('Price List', {'selling': 1})
|
||||
price_list_name = frappe.db.get_value(
|
||||
"Selling Settings", None, "selling_price_list"
|
||||
) or frappe.db.get_value("Price List", {"selling": 1})
|
||||
if doc.lab_test_rate:
|
||||
make_item_price(item.name, price_list_name, doc.lab_test_rate)
|
||||
else:
|
||||
make_item_price(item.name, price_list_name, 0.0)
|
||||
# Set item in the template
|
||||
frappe.db.set_value('Lab Test Template', doc.name, 'item', item.name)
|
||||
frappe.db.set_value("Lab Test Template", doc.name, "item", item.name)
|
||||
|
||||
doc.reload()
|
||||
|
||||
|
||||
def make_item_price(item, price_list_name, item_price):
|
||||
frappe.get_doc({
|
||||
'doctype': 'Item Price',
|
||||
'price_list': price_list_name,
|
||||
'item_code': item,
|
||||
'price_list_rate': item_price
|
||||
}).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
frappe.get_doc(
|
||||
{
|
||||
"doctype": "Item Price",
|
||||
"price_list": price_list_name,
|
||||
"item_code": item,
|
||||
"price_list_rate": item_price,
|
||||
}
|
||||
).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def change_test_code_from_template(lab_test_code, doc):
|
||||
doc = frappe._dict(json.loads(doc))
|
||||
|
||||
if frappe.db.exists({'doctype': 'Item', 'item_code': lab_test_code}):
|
||||
frappe.throw(_('Lab Test Item {0} already exist').format(lab_test_code))
|
||||
if frappe.db.exists({"doctype": "Item", "item_code": lab_test_code}):
|
||||
frappe.throw(_("Lab Test Item {0} already exist").format(lab_test_code))
|
||||
else:
|
||||
rename_doc('Item', doc.name, lab_test_code, ignore_permissions=True)
|
||||
frappe.db.set_value('Lab Test Template', doc.name, 'lab_test_code', lab_test_code)
|
||||
frappe.db.set_value('Lab Test Template', doc.name, 'lab_test_name', lab_test_code)
|
||||
rename_doc('Lab Test Template', doc.name, lab_test_code, ignore_permissions=True)
|
||||
rename_doc("Item", doc.name, lab_test_code, ignore_permissions=True)
|
||||
frappe.db.set_value("Lab Test Template", doc.name, "lab_test_code", lab_test_code)
|
||||
frappe.db.set_value("Lab Test Template", doc.name, "lab_test_name", lab_test_code)
|
||||
rename_doc("Lab Test Template", doc.name, lab_test_code, ignore_permissions=True)
|
||||
return lab_test_code
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
|
||||
from frappe import _
|
||||
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'template',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Lab Tests'),
|
||||
'items': ['Lab Test']
|
||||
}
|
||||
]
|
||||
"fieldname": "template",
|
||||
"transactions": [{"label": _("Lab Tests"), "items": ["Lab Test"]}],
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@ import unittest
|
||||
|
||||
# test_records = frappe.get_test_records('Lab Test Template')
|
||||
|
||||
|
||||
class TestLabTestTemplate(unittest.TestCase):
|
||||
pass
|
||||
|
||||
@@ -5,5 +5,6 @@ import unittest
|
||||
|
||||
# test_records = frappe.get_test_records('Lab Test UOM')
|
||||
|
||||
|
||||
class TestLabTestUOM(unittest.TestCase):
|
||||
pass
|
||||
|
||||
@@ -7,4 +7,4 @@ from frappe.model.document import Document
|
||||
|
||||
class MedicalCode(Document):
|
||||
def autoname(self):
|
||||
self.name = self.medical_code_standard+" "+self.code
|
||||
self.name = self.medical_code_standard + " " + self.code
|
||||
|
||||
@@ -5,5 +5,6 @@ import unittest
|
||||
|
||||
# test_records = frappe.get_test_records('Medical Department')
|
||||
|
||||
|
||||
class TestMedicalDepartment(unittest.TestCase):
|
||||
pass
|
||||
|
||||
@@ -23,7 +23,7 @@ from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import (
|
||||
|
||||
class Patient(Document):
|
||||
def onload(self):
|
||||
'''Load address and contacts in `__onload`'''
|
||||
"""Load address and contacts in `__onload`"""
|
||||
load_address_and_contact(self)
|
||||
self.load_dashboard_info()
|
||||
|
||||
@@ -34,16 +34,16 @@ class Patient(Document):
|
||||
self.set_missing_customer_details()
|
||||
|
||||
def after_insert(self):
|
||||
if frappe.db.get_single_value('Healthcare Settings', 'collect_registration_fee'):
|
||||
frappe.db.set_value('Patient', self.name, 'status', 'Disabled')
|
||||
if frappe.db.get_single_value("Healthcare Settings", "collect_registration_fee"):
|
||||
frappe.db.set_value("Patient", self.name, "status", "Disabled")
|
||||
else:
|
||||
send_registration_sms(self)
|
||||
self.reload()
|
||||
|
||||
def on_update(self):
|
||||
if frappe.db.get_single_value('Healthcare Settings', 'link_customer_to_patient'):
|
||||
if frappe.db.get_single_value("Healthcare Settings", "link_customer_to_patient"):
|
||||
if self.customer:
|
||||
customer = frappe.get_doc('Customer', self.customer)
|
||||
customer = frappe.get_doc("Customer", self.customer)
|
||||
if self.customer_group:
|
||||
customer.customer_group = self.customer_group
|
||||
if self.territory:
|
||||
@@ -58,64 +58,83 @@ class Patient(Document):
|
||||
else:
|
||||
create_customer(self)
|
||||
|
||||
self.set_contact() # add or update contact
|
||||
self.set_contact() # add or update contact
|
||||
|
||||
if not self.user_id and self.email and self.invite_user:
|
||||
self.create_website_user()
|
||||
|
||||
def load_dashboard_info(self):
|
||||
if self.customer:
|
||||
info = get_dashboard_info('Customer', self.customer, None)
|
||||
self.set_onload('dashboard_info', info)
|
||||
info = get_dashboard_info("Customer", self.customer, None)
|
||||
self.set_onload("dashboard_info", info)
|
||||
|
||||
def set_full_name(self):
|
||||
if self.last_name:
|
||||
self.patient_name = ' '.join(filter(None, [self.first_name, self.last_name]))
|
||||
self.patient_name = " ".join(filter(None, [self.first_name, self.last_name]))
|
||||
else:
|
||||
self.patient_name = self.first_name
|
||||
|
||||
def set_missing_customer_details(self):
|
||||
if not self.customer_group:
|
||||
self.customer_group = frappe.db.get_single_value('Selling Settings', 'customer_group') or get_root_of('Customer Group')
|
||||
self.customer_group = frappe.db.get_single_value(
|
||||
"Selling Settings", "customer_group"
|
||||
) or get_root_of("Customer Group")
|
||||
if not self.territory:
|
||||
self.territory = frappe.db.get_single_value('Selling Settings', 'territory') or get_root_of('Territory')
|
||||
self.territory = frappe.db.get_single_value("Selling Settings", "territory") or get_root_of(
|
||||
"Territory"
|
||||
)
|
||||
if not self.default_price_list:
|
||||
self.default_price_list = frappe.db.get_single_value('Selling Settings', 'selling_price_list')
|
||||
self.default_price_list = frappe.db.get_single_value("Selling Settings", "selling_price_list")
|
||||
|
||||
if not self.customer_group or not self.territory or not self.default_price_list:
|
||||
frappe.msgprint(_('Please set defaults for Customer Group, Territory and Selling Price List in Selling Settings'), alert=True)
|
||||
frappe.msgprint(
|
||||
_(
|
||||
"Please set defaults for Customer Group, Territory and Selling Price List in Selling Settings"
|
||||
),
|
||||
alert=True,
|
||||
)
|
||||
|
||||
if not self.default_currency:
|
||||
self.default_currency = get_default_currency()
|
||||
if not self.language:
|
||||
self.language = frappe.db.get_single_value('System Settings', 'language')
|
||||
self.language = frappe.db.get_single_value("System Settings", "language")
|
||||
|
||||
def create_website_user(self):
|
||||
users = frappe.db.get_all('User', fields=['email', 'mobile_no'], or_filters={'email': self.email, 'mobile_no': self.mobile})
|
||||
users = frappe.db.get_all(
|
||||
"User",
|
||||
fields=["email", "mobile_no"],
|
||||
or_filters={"email": self.email, "mobile_no": self.mobile},
|
||||
)
|
||||
if users and users[0]:
|
||||
frappe.throw(_("User exists with Email {}, Mobile {}<br>Please check email / mobile or disable 'Invite as User' to skip creating User")
|
||||
.format(frappe.bold(users[0].email), frappe.bold(users[0].mobile_no)), frappe.DuplicateEntryError)
|
||||
frappe.throw(
|
||||
_(
|
||||
"User exists with Email {}, Mobile {}<br>Please check email / mobile or disable 'Invite as User' to skip creating User"
|
||||
).format(frappe.bold(users[0].email), frappe.bold(users[0].mobile_no)),
|
||||
frappe.DuplicateEntryError,
|
||||
)
|
||||
|
||||
user = frappe.get_doc({
|
||||
'doctype': 'User',
|
||||
'first_name': self.first_name,
|
||||
'last_name': self.last_name,
|
||||
'email': self.email,
|
||||
'user_type': 'Website User',
|
||||
'gender': self.sex,
|
||||
'phone': self.phone,
|
||||
'mobile_no': self.mobile,
|
||||
'birth_date': self.dob
|
||||
})
|
||||
user = frappe.get_doc(
|
||||
{
|
||||
"doctype": "User",
|
||||
"first_name": self.first_name,
|
||||
"last_name": self.last_name,
|
||||
"email": self.email,
|
||||
"user_type": "Website User",
|
||||
"gender": self.sex,
|
||||
"phone": self.phone,
|
||||
"mobile_no": self.mobile,
|
||||
"birth_date": self.dob,
|
||||
}
|
||||
)
|
||||
user.flags.ignore_permissions = True
|
||||
user.enabled = True
|
||||
user.send_welcome_email = True
|
||||
user.add_roles('Patient')
|
||||
self.db_set('user_id', user.name)
|
||||
user.add_roles("Patient")
|
||||
self.db_set("user_id", user.name)
|
||||
|
||||
def autoname(self):
|
||||
patient_name_by = frappe.db.get_single_value('Healthcare Settings', 'patient_name_by')
|
||||
if patient_name_by == 'Patient Name':
|
||||
patient_name_by = frappe.db.get_single_value("Healthcare Settings", "patient_name_by")
|
||||
if patient_name_by == "Patient Name":
|
||||
self.name = self.get_patient_name()
|
||||
else:
|
||||
set_name_by_naming_series(self)
|
||||
@@ -123,9 +142,13 @@ class Patient(Document):
|
||||
def get_patient_name(self):
|
||||
self.set_full_name()
|
||||
name = self.patient_name
|
||||
if frappe.db.get_value('Patient', name):
|
||||
count = frappe.db.sql("""select ifnull(MAX(CAST(SUBSTRING_INDEX(name, ' ', -1) AS UNSIGNED)), 0) from tabPatient
|
||||
where name like %s""", "%{0} - %".format(name), as_list=1)[0][0]
|
||||
if frappe.db.get_value("Patient", name):
|
||||
count = frappe.db.sql(
|
||||
"""select ifnull(MAX(CAST(SUBSTRING_INDEX(name, ' ', -1) AS UNSIGNED)), 0) from tabPatient
|
||||
where name like %s""",
|
||||
"%{0} - %".format(name),
|
||||
as_list=1,
|
||||
)[0][0]
|
||||
count = cint(count) + 1
|
||||
return "{0} - {1}".format(name, cstr(count))
|
||||
|
||||
@@ -143,22 +166,34 @@ class Patient(Document):
|
||||
age = self.age
|
||||
if not age:
|
||||
return
|
||||
age_str = str(age.years) + ' ' + _("Year(s)") + ' ' + str(age.months) + ' ' + _("Month(s)") + ' ' + str(age.days) + ' ' + _("Day(s)")
|
||||
age_str = (
|
||||
str(age.years)
|
||||
+ " "
|
||||
+ _("Year(s)")
|
||||
+ " "
|
||||
+ str(age.months)
|
||||
+ " "
|
||||
+ _("Month(s)")
|
||||
+ " "
|
||||
+ str(age.days)
|
||||
+ " "
|
||||
+ _("Day(s)")
|
||||
)
|
||||
return age_str
|
||||
|
||||
@frappe.whitelist()
|
||||
def invoice_patient_registration(self):
|
||||
if frappe.db.get_single_value('Healthcare Settings', 'registration_fee'):
|
||||
company = frappe.defaults.get_user_default('company')
|
||||
if frappe.db.get_single_value("Healthcare Settings", "registration_fee"):
|
||||
company = frappe.defaults.get_user_default("company")
|
||||
if not company:
|
||||
company = frappe.db.get_single_value('Global Defaults', 'default_company')
|
||||
company = frappe.db.get_single_value("Global Defaults", "default_company")
|
||||
|
||||
sales_invoice = make_invoice(self.name, company)
|
||||
sales_invoice.save(ignore_permissions=True)
|
||||
frappe.db.set_value('Patient', self.name, 'status', 'Active')
|
||||
frappe.db.set_value("Patient", self.name, "status", "Active")
|
||||
send_registration_sms(self)
|
||||
|
||||
return {'invoice': sales_invoice.name}
|
||||
return {"invoice": sales_invoice.name}
|
||||
|
||||
def set_contact(self):
|
||||
contact = get_default_contact(self.doctype, self.name)
|
||||
@@ -173,33 +208,35 @@ class Patient(Document):
|
||||
else:
|
||||
if self.customer:
|
||||
# customer contact exists, link patient
|
||||
contact = get_default_contact('Customer', self.customer)
|
||||
contact = get_default_contact("Customer", self.customer)
|
||||
|
||||
if contact:
|
||||
self.update_contact(contact)
|
||||
else:
|
||||
self.reload()
|
||||
if self.email or self.mobile or self.phone:
|
||||
contact = frappe.get_doc({
|
||||
'doctype': 'Contact',
|
||||
'first_name': self.first_name,
|
||||
'middle_name': self.middle_name,
|
||||
'last_name': self.last_name,
|
||||
'gender': self.sex,
|
||||
'is_primary_contact': 1
|
||||
})
|
||||
contact.append('links', dict(link_doctype='Patient', link_name=self.name))
|
||||
contact = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Contact",
|
||||
"first_name": self.first_name,
|
||||
"middle_name": self.middle_name,
|
||||
"last_name": self.last_name,
|
||||
"gender": self.sex,
|
||||
"is_primary_contact": 1,
|
||||
}
|
||||
)
|
||||
contact.append("links", dict(link_doctype="Patient", link_name=self.name))
|
||||
if self.customer:
|
||||
contact.append('links', dict(link_doctype='Customer', link_name=self.customer))
|
||||
contact.append("links", dict(link_doctype="Customer", link_name=self.customer))
|
||||
|
||||
contact.insert(ignore_permissions=True)
|
||||
self.update_contact(contact.name)
|
||||
|
||||
def update_contact(self, contact):
|
||||
contact = frappe.get_doc('Contact', contact)
|
||||
contact = frappe.get_doc("Contact", contact)
|
||||
|
||||
if not contact.has_link(self.doctype, self.name):
|
||||
contact.append('links', dict(link_doctype=self.doctype, link_name=self.name))
|
||||
contact.append("links", dict(link_doctype=self.doctype, link_name=self.name))
|
||||
|
||||
if self.email and self.email != contact.email_id:
|
||||
for email in contact.email_ids:
|
||||
@@ -211,73 +248,85 @@ class Patient(Document):
|
||||
for mobile in contact.phone_nos:
|
||||
mobile.is_primary_mobile_no = True if mobile.phone == self.mobile else False
|
||||
contact.add_phone(self.mobile, is_primary_mobile_no=True)
|
||||
contact.set_primary('mobile_no')
|
||||
contact.set_primary("mobile_no")
|
||||
|
||||
if self.phone and self.phone != contact.phone:
|
||||
for phone in contact.phone_nos:
|
||||
phone.is_primary_phone = True if phone.phone == self.phone else False
|
||||
contact.add_phone(self.phone, is_primary_phone=True)
|
||||
contact.set_primary('phone')
|
||||
contact.set_primary("phone")
|
||||
|
||||
contact.flags.skip_patient_update = True
|
||||
contact.save(ignore_permissions=True)
|
||||
|
||||
|
||||
def create_customer(doc):
|
||||
customer = frappe.get_doc({
|
||||
'doctype': 'Customer',
|
||||
'customer_name': doc.patient_name,
|
||||
'customer_group': doc.customer_group or frappe.db.get_single_value('Selling Settings', 'customer_group'),
|
||||
'territory' : doc.territory or frappe.db.get_single_value('Selling Settings', 'territory'),
|
||||
'customer_type': 'Individual',
|
||||
'default_currency': doc.default_currency,
|
||||
'default_price_list': doc.default_price_list,
|
||||
'language': doc.language
|
||||
}).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
customer = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Customer",
|
||||
"customer_name": doc.patient_name,
|
||||
"customer_group": doc.customer_group
|
||||
or frappe.db.get_single_value("Selling Settings", "customer_group"),
|
||||
"territory": doc.territory or frappe.db.get_single_value("Selling Settings", "territory"),
|
||||
"customer_type": "Individual",
|
||||
"default_currency": doc.default_currency,
|
||||
"default_price_list": doc.default_price_list,
|
||||
"language": doc.language,
|
||||
}
|
||||
).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
|
||||
frappe.db.set_value("Patient", doc.name, "customer", customer.name)
|
||||
frappe.msgprint(_("Customer {0} is created.").format(customer.name), alert=True)
|
||||
|
||||
frappe.db.set_value('Patient', doc.name, 'customer', customer.name)
|
||||
frappe.msgprint(_('Customer {0} is created.').format(customer.name), alert=True)
|
||||
|
||||
def make_invoice(patient, company):
|
||||
uom = frappe.db.exists('UOM', 'Nos') or frappe.db.get_single_value('Stock Settings', 'stock_uom')
|
||||
sales_invoice = frappe.new_doc('Sales Invoice')
|
||||
sales_invoice.customer = frappe.db.get_value('Patient', patient, 'customer')
|
||||
uom = frappe.db.exists("UOM", "Nos") or frappe.db.get_single_value("Stock Settings", "stock_uom")
|
||||
sales_invoice = frappe.new_doc("Sales Invoice")
|
||||
sales_invoice.customer = frappe.db.get_value("Patient", patient, "customer")
|
||||
sales_invoice.due_date = getdate()
|
||||
sales_invoice.company = company
|
||||
sales_invoice.is_pos = 0
|
||||
sales_invoice.debit_to = get_receivable_account(company)
|
||||
|
||||
item_line = sales_invoice.append('items')
|
||||
item_line.item_name = 'Registration Fee'
|
||||
item_line.description = 'Registration Fee'
|
||||
item_line = sales_invoice.append("items")
|
||||
item_line.item_name = "Registration Fee"
|
||||
item_line.description = "Registration Fee"
|
||||
item_line.qty = 1
|
||||
item_line.uom = uom
|
||||
item_line.conversion_factor = 1
|
||||
item_line.income_account = get_income_account(None, company)
|
||||
item_line.rate = frappe.db.get_single_value('Healthcare Settings', 'registration_fee')
|
||||
item_line.rate = frappe.db.get_single_value("Healthcare Settings", "registration_fee")
|
||||
item_line.amount = item_line.rate
|
||||
sales_invoice.set_missing_values()
|
||||
return sales_invoice
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_patient_detail(patient):
|
||||
patient_dict = frappe.db.sql("""select * from tabPatient where name=%s""", (patient), as_dict=1)
|
||||
if not patient_dict:
|
||||
frappe.throw(_('Patient not found'))
|
||||
vital_sign = frappe.db.sql("""select * from `tabVital Signs` where patient=%s
|
||||
order by signs_date desc limit 1""", (patient), as_dict=1)
|
||||
frappe.throw(_("Patient not found"))
|
||||
vital_sign = frappe.db.sql(
|
||||
"""select * from `tabVital Signs` where patient=%s
|
||||
order by signs_date desc limit 1""",
|
||||
(patient),
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
details = patient_dict[0]
|
||||
if vital_sign:
|
||||
details.update(vital_sign[0])
|
||||
return details
|
||||
|
||||
|
||||
def get_timeline_data(doctype, name):
|
||||
'''
|
||||
"""
|
||||
Return Patient's timeline data from medical records
|
||||
Also include the associated Customer timeline data
|
||||
'''
|
||||
patient_timeline_data = dict(frappe.db.sql('''
|
||||
"""
|
||||
patient_timeline_data = dict(
|
||||
frappe.db.sql(
|
||||
"""
|
||||
SELECT
|
||||
unix_timestamp(communication_date), count(*)
|
||||
FROM
|
||||
@@ -285,12 +334,16 @@ def get_timeline_data(doctype, name):
|
||||
WHERE
|
||||
patient=%s
|
||||
and `communication_date` > date_sub(curdate(), interval 1 year)
|
||||
GROUP BY communication_date''', name))
|
||||
GROUP BY communication_date""",
|
||||
name,
|
||||
)
|
||||
)
|
||||
|
||||
customer = frappe.db.get_value(doctype, name, 'customer')
|
||||
customer = frappe.db.get_value(doctype, name, "customer")
|
||||
if customer:
|
||||
from erpnext.accounts.party import get_timeline_data
|
||||
customer_timeline_data = get_timeline_data('Customer', customer)
|
||||
|
||||
customer_timeline_data = get_timeline_data("Customer", customer)
|
||||
patient_timeline_data.update(customer_timeline_data)
|
||||
|
||||
return patient_timeline_data
|
||||
|
||||
@@ -1,39 +1,26 @@
|
||||
|
||||
from frappe import _
|
||||
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'heatmap': True,
|
||||
'heatmap_message': _('This is based on transactions against this Patient. See timeline below for details'),
|
||||
'fieldname': 'patient',
|
||||
'non_standard_fieldnames': {
|
||||
'Payment Entry': 'party'
|
||||
},
|
||||
'transactions': [
|
||||
"heatmap": True,
|
||||
"heatmap_message": _(
|
||||
"This is based on transactions against this Patient. See timeline below for details"
|
||||
),
|
||||
"fieldname": "patient",
|
||||
"non_standard_fieldnames": {"Payment Entry": "party"},
|
||||
"transactions": [
|
||||
{
|
||||
'label': _('Appointments and Encounters'),
|
||||
'items': ['Patient Appointment', 'Vital Signs', 'Patient Encounter']
|
||||
"label": _("Appointments and Encounters"),
|
||||
"items": ["Patient Appointment", "Vital Signs", "Patient Encounter"],
|
||||
},
|
||||
{"label": _("Lab Tests and Vital Signs"), "items": ["Lab Test", "Sample Collection"]},
|
||||
{
|
||||
'label': _('Lab Tests and Vital Signs'),
|
||||
'items': ['Lab Test', 'Sample Collection']
|
||||
"label": _("Rehab and Physiotherapy"),
|
||||
"items": ["Patient Assessment", "Therapy Session", "Therapy Plan"],
|
||||
},
|
||||
{
|
||||
'label': _('Rehab and Physiotherapy'),
|
||||
'items': ['Patient Assessment', 'Therapy Session', 'Therapy Plan']
|
||||
},
|
||||
{
|
||||
'label': _('Surgery'),
|
||||
'items': ['Clinical Procedure']
|
||||
},
|
||||
{
|
||||
'label': _('Admissions'),
|
||||
'items': ['Inpatient Record', 'Inpatient Medication Order']
|
||||
},
|
||||
{
|
||||
'label': _('Billing and Payments'),
|
||||
'items': ['Sales Invoice', 'Payment Entry']
|
||||
}
|
||||
]
|
||||
{"label": _("Surgery"), "items": ["Clinical Procedure"]},
|
||||
{"label": _("Admissions"), "items": ["Inpatient Record", "Inpatient Medication Order"]},
|
||||
{"label": _("Billing and Payments"), "items": ["Sales Invoice", "Payment Entry"]},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -11,25 +11,25 @@ from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment imp
|
||||
class TestPatient(unittest.TestCase):
|
||||
def test_customer_created(self):
|
||||
frappe.db.sql("""delete from `tabPatient`""")
|
||||
frappe.db.set_value('Healthcare Settings', None, 'link_customer_to_patient', 1)
|
||||
frappe.db.set_value("Healthcare Settings", None, "link_customer_to_patient", 1)
|
||||
patient = create_patient()
|
||||
self.assertTrue(frappe.db.get_value('Patient', patient, 'customer'))
|
||||
self.assertTrue(frappe.db.get_value("Patient", patient, "customer"))
|
||||
|
||||
def test_patient_registration(self):
|
||||
frappe.db.sql("""delete from `tabPatient`""")
|
||||
settings = frappe.get_single('Healthcare Settings')
|
||||
settings = frappe.get_single("Healthcare Settings")
|
||||
settings.collect_registration_fee = 1
|
||||
settings.registration_fee = 500
|
||||
settings.save()
|
||||
|
||||
patient = create_patient()
|
||||
patient = frappe.get_doc('Patient', patient)
|
||||
self.assertEqual(patient.status, 'Disabled')
|
||||
patient = frappe.get_doc("Patient", patient)
|
||||
self.assertEqual(patient.status, "Disabled")
|
||||
|
||||
# check sales invoice and patient status
|
||||
result = patient.invoice_patient_registration()
|
||||
self.assertTrue(frappe.db.exists('Sales Invoice', result.get('invoice')))
|
||||
self.assertTrue(patient.status, 'Active')
|
||||
self.assertTrue(frappe.db.exists("Sales Invoice", result.get("invoice")))
|
||||
self.assertTrue(patient.status, "Active")
|
||||
|
||||
settings.collect_registration_fee = 0
|
||||
settings.save()
|
||||
@@ -40,33 +40,60 @@ class TestPatient(unittest.TestCase):
|
||||
frappe.db.sql("""delete from `tabContact` where name like'_Test Patient%'""")
|
||||
frappe.db.sql("""delete from `tabDynamic Link` where parent like '_Test Patient%'""")
|
||||
|
||||
patient = create_patient(patient_name='_Test Patient Contact', email='test-patient@example.com', mobile='+91 0000000001')
|
||||
customer = frappe.db.get_value('Patient', patient, 'customer')
|
||||
patient = create_patient(
|
||||
patient_name="_Test Patient Contact", email="test-patient@example.com", mobile="+91 0000000001"
|
||||
)
|
||||
customer = frappe.db.get_value("Patient", patient, "customer")
|
||||
self.assertTrue(customer)
|
||||
self.assertTrue(frappe.db.exists('Dynamic Link', {'parenttype': 'Contact', 'link_doctype': 'Patient', 'link_name': patient}))
|
||||
self.assertTrue(frappe.db.exists('Dynamic Link', {'parenttype': 'Contact', 'link_doctype': 'Customer', 'link_name': customer}))
|
||||
self.assertTrue(
|
||||
frappe.db.exists(
|
||||
"Dynamic Link", {"parenttype": "Contact", "link_doctype": "Patient", "link_name": patient}
|
||||
)
|
||||
)
|
||||
self.assertTrue(
|
||||
frappe.db.exists(
|
||||
"Dynamic Link", {"parenttype": "Contact", "link_doctype": "Customer", "link_name": customer}
|
||||
)
|
||||
)
|
||||
|
||||
# a second patient linking with same customer
|
||||
new_patient = create_patient(email='test-patient@example.com', mobile='+91 0000000009', customer=customer)
|
||||
self.assertTrue(frappe.db.exists('Dynamic Link', {'parenttype': 'Contact', 'link_doctype': 'Patient', 'link_name': new_patient}))
|
||||
self.assertTrue(frappe.db.exists('Dynamic Link', {'parenttype': 'Contact', 'link_doctype': 'Customer', 'link_name': customer}))
|
||||
new_patient = create_patient(
|
||||
email="test-patient@example.com", mobile="+91 0000000009", customer=customer
|
||||
)
|
||||
self.assertTrue(
|
||||
frappe.db.exists(
|
||||
"Dynamic Link", {"parenttype": "Contact", "link_doctype": "Patient", "link_name": new_patient}
|
||||
)
|
||||
)
|
||||
self.assertTrue(
|
||||
frappe.db.exists(
|
||||
"Dynamic Link", {"parenttype": "Contact", "link_doctype": "Customer", "link_name": customer}
|
||||
)
|
||||
)
|
||||
|
||||
def test_patient_user(self):
|
||||
frappe.db.sql("""delete from `tabUser` where email='test-patient-user@example.com'""")
|
||||
frappe.db.sql("""delete from `tabDynamic Link` where parent like '_Test Patient%'""")
|
||||
frappe.db.sql("""delete from `tabPatient` where name like '_Test Patient%'""")
|
||||
|
||||
patient = create_patient(patient_name='_Test Patient User', email='test-patient-user@example.com', mobile='+91 0000000009', create_user=True)
|
||||
user = frappe.db.get_value('Patient', patient, 'user_id')
|
||||
self.assertTrue(frappe.db.exists('User', user))
|
||||
patient = create_patient(
|
||||
patient_name="_Test Patient User",
|
||||
email="test-patient-user@example.com",
|
||||
mobile="+91 0000000009",
|
||||
create_user=True,
|
||||
)
|
||||
user = frappe.db.get_value("Patient", patient, "user_id")
|
||||
self.assertTrue(frappe.db.exists("User", user))
|
||||
|
||||
new_patient = frappe.get_doc({
|
||||
'doctype': 'Patient',
|
||||
'first_name': '_Test Patient Duplicate User',
|
||||
'sex': 'Male',
|
||||
'email': 'test-patient-user@example.com',
|
||||
'mobile': '+91 0000000009',
|
||||
'invite_user': 1
|
||||
})
|
||||
new_patient = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Patient",
|
||||
"first_name": "_Test Patient Duplicate User",
|
||||
"sex": "Male",
|
||||
"email": "test-patient-user@example.com",
|
||||
"mobile": "+91 0000000009",
|
||||
"invite_user": 1,
|
||||
}
|
||||
)
|
||||
|
||||
self.assertRaises(frappe.exceptions.DuplicateEntryError, new_patient.insert)
|
||||
|
||||
@@ -26,9 +26,12 @@ from erpnext.hr.doctype.employee.employee import is_holiday
|
||||
|
||||
class MaximumCapacityError(frappe.ValidationError):
|
||||
pass
|
||||
|
||||
|
||||
class OverlapError(frappe.ValidationError):
|
||||
pass
|
||||
|
||||
|
||||
class PatientAppointment(Document):
|
||||
def validate(self):
|
||||
self.validate_overlaps()
|
||||
@@ -46,8 +49,9 @@ class PatientAppointment(Document):
|
||||
send_confirmation_msg(self)
|
||||
|
||||
def set_title(self):
|
||||
self.title = _('{0} with {1}').format(self.patient_name or self.patient,
|
||||
self.practitioner_name or self.practitioner)
|
||||
self.title = _("{0} with {1}").format(
|
||||
self.patient_name or self.patient, self.practitioner_name or self.practitioner
|
||||
)
|
||||
|
||||
def set_status(self):
|
||||
today = getdate()
|
||||
@@ -55,16 +59,18 @@ class PatientAppointment(Document):
|
||||
|
||||
# If appointment is created for today set status as Open else Scheduled
|
||||
if appointment_date == today:
|
||||
self.status = 'Open'
|
||||
self.status = "Open"
|
||||
elif appointment_date > today:
|
||||
self.status = 'Scheduled'
|
||||
self.status = "Scheduled"
|
||||
|
||||
def validate_overlaps(self):
|
||||
end_time = datetime.datetime.combine(getdate(self.appointment_date), get_time(self.appointment_time)) \
|
||||
+ datetime.timedelta(minutes=flt(self.duration))
|
||||
end_time = datetime.datetime.combine(
|
||||
getdate(self.appointment_date), get_time(self.appointment_time)
|
||||
) + datetime.timedelta(minutes=flt(self.duration))
|
||||
|
||||
# all appointments for both patient and practitioner overlapping the duration of this appointment
|
||||
overlapping_appointments = frappe.db.sql("""
|
||||
overlapping_appointments = frappe.db.sql(
|
||||
"""
|
||||
SELECT
|
||||
name, practitioner, patient, appointment_time, duration, service_unit
|
||||
FROM
|
||||
@@ -77,35 +83,52 @@ class PatientAppointment(Document):
|
||||
(appointment_time=%(appointment_time)s))
|
||||
""",
|
||||
{
|
||||
'appointment_date': self.appointment_date,
|
||||
'name': self.name,
|
||||
'practitioner': self.practitioner,
|
||||
'patient': self.patient,
|
||||
'appointment_time': self.appointment_time,
|
||||
'end_time':end_time.time()
|
||||
"appointment_date": self.appointment_date,
|
||||
"name": self.name,
|
||||
"practitioner": self.practitioner,
|
||||
"patient": self.patient,
|
||||
"appointment_time": self.appointment_time,
|
||||
"end_time": end_time.time(),
|
||||
},
|
||||
as_dict = True
|
||||
as_dict=True,
|
||||
)
|
||||
|
||||
if not overlapping_appointments:
|
||||
return # No overlaps, nothing to validate!
|
||||
return # No overlaps, nothing to validate!
|
||||
|
||||
if self.service_unit: # validate service unit capacity if overlap enabled
|
||||
allow_overlap, service_unit_capacity = frappe.get_value('Healthcare Service Unit', self.service_unit,
|
||||
['overlap_appointments', 'service_unit_capacity'])
|
||||
if self.service_unit: # validate service unit capacity if overlap enabled
|
||||
allow_overlap, service_unit_capacity = frappe.get_value(
|
||||
"Healthcare Service Unit", self.service_unit, ["overlap_appointments", "service_unit_capacity"]
|
||||
)
|
||||
if allow_overlap:
|
||||
service_unit_appointments = list(filter(lambda appointment: appointment['service_unit'] == self.service_unit and
|
||||
appointment['patient'] != self.patient, overlapping_appointments)) # if same patient already booked, it should be an overlap
|
||||
service_unit_appointments = list(
|
||||
filter(
|
||||
lambda appointment: appointment["service_unit"] == self.service_unit
|
||||
and appointment["patient"] != self.patient,
|
||||
overlapping_appointments,
|
||||
)
|
||||
) # if same patient already booked, it should be an overlap
|
||||
if len(service_unit_appointments) >= (service_unit_capacity or 1):
|
||||
frappe.throw(_("Not allowed, {} cannot exceed maximum capacity {}")
|
||||
.format(frappe.bold(self.service_unit), frappe.bold(service_unit_capacity or 1)), MaximumCapacityError)
|
||||
else: # service_unit_appointments within capacity, remove from overlapping_appointments
|
||||
overlapping_appointments = [appointment for appointment in overlapping_appointments if appointment not in service_unit_appointments]
|
||||
frappe.throw(
|
||||
_("Not allowed, {} cannot exceed maximum capacity {}").format(
|
||||
frappe.bold(self.service_unit), frappe.bold(service_unit_capacity or 1)
|
||||
),
|
||||
MaximumCapacityError,
|
||||
)
|
||||
else: # service_unit_appointments within capacity, remove from overlapping_appointments
|
||||
overlapping_appointments = [
|
||||
appointment
|
||||
for appointment in overlapping_appointments
|
||||
if appointment not in service_unit_appointments
|
||||
]
|
||||
|
||||
if overlapping_appointments:
|
||||
frappe.throw(_("Not allowed, cannot overlap appointment {}")
|
||||
.format(frappe.bold(', '.join([appointment['name'] for appointment in overlapping_appointments]))), OverlapError)
|
||||
|
||||
frappe.throw(
|
||||
_("Not allowed, cannot overlap appointment {}").format(
|
||||
frappe.bold(", ".join([appointment["name"] for appointment in overlapping_appointments]))
|
||||
),
|
||||
OverlapError,
|
||||
)
|
||||
|
||||
def validate_service_unit(self):
|
||||
if self.inpatient_record and self.service_unit:
|
||||
@@ -113,48 +136,65 @@ class PatientAppointment(Document):
|
||||
get_current_healthcare_service_unit,
|
||||
)
|
||||
|
||||
is_inpatient_occupancy_unit = frappe.db.get_value('Healthcare Service Unit', self.service_unit,
|
||||
'inpatient_occupancy')
|
||||
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'))
|
||||
|
||||
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):
|
||||
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",
|
||||
)
|
||||
|
||||
def set_payment_details(self):
|
||||
if frappe.db.get_single_value('Healthcare Settings', 'automate_appointment_invoicing'):
|
||||
if frappe.db.get_single_value("Healthcare Settings", "automate_appointment_invoicing"):
|
||||
details = get_service_item_and_practitioner_charge(self)
|
||||
self.db_set('billing_item', details.get('service_item'))
|
||||
self.db_set("billing_item", details.get("service_item"))
|
||||
if not self.paid_amount:
|
||||
self.db_set('paid_amount', details.get('practitioner_charge'))
|
||||
self.db_set("paid_amount", details.get("practitioner_charge"))
|
||||
|
||||
def validate_customer_created(self):
|
||||
if frappe.db.get_single_value('Healthcare Settings', 'automate_appointment_invoicing'):
|
||||
if not frappe.db.get_value('Patient', self.patient, 'customer'):
|
||||
if frappe.db.get_single_value("Healthcare Settings", "automate_appointment_invoicing"):
|
||||
if not frappe.db.get_value("Patient", self.patient, "customer"):
|
||||
msg = _("Please set a Customer linked to the Patient")
|
||||
msg += " <b><a href='/app/Form/Patient/{0}'>{0}</a></b>".format(self.patient)
|
||||
frappe.throw(msg, title=_('Customer Not Found'))
|
||||
msg += " <b><a href='/app/Form/Patient/{0}'>{0}</a></b>".format(self.patient)
|
||||
frappe.throw(msg, title=_("Customer Not Found"))
|
||||
|
||||
def update_prescription_details(self):
|
||||
if self.procedure_prescription:
|
||||
frappe.db.set_value('Procedure Prescription', self.procedure_prescription, 'appointment_booked', 1)
|
||||
frappe.db.set_value(
|
||||
"Procedure Prescription", self.procedure_prescription, "appointment_booked", 1
|
||||
)
|
||||
if self.procedure_template:
|
||||
comments = frappe.db.get_value('Procedure Prescription', self.procedure_prescription, 'comments')
|
||||
comments = frappe.db.get_value(
|
||||
"Procedure Prescription", self.procedure_prescription, "comments"
|
||||
)
|
||||
if comments:
|
||||
frappe.db.set_value('Patient Appointment', self.name, 'notes', comments)
|
||||
frappe.db.set_value("Patient Appointment", self.name, "notes", comments)
|
||||
|
||||
def update_fee_validity(self):
|
||||
if not frappe.db.get_single_value('Healthcare Settings', 'enable_free_follow_ups'):
|
||||
if not frappe.db.get_single_value("Healthcare Settings", "enable_free_follow_ups"):
|
||||
return
|
||||
|
||||
fee_validity = manage_fee_validity(self)
|
||||
if fee_validity:
|
||||
frappe.msgprint(_('{0}: {1} has fee validity till {2}').format(self.patient,
|
||||
frappe.bold(self.patient_name), fee_validity.valid_till))
|
||||
frappe.msgprint(
|
||||
_("{0}: {1} has fee validity till {2}").format(
|
||||
self.patient, frappe.bold(self.patient_name), fee_validity.valid_till
|
||||
)
|
||||
)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_therapy_types(self):
|
||||
@@ -162,7 +202,7 @@ class PatientAppointment(Document):
|
||||
return
|
||||
|
||||
therapy_types = []
|
||||
doc = frappe.get_doc('Therapy Plan', self.therapy_plan)
|
||||
doc = frappe.get_doc("Therapy Plan", self.therapy_plan)
|
||||
for entry in doc.therapy_plan_details:
|
||||
therapy_types.append(entry.therapy_type)
|
||||
|
||||
@@ -171,26 +211,35 @@ class PatientAppointment(Document):
|
||||
|
||||
@frappe.whitelist()
|
||||
def check_payment_fields_reqd(patient):
|
||||
automate_invoicing = frappe.db.get_single_value('Healthcare Settings', 'automate_appointment_invoicing')
|
||||
free_follow_ups = frappe.db.get_single_value('Healthcare Settings', 'enable_free_follow_ups')
|
||||
automate_invoicing = frappe.db.get_single_value(
|
||||
"Healthcare Settings", "automate_appointment_invoicing"
|
||||
)
|
||||
free_follow_ups = frappe.db.get_single_value("Healthcare Settings", "enable_free_follow_ups")
|
||||
if automate_invoicing:
|
||||
if free_follow_ups:
|
||||
fee_validity = frappe.db.exists('Fee Validity', {'patient': patient, 'status': 'Pending'})
|
||||
fee_validity = frappe.db.exists("Fee Validity", {"patient": patient, "status": "Pending"})
|
||||
if fee_validity:
|
||||
return {'fee_validity': fee_validity}
|
||||
return {"fee_validity": fee_validity}
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def invoice_appointment(appointment_doc):
|
||||
automate_invoicing = frappe.db.get_single_value('Healthcare Settings', 'automate_appointment_invoicing')
|
||||
appointment_invoiced = frappe.db.get_value('Patient Appointment', appointment_doc.name, 'invoiced')
|
||||
enable_free_follow_ups = frappe.db.get_single_value('Healthcare Settings', 'enable_free_follow_ups')
|
||||
automate_invoicing = frappe.db.get_single_value(
|
||||
"Healthcare Settings", "automate_appointment_invoicing"
|
||||
)
|
||||
appointment_invoiced = frappe.db.get_value(
|
||||
"Patient Appointment", appointment_doc.name, "invoiced"
|
||||
)
|
||||
enable_free_follow_ups = frappe.db.get_single_value(
|
||||
"Healthcare Settings", "enable_free_follow_ups"
|
||||
)
|
||||
if enable_free_follow_ups:
|
||||
fee_validity = check_fee_validity(appointment_doc)
|
||||
if fee_validity and fee_validity.status == 'Completed':
|
||||
if fee_validity and fee_validity.status == "Completed":
|
||||
fee_validity = None
|
||||
elif not fee_validity:
|
||||
if frappe.db.exists('Fee Validity Reference', {'appointment': appointment_doc.name}):
|
||||
if frappe.db.exists("Fee Validity Reference", {"appointment": appointment_doc.name}):
|
||||
return
|
||||
else:
|
||||
fee_validity = None
|
||||
@@ -200,21 +249,21 @@ def invoice_appointment(appointment_doc):
|
||||
|
||||
|
||||
def create_sales_invoice(appointment_doc):
|
||||
sales_invoice = frappe.new_doc('Sales Invoice')
|
||||
sales_invoice = frappe.new_doc("Sales Invoice")
|
||||
sales_invoice.patient = appointment_doc.patient
|
||||
sales_invoice.customer = frappe.get_value('Patient', appointment_doc.patient, 'customer')
|
||||
sales_invoice.customer = frappe.get_value("Patient", appointment_doc.patient, "customer")
|
||||
sales_invoice.appointment = appointment_doc.name
|
||||
sales_invoice.due_date = getdate()
|
||||
sales_invoice.company = appointment_doc.company
|
||||
sales_invoice.debit_to = get_receivable_account(appointment_doc.company)
|
||||
|
||||
item = sales_invoice.append('items', {})
|
||||
item = sales_invoice.append("items", {})
|
||||
item = get_appointment_item(appointment_doc, item)
|
||||
|
||||
# Add payments if payment details are supplied else proceed to create invoice as Unpaid
|
||||
if appointment_doc.mode_of_payment and appointment_doc.paid_amount:
|
||||
sales_invoice.is_pos = 1
|
||||
payment = sales_invoice.append('payments', {})
|
||||
payment = sales_invoice.append("payments", {})
|
||||
payment.mode_of_payment = appointment_doc.mode_of_payment
|
||||
payment.amount = appointment_doc.paid_amount
|
||||
|
||||
@@ -222,56 +271,61 @@ def create_sales_invoice(appointment_doc):
|
||||
sales_invoice.flags.ignore_mandatory = True
|
||||
sales_invoice.save(ignore_permissions=True)
|
||||
sales_invoice.submit()
|
||||
frappe.msgprint(_('Sales Invoice {0} created').format(sales_invoice.name), alert=True)
|
||||
frappe.db.set_value('Patient Appointment', appointment_doc.name, {
|
||||
'invoiced': 1,
|
||||
'ref_sales_invoice': sales_invoice.name
|
||||
})
|
||||
frappe.msgprint(_("Sales Invoice {0} created").format(sales_invoice.name), alert=True)
|
||||
frappe.db.set_value(
|
||||
"Patient Appointment",
|
||||
appointment_doc.name,
|
||||
{"invoiced": 1, "ref_sales_invoice": sales_invoice.name},
|
||||
)
|
||||
|
||||
|
||||
def check_is_new_patient(patient, name=None):
|
||||
filters = {'patient': patient, 'status': ('!=','Cancelled')}
|
||||
filters = {"patient": patient, "status": ("!=", "Cancelled")}
|
||||
if name:
|
||||
filters['name'] = ('!=', name)
|
||||
filters["name"] = ("!=", name)
|
||||
|
||||
has_previous_appointment = frappe.db.exists('Patient Appointment', filters)
|
||||
has_previous_appointment = frappe.db.exists("Patient Appointment", filters)
|
||||
return not has_previous_appointment
|
||||
|
||||
|
||||
def get_appointment_item(appointment_doc, item):
|
||||
details = get_service_item_and_practitioner_charge(appointment_doc)
|
||||
charge = appointment_doc.paid_amount or details.get('practitioner_charge')
|
||||
item.item_code = details.get('service_item')
|
||||
item.description = _('Consulting Charges: {0}').format(appointment_doc.practitioner)
|
||||
charge = appointment_doc.paid_amount or details.get("practitioner_charge")
|
||||
item.item_code = details.get("service_item")
|
||||
item.description = _("Consulting Charges: {0}").format(appointment_doc.practitioner)
|
||||
item.income_account = get_income_account(appointment_doc.practitioner, appointment_doc.company)
|
||||
item.cost_center = frappe.get_cached_value('Company', appointment_doc.company, 'cost_center')
|
||||
item.cost_center = frappe.get_cached_value("Company", appointment_doc.company, "cost_center")
|
||||
item.rate = charge
|
||||
item.amount = charge
|
||||
item.qty = 1
|
||||
item.reference_dt = 'Patient Appointment'
|
||||
item.reference_dt = "Patient Appointment"
|
||||
item.reference_dn = appointment_doc.name
|
||||
return item
|
||||
|
||||
|
||||
def cancel_appointment(appointment_id):
|
||||
appointment = frappe.get_doc('Patient Appointment', appointment_id)
|
||||
appointment = frappe.get_doc("Patient Appointment", appointment_id)
|
||||
if appointment.invoiced:
|
||||
sales_invoice = check_sales_invoice_exists(appointment)
|
||||
if sales_invoice and cancel_sales_invoice(sales_invoice):
|
||||
msg = _('Appointment {0} and Sales Invoice {1} cancelled').format(appointment.name, sales_invoice.name)
|
||||
msg = _("Appointment {0} and Sales Invoice {1} cancelled").format(
|
||||
appointment.name, sales_invoice.name
|
||||
)
|
||||
else:
|
||||
msg = _('Appointment Cancelled. Please review and cancel the invoice {0}').format(sales_invoice.name)
|
||||
msg = _("Appointment Cancelled. Please review and cancel the invoice {0}").format(
|
||||
sales_invoice.name
|
||||
)
|
||||
else:
|
||||
fee_validity = manage_fee_validity(appointment)
|
||||
msg = _('Appointment Cancelled.')
|
||||
msg = _("Appointment Cancelled.")
|
||||
if fee_validity:
|
||||
msg += _('Fee Validity {0} updated.').format(fee_validity.name)
|
||||
msg += _("Fee Validity {0} updated.").format(fee_validity.name)
|
||||
|
||||
frappe.msgprint(msg)
|
||||
|
||||
|
||||
def cancel_sales_invoice(sales_invoice):
|
||||
if frappe.db.get_single_value('Healthcare Settings', 'automate_appointment_invoicing'):
|
||||
if frappe.db.get_single_value("Healthcare Settings", "automate_appointment_invoicing"):
|
||||
if len(sales_invoice.items) == 1:
|
||||
sales_invoice.cancel()
|
||||
return True
|
||||
@@ -279,13 +333,14 @@ def cancel_sales_invoice(sales_invoice):
|
||||
|
||||
|
||||
def check_sales_invoice_exists(appointment):
|
||||
sales_invoice = frappe.db.get_value('Sales Invoice Item', {
|
||||
'reference_dt': 'Patient Appointment',
|
||||
'reference_dn': appointment.name
|
||||
}, 'parent')
|
||||
sales_invoice = frappe.db.get_value(
|
||||
"Sales Invoice Item",
|
||||
{"reference_dt": "Patient Appointment", "reference_dn": appointment.name},
|
||||
"parent",
|
||||
)
|
||||
|
||||
if sales_invoice:
|
||||
sales_invoice = frappe.get_doc('Sales Invoice', sales_invoice)
|
||||
sales_invoice = frappe.get_doc("Sales Invoice", sales_invoice)
|
||||
return sales_invoice
|
||||
return False
|
||||
|
||||
@@ -300,24 +355,29 @@ def get_availability_data(date, practitioner):
|
||||
"""
|
||||
|
||||
date = getdate(date)
|
||||
weekday = date.strftime('%A')
|
||||
weekday = date.strftime("%A")
|
||||
|
||||
practitioner_doc = frappe.get_doc('Healthcare Practitioner', practitioner)
|
||||
practitioner_doc = frappe.get_doc("Healthcare Practitioner", practitioner)
|
||||
|
||||
check_employee_wise_availability(date, practitioner_doc)
|
||||
|
||||
if practitioner_doc.practitioner_schedules:
|
||||
slot_details = get_available_slots(practitioner_doc, date)
|
||||
else:
|
||||
frappe.throw(_('{0} does not have a Healthcare Practitioner Schedule. Add it in Healthcare Practitioner master').format(
|
||||
practitioner), title=_('Practitioner Schedule Not Found'))
|
||||
|
||||
frappe.throw(
|
||||
_(
|
||||
"{0} does not have a Healthcare Practitioner Schedule. Add it in Healthcare Practitioner master"
|
||||
).format(practitioner),
|
||||
title=_("Practitioner Schedule Not Found"),
|
||||
)
|
||||
|
||||
if not slot_details:
|
||||
# TODO: return available slots in nearby dates
|
||||
frappe.throw(_('Healthcare Practitioner not available on {0}').format(weekday), title=_('Not Available'))
|
||||
frappe.throw(
|
||||
_("Healthcare Practitioner not available on {0}").format(weekday), title=_("Not Available")
|
||||
)
|
||||
|
||||
return {'slot_details': slot_details}
|
||||
return {"slot_details": slot_details}
|
||||
|
||||
|
||||
def check_employee_wise_availability(date, practitioner_doc):
|
||||
@@ -325,32 +385,41 @@ def check_employee_wise_availability(date, practitioner_doc):
|
||||
if practitioner_doc.employee:
|
||||
employee = practitioner_doc.employee
|
||||
elif practitioner_doc.user_id:
|
||||
employee = frappe.db.get_value('Employee', {'user_id': practitioner_doc.user_id}, 'name')
|
||||
employee = frappe.db.get_value("Employee", {"user_id": practitioner_doc.user_id}, "name")
|
||||
|
||||
if employee:
|
||||
# check holiday
|
||||
if is_holiday(employee, date):
|
||||
frappe.throw(_('{0} is a holiday'.format(date)), title=_('Not Available'))
|
||||
frappe.throw(_("{0} is a holiday".format(date)), title=_("Not Available"))
|
||||
|
||||
# check leave status
|
||||
leave_record = frappe.db.sql("""select half_day from `tabLeave Application`
|
||||
leave_record = frappe.db.sql(
|
||||
"""select half_day from `tabLeave Application`
|
||||
where employee = %s and %s between from_date and to_date
|
||||
and docstatus = 1""", (employee, date), as_dict=True)
|
||||
and docstatus = 1""",
|
||||
(employee, date),
|
||||
as_dict=True,
|
||||
)
|
||||
if leave_record:
|
||||
if leave_record[0].half_day:
|
||||
frappe.throw(_('{0} is on a Half day Leave on {1}').format(practitioner_doc.name, date), title=_('Not Available'))
|
||||
frappe.throw(
|
||||
_("{0} is on a Half day Leave on {1}").format(practitioner_doc.name, date),
|
||||
title=_("Not Available"),
|
||||
)
|
||||
else:
|
||||
frappe.throw(_('{0} is on Leave on {1}').format(practitioner_doc.name, date), title=_('Not Available'))
|
||||
frappe.throw(
|
||||
_("{0} is on Leave on {1}").format(practitioner_doc.name, date), title=_("Not Available")
|
||||
)
|
||||
|
||||
|
||||
def get_available_slots(practitioner_doc, date):
|
||||
available_slots = slot_details = []
|
||||
weekday = date.strftime('%A')
|
||||
weekday = date.strftime("%A")
|
||||
practitioner = practitioner_doc.name
|
||||
|
||||
for schedule_entry in practitioner_doc.practitioner_schedules:
|
||||
validate_practitioner_schedules(schedule_entry, practitioner)
|
||||
practitioner_schedule = frappe.get_doc('Practitioner Schedule', schedule_entry.schedule)
|
||||
practitioner_schedule = frappe.get_doc("Practitioner Schedule", schedule_entry.schedule)
|
||||
|
||||
if practitioner_schedule and not practitioner_schedule.disabled:
|
||||
available_slots = []
|
||||
@@ -364,32 +433,45 @@ def get_available_slots(practitioner_doc, date):
|
||||
service_unit_capacity = 0
|
||||
# fetch all appointments to practitioner by service unit
|
||||
filters = {
|
||||
'practitioner': practitioner,
|
||||
'service_unit': schedule_entry.service_unit,
|
||||
'appointment_date': date,
|
||||
'status': ['not in',['Cancelled']]
|
||||
"practitioner": practitioner,
|
||||
"service_unit": schedule_entry.service_unit,
|
||||
"appointment_date": date,
|
||||
"status": ["not in", ["Cancelled"]],
|
||||
}
|
||||
|
||||
if schedule_entry.service_unit:
|
||||
slot_name = f'{schedule_entry.schedule}'
|
||||
allow_overlap, service_unit_capacity = frappe.get_value('Healthcare Service Unit', schedule_entry.service_unit, ['overlap_appointments', 'service_unit_capacity'])
|
||||
slot_name = f"{schedule_entry.schedule}"
|
||||
allow_overlap, service_unit_capacity = frappe.get_value(
|
||||
"Healthcare Service Unit",
|
||||
schedule_entry.service_unit,
|
||||
["overlap_appointments", "service_unit_capacity"],
|
||||
)
|
||||
if not allow_overlap:
|
||||
# fetch all appointments to service unit
|
||||
filters.pop('practitioner')
|
||||
filters.pop("practitioner")
|
||||
else:
|
||||
slot_name = schedule_entry.schedule
|
||||
# fetch all appointments to practitioner without service unit
|
||||
filters['practitioner'] = practitioner
|
||||
filters.pop('service_unit')
|
||||
filters["practitioner"] = practitioner
|
||||
filters.pop("service_unit")
|
||||
|
||||
appointments = frappe.get_all(
|
||||
'Patient Appointment',
|
||||
"Patient Appointment",
|
||||
filters=filters,
|
||||
fields=['name', 'appointment_time', 'duration', 'status'])
|
||||
fields=["name", "appointment_time", "duration", "status"],
|
||||
)
|
||||
|
||||
slot_details.append({'slot_name': slot_name, 'service_unit': schedule_entry.service_unit, 'avail_slot': available_slots,
|
||||
'appointments': appointments, 'allow_overlap': allow_overlap, 'service_unit_capacity': service_unit_capacity,
|
||||
'practitioner_name': practitioner_doc.practitioner_name})
|
||||
slot_details.append(
|
||||
{
|
||||
"slot_name": slot_name,
|
||||
"service_unit": schedule_entry.service_unit,
|
||||
"avail_slot": available_slots,
|
||||
"appointments": appointments,
|
||||
"allow_overlap": allow_overlap,
|
||||
"service_unit_capacity": service_unit_capacity,
|
||||
"practitioner_name": practitioner_doc.practitioner_name,
|
||||
}
|
||||
)
|
||||
|
||||
return slot_details
|
||||
|
||||
@@ -397,82 +479,107 @@ def get_available_slots(practitioner_doc, date):
|
||||
def validate_practitioner_schedules(schedule_entry, practitioner):
|
||||
if schedule_entry.schedule:
|
||||
if not schedule_entry.service_unit:
|
||||
frappe.throw(_('Practitioner {0} does not have a Service Unit set against the Practitioner Schedule {1}.').format(
|
||||
get_link_to_form('Healthcare Practitioner', practitioner), frappe.bold(schedule_entry.schedule)),
|
||||
title=_('Service Unit Not Found'))
|
||||
frappe.throw(
|
||||
_(
|
||||
"Practitioner {0} does not have a Service Unit set against the Practitioner Schedule {1}."
|
||||
).format(
|
||||
get_link_to_form("Healthcare Practitioner", practitioner),
|
||||
frappe.bold(schedule_entry.schedule),
|
||||
),
|
||||
title=_("Service Unit Not Found"),
|
||||
)
|
||||
|
||||
else:
|
||||
frappe.throw(_('Practitioner {0} does not have a Practitioner Schedule assigned.').format(
|
||||
get_link_to_form('Healthcare Practitioner', practitioner)),
|
||||
title=_('Practitioner Schedule Not Found'))
|
||||
frappe.throw(
|
||||
_("Practitioner {0} does not have a Practitioner Schedule assigned.").format(
|
||||
get_link_to_form("Healthcare Practitioner", practitioner)
|
||||
),
|
||||
title=_("Practitioner Schedule Not Found"),
|
||||
)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def update_status(appointment_id, status):
|
||||
frappe.db.set_value('Patient Appointment', appointment_id, 'status', status)
|
||||
frappe.db.set_value("Patient Appointment", appointment_id, "status", status)
|
||||
appointment_booked = True
|
||||
if status == 'Cancelled':
|
||||
if status == "Cancelled":
|
||||
appointment_booked = False
|
||||
cancel_appointment(appointment_id)
|
||||
|
||||
procedure_prescription = frappe.db.get_value('Patient Appointment', appointment_id, 'procedure_prescription')
|
||||
procedure_prescription = frappe.db.get_value(
|
||||
"Patient Appointment", appointment_id, "procedure_prescription"
|
||||
)
|
||||
if procedure_prescription:
|
||||
frappe.db.set_value('Procedure Prescription', procedure_prescription, 'appointment_booked', appointment_booked)
|
||||
frappe.db.set_value(
|
||||
"Procedure Prescription", procedure_prescription, "appointment_booked", appointment_booked
|
||||
)
|
||||
|
||||
|
||||
def send_confirmation_msg(doc):
|
||||
if frappe.db.get_single_value('Healthcare Settings', 'send_appointment_confirmation'):
|
||||
message = frappe.db.get_single_value('Healthcare Settings', 'appointment_confirmation_msg')
|
||||
if frappe.db.get_single_value("Healthcare Settings", "send_appointment_confirmation"):
|
||||
message = frappe.db.get_single_value("Healthcare Settings", "appointment_confirmation_msg")
|
||||
try:
|
||||
send_message(doc, message)
|
||||
except Exception:
|
||||
frappe.log_error(frappe.get_traceback(), _('Appointment Confirmation Message Not Sent'))
|
||||
frappe.msgprint(_('Appointment Confirmation Message Not Sent'), indicator='orange')
|
||||
frappe.log_error(frappe.get_traceback(), _("Appointment Confirmation Message Not Sent"))
|
||||
frappe.msgprint(_("Appointment Confirmation Message Not Sent"), indicator="orange")
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_encounter(source_name, target_doc=None):
|
||||
doc = get_mapped_doc('Patient Appointment', source_name, {
|
||||
'Patient Appointment': {
|
||||
'doctype': 'Patient Encounter',
|
||||
'field_map': [
|
||||
['appointment', 'name'],
|
||||
['patient', 'patient'],
|
||||
['practitioner', 'practitioner'],
|
||||
['medical_department', 'department'],
|
||||
['patient_sex', 'patient_sex'],
|
||||
['invoiced', 'invoiced'],
|
||||
['company', 'company']
|
||||
]
|
||||
}
|
||||
}, target_doc)
|
||||
doc = get_mapped_doc(
|
||||
"Patient Appointment",
|
||||
source_name,
|
||||
{
|
||||
"Patient Appointment": {
|
||||
"doctype": "Patient Encounter",
|
||||
"field_map": [
|
||||
["appointment", "name"],
|
||||
["patient", "patient"],
|
||||
["practitioner", "practitioner"],
|
||||
["medical_department", "department"],
|
||||
["patient_sex", "patient_sex"],
|
||||
["invoiced", "invoiced"],
|
||||
["company", "company"],
|
||||
],
|
||||
}
|
||||
},
|
||||
target_doc,
|
||||
)
|
||||
return doc
|
||||
|
||||
|
||||
def send_appointment_reminder():
|
||||
if frappe.db.get_single_value('Healthcare Settings', 'send_appointment_reminder'):
|
||||
remind_before = datetime.datetime.strptime(frappe.db.get_single_value('Healthcare Settings', 'remind_before'), '%H:%M:%S')
|
||||
if frappe.db.get_single_value("Healthcare Settings", "send_appointment_reminder"):
|
||||
remind_before = datetime.datetime.strptime(
|
||||
frappe.db.get_single_value("Healthcare Settings", "remind_before"), "%H:%M:%S"
|
||||
)
|
||||
reminder_dt = datetime.datetime.now() + datetime.timedelta(
|
||||
hours=remind_before.hour, minutes=remind_before.minute, seconds=remind_before.second)
|
||||
hours=remind_before.hour, minutes=remind_before.minute, seconds=remind_before.second
|
||||
)
|
||||
|
||||
appointment_list = frappe.db.get_all('Patient Appointment', {
|
||||
'appointment_datetime': ['between', (datetime.datetime.now(), reminder_dt)],
|
||||
'reminded': 0,
|
||||
'status': ['!=', 'Cancelled']
|
||||
})
|
||||
appointment_list = frappe.db.get_all(
|
||||
"Patient Appointment",
|
||||
{
|
||||
"appointment_datetime": ["between", (datetime.datetime.now(), reminder_dt)],
|
||||
"reminded": 0,
|
||||
"status": ["!=", "Cancelled"],
|
||||
},
|
||||
)
|
||||
|
||||
for appointment in appointment_list:
|
||||
doc = frappe.get_doc('Patient Appointment', appointment.name)
|
||||
message = frappe.db.get_single_value('Healthcare Settings', 'appointment_reminder_msg')
|
||||
doc = frappe.get_doc("Patient Appointment", appointment.name)
|
||||
message = frappe.db.get_single_value("Healthcare Settings", "appointment_reminder_msg")
|
||||
send_message(doc, message)
|
||||
frappe.db.set_value('Patient Appointment', doc.name, 'reminded', 1)
|
||||
frappe.db.set_value("Patient Appointment", doc.name, "reminded", 1)
|
||||
|
||||
|
||||
def send_message(doc, message):
|
||||
patient_mobile = frappe.db.get_value('Patient', doc.patient, 'mobile')
|
||||
patient_mobile = frappe.db.get_value("Patient", doc.patient, "mobile")
|
||||
if patient_mobile:
|
||||
context = {'doc': doc, 'alert': doc, 'comments': None}
|
||||
if doc.get('_comments'):
|
||||
context['comments'] = json.loads(doc.get('_comments'))
|
||||
context = {"doc": doc, "alert": doc, "comments": None}
|
||||
if doc.get("_comments"):
|
||||
context["comments"] = json.loads(doc.get("_comments"))
|
||||
|
||||
# jinja to string convertion happens here
|
||||
message = frappe.render_template(message, context)
|
||||
@@ -480,7 +587,8 @@ def send_message(doc, message):
|
||||
try:
|
||||
send_sms(number, message)
|
||||
except Exception as e:
|
||||
frappe.msgprint(_('SMS not sent, please check SMS Settings'), alert=True)
|
||||
frappe.msgprint(_("SMS not sent, please check SMS Settings"), alert=True)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_events(start, end, filters=None):
|
||||
@@ -491,9 +599,11 @@ def get_events(start, end, filters=None):
|
||||
:param filters: Filters (JSON).
|
||||
"""
|
||||
from frappe.desk.calendar import get_event_conditions
|
||||
conditions = get_event_conditions('Patient Appointment', filters)
|
||||
|
||||
data = frappe.db.sql("""
|
||||
conditions = get_event_conditions("Patient Appointment", filters)
|
||||
|
||||
data = frappe.db.sql(
|
||||
"""
|
||||
select
|
||||
`tabPatient Appointment`.name, `tabPatient Appointment`.patient,
|
||||
`tabPatient Appointment`.practitioner, `tabPatient Appointment`.status,
|
||||
@@ -505,11 +615,16 @@ def get_events(start, end, filters=None):
|
||||
left join `tabAppointment Type` on `tabPatient Appointment`.appointment_type=`tabAppointment Type`.name
|
||||
where
|
||||
(`tabPatient Appointment`.appointment_date between %(start)s and %(end)s)
|
||||
and `tabPatient Appointment`.status != 'Cancelled' and `tabPatient Appointment`.docstatus < 2 {conditions}""".format(conditions=conditions),
|
||||
{"start": start, "end": end}, as_dict=True, update={"allDay": 0})
|
||||
and `tabPatient Appointment`.status != 'Cancelled' and `tabPatient Appointment`.docstatus < 2 {conditions}""".format(
|
||||
conditions=conditions
|
||||
),
|
||||
{"start": start, "end": end},
|
||||
as_dict=True,
|
||||
update={"allDay": 0},
|
||||
)
|
||||
|
||||
for item in data:
|
||||
item.end = item.start + datetime.timedelta(minutes = item.duration)
|
||||
item.end = item.start + datetime.timedelta(minutes=item.duration)
|
||||
|
||||
return data
|
||||
|
||||
@@ -527,7 +642,8 @@ def get_procedure_prescribed(patient):
|
||||
ct.patient=%(patient)s and pp.parent=ct.name and pp.appointment_booked=0
|
||||
ORDER BY
|
||||
ct.creation desc
|
||||
""", {'patient': patient}
|
||||
""",
|
||||
{"patient": patient},
|
||||
)
|
||||
|
||||
|
||||
@@ -544,15 +660,16 @@ def get_prescribed_therapies(patient):
|
||||
e.patient=%(patient)s and t.parent=e.name
|
||||
ORDER BY
|
||||
e.creation desc
|
||||
""", {'patient': patient}
|
||||
""",
|
||||
{"patient": patient},
|
||||
)
|
||||
|
||||
|
||||
def update_appointment_status():
|
||||
# update the status of appointments daily
|
||||
appointments = frappe.get_all('Patient Appointment', {
|
||||
'status': ('not in', ['Closed', 'Cancelled'])
|
||||
}, as_dict=1)
|
||||
appointments = frappe.get_all(
|
||||
"Patient Appointment", {"status": ("not in", ["Closed", "Cancelled"])}, as_dict=1
|
||||
)
|
||||
|
||||
for appointment in appointments:
|
||||
frappe.get_doc('Patient Appointment', appointment.name).set_status()
|
||||
frappe.get_doc("Patient Appointment", appointment.name).set_status()
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
|
||||
from frappe import _
|
||||
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'appointment',
|
||||
'non_standard_fieldnames': {
|
||||
'Patient Medical Record': 'reference_name'
|
||||
},
|
||||
'transactions': [
|
||||
"fieldname": "appointment",
|
||||
"non_standard_fieldnames": {"Patient Medical Record": "reference_name"},
|
||||
"transactions": [
|
||||
{
|
||||
'label': _('Consultations'),
|
||||
'items': ['Patient Encounter', 'Vital Signs', 'Patient Medical Record']
|
||||
"label": _("Consultations"),
|
||||
"items": ["Patient Encounter", "Vital Signs", "Patient Medical Record"],
|
||||
}
|
||||
]
|
||||
],
|
||||
}
|
||||
|
||||
@@ -22,24 +22,28 @@ class TestPatientAppointment(unittest.TestCase):
|
||||
frappe.db.sql("""delete from `tabPatient Encounter`""")
|
||||
make_pos_profile()
|
||||
frappe.db.sql("""delete from `tabHealthcare Service Unit` where name like '_Test %'""")
|
||||
frappe.db.sql("""delete from `tabHealthcare Service Unit` where name like '_Test Service Unit Type%'""")
|
||||
frappe.db.sql(
|
||||
"""delete from `tabHealthcare Service Unit` where name like '_Test Service Unit Type%'"""
|
||||
)
|
||||
|
||||
def test_status(self):
|
||||
patient, practitioner = create_healthcare_docs()
|
||||
frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 0)
|
||||
frappe.db.set_value("Healthcare Settings", None, "automate_appointment_invoicing", 0)
|
||||
appointment = create_appointment(patient, practitioner, nowdate())
|
||||
self.assertEqual(appointment.status, 'Open')
|
||||
self.assertEqual(appointment.status, "Open")
|
||||
appointment = create_appointment(patient, practitioner, add_days(nowdate(), 2))
|
||||
self.assertEqual(appointment.status, 'Scheduled')
|
||||
self.assertEqual(appointment.status, "Scheduled")
|
||||
encounter = create_encounter(appointment)
|
||||
self.assertEqual(frappe.db.get_value('Patient Appointment', appointment.name, 'status'), 'Closed')
|
||||
self.assertEqual(
|
||||
frappe.db.get_value("Patient Appointment", appointment.name, "status"), "Closed"
|
||||
)
|
||||
encounter.cancel()
|
||||
self.assertEqual(frappe.db.get_value('Patient Appointment', appointment.name, 'status'), 'Open')
|
||||
self.assertEqual(frappe.db.get_value("Patient Appointment", appointment.name, "status"), "Open")
|
||||
|
||||
def test_start_encounter(self):
|
||||
patient, practitioner = create_healthcare_docs()
|
||||
frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 1)
|
||||
appointment = create_appointment(patient, practitioner, add_days(nowdate(), 4), invoice = 1)
|
||||
frappe.db.set_value("Healthcare Settings", None, "automate_appointment_invoicing", 1)
|
||||
appointment = create_appointment(patient, practitioner, add_days(nowdate(), 4), invoice=1)
|
||||
appointment.reload()
|
||||
self.assertEqual(appointment.invoiced, 1)
|
||||
encounter = make_encounter(appointment.name)
|
||||
@@ -48,92 +52,115 @@ class TestPatientAppointment(unittest.TestCase):
|
||||
self.assertEqual(encounter.practitioner, appointment.practitioner)
|
||||
self.assertEqual(encounter.patient, appointment.patient)
|
||||
# invoiced flag mapped from appointment
|
||||
self.assertEqual(encounter.invoiced, frappe.db.get_value('Patient Appointment', appointment.name, 'invoiced'))
|
||||
self.assertEqual(
|
||||
encounter.invoiced, frappe.db.get_value("Patient Appointment", appointment.name, "invoiced")
|
||||
)
|
||||
|
||||
def test_auto_invoicing(self):
|
||||
patient, practitioner = create_healthcare_docs()
|
||||
frappe.db.set_value('Healthcare Settings', None, 'enable_free_follow_ups', 0)
|
||||
frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 0)
|
||||
frappe.db.set_value("Healthcare Settings", None, "enable_free_follow_ups", 0)
|
||||
frappe.db.set_value("Healthcare Settings", None, "automate_appointment_invoicing", 0)
|
||||
appointment = create_appointment(patient, practitioner, nowdate())
|
||||
self.assertEqual(frappe.db.get_value('Patient Appointment', appointment.name, 'invoiced'), 0)
|
||||
self.assertEqual(frappe.db.get_value("Patient Appointment", appointment.name, "invoiced"), 0)
|
||||
|
||||
frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 1)
|
||||
frappe.db.set_value("Healthcare Settings", None, "automate_appointment_invoicing", 1)
|
||||
appointment = create_appointment(patient, practitioner, add_days(nowdate(), 2), invoice=1)
|
||||
self.assertEqual(frappe.db.get_value('Patient Appointment', appointment.name, 'invoiced'), 1)
|
||||
sales_invoice_name = frappe.db.get_value('Sales Invoice Item', {'reference_dn': appointment.name}, 'parent')
|
||||
self.assertEqual(frappe.db.get_value("Patient Appointment", appointment.name, "invoiced"), 1)
|
||||
sales_invoice_name = frappe.db.get_value(
|
||||
"Sales Invoice Item", {"reference_dn": appointment.name}, "parent"
|
||||
)
|
||||
self.assertTrue(sales_invoice_name)
|
||||
self.assertEqual(frappe.db.get_value('Sales Invoice', sales_invoice_name, 'company'), appointment.company)
|
||||
self.assertEqual(frappe.db.get_value('Sales Invoice', sales_invoice_name, 'patient'), appointment.patient)
|
||||
self.assertEqual(frappe.db.get_value('Sales Invoice', sales_invoice_name, 'paid_amount'), appointment.paid_amount)
|
||||
self.assertEqual(
|
||||
frappe.db.get_value("Sales Invoice", sales_invoice_name, "company"), appointment.company
|
||||
)
|
||||
self.assertEqual(
|
||||
frappe.db.get_value("Sales Invoice", sales_invoice_name, "patient"), appointment.patient
|
||||
)
|
||||
self.assertEqual(
|
||||
frappe.db.get_value("Sales Invoice", sales_invoice_name, "paid_amount"), appointment.paid_amount
|
||||
)
|
||||
|
||||
def test_auto_invoicing_based_on_department(self):
|
||||
patient, practitioner = create_healthcare_docs()
|
||||
medical_department = create_medical_department()
|
||||
frappe.db.set_value('Healthcare Settings', None, 'enable_free_follow_ups', 0)
|
||||
frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 1)
|
||||
appointment_type = create_appointment_type({'medical_department': medical_department})
|
||||
frappe.db.set_value("Healthcare Settings", None, "enable_free_follow_ups", 0)
|
||||
frappe.db.set_value("Healthcare Settings", None, "automate_appointment_invoicing", 1)
|
||||
appointment_type = create_appointment_type({"medical_department": medical_department})
|
||||
|
||||
appointment = create_appointment(patient, practitioner, add_days(nowdate(), 2),
|
||||
invoice=1, appointment_type=appointment_type.name, department=medical_department)
|
||||
appointment = create_appointment(
|
||||
patient,
|
||||
practitioner,
|
||||
add_days(nowdate(), 2),
|
||||
invoice=1,
|
||||
appointment_type=appointment_type.name,
|
||||
department=medical_department,
|
||||
)
|
||||
appointment.reload()
|
||||
|
||||
self.assertEqual(appointment.invoiced, 1)
|
||||
self.assertEqual(appointment.billing_item, 'HLC-SI-001')
|
||||
self.assertEqual(appointment.billing_item, "HLC-SI-001")
|
||||
self.assertEqual(appointment.paid_amount, 200)
|
||||
|
||||
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.assertTrue(sales_invoice_name)
|
||||
self.assertEqual(frappe.db.get_value('Sales Invoice', sales_invoice_name, 'paid_amount'), appointment.paid_amount)
|
||||
self.assertEqual(
|
||||
frappe.db.get_value("Sales Invoice", sales_invoice_name, "paid_amount"), appointment.paid_amount
|
||||
)
|
||||
|
||||
def test_auto_invoicing_according_to_appointment_type_charge(self):
|
||||
patient, practitioner = create_healthcare_docs()
|
||||
frappe.db.set_value('Healthcare Settings', None, 'enable_free_follow_ups', 0)
|
||||
frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 1)
|
||||
frappe.db.set_value("Healthcare Settings", None, "enable_free_follow_ups", 0)
|
||||
frappe.db.set_value("Healthcare Settings", None, "automate_appointment_invoicing", 1)
|
||||
|
||||
item = create_healthcare_service_items()
|
||||
items = [{
|
||||
'op_consulting_charge_item': item,
|
||||
'op_consulting_charge': 300
|
||||
}]
|
||||
appointment_type = create_appointment_type(args={
|
||||
'name': 'Generic Appointment Type charge',
|
||||
'items': items
|
||||
})
|
||||
items = [{"op_consulting_charge_item": item, "op_consulting_charge": 300}]
|
||||
appointment_type = create_appointment_type(
|
||||
args={"name": "Generic Appointment Type charge", "items": items}
|
||||
)
|
||||
|
||||
appointment = create_appointment(patient, practitioner, add_days(nowdate(), 2),
|
||||
invoice=1, appointment_type=appointment_type.name)
|
||||
appointment = create_appointment(
|
||||
patient, practitioner, add_days(nowdate(), 2), invoice=1, appointment_type=appointment_type.name
|
||||
)
|
||||
appointment.reload()
|
||||
|
||||
self.assertEqual(appointment.invoiced, 1)
|
||||
self.assertEqual(appointment.billing_item, item)
|
||||
self.assertEqual(appointment.paid_amount, 300)
|
||||
|
||||
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.assertTrue(sales_invoice_name)
|
||||
|
||||
def test_appointment_cancel(self):
|
||||
patient, practitioner = create_healthcare_docs()
|
||||
frappe.db.set_value('Healthcare Settings', None, 'enable_free_follow_ups', 1)
|
||||
frappe.db.set_value("Healthcare Settings", None, "enable_free_follow_ups", 1)
|
||||
appointment = create_appointment(patient, practitioner, nowdate())
|
||||
fee_validity = frappe.db.get_value('Fee Validity', {'patient': patient, 'practitioner': practitioner})
|
||||
fee_validity = frappe.db.get_value(
|
||||
"Fee Validity", {"patient": patient, "practitioner": practitioner}
|
||||
)
|
||||
# fee validity created
|
||||
self.assertTrue(fee_validity)
|
||||
|
||||
# first follow up appointment
|
||||
appointment = create_appointment(patient, practitioner, add_days(nowdate(), 1))
|
||||
self.assertEqual(frappe.db.get_value('Fee Validity', fee_validity, 'visited'), 1)
|
||||
self.assertEqual(frappe.db.get_value("Fee Validity", fee_validity, "visited"), 1)
|
||||
|
||||
update_status(appointment.name, 'Cancelled')
|
||||
update_status(appointment.name, "Cancelled")
|
||||
# check fee validity updated
|
||||
self.assertEqual(frappe.db.get_value('Fee Validity', fee_validity, 'visited'), 0)
|
||||
self.assertEqual(frappe.db.get_value("Fee Validity", fee_validity, "visited"), 0)
|
||||
|
||||
frappe.db.set_value('Healthcare Settings', None, 'enable_free_follow_ups', 0)
|
||||
frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 1)
|
||||
frappe.db.set_value("Healthcare Settings", None, "enable_free_follow_ups", 0)
|
||||
frappe.db.set_value("Healthcare Settings", None, "automate_appointment_invoicing", 1)
|
||||
appointment = create_appointment(patient, practitioner, add_days(nowdate(), 1), invoice=1)
|
||||
update_status(appointment.name, 'Cancelled')
|
||||
update_status(appointment.name, "Cancelled")
|
||||
# check invoice cancelled
|
||||
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')
|
||||
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")
|
||||
|
||||
def test_appointment_booking_for_admission_service_unit(self):
|
||||
from erpnext.healthcare.doctype.inpatient_record.inpatient_record import (
|
||||
@@ -153,17 +180,19 @@ class TestPatientAppointment(unittest.TestCase):
|
||||
# Schedule Admission
|
||||
ip_record = create_inpatient(patient)
|
||||
ip_record.expected_length_of_stay = 0
|
||||
ip_record.save(ignore_permissions = True)
|
||||
ip_record.save(ignore_permissions=True)
|
||||
|
||||
# Admit
|
||||
service_unit = get_healthcare_service_unit('_Test Service Unit Ip Occupancy')
|
||||
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, 'discharge_ordered_datetime': now_datetime()}))
|
||||
schedule_discharge(
|
||||
frappe.as_json({"patient": patient, "discharge_ordered_datetime": now_datetime()})
|
||||
)
|
||||
ip_record1 = frappe.get_doc("Inpatient Record", ip_record.name)
|
||||
mark_invoiced_inpatient_occupancy(ip_record1)
|
||||
discharge_patient(ip_record1, now_datetime())
|
||||
@@ -186,27 +215,33 @@ class TestPatientAppointment(unittest.TestCase):
|
||||
# Schedule Admission
|
||||
ip_record = create_inpatient(patient)
|
||||
ip_record.expected_length_of_stay = 0
|
||||
ip_record.save(ignore_permissions = True)
|
||||
ip_record.save(ignore_permissions=True)
|
||||
|
||||
# Admit
|
||||
service_unit = get_healthcare_service_unit('_Test Service Unit Ip Occupancy')
|
||||
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)
|
||||
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, 'discharge_ordered_datetime': now_datetime()}))
|
||||
schedule_discharge(
|
||||
frappe.as_json({"patient": patient, "discharge_ordered_datetime": now_datetime()})
|
||||
)
|
||||
ip_record1 = frappe.get_doc("Inpatient Record", ip_record.name)
|
||||
mark_invoiced_inpatient_occupancy(ip_record1)
|
||||
discharge_patient(ip_record1, now_datetime())
|
||||
|
||||
def test_payment_should_be_mandatory_for_new_patient_appointment(self):
|
||||
frappe.db.set_value('Healthcare Settings', None, 'enable_free_follow_ups', 1)
|
||||
frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 1)
|
||||
frappe.db.set_value('Healthcare Settings', None, 'max_visits', 3)
|
||||
frappe.db.set_value('Healthcare Settings', None, 'valid_days', 30)
|
||||
frappe.db.set_value("Healthcare Settings", None, "enable_free_follow_ups", 1)
|
||||
frappe.db.set_value("Healthcare Settings", None, "automate_appointment_invoicing", 1)
|
||||
frappe.db.set_value("Healthcare Settings", None, "max_visits", 3)
|
||||
frappe.db.set_value("Healthcare Settings", None, "valid_days", 30)
|
||||
|
||||
patient = create_patient()
|
||||
assert check_is_new_patient(patient)
|
||||
@@ -215,43 +250,60 @@ class TestPatientAppointment(unittest.TestCase):
|
||||
|
||||
def test_sales_invoice_should_be_generated_for_new_patient_appointment(self):
|
||||
patient, practitioner = create_healthcare_docs()
|
||||
frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 1)
|
||||
invoice_count = frappe.db.count('Sales Invoice')
|
||||
frappe.db.set_value("Healthcare Settings", None, "automate_appointment_invoicing", 1)
|
||||
invoice_count = frappe.db.count("Sales Invoice")
|
||||
|
||||
assert check_is_new_patient(patient)
|
||||
create_appointment(patient, practitioner, nowdate())
|
||||
new_invoice_count = frappe.db.count('Sales Invoice')
|
||||
new_invoice_count = frappe.db.count("Sales Invoice")
|
||||
|
||||
assert new_invoice_count == invoice_count + 1
|
||||
|
||||
def test_overlap_appointment(self):
|
||||
from erpnext.healthcare.doctype.patient_appointment.patient_appointment import OverlapError
|
||||
|
||||
patient, practitioner = create_healthcare_docs(id=1)
|
||||
patient_1, practitioner_1 = create_healthcare_docs(id=2)
|
||||
service_unit = create_service_unit(id=0)
|
||||
service_unit_1 = create_service_unit(id=1)
|
||||
appointment = create_appointment(patient, practitioner, nowdate(), service_unit=service_unit) # valid
|
||||
appointment = create_appointment(
|
||||
patient, practitioner, nowdate(), service_unit=service_unit
|
||||
) # valid
|
||||
|
||||
# patient and practitioner cannot have overlapping appointments
|
||||
appointment = create_appointment(patient, practitioner, nowdate(), service_unit=service_unit, save=0)
|
||||
appointment = create_appointment(
|
||||
patient, practitioner, nowdate(), service_unit=service_unit, save=0
|
||||
)
|
||||
self.assertRaises(OverlapError, appointment.save)
|
||||
appointment = create_appointment(patient, practitioner, nowdate(), service_unit=service_unit_1, save=0) # diff service unit
|
||||
appointment = create_appointment(
|
||||
patient, practitioner, nowdate(), service_unit=service_unit_1, save=0
|
||||
) # diff service unit
|
||||
self.assertRaises(OverlapError, appointment.save)
|
||||
appointment = create_appointment(patient, practitioner, nowdate(), save=0) # with no service unit link
|
||||
appointment = create_appointment(
|
||||
patient, practitioner, nowdate(), save=0
|
||||
) # with no service unit link
|
||||
self.assertRaises(OverlapError, appointment.save)
|
||||
|
||||
# patient cannot have overlapping appointments with other practitioners
|
||||
appointment = create_appointment(patient, practitioner_1, nowdate(), service_unit=service_unit, save=0)
|
||||
appointment = create_appointment(
|
||||
patient, practitioner_1, nowdate(), service_unit=service_unit, save=0
|
||||
)
|
||||
self.assertRaises(OverlapError, appointment.save)
|
||||
appointment = create_appointment(patient, practitioner_1, nowdate(), service_unit=service_unit_1, save=0)
|
||||
appointment = create_appointment(
|
||||
patient, practitioner_1, nowdate(), service_unit=service_unit_1, save=0
|
||||
)
|
||||
self.assertRaises(OverlapError, appointment.save)
|
||||
appointment = create_appointment(patient, practitioner_1, nowdate(), save=0)
|
||||
self.assertRaises(OverlapError, appointment.save)
|
||||
|
||||
# practitioner cannot have overlapping appointments with other patients
|
||||
appointment = create_appointment(patient_1, practitioner, nowdate(), service_unit=service_unit, save=0)
|
||||
appointment = create_appointment(
|
||||
patient_1, practitioner, nowdate(), service_unit=service_unit, save=0
|
||||
)
|
||||
self.assertRaises(OverlapError, appointment.save)
|
||||
appointment = create_appointment(patient_1, practitioner, nowdate(), service_unit=service_unit_1, save=0)
|
||||
appointment = create_appointment(
|
||||
patient_1, practitioner, nowdate(), service_unit=service_unit_1, save=0
|
||||
)
|
||||
self.assertRaises(OverlapError, appointment.save)
|
||||
appointment = create_appointment(patient_1, practitioner, nowdate(), save=0)
|
||||
self.assertRaises(OverlapError, appointment.save)
|
||||
@@ -261,19 +313,28 @@ class TestPatientAppointment(unittest.TestCase):
|
||||
MaximumCapacityError,
|
||||
OverlapError,
|
||||
)
|
||||
|
||||
practitioner = create_practitioner()
|
||||
capacity = 3
|
||||
overlap_service_unit_type = create_service_unit_type(id=10, allow_appointments=1, overlap_appointments=1)
|
||||
overlap_service_unit = create_service_unit(id=100, service_unit_type=overlap_service_unit_type, service_unit_capacity=capacity)
|
||||
overlap_service_unit_type = create_service_unit_type(
|
||||
id=10, allow_appointments=1, overlap_appointments=1
|
||||
)
|
||||
overlap_service_unit = create_service_unit(
|
||||
id=100, service_unit_type=overlap_service_unit_type, service_unit_capacity=capacity
|
||||
)
|
||||
|
||||
for i in range(0, capacity):
|
||||
patient = create_patient(id=i)
|
||||
create_appointment(patient, practitioner, nowdate(), service_unit=overlap_service_unit) # valid
|
||||
appointment = create_appointment(patient, practitioner, nowdate(), service_unit=overlap_service_unit, save=0) # overlap
|
||||
create_appointment(patient, practitioner, nowdate(), service_unit=overlap_service_unit) # valid
|
||||
appointment = create_appointment(
|
||||
patient, practitioner, nowdate(), service_unit=overlap_service_unit, save=0
|
||||
) # overlap
|
||||
self.assertRaises(OverlapError, appointment.save)
|
||||
|
||||
patient = create_patient(id=capacity)
|
||||
appointment = create_appointment(patient, practitioner, nowdate(), service_unit=overlap_service_unit, save=0)
|
||||
appointment = create_appointment(
|
||||
patient, practitioner, nowdate(), service_unit=overlap_service_unit, save=0
|
||||
)
|
||||
self.assertRaises(MaximumCapacityError, appointment.save)
|
||||
|
||||
def test_patient_appointment_should_consider_permissions_while_fetching_appointments(self):
|
||||
@@ -285,16 +346,16 @@ class TestPatientAppointment(unittest.TestCase):
|
||||
|
||||
roles = [{"doctype": "Has Role", "role": "Physician"}]
|
||||
user = create_user(roles=roles)
|
||||
new_practitioner = frappe.get_doc('Healthcare Practitioner', new_practitioner)
|
||||
new_practitioner = frappe.get_doc("Healthcare Practitioner", new_practitioner)
|
||||
new_practitioner.user_id = user.email
|
||||
new_practitioner.save()
|
||||
|
||||
frappe.set_user(user.name)
|
||||
appointments = frappe.get_list('Patient Appointment')
|
||||
appointments = frappe.get_list("Patient Appointment")
|
||||
assert len(appointments) == 1
|
||||
|
||||
frappe.set_user("Administrator")
|
||||
appointments = frappe.get_list('Patient Appointment')
|
||||
appointments = frappe.get_list("Patient Appointment")
|
||||
assert len(appointments) == 2
|
||||
|
||||
|
||||
@@ -305,14 +366,16 @@ def create_healthcare_docs(id=0):
|
||||
return patient, practitioner
|
||||
|
||||
|
||||
def create_patient(id=0, patient_name=None, email=None, mobile=None, customer=None, create_user=False):
|
||||
if frappe.db.exists('Patient', {'firstname':f'_Test Patient {str(id)}'}):
|
||||
patient = frappe.db.get_value('Patient', {'first_name': f'_Test Patient {str(id)}'}, ['name'])
|
||||
def create_patient(
|
||||
id=0, patient_name=None, email=None, mobile=None, customer=None, create_user=False
|
||||
):
|
||||
if frappe.db.exists("Patient", {"firstname": f"_Test Patient {str(id)}"}):
|
||||
patient = frappe.db.get_value("Patient", {"first_name": f"_Test Patient {str(id)}"}, ["name"])
|
||||
return patient
|
||||
|
||||
patient = frappe.new_doc('Patient')
|
||||
patient.first_name = patient_name if patient_name else f'_Test Patient {str(id)}'
|
||||
patient.sex = 'Female'
|
||||
patient = frappe.new_doc("Patient")
|
||||
patient.first_name = patient_name if patient_name else f"_Test Patient {str(id)}"
|
||||
patient.sex = "Female"
|
||||
patient.mobile = mobile
|
||||
patient.email = email
|
||||
patient.customer = customer
|
||||
@@ -323,24 +386,28 @@ def create_patient(id=0, patient_name=None, email=None, mobile=None, customer=No
|
||||
|
||||
|
||||
def create_medical_department(id=0):
|
||||
if frappe.db.exists('Medical Department', f'_Test Medical Department {str(id)}'):
|
||||
return f'_Test Medical Department {str(id)}'
|
||||
if frappe.db.exists("Medical Department", f"_Test Medical Department {str(id)}"):
|
||||
return f"_Test Medical Department {str(id)}"
|
||||
|
||||
medical_department = frappe.new_doc('Medical Department')
|
||||
medical_department.department = f'_Test Medical Department {str(id)}'
|
||||
medical_department = frappe.new_doc("Medical Department")
|
||||
medical_department.department = f"_Test Medical Department {str(id)}"
|
||||
medical_department.save(ignore_permissions=True)
|
||||
|
||||
return medical_department.name
|
||||
|
||||
|
||||
def create_practitioner(id=0, medical_department=None):
|
||||
if frappe.db.exists('Healthcare Practitioner', {'firstname':f'_Test Healthcare Practitioner {str(id)}'}):
|
||||
practitioner = frappe.db.get_value('Healthcare Practitioner', {'firstname':f'_Test Healthcare Practitioner {str(id)}'}, ['name'])
|
||||
if frappe.db.exists(
|
||||
"Healthcare Practitioner", {"firstname": f"_Test Healthcare Practitioner {str(id)}"}
|
||||
):
|
||||
practitioner = frappe.db.get_value(
|
||||
"Healthcare Practitioner", {"firstname": f"_Test Healthcare Practitioner {str(id)}"}, ["name"]
|
||||
)
|
||||
return practitioner
|
||||
|
||||
practitioner = frappe.new_doc('Healthcare Practitioner')
|
||||
practitioner.first_name = f'_Test Healthcare Practitioner {str(id)}'
|
||||
practitioner.gender = 'Female'
|
||||
practitioner = frappe.new_doc("Healthcare Practitioner")
|
||||
practitioner.first_name = f"_Test Healthcare Practitioner {str(id)}"
|
||||
practitioner.gender = "Female"
|
||||
practitioner.department = medical_department or create_medical_department(id)
|
||||
practitioner.op_consulting_charge = 500
|
||||
practitioner.inpatient_visit_charge = 500
|
||||
@@ -348,9 +415,10 @@ def create_practitioner(id=0, medical_department=None):
|
||||
|
||||
return practitioner.name
|
||||
|
||||
|
||||
def create_encounter(appointment):
|
||||
if appointment:
|
||||
encounter = frappe.new_doc('Patient Encounter')
|
||||
encounter = frappe.new_doc("Patient Encounter")
|
||||
encounter.appointment = appointment.name
|
||||
encounter.patient = appointment.patient
|
||||
encounter.practitioner = appointment.practitioner
|
||||
@@ -362,27 +430,37 @@ def create_encounter(appointment):
|
||||
|
||||
return encounter
|
||||
|
||||
def create_appointment(patient, practitioner, appointment_date, invoice=0, procedure_template=0,
|
||||
service_unit=None, appointment_type=None, save=1, department=None):
|
||||
|
||||
def create_appointment(
|
||||
patient,
|
||||
practitioner,
|
||||
appointment_date,
|
||||
invoice=0,
|
||||
procedure_template=0,
|
||||
service_unit=None,
|
||||
appointment_type=None,
|
||||
save=1,
|
||||
department=None,
|
||||
):
|
||||
item = create_healthcare_service_items()
|
||||
frappe.db.set_value('Healthcare Settings', None, 'inpatient_visit_charge_item', item)
|
||||
frappe.db.set_value('Healthcare Settings', None, 'op_consulting_charge_item', item)
|
||||
appointment = frappe.new_doc('Patient Appointment')
|
||||
frappe.db.set_value("Healthcare Settings", None, "inpatient_visit_charge_item", item)
|
||||
frappe.db.set_value("Healthcare Settings", None, "op_consulting_charge_item", item)
|
||||
appointment = frappe.new_doc("Patient Appointment")
|
||||
appointment.patient = patient
|
||||
appointment.practitioner = practitioner
|
||||
appointment.department = department or '_Test Medical Department'
|
||||
appointment.department = department or "_Test Medical Department"
|
||||
appointment.appointment_date = appointment_date
|
||||
appointment.company = '_Test Company'
|
||||
appointment.company = "_Test Company"
|
||||
appointment.duration = 15
|
||||
|
||||
if service_unit:
|
||||
appointment.service_unit = service_unit
|
||||
if invoice:
|
||||
appointment.mode_of_payment = 'Cash'
|
||||
appointment.mode_of_payment = "Cash"
|
||||
if appointment_type:
|
||||
appointment.appointment_type = appointment_type
|
||||
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)
|
||||
|
||||
@@ -390,30 +468,30 @@ def create_appointment(patient, practitioner, appointment_date, invoice=0, proce
|
||||
|
||||
|
||||
def create_healthcare_service_items():
|
||||
if frappe.db.exists('Item', 'HLC-SI-001'):
|
||||
return 'HLC-SI-001'
|
||||
if frappe.db.exists("Item", "HLC-SI-001"):
|
||||
return "HLC-SI-001"
|
||||
|
||||
item = frappe.new_doc('Item')
|
||||
item.item_code = 'HLC-SI-001'
|
||||
item.item_name = 'Consulting Charges'
|
||||
item.item_group = 'Services'
|
||||
item = frappe.new_doc("Item")
|
||||
item.item_code = "HLC-SI-001"
|
||||
item.item_name = "Consulting Charges"
|
||||
item.item_group = "Services"
|
||||
item.is_stock_item = 0
|
||||
item.stock_uom = 'Nos'
|
||||
item.stock_uom = "Nos"
|
||||
item.save()
|
||||
|
||||
return item.name
|
||||
|
||||
|
||||
def create_clinical_procedure_template():
|
||||
if frappe.db.exists('Clinical Procedure Template', 'Knee Surgery and Rehab'):
|
||||
return frappe.get_doc('Clinical Procedure Template', 'Knee Surgery and Rehab')
|
||||
if frappe.db.exists("Clinical Procedure Template", "Knee Surgery and Rehab"):
|
||||
return frappe.get_doc("Clinical Procedure Template", "Knee Surgery and Rehab")
|
||||
|
||||
template = frappe.new_doc('Clinical Procedure Template')
|
||||
template.template = 'Knee Surgery and Rehab'
|
||||
template.item_code = 'Knee Surgery and Rehab'
|
||||
template.item_group = 'Services'
|
||||
template = frappe.new_doc("Clinical Procedure Template")
|
||||
template.template = "Knee Surgery and Rehab"
|
||||
template.item_code = "Knee Surgery and Rehab"
|
||||
template.item_group = "Services"
|
||||
template.is_billable = 1
|
||||
template.description = 'Knee Surgery and Rehab'
|
||||
template.description = "Knee Surgery and Rehab"
|
||||
template.rate = 50000
|
||||
template.save()
|
||||
|
||||
@@ -422,36 +500,40 @@ def create_clinical_procedure_template():
|
||||
|
||||
def create_appointment_type(args=None):
|
||||
if not args:
|
||||
args = frappe.local.form_dict
|
||||
args = frappe.local.form_dict
|
||||
|
||||
name = args.get('name') or 'Test Appointment Type wise Charge'
|
||||
name = args.get("name") or "Test Appointment Type wise Charge"
|
||||
|
||||
if frappe.db.exists('Appointment Type', name):
|
||||
return frappe.get_doc('Appointment Type', name)
|
||||
if frappe.db.exists("Appointment Type", name):
|
||||
return frappe.get_doc("Appointment Type", name)
|
||||
|
||||
else:
|
||||
item = create_healthcare_service_items()
|
||||
items = [{
|
||||
'medical_department': args.get('medical_department') or '_Test Medical Department',
|
||||
'op_consulting_charge_item': item,
|
||||
'op_consulting_charge': 200
|
||||
}]
|
||||
return frappe.get_doc({
|
||||
'doctype': 'Appointment Type',
|
||||
'appointment_type': args.get('name') or 'Test Appointment Type wise Charge',
|
||||
'default_duration': args.get('default_duration') or 20,
|
||||
'color': args.get('color') or '#7575ff',
|
||||
'price_list': args.get('price_list') or frappe.db.get_value("Price List", {"selling": 1}),
|
||||
'items': args.get('items') or items
|
||||
}).insert()
|
||||
items = [
|
||||
{
|
||||
"medical_department": args.get("medical_department") or "_Test Medical Department",
|
||||
"op_consulting_charge_item": item,
|
||||
"op_consulting_charge": 200,
|
||||
}
|
||||
]
|
||||
return frappe.get_doc(
|
||||
{
|
||||
"doctype": "Appointment Type",
|
||||
"appointment_type": args.get("name") or "Test Appointment Type wise Charge",
|
||||
"default_duration": args.get("default_duration") or 20,
|
||||
"color": args.get("color") or "#7575ff",
|
||||
"price_list": args.get("price_list") or frappe.db.get_value("Price List", {"selling": 1}),
|
||||
"items": args.get("items") or items,
|
||||
}
|
||||
).insert()
|
||||
|
||||
|
||||
def create_service_unit_type(id=0, allow_appointments=1, overlap_appointments=0):
|
||||
if frappe.db.exists('Healthcare Service Unit Type', f'_Test Service Unit Type {str(id)}'):
|
||||
return f'_Test Service Unit Type {str(id)}'
|
||||
if frappe.db.exists("Healthcare Service Unit Type", f"_Test Service Unit Type {str(id)}"):
|
||||
return f"_Test Service Unit Type {str(id)}"
|
||||
|
||||
service_unit_type = frappe.new_doc('Healthcare Service Unit Type')
|
||||
service_unit_type.service_unit_type = f'_Test Service Unit Type {str(id)}'
|
||||
service_unit_type = frappe.new_doc("Healthcare Service Unit Type")
|
||||
service_unit_type.service_unit_type = f"_Test Service Unit Type {str(id)}"
|
||||
service_unit_type.allow_appointments = allow_appointments
|
||||
service_unit_type.overlap_appointments = overlap_appointments
|
||||
service_unit_type.save(ignore_permissions=True)
|
||||
@@ -460,28 +542,31 @@ def create_service_unit_type(id=0, allow_appointments=1, overlap_appointments=0)
|
||||
|
||||
|
||||
def create_service_unit(id=0, service_unit_type=None, service_unit_capacity=0):
|
||||
if frappe.db.exists('Healthcare Service Unit', f'_Test Service Unit {str(id)}'):
|
||||
return f'_Test service_unit {str(id)}'
|
||||
if frappe.db.exists("Healthcare Service Unit", f"_Test Service Unit {str(id)}"):
|
||||
return f"_Test service_unit {str(id)}"
|
||||
|
||||
service_unit = frappe.new_doc('Healthcare Service Unit')
|
||||
service_unit = frappe.new_doc("Healthcare Service Unit")
|
||||
service_unit.is_group = 0
|
||||
service_unit.healthcare_service_unit_name= f'_Test Service Unit {str(id)}'
|
||||
service_unit.healthcare_service_unit_name = f"_Test Service Unit {str(id)}"
|
||||
service_unit.service_unit_type = service_unit_type or create_service_unit_type(id)
|
||||
service_unit.service_unit_capacity = service_unit_capacity
|
||||
service_unit.save(ignore_permissions=True)
|
||||
|
||||
return service_unit.name
|
||||
|
||||
|
||||
def create_user(email=None, roles=None):
|
||||
if not email:
|
||||
email = '{}@frappe.com'.format(frappe.utils.random_string(10))
|
||||
user = frappe.db.exists('User', email)
|
||||
email = "{}@frappe.com".format(frappe.utils.random_string(10))
|
||||
user = frappe.db.exists("User", email)
|
||||
if not user:
|
||||
user = frappe.get_doc({
|
||||
"doctype": "User",
|
||||
"email": email,
|
||||
"first_name": "test_user",
|
||||
"password": "password",
|
||||
"roles": roles,
|
||||
}).insert()
|
||||
user = frappe.get_doc(
|
||||
{
|
||||
"doctype": "User",
|
||||
"email": email,
|
||||
"first_name": "test_user",
|
||||
"password": "password",
|
||||
"roles": roles,
|
||||
}
|
||||
).insert()
|
||||
return user
|
||||
|
||||
@@ -17,17 +17,23 @@ class PatientAssessment(Document):
|
||||
total_score += int(entry.score)
|
||||
self.total_score_obtained = total_score
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_patient_assessment(source_name, target_doc=None):
|
||||
doc = get_mapped_doc('Therapy Session', source_name, {
|
||||
'Therapy Session': {
|
||||
'doctype': 'Patient Assessment',
|
||||
'field_map': [
|
||||
['therapy_session', 'name'],
|
||||
['patient', 'patient'],
|
||||
['practitioner', 'practitioner']
|
||||
]
|
||||
doc = get_mapped_doc(
|
||||
"Therapy Session",
|
||||
source_name,
|
||||
{
|
||||
"Therapy Session": {
|
||||
"doctype": "Patient Assessment",
|
||||
"field_map": [
|
||||
["therapy_session", "name"],
|
||||
["patient", "patient"],
|
||||
["practitioner", "practitioner"],
|
||||
],
|
||||
}
|
||||
}, target_doc)
|
||||
},
|
||||
target_doc,
|
||||
)
|
||||
|
||||
return doc
|
||||
|
||||
@@ -15,7 +15,7 @@ class PatientEncounter(Document):
|
||||
|
||||
def on_update(self):
|
||||
if self.appointment:
|
||||
frappe.db.set_value('Patient Appointment', self.appointment, 'status', 'Closed')
|
||||
frappe.db.set_value("Patient Appointment", self.appointment, "status", "Closed")
|
||||
|
||||
def on_submit(self):
|
||||
if self.therapies:
|
||||
@@ -23,58 +23,59 @@ class PatientEncounter(Document):
|
||||
|
||||
def on_cancel(self):
|
||||
if self.appointment:
|
||||
frappe.db.set_value('Patient Appointment', self.appointment, 'status', 'Open')
|
||||
frappe.db.set_value("Patient Appointment", self.appointment, "status", "Open")
|
||||
|
||||
if self.inpatient_record and self.drug_prescription:
|
||||
delete_ip_medication_order(self)
|
||||
|
||||
def set_title(self):
|
||||
self.title = _('{0} with {1}').format(self.patient_name or self.patient,
|
||||
self.practitioner_name or self.practitioner)[:100]
|
||||
self.title = _("{0} with {1}").format(
|
||||
self.patient_name or self.patient, self.practitioner_name or self.practitioner
|
||||
)[:100]
|
||||
|
||||
@frappe.whitelist()
|
||||
@staticmethod
|
||||
def get_applicable_treatment_plans(encounter):
|
||||
patient = frappe.get_doc('Patient', encounter['patient'])
|
||||
patient = frappe.get_doc("Patient", encounter["patient"])
|
||||
|
||||
plan_filters = {}
|
||||
plan_filters['name'] = ['in', []]
|
||||
plan_filters["name"] = ["in", []]
|
||||
|
||||
age = patient.age
|
||||
if age:
|
||||
plan_filters['patient_age_from'] = ['<=', age.years]
|
||||
plan_filters['patient_age_to'] = ['>=', age.years]
|
||||
plan_filters["patient_age_from"] = ["<=", age.years]
|
||||
plan_filters["patient_age_to"] = [">=", age.years]
|
||||
|
||||
gender = patient.sex
|
||||
if gender:
|
||||
plan_filters['gender'] = ['in', [gender, None]]
|
||||
plan_filters["gender"] = ["in", [gender, None]]
|
||||
|
||||
diagnosis = encounter.get('diagnosis')
|
||||
diagnosis = encounter.get("diagnosis")
|
||||
if diagnosis:
|
||||
diagnosis = [_diagnosis['diagnosis'] for _diagnosis in encounter['diagnosis']]
|
||||
diagnosis = [_diagnosis["diagnosis"] for _diagnosis in encounter["diagnosis"]]
|
||||
filters = [
|
||||
['diagnosis', 'in', diagnosis],
|
||||
['parenttype', '=', 'Treatment Plan Template'],
|
||||
["diagnosis", "in", diagnosis],
|
||||
["parenttype", "=", "Treatment Plan Template"],
|
||||
]
|
||||
diagnosis = frappe.get_list('Patient Encounter Diagnosis', filters=filters, fields='*')
|
||||
plan_names = [_diagnosis['parent'] for _diagnosis in diagnosis]
|
||||
plan_filters['name'][1].extend(plan_names)
|
||||
diagnosis = frappe.get_list("Patient Encounter Diagnosis", filters=filters, fields="*")
|
||||
plan_names = [_diagnosis["parent"] for _diagnosis in diagnosis]
|
||||
plan_filters["name"][1].extend(plan_names)
|
||||
|
||||
symptoms = encounter.get('symptoms')
|
||||
symptoms = encounter.get("symptoms")
|
||||
if symptoms:
|
||||
symptoms = [symptom['complaint'] for symptom in encounter['symptoms']]
|
||||
symptoms = [symptom["complaint"] for symptom in encounter["symptoms"]]
|
||||
filters = [
|
||||
['complaint', 'in', symptoms],
|
||||
['parenttype', '=', 'Treatment Plan Template'],
|
||||
["complaint", "in", symptoms],
|
||||
["parenttype", "=", "Treatment Plan Template"],
|
||||
]
|
||||
symptoms = frappe.get_list('Patient Encounter Symptom', filters=filters, fields='*')
|
||||
plan_names = [symptom['parent'] for symptom in symptoms]
|
||||
plan_filters['name'][1].extend(plan_names)
|
||||
symptoms = frappe.get_list("Patient Encounter Symptom", filters=filters, fields="*")
|
||||
plan_names = [symptom["parent"] for symptom in symptoms]
|
||||
plan_filters["name"][1].extend(plan_names)
|
||||
|
||||
if not plan_filters['name'][1]:
|
||||
plan_filters.pop('name')
|
||||
if not plan_filters["name"][1]:
|
||||
plan_filters.pop("name")
|
||||
|
||||
plans = frappe.get_list('Treatment Plan Template', fields='*', filters=plan_filters)
|
||||
plans = frappe.get_list("Treatment Plan Template", fields="*", filters=plan_filters)
|
||||
|
||||
return plans
|
||||
|
||||
@@ -84,31 +85,27 @@ class PatientEncounter(Document):
|
||||
self.set_treatment_plan(treatment_plan)
|
||||
|
||||
def set_treatment_plan(self, plan):
|
||||
plan_items = frappe.get_list('Treatment Plan Template Item', filters={'parent': plan}, fields='*')
|
||||
plan_items = frappe.get_list(
|
||||
"Treatment Plan Template Item", filters={"parent": plan}, fields="*"
|
||||
)
|
||||
for plan_item in plan_items:
|
||||
self.set_treatment_plan_item(plan_item)
|
||||
|
||||
drugs = frappe.get_list('Drug Prescription', filters={'parent': plan}, fields='*')
|
||||
drugs = frappe.get_list("Drug Prescription", filters={"parent": plan}, fields="*")
|
||||
for drug in drugs:
|
||||
self.append('drug_prescription', drug)
|
||||
self.append("drug_prescription", drug)
|
||||
|
||||
self.save()
|
||||
|
||||
def set_treatment_plan_item(self, plan_item):
|
||||
if plan_item.type == 'Clinical Procedure Template':
|
||||
self.append('procedure_prescription', {
|
||||
'procedure': plan_item.template
|
||||
})
|
||||
if plan_item.type == "Clinical Procedure Template":
|
||||
self.append("procedure_prescription", {"procedure": plan_item.template})
|
||||
|
||||
if plan_item.type == 'Lab Test Template':
|
||||
self.append('lab_test_prescription', {
|
||||
'lab_test_code': plan_item.template
|
||||
})
|
||||
if plan_item.type == "Lab Test Template":
|
||||
self.append("lab_test_prescription", {"lab_test_code": plan_item.template})
|
||||
|
||||
if plan_item.type == 'Therapy Type':
|
||||
self.append('therapies', {
|
||||
'therapy_type': plan_item.template
|
||||
})
|
||||
if plan_item.type == "Therapy Type":
|
||||
self.append("therapies", {"therapy_type": plan_item.template})
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@@ -117,11 +114,11 @@ def make_ip_medication_order(source_name, target_doc=None):
|
||||
target.start_date = source.encounter_date
|
||||
for entry in source.drug_prescription:
|
||||
if entry.drug_code:
|
||||
dosage = frappe.get_doc('Prescription Dosage', entry.dosage)
|
||||
dosage = frappe.get_doc("Prescription Dosage", entry.dosage)
|
||||
dates = get_prescription_dates(entry.period, target.start_date)
|
||||
for date in dates:
|
||||
for dose in dosage.dosage_strength:
|
||||
order = target.append('medication_orders')
|
||||
order = target.append("medication_orders")
|
||||
order.drug = entry.drug_code
|
||||
order.drug_name = entry.drug_name
|
||||
order.dosage = dose.strength
|
||||
@@ -131,26 +128,32 @@ def make_ip_medication_order(source_name, target_doc=None):
|
||||
order.time = dose.strength_time
|
||||
target.end_date = dates[-1]
|
||||
|
||||
doc = get_mapped_doc('Patient Encounter', source_name, {
|
||||
'Patient Encounter': {
|
||||
'doctype': 'Inpatient Medication Order',
|
||||
'field_map': {
|
||||
'name': 'patient_encounter',
|
||||
'patient': 'patient',
|
||||
'patient_name': 'patient_name',
|
||||
'patient_age': 'patient_age',
|
||||
'inpatient_record': 'inpatient_record',
|
||||
'practitioner': 'practitioner',
|
||||
'start_date': 'encounter_date'
|
||||
doc = get_mapped_doc(
|
||||
"Patient Encounter",
|
||||
source_name,
|
||||
{
|
||||
"Patient Encounter": {
|
||||
"doctype": "Inpatient Medication Order",
|
||||
"field_map": {
|
||||
"name": "patient_encounter",
|
||||
"patient": "patient",
|
||||
"patient_name": "patient_name",
|
||||
"patient_age": "patient_age",
|
||||
"inpatient_record": "inpatient_record",
|
||||
"practitioner": "practitioner",
|
||||
"start_date": "encounter_date",
|
||||
},
|
||||
}
|
||||
}, target_doc, set_missing_values)
|
||||
},
|
||||
target_doc,
|
||||
set_missing_values,
|
||||
)
|
||||
|
||||
return doc
|
||||
|
||||
|
||||
def get_prescription_dates(period, start_date):
|
||||
prescription_duration = frappe.get_doc('Prescription Duration', period)
|
||||
prescription_duration = frappe.get_doc("Prescription Duration", period)
|
||||
days = prescription_duration.get_days()
|
||||
dates = [start_date]
|
||||
for i in range(1, days):
|
||||
@@ -160,21 +163,23 @@ def get_prescription_dates(period, start_date):
|
||||
|
||||
def create_therapy_plan(encounter):
|
||||
if len(encounter.therapies):
|
||||
doc = frappe.new_doc('Therapy Plan')
|
||||
doc = frappe.new_doc("Therapy Plan")
|
||||
doc.patient = encounter.patient
|
||||
doc.start_date = encounter.encounter_date
|
||||
for entry in encounter.therapies:
|
||||
doc.append('therapy_plan_details', {
|
||||
'therapy_type': entry.therapy_type,
|
||||
'no_of_sessions': entry.no_of_sessions
|
||||
})
|
||||
doc.append(
|
||||
"therapy_plan_details",
|
||||
{"therapy_type": entry.therapy_type, "no_of_sessions": entry.no_of_sessions},
|
||||
)
|
||||
doc.save(ignore_permissions=True)
|
||||
if doc.get('name'):
|
||||
encounter.db_set('therapy_plan', doc.name)
|
||||
frappe.msgprint(_('Therapy Plan {0} created successfully.').format(frappe.bold(doc.name)), alert=True)
|
||||
if doc.get("name"):
|
||||
encounter.db_set("therapy_plan", doc.name)
|
||||
frappe.msgprint(
|
||||
_("Therapy Plan {0} created successfully.").format(frappe.bold(doc.name)), alert=True
|
||||
)
|
||||
|
||||
|
||||
def delete_ip_medication_order(encounter):
|
||||
record = frappe.db.exists('Inpatient Medication Order', {'patient_encounter': encounter.name})
|
||||
record = frappe.db.exists("Inpatient Medication Order", {"patient_encounter": encounter.name})
|
||||
if record:
|
||||
frappe.delete_doc('Inpatient Medication Order', record, force=1)
|
||||
frappe.delete_doc("Inpatient Medication Order", record, force=1)
|
||||
|
||||
@@ -1,23 +1,16 @@
|
||||
|
||||
from frappe import _
|
||||
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'encounter',
|
||||
'non_standard_fieldnames': {
|
||||
'Patient Medical Record': 'reference_name',
|
||||
'Inpatient Medication Order': 'patient_encounter'
|
||||
"fieldname": "encounter",
|
||||
"non_standard_fieldnames": {
|
||||
"Patient Medical Record": "reference_name",
|
||||
"Inpatient Medication Order": "patient_encounter",
|
||||
},
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Records'),
|
||||
'items': ['Vital Signs', 'Patient Medical Record']
|
||||
},
|
||||
{
|
||||
'label': _('Orders'),
|
||||
'items': ['Inpatient Medication Order']
|
||||
}
|
||||
"transactions": [
|
||||
{"label": _("Records"), "items": ["Vital Signs", "Patient Medical Record"]},
|
||||
{"label": _("Orders"), "items": ["Inpatient Medication Order"]},
|
||||
],
|
||||
'disable_create_buttons': ['Inpatient Medication Order']
|
||||
"disable_create_buttons": ["Inpatient Medication Order"],
|
||||
}
|
||||
|
||||
@@ -11,75 +11,81 @@ from erpnext.healthcare.doctype.patient_encounter.patient_encounter import Patie
|
||||
class TestPatientEncounter(unittest.TestCase):
|
||||
def setUp(self):
|
||||
try:
|
||||
gender_m = frappe.get_doc({
|
||||
'doctype': 'Gender',
|
||||
'gender': 'MALE'
|
||||
}).insert()
|
||||
gender_f = frappe.get_doc({
|
||||
'doctype': 'Gender',
|
||||
'gender': 'FEMALE'
|
||||
}).insert()
|
||||
gender_m = frappe.get_doc({"doctype": "Gender", "gender": "MALE"}).insert()
|
||||
gender_f = frappe.get_doc({"doctype": "Gender", "gender": "FEMALE"}).insert()
|
||||
except frappe.exceptions.DuplicateEntryError:
|
||||
gender_m = frappe.get_doc({
|
||||
'doctype': 'Gender',
|
||||
'gender': 'MALE'
|
||||
})
|
||||
gender_f = frappe.get_doc({
|
||||
'doctype': 'Gender',
|
||||
'gender': 'FEMALE'
|
||||
})
|
||||
gender_m = frappe.get_doc({"doctype": "Gender", "gender": "MALE"})
|
||||
gender_f = frappe.get_doc({"doctype": "Gender", "gender": "FEMALE"})
|
||||
|
||||
self.patient_male = frappe.get_doc({
|
||||
'doctype': 'Patient',
|
||||
'first_name': 'John',
|
||||
'sex': gender_m.gender,
|
||||
}).insert()
|
||||
self.patient_female = frappe.get_doc({
|
||||
'doctype': 'Patient',
|
||||
'first_name': 'Curie',
|
||||
'sex': gender_f.gender,
|
||||
}).insert()
|
||||
self.practitioner = frappe.get_doc({
|
||||
'doctype': 'Healthcare Practitioner',
|
||||
'first_name': 'Doc',
|
||||
'sex': 'MALE',
|
||||
}).insert()
|
||||
self.patient_male = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Patient",
|
||||
"first_name": "John",
|
||||
"sex": gender_m.gender,
|
||||
}
|
||||
).insert()
|
||||
self.patient_female = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Patient",
|
||||
"first_name": "Curie",
|
||||
"sex": gender_f.gender,
|
||||
}
|
||||
).insert()
|
||||
self.practitioner = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Healthcare Practitioner",
|
||||
"first_name": "Doc",
|
||||
"sex": "MALE",
|
||||
}
|
||||
).insert()
|
||||
try:
|
||||
self.care_plan_male = frappe.get_doc({
|
||||
'doctype': 'Treatment Plan Template',
|
||||
'template_name': 'test plan - m',
|
||||
'gender': gender_m.gender,
|
||||
}).insert()
|
||||
self.care_plan_female = frappe.get_doc({
|
||||
'doctype': 'Treatment Plan Template',
|
||||
'template_name': 'test plan - f',
|
||||
'gender': gender_f.gender,
|
||||
}).insert()
|
||||
self.care_plan_male = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Treatment Plan Template",
|
||||
"template_name": "test plan - m",
|
||||
"gender": gender_m.gender,
|
||||
}
|
||||
).insert()
|
||||
self.care_plan_female = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Treatment Plan Template",
|
||||
"template_name": "test plan - f",
|
||||
"gender": gender_f.gender,
|
||||
}
|
||||
).insert()
|
||||
except frappe.exceptions.DuplicateEntryError:
|
||||
self.care_plan_male = frappe.get_doc({
|
||||
'doctype': 'Treatment Plan Template',
|
||||
'template_name': 'test plan - m',
|
||||
'gender': gender_m.gender,
|
||||
})
|
||||
self.care_plan_female = frappe.get_doc({
|
||||
'doctype': 'Treatment Plan Template',
|
||||
'template_name': 'test plan - f',
|
||||
'gender': gender_f.gender,
|
||||
})
|
||||
self.care_plan_male = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Treatment Plan Template",
|
||||
"template_name": "test plan - m",
|
||||
"gender": gender_m.gender,
|
||||
}
|
||||
)
|
||||
self.care_plan_female = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Treatment Plan Template",
|
||||
"template_name": "test plan - f",
|
||||
"gender": gender_f.gender,
|
||||
}
|
||||
)
|
||||
|
||||
def test_treatment_plan_template_filter(self):
|
||||
encounter = frappe.get_doc({
|
||||
'doctype': 'Patient Encounter',
|
||||
'patient': self.patient_male.name,
|
||||
'practitioner': self.practitioner.name,
|
||||
}).insert()
|
||||
encounter = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Patient Encounter",
|
||||
"patient": self.patient_male.name,
|
||||
"practitioner": self.practitioner.name,
|
||||
}
|
||||
).insert()
|
||||
plans = PatientEncounter.get_applicable_treatment_plans(encounter.as_dict())
|
||||
self.assertEqual(plans[0]['name'], self.care_plan_male.template_name)
|
||||
self.assertEqual(plans[0]["name"], self.care_plan_male.template_name)
|
||||
|
||||
encounter = frappe.get_doc({
|
||||
'doctype': 'Patient Encounter',
|
||||
'patient': self.patient_female.name,
|
||||
'practitioner': self.practitioner.name,
|
||||
}).insert()
|
||||
encounter = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Patient Encounter",
|
||||
"patient": self.patient_female.name,
|
||||
"practitioner": self.practitioner.name,
|
||||
}
|
||||
).insert()
|
||||
plans = PatientEncounter.get_applicable_treatment_plans(encounter.as_dict())
|
||||
self.assertEqual(plans[0]['name'], self.care_plan_female.template_name)
|
||||
self.assertEqual(plans[0]["name"], self.care_plan_female.template_name)
|
||||
|
||||
@@ -19,22 +19,29 @@ class PatientHistorySettings(Document):
|
||||
|
||||
def validate_submittable_doctypes(self):
|
||||
for entry in self.custom_doctypes:
|
||||
if not cint(frappe.db.get_value('DocType', entry.document_type, 'is_submittable')):
|
||||
msg = _('Row #{0}: Document Type {1} is not submittable.').format(
|
||||
entry.idx, frappe.bold(entry.document_type))
|
||||
msg += _('Patient Medical Record can only be created for submittable document types.')
|
||||
if not cint(frappe.db.get_value("DocType", entry.document_type, "is_submittable")):
|
||||
msg = _("Row #{0}: Document Type {1} is not submittable.").format(
|
||||
entry.idx, frappe.bold(entry.document_type)
|
||||
)
|
||||
msg += _("Patient Medical Record can only be created for submittable document types.")
|
||||
frappe.throw(msg)
|
||||
|
||||
def validate_date_fieldnames(self):
|
||||
for entry in self.custom_doctypes:
|
||||
field = frappe.get_meta(entry.document_type).get_field(entry.date_fieldname)
|
||||
if not field:
|
||||
frappe.throw(_('Row #{0}: No such Field named {1} found in the Document Type {2}.').format(
|
||||
entry.idx, frappe.bold(entry.date_fieldname), frappe.bold(entry.document_type)))
|
||||
frappe.throw(
|
||||
_("Row #{0}: No such Field named {1} found in the Document Type {2}.").format(
|
||||
entry.idx, frappe.bold(entry.date_fieldname), frappe.bold(entry.document_type)
|
||||
)
|
||||
)
|
||||
|
||||
if field.fieldtype not in ['Date', 'Datetime']:
|
||||
frappe.throw(_('Row #{0}: Field {1} in Document Type {2} is not a Date / Datetime field.').format(
|
||||
entry.idx, frappe.bold(entry.date_fieldname), frappe.bold(entry.document_type)))
|
||||
if field.fieldtype not in ["Date", "Datetime"]:
|
||||
frappe.throw(
|
||||
_("Row #{0}: Field {1} in Document Type {2} is not a Date / Datetime field.").format(
|
||||
entry.idx, frappe.bold(entry.date_fieldname), frappe.bold(entry.document_type)
|
||||
)
|
||||
)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_doctype_fields(self, document_type, fields):
|
||||
@@ -42,40 +49,44 @@ class PatientHistorySettings(Document):
|
||||
doc_fields = frappe.get_meta(document_type).fields
|
||||
|
||||
for field in doc_fields:
|
||||
if field.fieldtype not in frappe.model.no_value_fields or \
|
||||
field.fieldtype in frappe.model.table_fields and not field.hidden:
|
||||
multicheck_fields.append({
|
||||
'label': field.label,
|
||||
'value': field.fieldname,
|
||||
'checked': 1 if field.fieldname in fields else 0
|
||||
})
|
||||
if (
|
||||
field.fieldtype not in frappe.model.no_value_fields
|
||||
or field.fieldtype in frappe.model.table_fields
|
||||
and not field.hidden
|
||||
):
|
||||
multicheck_fields.append(
|
||||
{
|
||||
"label": field.label,
|
||||
"value": field.fieldname,
|
||||
"checked": 1 if field.fieldname in fields else 0,
|
||||
}
|
||||
)
|
||||
|
||||
return multicheck_fields
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_date_field_for_dt(self, document_type):
|
||||
meta = frappe.get_meta(document_type)
|
||||
date_fields = meta.get('fields', {
|
||||
'fieldtype': ['in', ['Date', 'Datetime']]
|
||||
})
|
||||
date_fields = meta.get("fields", {"fieldtype": ["in", ["Date", "Datetime"]]})
|
||||
|
||||
if date_fields:
|
||||
return date_fields[0].get('fieldname')
|
||||
return date_fields[0].get("fieldname")
|
||||
|
||||
|
||||
def create_medical_record(doc, method=None):
|
||||
medical_record_required = validate_medical_record_required(doc)
|
||||
if not medical_record_required:
|
||||
return
|
||||
|
||||
if frappe.db.exists('Patient Medical Record', { 'reference_name': doc.name }):
|
||||
if frappe.db.exists("Patient Medical Record", {"reference_name": doc.name}):
|
||||
return
|
||||
|
||||
subject = set_subject_field(doc)
|
||||
date_field = get_date_field(doc.doctype)
|
||||
medical_record = frappe.new_doc('Patient Medical Record')
|
||||
medical_record = frappe.new_doc("Patient Medical Record")
|
||||
medical_record.patient = doc.patient
|
||||
medical_record.subject = subject
|
||||
medical_record.status = 'Open'
|
||||
medical_record.status = "Open"
|
||||
medical_record.communication_date = doc.get(date_field)
|
||||
medical_record.reference_doctype = doc.doctype
|
||||
medical_record.reference_name = doc.name
|
||||
@@ -88,11 +99,11 @@ def update_medical_record(doc, method=None):
|
||||
if not medical_record_required:
|
||||
return
|
||||
|
||||
medical_record_id = frappe.db.exists('Patient Medical Record', { 'reference_name': doc.name })
|
||||
medical_record_id = frappe.db.exists("Patient Medical Record", {"reference_name": doc.name})
|
||||
|
||||
if medical_record_id:
|
||||
subject = set_subject_field(doc)
|
||||
frappe.db.set_value('Patient Medical Record', medical_record_id[0][0], 'subject', subject)
|
||||
frappe.db.set_value("Patient Medical Record", medical_record_id[0][0], "subject", subject)
|
||||
else:
|
||||
create_medical_record(doc)
|
||||
|
||||
@@ -102,28 +113,30 @@ def delete_medical_record(doc, method=None):
|
||||
if not medical_record_required:
|
||||
return
|
||||
|
||||
record = frappe.db.exists('Patient Medical Record', { 'reference_name': doc.name })
|
||||
record = frappe.db.exists("Patient Medical Record", {"reference_name": doc.name})
|
||||
if record:
|
||||
frappe.delete_doc('Patient Medical Record', record, force=1)
|
||||
frappe.delete_doc("Patient Medical Record", record, force=1)
|
||||
|
||||
|
||||
def set_subject_field(doc):
|
||||
from frappe.utils.formatters import format_value
|
||||
|
||||
meta = frappe.get_meta(doc.doctype)
|
||||
subject = ''
|
||||
subject = ""
|
||||
patient_history_fields = get_patient_history_fields(doc)
|
||||
|
||||
for entry in patient_history_fields:
|
||||
fieldname = entry.get('fieldname')
|
||||
if entry.get('fieldtype') == 'Table' and doc.get(fieldname):
|
||||
formatted_value = get_formatted_value_for_table_field(doc.get(fieldname), meta.get_field(fieldname))
|
||||
subject += frappe.bold(_(entry.get('label')) + ':') + '<br>' + cstr(formatted_value) + '<br>'
|
||||
fieldname = entry.get("fieldname")
|
||||
if entry.get("fieldtype") == "Table" and doc.get(fieldname):
|
||||
formatted_value = get_formatted_value_for_table_field(
|
||||
doc.get(fieldname), meta.get_field(fieldname)
|
||||
)
|
||||
subject += frappe.bold(_(entry.get("label")) + ":") + "<br>" + cstr(formatted_value) + "<br>"
|
||||
|
||||
else:
|
||||
if doc.get(fieldname):
|
||||
formatted_value = format_value(doc.get(fieldname), meta.get_field(fieldname), doc)
|
||||
subject += frappe.bold(_(entry.get('label')) + ':') + cstr(formatted_value) + '<br>'
|
||||
subject += frappe.bold(_(entry.get("label")) + ":") + cstr(formatted_value) + "<br>"
|
||||
|
||||
return subject
|
||||
|
||||
@@ -131,12 +144,14 @@ def set_subject_field(doc):
|
||||
def get_date_field(doctype):
|
||||
dt = get_patient_history_config_dt(doctype)
|
||||
|
||||
return frappe.db.get_value(dt, { 'document_type': doctype }, 'date_fieldname')
|
||||
return frappe.db.get_value(dt, {"document_type": doctype}, "date_fieldname")
|
||||
|
||||
|
||||
def get_patient_history_fields(doc):
|
||||
dt = get_patient_history_config_dt(doc.doctype)
|
||||
patient_history_fields = frappe.db.get_value(dt, { 'document_type': doc.doctype }, 'selected_fields')
|
||||
patient_history_fields = frappe.db.get_value(
|
||||
dt, {"document_type": doc.doctype}, "selected_fields"
|
||||
)
|
||||
|
||||
if patient_history_fields:
|
||||
return json.loads(patient_history_fields)
|
||||
@@ -145,38 +160,44 @@ def get_patient_history_fields(doc):
|
||||
def get_formatted_value_for_table_field(items, df):
|
||||
child_meta = frappe.get_meta(df.options)
|
||||
|
||||
table_head = ''
|
||||
table_row = ''
|
||||
html = ''
|
||||
table_head = ""
|
||||
table_row = ""
|
||||
html = ""
|
||||
create_head = True
|
||||
for item in items:
|
||||
table_row += '<tr>'
|
||||
table_row += "<tr>"
|
||||
for cdf in child_meta.fields:
|
||||
if cdf.in_list_view:
|
||||
if create_head:
|
||||
table_head += '<td>' + cdf.label + '</td>'
|
||||
table_head += "<td>" + cdf.label + "</td>"
|
||||
if item.get(cdf.fieldname):
|
||||
table_row += '<td>' + str(item.get(cdf.fieldname)) + '</td>'
|
||||
table_row += "<td>" + str(item.get(cdf.fieldname)) + "</td>"
|
||||
else:
|
||||
table_row += '<td></td>'
|
||||
table_row += "<td></td>"
|
||||
create_head = False
|
||||
table_row += '</tr>'
|
||||
table_row += "</tr>"
|
||||
|
||||
html += "<table class='table table-condensed table-bordered'>" + table_head + table_row + "</table>"
|
||||
html += (
|
||||
"<table class='table table-condensed table-bordered'>" + table_head + table_row + "</table>"
|
||||
)
|
||||
|
||||
return html
|
||||
|
||||
|
||||
def get_patient_history_config_dt(doctype):
|
||||
if frappe.db.get_value('DocType', doctype, 'custom'):
|
||||
return 'Patient History Custom Document Type'
|
||||
if frappe.db.get_value("DocType", doctype, "custom"):
|
||||
return "Patient History Custom Document Type"
|
||||
else:
|
||||
return 'Patient History Standard Document Type'
|
||||
return "Patient History Standard Document Type"
|
||||
|
||||
|
||||
def validate_medical_record_required(doc):
|
||||
if frappe.flags.in_patch or frappe.flags.in_install or frappe.flags.in_setup_wizard \
|
||||
or get_module(doc) != 'Healthcare':
|
||||
if (
|
||||
frappe.flags.in_patch
|
||||
or frappe.flags.in_install
|
||||
or frappe.flags.in_setup_wizard
|
||||
or get_module(doc) != "Healthcare"
|
||||
):
|
||||
return False
|
||||
|
||||
if doc.doctype not in get_patient_history_doctypes():
|
||||
@@ -184,9 +205,10 @@ def validate_medical_record_required(doc):
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def get_module(doc):
|
||||
module = doc.meta.module
|
||||
if not module:
|
||||
module = frappe.db.get_value('DocType', doc.doctype, 'module')
|
||||
module = frappe.db.get_value("DocType", doc.doctype, "module")
|
||||
|
||||
return module
|
||||
|
||||
@@ -14,25 +14,20 @@ class TestPatientHistorySettings(unittest.TestCase):
|
||||
def setUp(self):
|
||||
dt = create_custom_doctype()
|
||||
settings = frappe.get_single("Patient History Settings")
|
||||
settings.append("custom_doctypes", {
|
||||
"document_type": dt.name,
|
||||
"date_fieldname": "date",
|
||||
"selected_fields": json.dumps([{
|
||||
"label": "Date",
|
||||
"fieldname": "date",
|
||||
"fieldtype": "Date"
|
||||
},
|
||||
settings.append(
|
||||
"custom_doctypes",
|
||||
{
|
||||
"label": "Rating",
|
||||
"fieldname": "rating",
|
||||
"fieldtype": "Rating"
|
||||
"document_type": dt.name,
|
||||
"date_fieldname": "date",
|
||||
"selected_fields": json.dumps(
|
||||
[
|
||||
{"label": "Date", "fieldname": "date", "fieldtype": "Date"},
|
||||
{"label": "Rating", "fieldname": "rating", "fieldtype": "Rating"},
|
||||
{"label": "Feedback", "fieldname": "feedback", "fieldtype": "Small Text"},
|
||||
]
|
||||
),
|
||||
},
|
||||
{
|
||||
"label": "Feedback",
|
||||
"fieldname": "feedback",
|
||||
"fieldtype": "Small Text"
|
||||
}])
|
||||
})
|
||||
)
|
||||
settings.save()
|
||||
|
||||
def test_custom_doctype_medical_record(self):
|
||||
@@ -40,12 +35,15 @@ class TestPatientHistorySettings(unittest.TestCase):
|
||||
patient = create_patient()
|
||||
doc = create_doc(patient)
|
||||
# check for medical record
|
||||
medical_rec = frappe.db.exists("Patient Medical Record", {"status": "Open", "reference_name": doc.name})
|
||||
medical_rec = frappe.db.exists(
|
||||
"Patient Medical Record", {"status": "Open", "reference_name": doc.name}
|
||||
)
|
||||
self.assertTrue(medical_rec)
|
||||
|
||||
medical_rec = frappe.get_doc("Patient Medical Record", medical_rec)
|
||||
expected_subject = "Date:{0}Rating:3Feedback:Test Patient History Settings".format(
|
||||
frappe.utils.format_date(getdate()))
|
||||
frappe.utils.format_date(getdate())
|
||||
)
|
||||
self.assertEqual(strip_html(medical_rec.subject), expected_subject)
|
||||
self.assertEqual(medical_rec.patient, patient)
|
||||
self.assertEqual(medical_rec.communication_date, getdate())
|
||||
@@ -53,38 +51,22 @@ class TestPatientHistorySettings(unittest.TestCase):
|
||||
|
||||
def create_custom_doctype():
|
||||
if not frappe.db.exists("DocType", "Test Patient Feedback"):
|
||||
doc = frappe.get_doc({
|
||||
doc = frappe.get_doc(
|
||||
{
|
||||
"doctype": "DocType",
|
||||
"module": "Healthcare",
|
||||
"custom": 1,
|
||||
"is_submittable": 1,
|
||||
"fields": [{
|
||||
"label": "Date",
|
||||
"fieldname": "date",
|
||||
"fieldtype": "Date"
|
||||
},
|
||||
{
|
||||
"label": "Patient",
|
||||
"fieldname": "patient",
|
||||
"fieldtype": "Link",
|
||||
"options": "Patient"
|
||||
},
|
||||
{
|
||||
"label": "Rating",
|
||||
"fieldname": "rating",
|
||||
"fieldtype": "Rating"
|
||||
},
|
||||
{
|
||||
"label": "Feedback",
|
||||
"fieldname": "feedback",
|
||||
"fieldtype": "Small Text"
|
||||
}],
|
||||
"permissions": [{
|
||||
"role": "System Manager",
|
||||
"read": 1
|
||||
}],
|
||||
"fields": [
|
||||
{"label": "Date", "fieldname": "date", "fieldtype": "Date"},
|
||||
{"label": "Patient", "fieldname": "patient", "fieldtype": "Link", "options": "Patient"},
|
||||
{"label": "Rating", "fieldname": "rating", "fieldtype": "Rating"},
|
||||
{"label": "Feedback", "fieldname": "feedback", "fieldtype": "Small Text"},
|
||||
],
|
||||
"permissions": [{"role": "System Manager", "read": 1}],
|
||||
"name": "Test Patient Feedback",
|
||||
})
|
||||
}
|
||||
)
|
||||
doc.insert()
|
||||
return doc
|
||||
else:
|
||||
@@ -92,13 +74,15 @@ def create_custom_doctype():
|
||||
|
||||
|
||||
def create_doc(patient):
|
||||
doc = frappe.get_doc({
|
||||
"doctype": "Test Patient Feedback",
|
||||
"patient": patient,
|
||||
"date": getdate(),
|
||||
"rating": 3,
|
||||
"feedback": "Test Patient History Settings"
|
||||
}).insert()
|
||||
doc = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Test Patient Feedback",
|
||||
"patient": patient,
|
||||
"date": getdate(),
|
||||
"rating": 3,
|
||||
"feedback": "Test Patient History Settings",
|
||||
}
|
||||
).insert()
|
||||
doc.submit()
|
||||
|
||||
return doc
|
||||
|
||||
@@ -8,5 +8,5 @@ from frappe.model.document import Document
|
||||
|
||||
class PatientMedicalRecord(Document):
|
||||
def after_insert(self):
|
||||
if self.reference_doctype == "Patient Medical Record" :
|
||||
if self.reference_doctype == "Patient Medical Record":
|
||||
frappe.db.set_value("Patient Medical Record", self.name, "reference_name", self.name)
|
||||
|
||||
@@ -17,9 +17,9 @@ from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment imp
|
||||
|
||||
class TestPatientMedicalRecord(unittest.TestCase):
|
||||
def setUp(self):
|
||||
frappe.db.set_value('Healthcare Settings', None, 'enable_free_follow_ups', 0)
|
||||
frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 1)
|
||||
frappe.db.sql('delete from `tabPatient Appointment`')
|
||||
frappe.db.set_value("Healthcare Settings", None, "enable_free_follow_ups", 0)
|
||||
frappe.db.set_value("Healthcare Settings", None, "automate_appointment_invoicing", 1)
|
||||
frappe.db.sql("delete from `tabPatient Appointment`")
|
||||
make_pos_profile()
|
||||
|
||||
def test_medical_record(self):
|
||||
@@ -29,32 +29,42 @@ class TestPatientMedicalRecord(unittest.TestCase):
|
||||
encounter = create_encounter(appointment)
|
||||
|
||||
# check for encounter
|
||||
medical_rec = frappe.db.exists('Patient Medical Record', {'status': 'Open', 'reference_name': encounter.name})
|
||||
medical_rec = frappe.db.exists(
|
||||
"Patient Medical Record", {"status": "Open", "reference_name": encounter.name}
|
||||
)
|
||||
self.assertTrue(medical_rec)
|
||||
|
||||
vital_signs = create_vital_signs(appointment)
|
||||
# check for vital signs
|
||||
medical_rec = frappe.db.exists('Patient Medical Record', {'status': 'Open', 'reference_name': vital_signs.name})
|
||||
medical_rec = frappe.db.exists(
|
||||
"Patient Medical Record", {"status": "Open", "reference_name": vital_signs.name}
|
||||
)
|
||||
self.assertTrue(medical_rec)
|
||||
|
||||
appointment = create_appointment(patient, practitioner, add_days(nowdate(), 1), invoice=1, procedure_template=1)
|
||||
appointment = create_appointment(
|
||||
patient, practitioner, add_days(nowdate(), 1), invoice=1, procedure_template=1
|
||||
)
|
||||
procedure = create_procedure(appointment)
|
||||
procedure.start_procedure()
|
||||
procedure.complete_procedure()
|
||||
# check for clinical procedure
|
||||
medical_rec = frappe.db.exists('Patient Medical Record', {'status': 'Open', 'reference_name': procedure.name})
|
||||
medical_rec = frappe.db.exists(
|
||||
"Patient Medical Record", {"status": "Open", "reference_name": procedure.name}
|
||||
)
|
||||
self.assertTrue(medical_rec)
|
||||
|
||||
template = create_lab_test_template(medical_department)
|
||||
lab_test = create_lab_test(template.name, patient)
|
||||
# check for lab test
|
||||
medical_rec = frappe.db.exists('Patient Medical Record', {'status': 'Open', 'reference_name': lab_test.name})
|
||||
medical_rec = frappe.db.exists(
|
||||
"Patient Medical Record", {"status": "Open", "reference_name": lab_test.name}
|
||||
)
|
||||
self.assertTrue(medical_rec)
|
||||
|
||||
|
||||
def create_procedure(appointment):
|
||||
if appointment:
|
||||
procedure = frappe.new_doc('Clinical Procedure')
|
||||
procedure = frappe.new_doc("Clinical Procedure")
|
||||
procedure.procedure_template = appointment.procedure_template
|
||||
procedure.appointment = appointment.name
|
||||
procedure.patient = appointment.patient
|
||||
@@ -66,8 +76,9 @@ def create_procedure(appointment):
|
||||
procedure.submit()
|
||||
return procedure
|
||||
|
||||
|
||||
def create_vital_signs(appointment):
|
||||
vital_signs = frappe.new_doc('Vital Signs')
|
||||
vital_signs = frappe.new_doc("Vital Signs")
|
||||
vital_signs.patient = appointment.patient
|
||||
vital_signs.signs_date = appointment.appointment_date
|
||||
vital_signs.signs_time = appointment.appointment_time
|
||||
@@ -76,24 +87,26 @@ def create_vital_signs(appointment):
|
||||
vital_signs.submit()
|
||||
return vital_signs
|
||||
|
||||
def create_lab_test_template(medical_department):
|
||||
if frappe.db.exists('Lab Test Template', 'Blood Test'):
|
||||
return frappe.get_doc('Lab Test Template', 'Blood Test')
|
||||
|
||||
template = frappe.new_doc('Lab Test Template')
|
||||
template.lab_test_name = 'Blood Test'
|
||||
template.lab_test_code = 'Blood Test'
|
||||
template.lab_test_group = 'Services'
|
||||
def create_lab_test_template(medical_department):
|
||||
if frappe.db.exists("Lab Test Template", "Blood Test"):
|
||||
return frappe.get_doc("Lab Test Template", "Blood Test")
|
||||
|
||||
template = frappe.new_doc("Lab Test Template")
|
||||
template.lab_test_name = "Blood Test"
|
||||
template.lab_test_code = "Blood Test"
|
||||
template.lab_test_group = "Services"
|
||||
template.department = medical_department
|
||||
template.is_billable = 1
|
||||
template.lab_test_rate = 2000
|
||||
template.save()
|
||||
return template
|
||||
|
||||
|
||||
def create_lab_test(template, patient):
|
||||
lab_test = frappe.new_doc('Lab Test')
|
||||
lab_test = frappe.new_doc("Lab Test")
|
||||
lab_test.patient = patient
|
||||
lab_test.patient_sex = frappe.db.get_value('Patient', patient, 'sex')
|
||||
lab_test.patient_sex = frappe.db.get_value("Patient", patient, "sex")
|
||||
lab_test.template = template
|
||||
lab_test.save()
|
||||
lab_test.submit()
|
||||
|
||||
@@ -8,65 +8,69 @@ from frappe.utils import cstr
|
||||
|
||||
class PrescriptionDuration(Document):
|
||||
def autoname(self):
|
||||
self.name = " ".join(filter(None,
|
||||
[cstr(self.get(f)).strip() for f in ["number", "period"]]))
|
||||
self.name = " ".join(filter(None, [cstr(self.get(f)).strip() for f in ["number", "period"]]))
|
||||
|
||||
def get_days(self):
|
||||
days = 0
|
||||
duration = self
|
||||
if(duration.period == 'Day'):
|
||||
if duration.period == "Day":
|
||||
days = duration.number
|
||||
if(duration.period == 'Hour'):
|
||||
days = (duration.number)/24
|
||||
if(duration.period == 'Week'):
|
||||
days = (duration.number*7)
|
||||
if(duration.period == 'Month'):
|
||||
days = (duration.number*30)
|
||||
if duration.period == "Hour":
|
||||
days = (duration.number) / 24
|
||||
if duration.period == "Week":
|
||||
days = duration.number * 7
|
||||
if duration.period == "Month":
|
||||
days = duration.number * 30
|
||||
return days
|
||||
|
||||
def get_weeks(self):
|
||||
weeks = 0
|
||||
duration = self
|
||||
if(duration.period == 'Day'):
|
||||
weeks = (duration.number)/7
|
||||
#if(duration.period == 'Hour'):
|
||||
# weeks = (duration.number)/x
|
||||
if(duration.period == 'Week'):
|
||||
if duration.period == "Day":
|
||||
weeks = (duration.number) / 7
|
||||
# if(duration.period == 'Hour'):
|
||||
# weeks = (duration.number)/x
|
||||
if duration.period == "Week":
|
||||
weeks = duration.number
|
||||
if(duration.period == 'Month'):
|
||||
weeks = duration.number*4
|
||||
if duration.period == "Month":
|
||||
weeks = duration.number * 4
|
||||
return weeks
|
||||
|
||||
def get_months(self):
|
||||
months = 0
|
||||
duration = self
|
||||
if(duration.period == 'Day'):
|
||||
months = (duration.number)/30
|
||||
#if(duration.period == 'Hour'):
|
||||
# months = (duration.number)/x
|
||||
if(duration.period == 'Week'):
|
||||
months = (duration.number)/4
|
||||
if(duration.period == 'Month'):
|
||||
if duration.period == "Day":
|
||||
months = (duration.number) / 30
|
||||
# if(duration.period == 'Hour'):
|
||||
# months = (duration.number)/x
|
||||
if duration.period == "Week":
|
||||
months = (duration.number) / 4
|
||||
if duration.period == "Month":
|
||||
months = duration.number
|
||||
return months
|
||||
|
||||
def get_hours(self):
|
||||
hours = 0
|
||||
duration = self
|
||||
if(duration.period == 'Day'):
|
||||
hours = (duration.number*24)
|
||||
if(duration.period == 'Hour'):
|
||||
if duration.period == "Day":
|
||||
hours = duration.number * 24
|
||||
if duration.period == "Hour":
|
||||
hours = duration.number
|
||||
if(duration.period == 'Week'):
|
||||
hours = (duration.number*24)*7
|
||||
if(duration.period == 'Month'):
|
||||
hours = (duration.number*24)*30
|
||||
if duration.period == "Week":
|
||||
hours = (duration.number * 24) * 7
|
||||
if duration.period == "Month":
|
||||
hours = (duration.number * 24) * 30
|
||||
return hours
|
||||
|
||||
def get_minutes(self):
|
||||
minutes = 0
|
||||
duration = self
|
||||
if(duration.period == 'Day'):
|
||||
minutes = (duration.number*1440)
|
||||
if(duration.period == 'Hour'):
|
||||
minutes = (duration.number*60)
|
||||
if(duration.period == 'Week'):
|
||||
minutes = (duration.number*10080)
|
||||
if(duration.period == 'Month'):
|
||||
minutes = (duration.number*43800)
|
||||
if duration.period == "Day":
|
||||
minutes = duration.number * 1440
|
||||
if duration.period == "Hour":
|
||||
minutes = duration.number * 60
|
||||
if duration.period == "Week":
|
||||
minutes = duration.number * 10080
|
||||
if duration.period == "Month":
|
||||
minutes = duration.number * 43800
|
||||
return minutes
|
||||
|
||||
@@ -11,4 +11,4 @@ from frappe.utils import flt
|
||||
class SampleCollection(Document):
|
||||
def validate(self):
|
||||
if flt(self.sample_qty) <= 0:
|
||||
frappe.throw(_('Sample Quantity cannot be negative or 0'), title=_('Invalid Quantity'))
|
||||
frappe.throw(_("Sample Quantity cannot be negative or 0"), title=_("Invalid Quantity"))
|
||||
|
||||
@@ -5,5 +5,6 @@ import unittest
|
||||
|
||||
# test_records = frappe.get_test_records('Sample Collection')
|
||||
|
||||
|
||||
class TestSampleCollection(unittest.TestCase):
|
||||
pass
|
||||
|
||||
@@ -5,5 +5,6 @@ import unittest
|
||||
|
||||
# test_records = frappe.get_test_records('Sensitivity')
|
||||
|
||||
|
||||
class TestSensitivity(unittest.TestCase):
|
||||
pass
|
||||
|
||||
@@ -24,52 +24,58 @@ class TestTherapyPlan(unittest.TestCase):
|
||||
patient, practitioner = create_healthcare_docs()
|
||||
medical_department = create_medical_department()
|
||||
encounter = create_encounter(patient, medical_department, practitioner)
|
||||
self.assertTrue(frappe.db.exists('Therapy Plan', encounter.therapy_plan))
|
||||
self.assertTrue(frappe.db.exists("Therapy Plan", encounter.therapy_plan))
|
||||
|
||||
def test_status(self):
|
||||
plan = create_therapy_plan()
|
||||
self.assertEqual(plan.status, 'Not Started')
|
||||
self.assertEqual(plan.status, "Not Started")
|
||||
|
||||
session = make_therapy_session(plan.name, plan.patient, 'Basic Rehab', '_Test Company')
|
||||
session = make_therapy_session(plan.name, plan.patient, "Basic Rehab", "_Test Company")
|
||||
session.start_date = getdate()
|
||||
frappe.get_doc(session).submit()
|
||||
self.assertEqual(frappe.db.get_value('Therapy Plan', plan.name, 'status'), 'In Progress')
|
||||
self.assertEqual(frappe.db.get_value("Therapy Plan", plan.name, "status"), "In Progress")
|
||||
|
||||
session = make_therapy_session(plan.name, plan.patient, 'Basic Rehab', '_Test Company')
|
||||
session = make_therapy_session(plan.name, plan.patient, "Basic Rehab", "_Test Company")
|
||||
session.start_date = add_days(getdate(), 1)
|
||||
frappe.get_doc(session).submit()
|
||||
self.assertEqual(frappe.db.get_value('Therapy Plan', plan.name, 'status'), 'Completed')
|
||||
self.assertEqual(frappe.db.get_value("Therapy Plan", plan.name, "status"), "Completed")
|
||||
|
||||
patient, practitioner = create_healthcare_docs()
|
||||
appointment = create_appointment(patient, practitioner, nowdate())
|
||||
|
||||
session = make_therapy_session(plan.name, plan.patient, 'Basic Rehab', '_Test Company', appointment.name)
|
||||
session = make_therapy_session(
|
||||
plan.name, plan.patient, "Basic Rehab", "_Test Company", appointment.name
|
||||
)
|
||||
session.start_date = add_days(getdate(), 2)
|
||||
session = frappe.get_doc(session)
|
||||
session.submit()
|
||||
self.assertEqual(frappe.db.get_value('Patient Appointment', appointment.name, 'status'), 'Closed')
|
||||
self.assertEqual(
|
||||
frappe.db.get_value("Patient Appointment", appointment.name, "status"), "Closed"
|
||||
)
|
||||
session.cancel()
|
||||
self.assertEqual(frappe.db.get_value('Patient Appointment', appointment.name, 'status'), 'Open')
|
||||
self.assertEqual(frappe.db.get_value("Patient Appointment", appointment.name, "status"), "Open")
|
||||
|
||||
def test_therapy_plan_from_template(self):
|
||||
patient = create_patient()
|
||||
template = create_therapy_plan_template()
|
||||
# check linked item
|
||||
self.assertTrue(frappe.db.exists('Therapy Plan Template', {'linked_item': 'Complete Rehab'}))
|
||||
self.assertTrue(frappe.db.exists("Therapy Plan Template", {"linked_item": "Complete Rehab"}))
|
||||
|
||||
plan = create_therapy_plan(template)
|
||||
# invoice
|
||||
si = make_sales_invoice(plan.name, patient, '_Test Company', template)
|
||||
si = make_sales_invoice(plan.name, patient, "_Test Company", template)
|
||||
si.save()
|
||||
|
||||
therapy_plan_template_amt = frappe.db.get_value('Therapy Plan Template', template, 'total_amount')
|
||||
therapy_plan_template_amt = frappe.db.get_value(
|
||||
"Therapy Plan Template", template, "total_amount"
|
||||
)
|
||||
self.assertEqual(si.items[0].amount, therapy_plan_template_amt)
|
||||
|
||||
|
||||
def create_therapy_plan(template=None):
|
||||
patient = create_patient()
|
||||
therapy_type = create_therapy_type()
|
||||
plan = frappe.new_doc('Therapy Plan')
|
||||
plan = frappe.new_doc("Therapy Plan")
|
||||
plan.patient = patient
|
||||
plan.start_date = getdate()
|
||||
|
||||
@@ -77,42 +83,36 @@ def create_therapy_plan(template=None):
|
||||
plan.therapy_plan_template = template
|
||||
plan = plan.set_therapy_details_from_template()
|
||||
else:
|
||||
plan.append('therapy_plan_details', {
|
||||
'therapy_type': therapy_type.name,
|
||||
'no_of_sessions': 2
|
||||
})
|
||||
plan.append("therapy_plan_details", {"therapy_type": therapy_type.name, "no_of_sessions": 2})
|
||||
|
||||
plan.save()
|
||||
return plan
|
||||
|
||||
|
||||
def create_encounter(patient, medical_department, practitioner):
|
||||
encounter = frappe.new_doc('Patient Encounter')
|
||||
encounter = frappe.new_doc("Patient Encounter")
|
||||
encounter.patient = patient
|
||||
encounter.practitioner = practitioner
|
||||
encounter.medical_department = medical_department
|
||||
therapy_type = create_therapy_type()
|
||||
encounter.append('therapies', {
|
||||
'therapy_type': therapy_type.name,
|
||||
'no_of_sessions': 2
|
||||
})
|
||||
encounter.append("therapies", {"therapy_type": therapy_type.name, "no_of_sessions": 2})
|
||||
encounter.save()
|
||||
encounter.submit()
|
||||
return encounter
|
||||
|
||||
|
||||
def create_therapy_plan_template():
|
||||
template_name = frappe.db.exists('Therapy Plan Template', 'Complete Rehab')
|
||||
template_name = frappe.db.exists("Therapy Plan Template", "Complete Rehab")
|
||||
if not template_name:
|
||||
therapy_type = create_therapy_type()
|
||||
template = frappe.new_doc('Therapy Plan Template')
|
||||
template.plan_name = template.item_code = template.item_name = 'Complete Rehab'
|
||||
template.item_group = 'Services'
|
||||
rate = frappe.db.get_value('Therapy Type', therapy_type.name, 'rate')
|
||||
template.append('therapy_types', {
|
||||
'therapy_type': therapy_type.name,
|
||||
'no_of_sessions': 2,
|
||||
'rate': rate,
|
||||
'amount': 2 * flt(rate)
|
||||
})
|
||||
template = frappe.new_doc("Therapy Plan Template")
|
||||
template.plan_name = template.item_code = template.item_name = "Complete Rehab"
|
||||
template.item_group = "Services"
|
||||
rate = frappe.db.get_value("Therapy Type", therapy_type.name, "rate")
|
||||
template.append(
|
||||
"therapy_types",
|
||||
{"therapy_type": therapy_type.name, "no_of_sessions": 2, "rate": rate, "amount": 2 * flt(rate)},
|
||||
)
|
||||
template.save()
|
||||
template_name = template.name
|
||||
|
||||
|
||||
@@ -14,12 +14,12 @@ class TherapyPlan(Document):
|
||||
|
||||
def set_status(self):
|
||||
if not self.total_sessions_completed:
|
||||
self.status = 'Not Started'
|
||||
self.status = "Not Started"
|
||||
else:
|
||||
if self.total_sessions_completed < self.total_sessions:
|
||||
self.status = 'In Progress'
|
||||
self.status = "In Progress"
|
||||
elif self.total_sessions_completed == self.total_sessions:
|
||||
self.status = 'Completed'
|
||||
self.status = "Completed"
|
||||
|
||||
def set_totals(self):
|
||||
total_sessions = 0
|
||||
@@ -30,28 +30,28 @@ class TherapyPlan(Document):
|
||||
if entry.sessions_completed:
|
||||
total_sessions_completed += entry.sessions_completed
|
||||
|
||||
self.db_set('total_sessions', total_sessions)
|
||||
self.db_set('total_sessions_completed', total_sessions_completed)
|
||||
self.db_set("total_sessions", total_sessions)
|
||||
self.db_set("total_sessions_completed", total_sessions_completed)
|
||||
|
||||
@frappe.whitelist()
|
||||
def set_therapy_details_from_template(self):
|
||||
# Add therapy types in the child table
|
||||
self.set('therapy_plan_details', [])
|
||||
therapy_plan_template = frappe.get_doc('Therapy Plan Template', self.therapy_plan_template)
|
||||
self.set("therapy_plan_details", [])
|
||||
therapy_plan_template = frappe.get_doc("Therapy Plan Template", self.therapy_plan_template)
|
||||
|
||||
for data in therapy_plan_template.therapy_types:
|
||||
self.append('therapy_plan_details', {
|
||||
'therapy_type': data.therapy_type,
|
||||
'no_of_sessions': data.no_of_sessions
|
||||
})
|
||||
self.append(
|
||||
"therapy_plan_details",
|
||||
{"therapy_type": data.therapy_type, "no_of_sessions": data.no_of_sessions},
|
||||
)
|
||||
return self
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_therapy_session(therapy_plan, patient, therapy_type, company, appointment=None):
|
||||
therapy_type = frappe.get_doc('Therapy Type', therapy_type)
|
||||
therapy_type = frappe.get_doc("Therapy Type", therapy_type)
|
||||
|
||||
therapy_session = frappe.new_doc('Therapy Session')
|
||||
therapy_session = frappe.new_doc("Therapy Session")
|
||||
therapy_session.therapy_plan = therapy_plan
|
||||
therapy_session.company = company
|
||||
therapy_session.patient = patient
|
||||
@@ -67,33 +67,36 @@ def make_therapy_session(therapy_plan, patient, therapy_type, company, appointme
|
||||
@frappe.whitelist()
|
||||
def make_sales_invoice(reference_name, patient, company, therapy_plan_template):
|
||||
from erpnext.stock.get_item_details import get_item_details
|
||||
si = frappe.new_doc('Sales Invoice')
|
||||
|
||||
si = frappe.new_doc("Sales Invoice")
|
||||
si.company = company
|
||||
si.patient = patient
|
||||
si.customer = frappe.db.get_value('Patient', patient, 'customer')
|
||||
si.customer = frappe.db.get_value("Patient", patient, "customer")
|
||||
|
||||
item = frappe.db.get_value('Therapy Plan Template', therapy_plan_template, 'linked_item')
|
||||
price_list, price_list_currency = frappe.db.get_values('Price List', {'selling': 1}, ['name', 'currency'])[0]
|
||||
item = frappe.db.get_value("Therapy Plan Template", therapy_plan_template, "linked_item")
|
||||
price_list, price_list_currency = frappe.db.get_values(
|
||||
"Price List", {"selling": 1}, ["name", "currency"]
|
||||
)[0]
|
||||
args = {
|
||||
'doctype': 'Sales Invoice',
|
||||
'item_code': item,
|
||||
'company': company,
|
||||
'customer': si.customer,
|
||||
'selling_price_list': price_list,
|
||||
'price_list_currency': price_list_currency,
|
||||
'plc_conversion_rate': 1.0,
|
||||
'conversion_rate': 1.0
|
||||
"doctype": "Sales Invoice",
|
||||
"item_code": item,
|
||||
"company": company,
|
||||
"customer": si.customer,
|
||||
"selling_price_list": price_list,
|
||||
"price_list_currency": price_list_currency,
|
||||
"plc_conversion_rate": 1.0,
|
||||
"conversion_rate": 1.0,
|
||||
}
|
||||
|
||||
item_line = si.append('items', {})
|
||||
item_line = si.append("items", {})
|
||||
item_details = get_item_details(args)
|
||||
item_line.item_code = item
|
||||
item_line.qty = 1
|
||||
item_line.rate = item_details.price_list_rate
|
||||
item_line.amount = flt(item_line.rate) * flt(item_line.qty)
|
||||
item_line.reference_dt = 'Therapy Plan'
|
||||
item_line.reference_dt = "Therapy Plan"
|
||||
item_line.reference_dn = reference_name
|
||||
item_line.description = item_details.description
|
||||
|
||||
si.set_missing_values(for_validate = True)
|
||||
si.set_missing_values(for_validate=True)
|
||||
return si
|
||||
|
||||
@@ -1,22 +1,13 @@
|
||||
|
||||
from frappe import _
|
||||
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'therapy_plan',
|
||||
'non_standard_fieldnames': {
|
||||
'Sales Invoice': 'reference_dn'
|
||||
},
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Therapy Sessions'),
|
||||
'items': ['Therapy Session']
|
||||
},
|
||||
{
|
||||
'label': _('Billing'),
|
||||
'items': ['Sales Invoice']
|
||||
}
|
||||
"fieldname": "therapy_plan",
|
||||
"non_standard_fieldnames": {"Sales Invoice": "reference_dn"},
|
||||
"transactions": [
|
||||
{"label": _("Therapy Sessions"), "items": ["Therapy Session"]},
|
||||
{"label": _("Billing"), "items": ["Sales Invoice"]},
|
||||
],
|
||||
'disable_create_buttons': ['Sales Invoice']
|
||||
"disable_create_buttons": ["Sales Invoice"],
|
||||
}
|
||||
|
||||
@@ -18,9 +18,13 @@ class TherapyPlanTemplate(Document):
|
||||
|
||||
def on_update(self):
|
||||
doc_before_save = self.get_doc_before_save()
|
||||
if not doc_before_save: return
|
||||
if doc_before_save.item_name != self.item_name or doc_before_save.item_group != self.item_group \
|
||||
or doc_before_save.description != self.description:
|
||||
if not doc_before_save:
|
||||
return
|
||||
if (
|
||||
doc_before_save.item_name != self.item_name
|
||||
or doc_before_save.item_group != self.item_group
|
||||
or doc_before_save.description != self.description
|
||||
):
|
||||
self.update_item()
|
||||
|
||||
if doc_before_save.therapy_types != self.therapy_types:
|
||||
@@ -38,28 +42,30 @@ class TherapyPlanTemplate(Document):
|
||||
self.total_amount = total_amount
|
||||
|
||||
def create_item_from_template(self):
|
||||
uom = frappe.db.exists('UOM', 'Nos') or frappe.db.get_single_value('Stock Settings', 'stock_uom')
|
||||
uom = frappe.db.exists("UOM", "Nos") or frappe.db.get_single_value("Stock Settings", "stock_uom")
|
||||
|
||||
item = frappe.get_doc({
|
||||
'doctype': 'Item',
|
||||
'item_code': self.item_code,
|
||||
'item_name': self.item_name,
|
||||
'item_group': self.item_group,
|
||||
'description': self.description,
|
||||
'is_sales_item': 1,
|
||||
'is_service_item': 1,
|
||||
'is_purchase_item': 0,
|
||||
'is_stock_item': 0,
|
||||
'show_in_website': 0,
|
||||
'is_pro_applicable': 0,
|
||||
'stock_uom': uom
|
||||
}).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
item = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Item",
|
||||
"item_code": self.item_code,
|
||||
"item_name": self.item_name,
|
||||
"item_group": self.item_group,
|
||||
"description": self.description,
|
||||
"is_sales_item": 1,
|
||||
"is_service_item": 1,
|
||||
"is_purchase_item": 0,
|
||||
"is_stock_item": 0,
|
||||
"show_in_website": 0,
|
||||
"is_pro_applicable": 0,
|
||||
"stock_uom": uom,
|
||||
}
|
||||
).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
|
||||
make_item_price(item.name, self.total_amount)
|
||||
self.db_set('linked_item', item.name)
|
||||
self.db_set("linked_item", item.name)
|
||||
|
||||
def update_item(self):
|
||||
item_doc = frappe.get_doc('Item', {'item_code': self.linked_item})
|
||||
item_doc = frappe.get_doc("Item", {"item_code": self.linked_item})
|
||||
item_doc.item_name = self.item_name
|
||||
item_doc.item_group = self.item_group
|
||||
item_doc.description = self.description
|
||||
@@ -67,7 +73,7 @@ class TherapyPlanTemplate(Document):
|
||||
item_doc.save(ignore_permissions=True)
|
||||
|
||||
def update_item_price(self):
|
||||
item_price = frappe.get_doc('Item Price', {'item_code': self.linked_item})
|
||||
item_price = frappe.get_doc("Item Price", {"item_code": self.linked_item})
|
||||
item_price.item_name = self.item_name
|
||||
item_price.price_list_rate = self.total_amount
|
||||
item_price.ignore_mandatory = True
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
|
||||
from frappe import _
|
||||
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'therapy_plan_template',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Therapy Plans'),
|
||||
'items': ['Therapy Plan']
|
||||
}
|
||||
]
|
||||
"fieldname": "therapy_plan_template",
|
||||
"transactions": [{"label": _("Therapy Plans"), "items": ["Therapy Plan"]}],
|
||||
}
|
||||
|
||||
@@ -22,10 +22,12 @@ class TherapySession(Document):
|
||||
self.set_total_counts()
|
||||
|
||||
def validate_duplicate(self):
|
||||
end_time = datetime.datetime.combine(getdate(self.start_date), get_time(self.start_time)) \
|
||||
+ datetime.timedelta(minutes=flt(self.duration))
|
||||
end_time = datetime.datetime.combine(
|
||||
getdate(self.start_date), get_time(self.start_time)
|
||||
) + datetime.timedelta(minutes=flt(self.duration))
|
||||
|
||||
overlaps = frappe.db.sql("""
|
||||
overlaps = frappe.db.sql(
|
||||
"""
|
||||
select
|
||||
name
|
||||
from
|
||||
@@ -36,28 +38,41 @@ class TherapySession(Document):
|
||||
((start_time<%s and start_time + INTERVAL duration MINUTE>%s) or
|
||||
(start_time>%s and start_time<%s) or
|
||||
(start_time=%s))
|
||||
""", (self.start_date, self.name, self.practitioner, self.patient,
|
||||
self.start_time, end_time.time(), self.start_time, end_time.time(), self.start_time))
|
||||
""",
|
||||
(
|
||||
self.start_date,
|
||||
self.name,
|
||||
self.practitioner,
|
||||
self.patient,
|
||||
self.start_time,
|
||||
end_time.time(),
|
||||
self.start_time,
|
||||
end_time.time(),
|
||||
self.start_time,
|
||||
),
|
||||
)
|
||||
|
||||
if overlaps:
|
||||
overlapping_details = _('Therapy Session overlaps with {0}').format(get_link_to_form('Therapy Session', overlaps[0][0]))
|
||||
frappe.throw(overlapping_details, title=_('Therapy Sessions Overlapping'))
|
||||
overlapping_details = _("Therapy Session overlaps with {0}").format(
|
||||
get_link_to_form("Therapy Session", overlaps[0][0])
|
||||
)
|
||||
frappe.throw(overlapping_details, title=_("Therapy Sessions Overlapping"))
|
||||
|
||||
def on_submit(self):
|
||||
self.update_sessions_count_in_therapy_plan()
|
||||
|
||||
def on_update(self):
|
||||
if self.appointment:
|
||||
frappe.db.set_value('Patient Appointment', self.appointment, 'status', 'Closed')
|
||||
frappe.db.set_value("Patient Appointment", self.appointment, "status", "Closed")
|
||||
|
||||
def on_cancel(self):
|
||||
if self.appointment:
|
||||
frappe.db.set_value('Patient Appointment', self.appointment, 'status', 'Open')
|
||||
frappe.db.set_value("Patient Appointment", self.appointment, "status", "Open")
|
||||
|
||||
self.update_sessions_count_in_therapy_plan(on_cancel=True)
|
||||
|
||||
def update_sessions_count_in_therapy_plan(self, on_cancel=False):
|
||||
therapy_plan = frappe.get_doc('Therapy Plan', self.therapy_plan)
|
||||
therapy_plan = frappe.get_doc("Therapy Plan", self.therapy_plan)
|
||||
for entry in therapy_plan.therapy_plan_details:
|
||||
if entry.therapy_type == self.therapy_type:
|
||||
if on_cancel:
|
||||
@@ -75,36 +90,42 @@ class TherapySession(Document):
|
||||
if entry.counts_completed:
|
||||
counts_completed += entry.counts_completed
|
||||
|
||||
self.db_set('total_counts_targeted', target_total)
|
||||
self.db_set('total_counts_completed', counts_completed)
|
||||
self.db_set("total_counts_targeted", target_total)
|
||||
self.db_set("total_counts_completed", counts_completed)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_therapy_session(source_name, target_doc=None):
|
||||
def set_missing_values(source, target):
|
||||
therapy_type = frappe.get_doc('Therapy Type', source.therapy_type)
|
||||
therapy_type = frappe.get_doc("Therapy Type", source.therapy_type)
|
||||
target.exercises = therapy_type.exercises
|
||||
|
||||
doc = get_mapped_doc('Patient Appointment', source_name, {
|
||||
'Patient Appointment': {
|
||||
'doctype': 'Therapy Session',
|
||||
'field_map': [
|
||||
['appointment', 'name'],
|
||||
['patient', 'patient'],
|
||||
['patient_age', 'patient_age'],
|
||||
['gender', 'patient_sex'],
|
||||
['therapy_type', 'therapy_type'],
|
||||
['therapy_plan', 'therapy_plan'],
|
||||
['practitioner', 'practitioner'],
|
||||
['department', 'department'],
|
||||
['start_date', 'appointment_date'],
|
||||
['start_time', 'appointment_time'],
|
||||
['service_unit', 'service_unit'],
|
||||
['company', 'company'],
|
||||
['invoiced', 'invoiced']
|
||||
]
|
||||
doc = get_mapped_doc(
|
||||
"Patient Appointment",
|
||||
source_name,
|
||||
{
|
||||
"Patient Appointment": {
|
||||
"doctype": "Therapy Session",
|
||||
"field_map": [
|
||||
["appointment", "name"],
|
||||
["patient", "patient"],
|
||||
["patient_age", "patient_age"],
|
||||
["gender", "patient_sex"],
|
||||
["therapy_type", "therapy_type"],
|
||||
["therapy_plan", "therapy_plan"],
|
||||
["practitioner", "practitioner"],
|
||||
["department", "department"],
|
||||
["start_date", "appointment_date"],
|
||||
["start_time", "appointment_time"],
|
||||
["service_unit", "service_unit"],
|
||||
["company", "company"],
|
||||
["invoiced", "invoiced"],
|
||||
],
|
||||
}
|
||||
}, target_doc, set_missing_values)
|
||||
},
|
||||
target_doc,
|
||||
set_missing_values,
|
||||
)
|
||||
|
||||
return doc
|
||||
|
||||
@@ -112,36 +133,42 @@ def create_therapy_session(source_name, target_doc=None):
|
||||
@frappe.whitelist()
|
||||
def invoice_therapy_session(source_name, target_doc=None):
|
||||
def set_missing_values(source, target):
|
||||
target.customer = frappe.db.get_value('Patient', source.patient, 'customer')
|
||||
target.customer = frappe.db.get_value("Patient", source.patient, "customer")
|
||||
target.due_date = getdate()
|
||||
target.debit_to = get_receivable_account(source.company)
|
||||
item = target.append('items', {})
|
||||
item = target.append("items", {})
|
||||
item = get_therapy_item(source, item)
|
||||
target.set_missing_values(for_validate=True)
|
||||
|
||||
doc = get_mapped_doc('Therapy Session', source_name, {
|
||||
'Therapy Session': {
|
||||
'doctype': 'Sales Invoice',
|
||||
'field_map': [
|
||||
['patient', 'patient'],
|
||||
['referring_practitioner', 'practitioner'],
|
||||
['company', 'company'],
|
||||
['due_date', 'start_date']
|
||||
]
|
||||
doc = get_mapped_doc(
|
||||
"Therapy Session",
|
||||
source_name,
|
||||
{
|
||||
"Therapy Session": {
|
||||
"doctype": "Sales Invoice",
|
||||
"field_map": [
|
||||
["patient", "patient"],
|
||||
["referring_practitioner", "practitioner"],
|
||||
["company", "company"],
|
||||
["due_date", "start_date"],
|
||||
],
|
||||
}
|
||||
}, target_doc, set_missing_values)
|
||||
},
|
||||
target_doc,
|
||||
set_missing_values,
|
||||
)
|
||||
|
||||
return doc
|
||||
|
||||
|
||||
def get_therapy_item(therapy, item):
|
||||
item.item_code = frappe.db.get_value('Therapy Type', therapy.therapy_type, 'item')
|
||||
item.description = _('Therapy Session Charges: {0}').format(therapy.practitioner)
|
||||
item.item_code = frappe.db.get_value("Therapy Type", therapy.therapy_type, "item")
|
||||
item.description = _("Therapy Session Charges: {0}").format(therapy.practitioner)
|
||||
item.income_account = get_income_account(therapy.practitioner, therapy.company)
|
||||
item.cost_center = frappe.get_cached_value('Company', therapy.company, 'cost_center')
|
||||
item.cost_center = frappe.get_cached_value("Company", therapy.company, "cost_center")
|
||||
item.rate = therapy.rate
|
||||
item.amount = therapy.rate
|
||||
item.qty = 1
|
||||
item.reference_dt = 'Therapy Session'
|
||||
item.reference_dt = "Therapy Session"
|
||||
item.reference_dn = therapy.name
|
||||
return item
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
|
||||
from frappe import _
|
||||
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'therapy_session',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Assessments'),
|
||||
'items': ['Patient Assessment']
|
||||
}
|
||||
]
|
||||
"fieldname": "therapy_session",
|
||||
"transactions": [{"label": _("Assessments"), "items": ["Patient Assessment"]}],
|
||||
}
|
||||
|
||||
@@ -9,46 +9,44 @@ import frappe
|
||||
class TestTherapyType(unittest.TestCase):
|
||||
def test_therapy_type_item(self):
|
||||
therapy_type = create_therapy_type()
|
||||
self.assertTrue(frappe.db.exists('Item', therapy_type.item))
|
||||
self.assertTrue(frappe.db.exists("Item", therapy_type.item))
|
||||
|
||||
therapy_type.disabled = 1
|
||||
therapy_type.save()
|
||||
self.assertEqual(frappe.db.get_value('Item', therapy_type.item, 'disabled'), 1)
|
||||
self.assertEqual(frappe.db.get_value("Item", therapy_type.item, "disabled"), 1)
|
||||
|
||||
|
||||
def create_therapy_type():
|
||||
exercise = create_exercise_type()
|
||||
therapy_type = frappe.db.exists('Therapy Type', 'Basic Rehab')
|
||||
therapy_type = frappe.db.exists("Therapy Type", "Basic Rehab")
|
||||
if not therapy_type:
|
||||
therapy_type = frappe.new_doc('Therapy Type')
|
||||
therapy_type.therapy_type = 'Basic Rehab'
|
||||
therapy_type = frappe.new_doc("Therapy Type")
|
||||
therapy_type.therapy_type = "Basic Rehab"
|
||||
therapy_type.default_duration = 30
|
||||
therapy_type.is_billable = 1
|
||||
therapy_type.rate = 5000
|
||||
therapy_type.item_code = 'Basic Rehab'
|
||||
therapy_type.item_name = 'Basic Rehab'
|
||||
therapy_type.item_group = 'Services'
|
||||
therapy_type.append('exercises', {
|
||||
'exercise_type': exercise.name,
|
||||
'counts_target': 10,
|
||||
'assistance_level': 'Passive'
|
||||
})
|
||||
therapy_type.item_code = "Basic Rehab"
|
||||
therapy_type.item_name = "Basic Rehab"
|
||||
therapy_type.item_group = "Services"
|
||||
therapy_type.append(
|
||||
"exercises",
|
||||
{"exercise_type": exercise.name, "counts_target": 10, "assistance_level": "Passive"},
|
||||
)
|
||||
therapy_type.save()
|
||||
else:
|
||||
therapy_type = frappe.get_doc('Therapy Type', therapy_type)
|
||||
therapy_type = frappe.get_doc("Therapy Type", therapy_type)
|
||||
|
||||
return therapy_type
|
||||
|
||||
|
||||
def create_exercise_type():
|
||||
exercise_type = frappe.db.exists('Exercise Type', 'Sit to Stand')
|
||||
exercise_type = frappe.db.exists("Exercise Type", "Sit to Stand")
|
||||
if not exercise_type:
|
||||
exercise_type = frappe.new_doc('Exercise Type')
|
||||
exercise_type.exercise_name = 'Sit to Stand'
|
||||
exercise_type.append('steps_table', {
|
||||
'title': 'Step 1',
|
||||
'description': 'Squat and Rise'
|
||||
})
|
||||
exercise_type = frappe.new_doc("Exercise Type")
|
||||
exercise_type.exercise_name = "Sit to Stand"
|
||||
exercise_type.append("steps_table", {"title": "Step 1", "description": "Squat and Rise"})
|
||||
exercise_type.save()
|
||||
else:
|
||||
exercise_type = frappe.get_doc('Exercise Type', exercise_type)
|
||||
exercise_type = frappe.get_doc("Exercise Type", exercise_type)
|
||||
|
||||
return exercise_type
|
||||
|
||||
@@ -25,13 +25,13 @@ class TherapyType(Document):
|
||||
def enable_disable_item(self):
|
||||
if self.is_billable:
|
||||
if self.disabled:
|
||||
frappe.db.set_value('Item', self.item, 'disabled', 1)
|
||||
frappe.db.set_value("Item", self.item, "disabled", 1)
|
||||
else:
|
||||
frappe.db.set_value('Item', self.item, 'disabled', 0)
|
||||
frappe.db.set_value("Item", self.item, "disabled", 0)
|
||||
|
||||
def update_item_and_item_price(self):
|
||||
if self.is_billable and self.item:
|
||||
item_doc = frappe.get_doc('Item', {'item_code': self.item})
|
||||
item_doc = frappe.get_doc("Item", {"item_code": self.item})
|
||||
item_doc.item_name = self.item_name
|
||||
item_doc.item_group = self.item_group
|
||||
item_doc.description = self.description
|
||||
@@ -40,23 +40,28 @@ class TherapyType(Document):
|
||||
item_doc.save(ignore_permissions=True)
|
||||
|
||||
if self.rate:
|
||||
item_price = frappe.get_doc('Item Price', {'item_code': self.item})
|
||||
item_price = frappe.get_doc("Item Price", {"item_code": self.item})
|
||||
item_price.item_name = self.item_name
|
||||
item_price.price_list_rate = self.rate
|
||||
item_price.ignore_mandatory = True
|
||||
item_price.save()
|
||||
|
||||
elif not self.is_billable and self.item:
|
||||
frappe.db.set_value('Item', self.item, 'disabled', 1)
|
||||
frappe.db.set_value("Item", self.item, "disabled", 1)
|
||||
|
||||
self.db_set('change_in_item', 0)
|
||||
self.db_set("change_in_item", 0)
|
||||
|
||||
@frappe.whitelist()
|
||||
def add_exercises(self):
|
||||
exercises = self.get_exercises_for_body_parts()
|
||||
last_idx = max([cint(d.idx) for d in self.get('exercises')] or [0,])
|
||||
last_idx = max(
|
||||
[cint(d.idx) for d in self.get("exercises")]
|
||||
or [
|
||||
0,
|
||||
]
|
||||
)
|
||||
for i, d in enumerate(exercises):
|
||||
ch = self.append('exercises', {})
|
||||
ch = self.append("exercises", {})
|
||||
ch.exercise_type = d.parent
|
||||
ch.idx = last_idx + i + 1
|
||||
|
||||
@@ -71,7 +76,10 @@ class TherapyType(Document):
|
||||
`tabExercise Type` e, `tabBody Part Link` b
|
||||
WHERE
|
||||
b.body_part IN %(body_parts)s AND b.parent=e.name
|
||||
""", {'body_parts': body_parts}, as_dict=1)
|
||||
""",
|
||||
{"body_parts": body_parts},
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
return exercises
|
||||
|
||||
@@ -81,44 +89,49 @@ def create_item_from_therapy(doc):
|
||||
if doc.is_billable and not doc.disabled:
|
||||
disabled = 0
|
||||
|
||||
uom = frappe.db.exists('UOM', 'Unit') or frappe.db.get_single_value('Stock Settings', 'stock_uom')
|
||||
uom = frappe.db.exists("UOM", "Unit") or frappe.db.get_single_value("Stock Settings", "stock_uom")
|
||||
|
||||
item = frappe.get_doc({
|
||||
'doctype': 'Item',
|
||||
'item_code': doc.item_code,
|
||||
'item_name': doc.item_name,
|
||||
'item_group': doc.item_group,
|
||||
'description': doc.description,
|
||||
'is_sales_item': 1,
|
||||
'is_service_item': 1,
|
||||
'is_purchase_item': 0,
|
||||
'is_stock_item': 0,
|
||||
'show_in_website': 0,
|
||||
'is_pro_applicable': 0,
|
||||
'disabled': disabled,
|
||||
'stock_uom': uom
|
||||
}).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
item = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Item",
|
||||
"item_code": doc.item_code,
|
||||
"item_name": doc.item_name,
|
||||
"item_group": doc.item_group,
|
||||
"description": doc.description,
|
||||
"is_sales_item": 1,
|
||||
"is_service_item": 1,
|
||||
"is_purchase_item": 0,
|
||||
"is_stock_item": 0,
|
||||
"show_in_website": 0,
|
||||
"is_pro_applicable": 0,
|
||||
"disabled": disabled,
|
||||
"stock_uom": uom,
|
||||
}
|
||||
).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
|
||||
make_item_price(item.name, doc.rate)
|
||||
doc.db_set('item', item.name)
|
||||
doc.db_set("item", item.name)
|
||||
|
||||
|
||||
def make_item_price(item, item_price):
|
||||
price_list_name = frappe.db.get_value('Price List', {'selling': 1})
|
||||
frappe.get_doc({
|
||||
'doctype': 'Item Price',
|
||||
'price_list': price_list_name,
|
||||
'item_code': item,
|
||||
'price_list_rate': item_price
|
||||
}).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
price_list_name = frappe.db.get_value("Price List", {"selling": 1})
|
||||
frappe.get_doc(
|
||||
{
|
||||
"doctype": "Item Price",
|
||||
"price_list": price_list_name,
|
||||
"item_code": item,
|
||||
"price_list_rate": item_price,
|
||||
}
|
||||
).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def change_item_code_from_therapy(item_code, doc):
|
||||
doc = frappe._dict(json.loads(doc))
|
||||
|
||||
if frappe.db.exists('Item', {'item_code': item_code}):
|
||||
frappe.throw(_('Item with Item Code {0} already exists').format(item_code))
|
||||
if frappe.db.exists("Item", {"item_code": item_code}):
|
||||
frappe.throw(_("Item with Item Code {0} already exists").format(item_code))
|
||||
else:
|
||||
rename_doc('Item', doc.item, item_code, ignore_permissions=True)
|
||||
frappe.db.set_value('Therapy Type', doc.name, 'item_code', item_code)
|
||||
rename_doc("Item", doc.item, item_code, ignore_permissions=True)
|
||||
frappe.db.set_value("Therapy Type", doc.name, "item_code", item_code)
|
||||
return
|
||||
|
||||
@@ -12,9 +12,8 @@ class TreatmentPlanTemplate(Document):
|
||||
|
||||
def validate_age(self):
|
||||
if self.patient_age_from and self.patient_age_from < 0:
|
||||
frappe.throw(_('Patient Age From cannot be less than 0'))
|
||||
frappe.throw(_("Patient Age From cannot be less than 0"))
|
||||
if self.patient_age_to and self.patient_age_to < 0:
|
||||
frappe.throw(_('Patient Age To cannot be less than 0'))
|
||||
if self.patient_age_to and self.patient_age_from and \
|
||||
self.patient_age_to < self.patient_age_from:
|
||||
frappe.throw(_('Patient Age To cannot be less than Patient Age From'))
|
||||
frappe.throw(_("Patient Age To cannot be less than 0"))
|
||||
if self.patient_age_to and self.patient_age_from and self.patient_age_to < self.patient_age_from:
|
||||
frappe.throw(_("Patient Age To cannot be less than Patient Age From"))
|
||||
|
||||
@@ -5,5 +5,6 @@ import unittest
|
||||
|
||||
# test_records = frappe.get_test_records('Vital Signs')
|
||||
|
||||
|
||||
class TestVitalSigns(unittest.TestCase):
|
||||
pass
|
||||
|
||||
@@ -12,5 +12,6 @@ class VitalSigns(Document):
|
||||
self.set_title()
|
||||
|
||||
def set_title(self):
|
||||
self.title = _('{0} on {1}').format(self.patient_name or self.patient,
|
||||
frappe.utils.format_date(self.signs_date))[:100]
|
||||
self.title = _("{0} on {1}").format(
|
||||
self.patient_name or self.patient, frappe.utils.format_date(self.signs_date)
|
||||
)[:100]
|
||||
|
||||
@@ -13,30 +13,30 @@ def get_feed(name, document_types=None, date_range=None, start=0, page_length=20
|
||||
"""get feed"""
|
||||
filters = get_filters(name, document_types, date_range)
|
||||
|
||||
result = frappe.db.get_all('Patient Medical Record',
|
||||
fields=['name', 'owner', 'communication_date',
|
||||
'reference_doctype', 'reference_name', 'subject'],
|
||||
result = frappe.db.get_all(
|
||||
"Patient Medical Record",
|
||||
fields=["name", "owner", "communication_date", "reference_doctype", "reference_name", "subject"],
|
||||
filters=filters,
|
||||
order_by='communication_date DESC',
|
||||
order_by="communication_date DESC",
|
||||
limit=cint(page_length),
|
||||
start=cint(start)
|
||||
start=cint(start),
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def get_filters(name, document_types=None, date_range=None):
|
||||
filters = {'patient': name}
|
||||
filters = {"patient": name}
|
||||
if document_types:
|
||||
document_types = json.loads(document_types)
|
||||
if len(document_types):
|
||||
filters['reference_doctype'] = ['IN', document_types]
|
||||
filters["reference_doctype"] = ["IN", document_types]
|
||||
|
||||
if date_range:
|
||||
try:
|
||||
date_range = json.loads(date_range)
|
||||
if date_range:
|
||||
filters['communication_date'] = ['between', [date_range[0], date_range[1]]]
|
||||
filters["communication_date"] = ["between", [date_range[0], date_range[1]]]
|
||||
except json.decoder.JSONDecodeError:
|
||||
pass
|
||||
|
||||
@@ -46,14 +46,11 @@ def get_filters(name, document_types=None, date_range=None):
|
||||
@frappe.whitelist()
|
||||
def get_feed_for_dt(doctype, docname):
|
||||
"""get feed"""
|
||||
result = frappe.db.get_all('Patient Medical Record',
|
||||
fields=['name', 'owner', 'communication_date',
|
||||
'reference_doctype', 'reference_name', 'subject'],
|
||||
filters={
|
||||
'reference_doctype': doctype,
|
||||
'reference_name': docname
|
||||
},
|
||||
order_by='communication_date DESC'
|
||||
result = frappe.db.get_all(
|
||||
"Patient Medical Record",
|
||||
fields=["name", "owner", "communication_date", "reference_doctype", "reference_name", "subject"],
|
||||
filters={"reference_doctype": doctype, "reference_name": docname},
|
||||
order_by="communication_date DESC",
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
@@ -8,27 +8,21 @@ from frappe.utils import get_timespan_date_range, getdate
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_therapy_sessions_count(patient):
|
||||
total = frappe.db.count('Therapy Session', filters={
|
||||
'docstatus': 1,
|
||||
'patient': patient
|
||||
})
|
||||
total = frappe.db.count("Therapy Session", filters={"docstatus": 1, "patient": patient})
|
||||
|
||||
month_start = datetime.today().replace(day=1)
|
||||
this_month = frappe.db.count('Therapy Session', filters={
|
||||
'creation': ['>', month_start],
|
||||
'docstatus': 1,
|
||||
'patient': patient
|
||||
})
|
||||
this_month = frappe.db.count(
|
||||
"Therapy Session", filters={"creation": [">", month_start], "docstatus": 1, "patient": patient}
|
||||
)
|
||||
|
||||
return {
|
||||
'total_therapy_sessions': total,
|
||||
'therapy_sessions_this_month': this_month
|
||||
}
|
||||
return {"total_therapy_sessions": total, "therapy_sessions_this_month": this_month}
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_patient_heatmap_data(patient, date):
|
||||
return dict(frappe.db.sql("""
|
||||
return dict(
|
||||
frappe.db.sql(
|
||||
"""
|
||||
SELECT
|
||||
unix_timestamp(communication_date), count(*)
|
||||
FROM
|
||||
@@ -38,50 +32,56 @@ def get_patient_heatmap_data(patient, date):
|
||||
communication_date < subdate(%(date)s, interval -1 year) and
|
||||
patient = %(patient)s
|
||||
GROUP BY communication_date
|
||||
ORDER BY communication_date asc""", {'date': date, 'patient': patient}))
|
||||
ORDER BY communication_date asc""",
|
||||
{"date": date, "patient": patient},
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_therapy_sessions_distribution_data(patient, field):
|
||||
if field == 'therapy_type':
|
||||
result = frappe.db.get_all('Therapy Session',
|
||||
filters = {'patient': patient, 'docstatus': 1},
|
||||
group_by = field,
|
||||
order_by = field,
|
||||
fields = [field, 'count(*)'],
|
||||
as_list = True)
|
||||
if field == "therapy_type":
|
||||
result = frappe.db.get_all(
|
||||
"Therapy Session",
|
||||
filters={"patient": patient, "docstatus": 1},
|
||||
group_by=field,
|
||||
order_by=field,
|
||||
fields=[field, "count(*)"],
|
||||
as_list=True,
|
||||
)
|
||||
|
||||
elif field == 'exercise_type':
|
||||
data = frappe.db.get_all('Therapy Session', filters={
|
||||
'docstatus': 1,
|
||||
'patient': patient
|
||||
}, as_list=True)
|
||||
elif field == "exercise_type":
|
||||
data = frappe.db.get_all(
|
||||
"Therapy Session", filters={"docstatus": 1, "patient": patient}, as_list=True
|
||||
)
|
||||
therapy_sessions = [entry[0] for entry in data]
|
||||
|
||||
result = frappe.db.get_all('Exercise',
|
||||
filters = {
|
||||
'parenttype': 'Therapy Session',
|
||||
'parent': ['in', therapy_sessions],
|
||||
'docstatus': 1
|
||||
},
|
||||
group_by = field,
|
||||
order_by = field,
|
||||
fields = [field, 'count(*)'],
|
||||
as_list = True)
|
||||
result = frappe.db.get_all(
|
||||
"Exercise",
|
||||
filters={"parenttype": "Therapy Session", "parent": ["in", therapy_sessions], "docstatus": 1},
|
||||
group_by=field,
|
||||
order_by=field,
|
||||
fields=[field, "count(*)"],
|
||||
as_list=True,
|
||||
)
|
||||
|
||||
return {
|
||||
'labels': [r[0] for r in result if r[0] != None],
|
||||
'datasets': [{
|
||||
'values': [r[1] for r in result]
|
||||
}]
|
||||
"labels": [r[0] for r in result if r[0] != None],
|
||||
"datasets": [{"values": [r[1] for r in result]}],
|
||||
}
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_therapy_progress_data(patient, therapy_type, time_span):
|
||||
date_range = get_date_range(time_span)
|
||||
query_values = {'from_date': date_range[0], 'to_date': date_range[1], 'therapy_type': therapy_type, 'patient': patient}
|
||||
result = frappe.db.sql("""
|
||||
query_values = {
|
||||
"from_date": date_range[0],
|
||||
"to_date": date_range[1],
|
||||
"therapy_type": therapy_type,
|
||||
"patient": patient,
|
||||
}
|
||||
result = frappe.db.sql(
|
||||
"""
|
||||
SELECT
|
||||
start_date, total_counts_targeted, total_counts_completed
|
||||
FROM
|
||||
@@ -91,21 +91,31 @@ def get_therapy_progress_data(patient, therapy_type, time_span):
|
||||
docstatus = 1 and
|
||||
therapy_type = %(therapy_type)s and
|
||||
patient = %(patient)s
|
||||
ORDER BY start_date""", query_values, as_list=1)
|
||||
ORDER BY start_date""",
|
||||
query_values,
|
||||
as_list=1,
|
||||
)
|
||||
|
||||
return {
|
||||
'labels': [r[0] for r in result if r[0] != None],
|
||||
'datasets': [
|
||||
{ 'name': _('Targetted'), 'values': [r[1] for r in result if r[0] != None] },
|
||||
{ 'name': _('Completed'), 'values': [r[2] for r in result if r[0] != None] }
|
||||
]
|
||||
"labels": [r[0] for r in result if r[0] != None],
|
||||
"datasets": [
|
||||
{"name": _("Targetted"), "values": [r[1] for r in result if r[0] != None]},
|
||||
{"name": _("Completed"), "values": [r[2] for r in result if r[0] != None]},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_patient_assessment_data(patient, assessment_template, time_span):
|
||||
date_range = get_date_range(time_span)
|
||||
query_values = {'from_date': date_range[0], 'to_date': date_range[1], 'assessment_template': assessment_template, 'patient': patient}
|
||||
result = frappe.db.sql("""
|
||||
query_values = {
|
||||
"from_date": date_range[0],
|
||||
"to_date": date_range[1],
|
||||
"assessment_template": assessment_template,
|
||||
"patient": patient,
|
||||
}
|
||||
result = frappe.db.sql(
|
||||
"""
|
||||
SELECT
|
||||
assessment_datetime, total_score, total_score_obtained
|
||||
FROM
|
||||
@@ -115,21 +125,29 @@ def get_patient_assessment_data(patient, assessment_template, time_span):
|
||||
docstatus = 1 and
|
||||
assessment_template = %(assessment_template)s and
|
||||
patient = %(patient)s
|
||||
ORDER BY assessment_datetime""", query_values, as_list=1)
|
||||
ORDER BY assessment_datetime""",
|
||||
query_values,
|
||||
as_list=1,
|
||||
)
|
||||
|
||||
return {
|
||||
'labels': [getdate(r[0]) for r in result if r[0] != None],
|
||||
'datasets': [
|
||||
{ 'name': _('Score Obtained'), 'values': [r[2] for r in result if r[0] != None] }
|
||||
],
|
||||
'max_score': result[0][1] if result else None
|
||||
"labels": [getdate(r[0]) for r in result if r[0] != None],
|
||||
"datasets": [{"name": _("Score Obtained"), "values": [r[2] for r in result if r[0] != None]}],
|
||||
"max_score": result[0][1] if result else None,
|
||||
}
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_therapy_assessment_correlation_data(patient, assessment_template, time_span):
|
||||
date_range = get_date_range(time_span)
|
||||
query_values = {'from_date': date_range[0], 'to_date': date_range[1], 'assessment': assessment_template, 'patient': patient}
|
||||
result = frappe.db.sql("""
|
||||
query_values = {
|
||||
"from_date": date_range[0],
|
||||
"to_date": date_range[1],
|
||||
"assessment": assessment_template,
|
||||
"patient": patient,
|
||||
}
|
||||
result = frappe.db.sql(
|
||||
"""
|
||||
SELECT
|
||||
therapy.therapy_type, count(*), avg(assessment.total_score_obtained), total_score
|
||||
FROM
|
||||
@@ -142,22 +160,36 @@ def get_therapy_assessment_correlation_data(patient, assessment_template, time_s
|
||||
assessment.patient = %(patient)s and
|
||||
assessment.assessment_template = %(assessment)s
|
||||
GROUP BY therapy.therapy_type
|
||||
""", query_values, as_list=1)
|
||||
""",
|
||||
query_values,
|
||||
as_list=1,
|
||||
)
|
||||
|
||||
return {
|
||||
'labels': [r[0] for r in result if r[0] != None],
|
||||
'datasets': [
|
||||
{ 'name': _('Sessions'), 'chartType': 'bar', 'values': [r[1] for r in result if r[0] != None] },
|
||||
{ 'name': _('Average Score'), 'chartType': 'line', 'values': [round(r[2], 2) for r in result if r[0] != None] }
|
||||
"labels": [r[0] for r in result if r[0] != None],
|
||||
"datasets": [
|
||||
{"name": _("Sessions"), "chartType": "bar", "values": [r[1] for r in result if r[0] != None]},
|
||||
{
|
||||
"name": _("Average Score"),
|
||||
"chartType": "line",
|
||||
"values": [round(r[2], 2) for r in result if r[0] != None],
|
||||
},
|
||||
],
|
||||
'max_score': result[0][1] if result else None
|
||||
"max_score": result[0][1] if result else None,
|
||||
}
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_assessment_parameter_data(patient, parameter, time_span):
|
||||
date_range = get_date_range(time_span)
|
||||
query_values = {'from_date': date_range[0], 'to_date': date_range[1], 'parameter': parameter, 'patient': patient}
|
||||
results = frappe.db.sql("""
|
||||
query_values = {
|
||||
"from_date": date_range[0],
|
||||
"to_date": date_range[1],
|
||||
"parameter": parameter,
|
||||
"patient": patient,
|
||||
}
|
||||
results = frappe.db.sql(
|
||||
"""
|
||||
SELECT
|
||||
assessment.assessment_datetime,
|
||||
sheet.score,
|
||||
@@ -175,7 +207,10 @@ def get_assessment_parameter_data(patient, parameter, time_span):
|
||||
assessment.patient = %(patient)s
|
||||
ORDER BY
|
||||
assessment.assessment_datetime asc
|
||||
""", query_values, as_list=1)
|
||||
""",
|
||||
query_values,
|
||||
as_list=1,
|
||||
)
|
||||
|
||||
score_percentages = []
|
||||
for r in results:
|
||||
@@ -184,12 +219,11 @@ def get_assessment_parameter_data(patient, parameter, time_span):
|
||||
score_percentages.append(score)
|
||||
|
||||
return {
|
||||
'labels': [getdate(r[0]) for r in results if r[0] != None],
|
||||
'datasets': [
|
||||
{ 'name': _('Score'), 'values': score_percentages }
|
||||
]
|
||||
"labels": [getdate(r[0]) for r in results if r[0] != None],
|
||||
"datasets": [{"name": _("Score"), "values": score_percentages}],
|
||||
}
|
||||
|
||||
|
||||
def get_date_range(time_span):
|
||||
try:
|
||||
time_span = json.loads(time_span)
|
||||
|
||||
@@ -16,6 +16,7 @@ def execute(filters=None):
|
||||
|
||||
return columns, data, None, chart
|
||||
|
||||
|
||||
def get_columns():
|
||||
return [
|
||||
{
|
||||
@@ -23,87 +24,69 @@ def get_columns():
|
||||
"fieldtype": "Link",
|
||||
"label": "Patient",
|
||||
"options": "Patient",
|
||||
"width": 200
|
||||
"width": 200,
|
||||
},
|
||||
{
|
||||
"fieldname": "healthcare_service_unit",
|
||||
"fieldtype": "Link",
|
||||
"label": "Healthcare Service Unit",
|
||||
"options": "Healthcare Service Unit",
|
||||
"width": 150
|
||||
"width": 150,
|
||||
},
|
||||
{
|
||||
"fieldname": "drug",
|
||||
"fieldtype": "Link",
|
||||
"label": "Drug Code",
|
||||
"options": "Item",
|
||||
"width": 150
|
||||
},
|
||||
{
|
||||
"fieldname": "drug_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "Drug Name",
|
||||
"width": 150
|
||||
"width": 150,
|
||||
},
|
||||
{"fieldname": "drug_name", "fieldtype": "Data", "label": "Drug Name", "width": 150},
|
||||
{
|
||||
"fieldname": "dosage",
|
||||
"fieldtype": "Link",
|
||||
"label": "Dosage",
|
||||
"options": "Prescription Dosage",
|
||||
"width": 80
|
||||
"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
|
||||
"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
|
||||
"width": 200,
|
||||
},
|
||||
{
|
||||
"fieldname": "inpatient_medication_entry",
|
||||
"fieldtype": "Link",
|
||||
"label": "Inpatient Medication Entry",
|
||||
"options": "Inpatient Medication Entry",
|
||||
"width": 200
|
||||
"width": 200,
|
||||
},
|
||||
{
|
||||
"fieldname": "inpatient_record",
|
||||
"fieldtype": "Link",
|
||||
"label": "Inpatient Record",
|
||||
"options": "Inpatient Record",
|
||||
"width": 200
|
||||
}
|
||||
"width": 200,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def get_data(filters):
|
||||
conditions, values = get_conditions(filters)
|
||||
|
||||
data = frappe.db.sql("""
|
||||
data = frappe.db.sql(
|
||||
"""
|
||||
SELECT
|
||||
parent.patient, parent.inpatient_record, parent.practitioner,
|
||||
child.drug, child.drug_name, child.dosage, child.dosage_form,
|
||||
@@ -115,12 +98,18 @@ def get_data(filters):
|
||||
parent.docstatus = 1
|
||||
{conditions}
|
||||
ORDER BY date, time
|
||||
""".format(conditions=conditions), values, as_dict=1)
|
||||
""".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()
|
||||
@@ -152,7 +141,9 @@ def get_inpatient_details(data, service_unit):
|
||||
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:
|
||||
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)
|
||||
@@ -162,8 +153,12 @@ def get_inpatient_details(data, service_unit):
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def get_inpatient_medication_entry(order_entry):
|
||||
return frappe.db.get_value("Inpatient Medication Entry Detail", {"against_imoe": order_entry}, "parent")
|
||||
return frappe.db.get_value(
|
||||
"Inpatient Medication Entry Detail", {"against_imoe": order_entry}, "parent"
|
||||
)
|
||||
|
||||
|
||||
def get_chart_data(data):
|
||||
if not data:
|
||||
@@ -172,10 +167,7 @@ def get_chart_data(data):
|
||||
labels = ["Pending", "Completed"]
|
||||
datasets = []
|
||||
|
||||
status_wise_data = {
|
||||
"Pending": 0,
|
||||
"Completed": 0
|
||||
}
|
||||
status_wise_data = {"Pending": 0, "Completed": 0}
|
||||
|
||||
for d in data:
|
||||
if d.is_completed:
|
||||
@@ -183,19 +175,14 @@ def get_chart_data(data):
|
||||
else:
|
||||
status_wise_data["Pending"] += 1
|
||||
|
||||
datasets.append({
|
||||
"name": "Inpatient Medication Order Status",
|
||||
"values": [status_wise_data.get("Pending"), status_wise_data.get("Completed")]
|
||||
})
|
||||
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 = {"data": {"labels": labels, "datasets": datasets}, "type": "donut", "height": 300}
|
||||
|
||||
chart["fieldtype"] = "Data"
|
||||
|
||||
|
||||
@@ -38,92 +38,94 @@ class TestInpatientMedicationOrders(unittest.TestCase):
|
||||
|
||||
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'
|
||||
"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=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=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'
|
||||
}
|
||||
"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='')
|
||||
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
|
||||
"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'):
|
||||
if frappe.db.get_value("Patient", self.patient, "inpatient_record"):
|
||||
# cleanup - Discharge
|
||||
schedule_discharge(frappe.as_json({'patient': self.patient, 'discharge_ordered_datetime': now_datetime()}))
|
||||
schedule_discharge(
|
||||
frappe.as_json({"patient": self.patient, "discharge_ordered_datetime": now_datetime()})
|
||||
)
|
||||
self.ip_record.reload()
|
||||
mark_invoiced_inpatient_occupancy(self.ip_record)
|
||||
|
||||
self.ip_record.reload()
|
||||
discharge_patient(self.ip_record, now_datetime())
|
||||
|
||||
for entry in frappe.get_all('Inpatient Medication Entry'):
|
||||
doc = frappe.get_doc('Inpatient Medication Entry', entry.name)
|
||||
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)
|
||||
for entry in frappe.get_all("Inpatient Medication Order"):
|
||||
doc = frappe.get_doc("Inpatient Medication Order", entry.name)
|
||||
doc.cancel()
|
||||
doc.delete()
|
||||
|
||||
@@ -136,7 +138,7 @@ def create_records(patient):
|
||||
ip_record.expected_length_of_stay = 0
|
||||
ip_record.save()
|
||||
ip_record.reload()
|
||||
service_unit = get_healthcare_service_unit('_Test Service Unit Ip Occupancy')
|
||||
service_unit = get_healthcare_service_unit("_Test Service Unit Ip Occupancy")
|
||||
admit_patient(ip_record, service_unit, now_datetime())
|
||||
|
||||
ipmo = create_ipmo(patient)
|
||||
|
||||
@@ -7,7 +7,8 @@ from frappe import _, msgprint
|
||||
|
||||
|
||||
def execute(filters=None):
|
||||
if not filters: filters = {}
|
||||
if not filters:
|
||||
filters = {}
|
||||
|
||||
data, columns = [], []
|
||||
|
||||
@@ -15,24 +16,26 @@ def execute(filters=None):
|
||||
lab_test_list = get_lab_tests(filters)
|
||||
|
||||
if not lab_test_list:
|
||||
msgprint(_('No records found'))
|
||||
msgprint(_("No records found"))
|
||||
return columns, lab_test_list
|
||||
|
||||
data = []
|
||||
for lab_test in lab_test_list:
|
||||
row = frappe._dict({
|
||||
'test': lab_test.name,
|
||||
'template': lab_test.template,
|
||||
'company': lab_test.company,
|
||||
'patient': lab_test.patient,
|
||||
'patient_name': lab_test.patient_name,
|
||||
'practitioner': lab_test.practitioner,
|
||||
'employee': lab_test.employee,
|
||||
'status': lab_test.status,
|
||||
'invoiced': lab_test.invoiced,
|
||||
'result_date': lab_test.result_date,
|
||||
'department': lab_test.department
|
||||
})
|
||||
row = frappe._dict(
|
||||
{
|
||||
"test": lab_test.name,
|
||||
"template": lab_test.template,
|
||||
"company": lab_test.company,
|
||||
"patient": lab_test.patient,
|
||||
"patient_name": lab_test.patient_name,
|
||||
"practitioner": lab_test.practitioner,
|
||||
"employee": lab_test.employee,
|
||||
"status": lab_test.status,
|
||||
"invoiced": lab_test.invoiced,
|
||||
"result_date": lab_test.result_date,
|
||||
"department": lab_test.department,
|
||||
}
|
||||
)
|
||||
data.append(row)
|
||||
|
||||
chart = get_chart_data(data)
|
||||
@@ -43,99 +46,91 @@ def execute(filters=None):
|
||||
def get_columns():
|
||||
return [
|
||||
{
|
||||
'fieldname': 'test',
|
||||
'label': _('Lab Test'),
|
||||
'fieldtype': 'Link',
|
||||
'options': 'Lab Test',
|
||||
'width': '120'
|
||||
"fieldname": "test",
|
||||
"label": _("Lab Test"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Lab Test",
|
||||
"width": "120",
|
||||
},
|
||||
{
|
||||
'fieldname': 'template',
|
||||
'label': _('Lab Test Template'),
|
||||
'fieldtype': 'Link',
|
||||
'options': 'Lab Test Template',
|
||||
'width': '120'
|
||||
"fieldname": "template",
|
||||
"label": _("Lab Test Template"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Lab Test Template",
|
||||
"width": "120",
|
||||
},
|
||||
{
|
||||
'fieldname': 'company',
|
||||
'label': _('Company'),
|
||||
'fieldtype': 'Link',
|
||||
'options': 'Company',
|
||||
'width': '120'
|
||||
"fieldname": "company",
|
||||
"label": _("Company"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Company",
|
||||
"width": "120",
|
||||
},
|
||||
{
|
||||
'fieldname': 'patient',
|
||||
'label': _('Patient'),
|
||||
'fieldtype': 'Link',
|
||||
'options': 'Patient',
|
||||
'width': '120'
|
||||
"fieldname": "patient",
|
||||
"label": _("Patient"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Patient",
|
||||
"width": "120",
|
||||
},
|
||||
{"fieldname": "patient_name", "label": _("Patient Name"), "fieldtype": "Data", "width": "120"},
|
||||
{
|
||||
"fieldname": "employee",
|
||||
"label": _("Lab Technician"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Employee",
|
||||
"width": "120",
|
||||
},
|
||||
{"fieldname": "status", "label": _("Status"), "fieldtype": "Data", "width": "100"},
|
||||
{"fieldname": "invoiced", "label": _("Invoiced"), "fieldtype": "Check", "width": "100"},
|
||||
{"fieldname": "result_date", "label": _("Result Date"), "fieldtype": "Date", "width": "100"},
|
||||
{
|
||||
"fieldname": "practitioner",
|
||||
"label": _("Requesting Practitioner"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Healthcare Practitioner",
|
||||
"width": "120",
|
||||
},
|
||||
{
|
||||
'fieldname': 'patient_name',
|
||||
'label': _('Patient Name'),
|
||||
'fieldtype': 'Data',
|
||||
'width': '120'
|
||||
"fieldname": "department",
|
||||
"label": _("Medical Department"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Medical Department",
|
||||
"width": "100",
|
||||
},
|
||||
{
|
||||
'fieldname': 'employee',
|
||||
'label': _('Lab Technician'),
|
||||
'fieldtype': 'Link',
|
||||
'options': 'Employee',
|
||||
'width': '120'
|
||||
},
|
||||
{
|
||||
'fieldname': 'status',
|
||||
'label': _('Status'),
|
||||
'fieldtype': 'Data',
|
||||
'width': '100'
|
||||
},
|
||||
{
|
||||
'fieldname': 'invoiced',
|
||||
'label': _('Invoiced'),
|
||||
'fieldtype': 'Check',
|
||||
'width': '100'
|
||||
},
|
||||
{
|
||||
'fieldname': 'result_date',
|
||||
'label': _('Result Date'),
|
||||
'fieldtype': 'Date',
|
||||
'width': '100'
|
||||
},
|
||||
{
|
||||
'fieldname': 'practitioner',
|
||||
'label': _('Requesting Practitioner'),
|
||||
'fieldtype': 'Link',
|
||||
'options': 'Healthcare Practitioner',
|
||||
'width': '120'
|
||||
},
|
||||
{
|
||||
'fieldname': 'department',
|
||||
'label': _('Medical Department'),
|
||||
'fieldtype': 'Link',
|
||||
'options': 'Medical Department',
|
||||
'width': '100'
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
def get_lab_tests(filters):
|
||||
conditions = get_conditions(filters)
|
||||
data = frappe.get_all(
|
||||
doctype='Lab Test',
|
||||
fields=['name', 'template', 'company', 'patient', 'patient_name', 'practitioner', 'employee', 'status', 'invoiced', 'result_date', 'department'],
|
||||
doctype="Lab Test",
|
||||
fields=[
|
||||
"name",
|
||||
"template",
|
||||
"company",
|
||||
"patient",
|
||||
"patient_name",
|
||||
"practitioner",
|
||||
"employee",
|
||||
"status",
|
||||
"invoiced",
|
||||
"result_date",
|
||||
"department",
|
||||
],
|
||||
filters=conditions,
|
||||
order_by='submitted_date desc'
|
||||
order_by="submitted_date desc",
|
||||
)
|
||||
return data
|
||||
|
||||
def get_conditions(filters):
|
||||
conditions = {
|
||||
'docstatus': ('=', 1)
|
||||
}
|
||||
|
||||
if filters.get('from_date') and filters.get('to_date'):
|
||||
conditions['result_date'] = ('between', (filters.get('from_date'), filters.get('to_date')))
|
||||
filters.pop('from_date')
|
||||
filters.pop('to_date')
|
||||
def get_conditions(filters):
|
||||
conditions = {"docstatus": ("=", 1)}
|
||||
|
||||
if filters.get("from_date") and filters.get("to_date"):
|
||||
conditions["result_date"] = ("between", (filters.get("from_date"), filters.get("to_date")))
|
||||
filters.pop("from_date")
|
||||
filters.pop("to_date")
|
||||
|
||||
for key, value in filters.items():
|
||||
if filters.get(key):
|
||||
@@ -143,35 +138,35 @@ def get_conditions(filters):
|
||||
|
||||
return conditions
|
||||
|
||||
|
||||
def get_chart_data(data):
|
||||
if not data:
|
||||
return None
|
||||
|
||||
labels = ['Completed', 'Approved', 'Rejected']
|
||||
labels = ["Completed", "Approved", "Rejected"]
|
||||
|
||||
status_wise_data = {
|
||||
'Completed': 0,
|
||||
'Approved': 0,
|
||||
'Rejected': 0
|
||||
}
|
||||
status_wise_data = {"Completed": 0, "Approved": 0, "Rejected": 0}
|
||||
|
||||
datasets = []
|
||||
|
||||
for entry in data:
|
||||
status_wise_data[entry.status] += 1
|
||||
|
||||
datasets.append({
|
||||
'name': 'Lab Test Status',
|
||||
'values': [status_wise_data.get('Completed'), status_wise_data.get('Approved'), status_wise_data.get('Rejected')]
|
||||
})
|
||||
datasets.append(
|
||||
{
|
||||
"name": "Lab Test Status",
|
||||
"values": [
|
||||
status_wise_data.get("Completed"),
|
||||
status_wise_data.get("Approved"),
|
||||
status_wise_data.get("Rejected"),
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
chart = {
|
||||
'data': {
|
||||
'labels': labels,
|
||||
'datasets': datasets
|
||||
},
|
||||
'type': 'bar',
|
||||
'height': 300,
|
||||
"data": {"labels": labels, "datasets": datasets},
|
||||
"type": "bar",
|
||||
"height": 300,
|
||||
}
|
||||
|
||||
return chart
|
||||
@@ -192,21 +187,21 @@ def get_report_summary(data):
|
||||
|
||||
return [
|
||||
{
|
||||
'value': total_lab_tests,
|
||||
'indicator': 'Blue',
|
||||
'label': 'Total Lab Tests',
|
||||
'datatype': 'Int',
|
||||
"value": total_lab_tests,
|
||||
"indicator": "Blue",
|
||||
"label": "Total Lab Tests",
|
||||
"datatype": "Int",
|
||||
},
|
||||
{
|
||||
'value': invoiced_lab_tests,
|
||||
'indicator': 'Green',
|
||||
'label': 'Invoiced Lab Tests',
|
||||
'datatype': 'Int',
|
||||
"value": invoiced_lab_tests,
|
||||
"indicator": "Green",
|
||||
"label": "Invoiced Lab Tests",
|
||||
"datatype": "Int",
|
||||
},
|
||||
{
|
||||
'value': unbilled_lab_tests,
|
||||
'indicator': 'Red',
|
||||
'label': 'Unbilled Lab Tests',
|
||||
'datatype': 'Int',
|
||||
}
|
||||
"value": unbilled_lab_tests,
|
||||
"indicator": "Red",
|
||||
"label": "Unbilled Lab Tests",
|
||||
"datatype": "Int",
|
||||
},
|
||||
]
|
||||
|
||||
@@ -13,11 +13,25 @@ from erpnext.accounts.utils import get_fiscal_year
|
||||
def execute(filters=None):
|
||||
return Analytics(filters).run()
|
||||
|
||||
|
||||
class Analytics(object):
|
||||
def __init__(self, filters=None):
|
||||
"""Patient Appointment Analytics Report."""
|
||||
self.filters = frappe._dict(filters or {})
|
||||
self.months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
|
||||
self.months = [
|
||||
"Jan",
|
||||
"Feb",
|
||||
"Mar",
|
||||
"Apr",
|
||||
"May",
|
||||
"Jun",
|
||||
"Jul",
|
||||
"Aug",
|
||||
"Sep",
|
||||
"Oct",
|
||||
"Nov",
|
||||
"Dec",
|
||||
]
|
||||
self.get_period_date_ranges()
|
||||
|
||||
def run(self):
|
||||
@@ -29,25 +43,23 @@ class Analytics(object):
|
||||
|
||||
def get_period_date_ranges(self):
|
||||
from dateutil.relativedelta import MO, relativedelta
|
||||
|
||||
from_date, to_date = getdate(self.filters.from_date), getdate(self.filters.to_date)
|
||||
|
||||
increment = {
|
||||
'Monthly': 1,
|
||||
'Quarterly': 3,
|
||||
'Half-Yearly': 6,
|
||||
'Yearly': 12
|
||||
}.get(self.filters.range, 1)
|
||||
increment = {"Monthly": 1, "Quarterly": 3, "Half-Yearly": 6, "Yearly": 12}.get(
|
||||
self.filters.range, 1
|
||||
)
|
||||
|
||||
if self.filters.range in ['Monthly', 'Quarterly']:
|
||||
if self.filters.range in ["Monthly", "Quarterly"]:
|
||||
from_date = from_date.replace(day=1)
|
||||
elif self.filters.range == 'Yearly':
|
||||
elif self.filters.range == "Yearly":
|
||||
from_date = get_fiscal_year(from_date)[1]
|
||||
else:
|
||||
from_date = from_date + relativedelta(from_date, weekday=MO(-1))
|
||||
|
||||
self.periodic_daterange = []
|
||||
for dummy in range(1, 53):
|
||||
if self.filters.range == 'Weekly':
|
||||
if self.filters.range == "Weekly":
|
||||
period_end_date = add_days(from_date, 6)
|
||||
else:
|
||||
period_end_date = add_to_date(from_date, months=increment, days=-1)
|
||||
@@ -64,87 +76,87 @@ class Analytics(object):
|
||||
def get_columns(self):
|
||||
self.columns = []
|
||||
|
||||
if self.filters.tree_type == 'Healthcare Practitioner':
|
||||
self.columns.append({
|
||||
'label': _('Healthcare Practitioner'),
|
||||
'options': 'Healthcare Practitioner',
|
||||
'fieldname': 'practitioner',
|
||||
'fieldtype': 'Link',
|
||||
'width': 200
|
||||
})
|
||||
if self.filters.tree_type == "Healthcare Practitioner":
|
||||
self.columns.append(
|
||||
{
|
||||
"label": _("Healthcare Practitioner"),
|
||||
"options": "Healthcare Practitioner",
|
||||
"fieldname": "practitioner",
|
||||
"fieldtype": "Link",
|
||||
"width": 200,
|
||||
}
|
||||
)
|
||||
|
||||
elif self.filters.tree_type == 'Medical Department':
|
||||
self.columns.append({
|
||||
'label': _('Medical Department'),
|
||||
'fieldname': 'department',
|
||||
'fieldtype': 'Link',
|
||||
'options': 'Medical Department',
|
||||
'width': 150
|
||||
})
|
||||
elif self.filters.tree_type == "Medical Department":
|
||||
self.columns.append(
|
||||
{
|
||||
"label": _("Medical Department"),
|
||||
"fieldname": "department",
|
||||
"fieldtype": "Link",
|
||||
"options": "Medical Department",
|
||||
"width": 150,
|
||||
}
|
||||
)
|
||||
|
||||
for end_date in self.periodic_daterange:
|
||||
period = self.get_period(end_date)
|
||||
self.columns.append({
|
||||
'label': _(period),
|
||||
'fieldname': scrub(period),
|
||||
'fieldtype': 'Int',
|
||||
'width': 120
|
||||
})
|
||||
self.columns.append(
|
||||
{"label": _(period), "fieldname": scrub(period), "fieldtype": "Int", "width": 120}
|
||||
)
|
||||
|
||||
self.columns.append({
|
||||
'label': _('Total'),
|
||||
'fieldname': 'total',
|
||||
'fieldtype': 'Int',
|
||||
'width': 120
|
||||
})
|
||||
self.columns.append(
|
||||
{"label": _("Total"), "fieldname": "total", "fieldtype": "Int", "width": 120}
|
||||
)
|
||||
|
||||
def get_data(self):
|
||||
if self.filters.tree_type == 'Healthcare Practitioner':
|
||||
if self.filters.tree_type == "Healthcare Practitioner":
|
||||
self.get_appointments_based_on_healthcare_practitioner()
|
||||
self.get_rows()
|
||||
|
||||
elif self.filters.tree_type == 'Medical Department':
|
||||
elif self.filters.tree_type == "Medical Department":
|
||||
self.get_appointments_based_on_medical_department()
|
||||
self.get_rows()
|
||||
|
||||
def get_period(self, appointment_date):
|
||||
if self.filters.range == 'Weekly':
|
||||
period = 'Week ' + str(appointment_date.isocalendar()[1])
|
||||
elif self.filters.range == 'Monthly':
|
||||
if self.filters.range == "Weekly":
|
||||
period = "Week " + str(appointment_date.isocalendar()[1])
|
||||
elif self.filters.range == "Monthly":
|
||||
period = str(self.months[appointment_date.month - 1])
|
||||
elif self.filters.range == 'Quarterly':
|
||||
period = 'Quarter ' + str(((appointment_date.month - 1) // 3) + 1)
|
||||
elif self.filters.range == "Quarterly":
|
||||
period = "Quarter " + str(((appointment_date.month - 1) // 3) + 1)
|
||||
else:
|
||||
year = get_fiscal_year(appointment_date, company=self.filters.company)
|
||||
period = str(year[0])
|
||||
|
||||
if getdate(self.filters.from_date).year != getdate(self.filters.to_date).year:
|
||||
period += ' ' + str(appointment_date.year)
|
||||
period += " " + str(appointment_date.year)
|
||||
|
||||
return period
|
||||
|
||||
def get_appointments_based_on_healthcare_practitioner(self):
|
||||
filters = self.get_common_filters()
|
||||
|
||||
self.entries = frappe.db.get_all('Patient Appointment',
|
||||
fields=['appointment_date', 'name', 'patient', 'practitioner'],
|
||||
filters=filters
|
||||
self.entries = frappe.db.get_all(
|
||||
"Patient Appointment",
|
||||
fields=["appointment_date", "name", "patient", "practitioner"],
|
||||
filters=filters,
|
||||
)
|
||||
|
||||
def get_appointments_based_on_medical_department(self):
|
||||
filters = self.get_common_filters()
|
||||
if not filters.get('department'):
|
||||
filters['department'] = ('!=', '')
|
||||
if not filters.get("department"):
|
||||
filters["department"] = ("!=", "")
|
||||
|
||||
self.entries = frappe.db.get_all('Patient Appointment',
|
||||
fields=['appointment_date', 'name', 'patient', 'practitioner', 'department'],
|
||||
filters=filters
|
||||
self.entries = frappe.db.get_all(
|
||||
"Patient Appointment",
|
||||
fields=["appointment_date", "name", "patient", "practitioner", "department"],
|
||||
filters=filters,
|
||||
)
|
||||
|
||||
def get_common_filters(self):
|
||||
filters = {}
|
||||
filters['appointment_date'] = ('between', [self.filters.from_date, self.filters.to_date])
|
||||
for entry in ['appointment_type', 'practitioner', 'department', 'status']:
|
||||
filters["appointment_date"] = ("between", [self.filters.from_date, self.filters.to_date])
|
||||
for entry in ["appointment_type", "practitioner", "department", "status"]:
|
||||
if self.filters.get(entry):
|
||||
filters[entry] = self.filters.get(entry)
|
||||
|
||||
@@ -155,10 +167,10 @@ class Analytics(object):
|
||||
self.get_periodic_data()
|
||||
|
||||
for entity, period_data in iteritems(self.appointment_periodic_data):
|
||||
if self.filters.tree_type == 'Healthcare Practitioner':
|
||||
row = {'practitioner': entity}
|
||||
elif self.filters.tree_type == 'Medical Department':
|
||||
row = {'department': entity}
|
||||
if self.filters.tree_type == "Healthcare Practitioner":
|
||||
row = {"practitioner": entity}
|
||||
elif self.filters.tree_type == "Medical Department":
|
||||
row = {"department": entity}
|
||||
|
||||
total = 0
|
||||
for end_date in self.periodic_daterange:
|
||||
@@ -167,7 +179,7 @@ class Analytics(object):
|
||||
row[scrub(period)] = amount
|
||||
total += amount
|
||||
|
||||
row['total'] = total
|
||||
row["total"] = total
|
||||
|
||||
self.data.append(row)
|
||||
|
||||
@@ -175,22 +187,18 @@ class Analytics(object):
|
||||
self.appointment_periodic_data = frappe._dict()
|
||||
|
||||
for d in self.entries:
|
||||
period = self.get_period(d.get('appointment_date'))
|
||||
if self.filters.tree_type == 'Healthcare Practitioner':
|
||||
self.appointment_periodic_data.setdefault(d.practitioner, frappe._dict()).setdefault(period, 0.0)
|
||||
period = self.get_period(d.get("appointment_date"))
|
||||
if self.filters.tree_type == "Healthcare Practitioner":
|
||||
self.appointment_periodic_data.setdefault(d.practitioner, frappe._dict()).setdefault(
|
||||
period, 0.0
|
||||
)
|
||||
self.appointment_periodic_data[d.practitioner][period] += 1
|
||||
|
||||
elif self.filters.tree_type == 'Medical Department':
|
||||
elif self.filters.tree_type == "Medical Department":
|
||||
self.appointment_periodic_data.setdefault(d.department, frappe._dict()).setdefault(period, 0.0)
|
||||
self.appointment_periodic_data[d.department][period] += 1
|
||||
|
||||
def get_chart_data(self):
|
||||
length = len(self.columns)
|
||||
labels = [d.get("label") for d in self.columns[1:length - 1]]
|
||||
self.chart = {
|
||||
"data": {
|
||||
'labels': labels,
|
||||
'datasets': []
|
||||
},
|
||||
"type": "line"
|
||||
}
|
||||
labels = [d.get("label") for d in self.columns[1 : length - 1]]
|
||||
self.chart = {"data": {"labels": labels, "datasets": []}, "type": "line"}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
|
||||
@@ -6,7 +5,7 @@ from erpnext.setup.utils import insert_record
|
||||
|
||||
|
||||
def setup_healthcare():
|
||||
if frappe.db.exists('Medical Department', 'Cardiology'):
|
||||
if frappe.db.exists("Medical Department", "Cardiology"):
|
||||
# already setup
|
||||
return
|
||||
create_medical_departments()
|
||||
@@ -19,12 +18,31 @@ def setup_healthcare():
|
||||
add_healthcare_service_unit_tree_root()
|
||||
setup_patient_history_settings()
|
||||
|
||||
|
||||
def create_medical_departments():
|
||||
departments = [
|
||||
"Accident And Emergency Care" ,"Anaesthetics", "Biochemistry", "Cardiology", "Dermatology",
|
||||
"Diagnostic Imaging", "ENT", "Gastroenterology", "General Surgery", "Gynaecology",
|
||||
"Haematology", "Maternity", "Microbiology", "Nephrology", "Neurology", "Oncology",
|
||||
"Orthopaedics", "Pathology", "Physiotherapy", "Rheumatology", "Serology", "Urology"
|
||||
"Accident And Emergency Care",
|
||||
"Anaesthetics",
|
||||
"Biochemistry",
|
||||
"Cardiology",
|
||||
"Dermatology",
|
||||
"Diagnostic Imaging",
|
||||
"ENT",
|
||||
"Gastroenterology",
|
||||
"General Surgery",
|
||||
"Gynaecology",
|
||||
"Haematology",
|
||||
"Maternity",
|
||||
"Microbiology",
|
||||
"Nephrology",
|
||||
"Neurology",
|
||||
"Oncology",
|
||||
"Orthopaedics",
|
||||
"Pathology",
|
||||
"Physiotherapy",
|
||||
"Rheumatology",
|
||||
"Serology",
|
||||
"Urology",
|
||||
]
|
||||
for department in departments:
|
||||
mediacal_department = frappe.new_doc("Medical Department")
|
||||
@@ -34,37 +52,175 @@ def create_medical_departments():
|
||||
except frappe.DuplicateEntryError:
|
||||
pass
|
||||
|
||||
|
||||
def create_antibiotics():
|
||||
abt = [
|
||||
"Amoxicillin", "Ampicillin", "Bacampicillin", "Carbenicillin", "Cloxacillin", "Dicloxacillin",
|
||||
"Flucloxacillin", "Mezlocillin", "Nafcillin", "Oxacillin", "Penicillin G", "Penicillin V",
|
||||
"Piperacillin", "Pivampicillin", "Pivmecillinam", "Ticarcillin", "Cefacetrile (cephacetrile)",
|
||||
"Cefadroxil (cefadroxyl)", "Cefalexin (cephalexin)", "Cefaloglycin (cephaloglycin)",
|
||||
"Cefalonium (cephalonium)", "Cefaloridine (cephaloradine)", "Cefalotin (cephalothin)",
|
||||
"Cefapirin (cephapirin)", "Cefatrizine", "Cefazaflur", "Cefazedone", "Cefazolin (cephazolin)",
|
||||
"Cefradine (cephradine)", "Cefroxadine", "Ceftezole", "Cefaclor", "Cefamandole", "Cefmetazole",
|
||||
"Cefonicid", "Cefotetan", "Cefoxitin", "Cefprozil (cefproxil)", "Cefuroxime", "Cefuzonam",
|
||||
"Cefcapene", "Cefdaloxime", "Cefdinir", "Cefditoren", "Cefetamet", "Cefixime", "Cefmenoxime",
|
||||
"Cefodizime", "Cefotaxime", "Cefpimizole", "Cefpodoxime", "Cefteram", "Ceftibuten", "Ceftiofur",
|
||||
"Ceftiolene", "Ceftizoxime", "Ceftriaxone", "Cefoperazone", "Ceftazidime", "Cefclidine", "Cefepime",
|
||||
"Cefluprenam", "Cefoselis", "Cefozopran", "Cefpirome", "Cefquinome", "Ceftobiprole", "Ceftaroline",
|
||||
"Cefaclomezine","Cefaloram", "Cefaparole", "Cefcanel", "Cefedrolor", "Cefempidone", "Cefetrizole",
|
||||
"Cefivitril", "Cefmatilen", "Cefmepidium", "Cefovecin", "Cefoxazole", "Cefrotil", "Cefsumide",
|
||||
"Cefuracetime", "Ceftioxide", "Ceftazidime/Avibactam", "Ceftolozane/Tazobactam", "Aztreonam",
|
||||
"Imipenem", "Imipenem/cilastatin", "Doripenem", "Meropenem", "Ertapenem", "Azithromycin",
|
||||
"Erythromycin", "Clarithromycin", "Dirithromycin", "Roxithromycin", "Telithromycin", "Clindamycin",
|
||||
"Lincomycin", "Pristinamycin", "Quinupristin/dalfopristin", "Amikacin", "Gentamicin", "Kanamycin",
|
||||
"Neomycin", "Netilmicin", "Paromomycin", "Streptomycin", "Tobramycin", "Flumequine", "Nalidixic acid",
|
||||
"Oxolinic acid", "Piromidic acid", "Pipemidic acid", "Rosoxacin", "Ciprofloxacin", "Enoxacin",
|
||||
"Lomefloxacin", "Nadifloxacin", "Norfloxacin", "Ofloxacin", "Pefloxacin", "Rufloxacin", "Balofloxacin",
|
||||
"Gatifloxacin", "Grepafloxacin", "Levofloxacin", "Moxifloxacin", "Pazufloxacin", "Sparfloxacin",
|
||||
"Temafloxacin", "Tosufloxacin", "Besifloxacin", "Clinafloxacin", "Gemifloxacin",
|
||||
"Sitafloxacin", "Trovafloxacin", "Prulifloxacin", "Sulfamethizole", "Sulfamethoxazole",
|
||||
"Sulfisoxazole", "Trimethoprim-Sulfamethoxazole", "Demeclocycline", "Doxycycline", "Minocycline",
|
||||
"Oxytetracycline", "Tetracycline", "Tigecycline", "Chloramphenicol", "Metronidazole",
|
||||
"Tinidazole", "Nitrofurantoin", "Vancomycin", "Teicoplanin", "Telavancin", "Linezolid",
|
||||
"Cycloserine 2", "Rifampin", "Rifabutin", "Rifapentine", "Rifalazil", "Bacitracin", "Polymyxin B",
|
||||
"Viomycin", "Capreomycin"
|
||||
"Amoxicillin",
|
||||
"Ampicillin",
|
||||
"Bacampicillin",
|
||||
"Carbenicillin",
|
||||
"Cloxacillin",
|
||||
"Dicloxacillin",
|
||||
"Flucloxacillin",
|
||||
"Mezlocillin",
|
||||
"Nafcillin",
|
||||
"Oxacillin",
|
||||
"Penicillin G",
|
||||
"Penicillin V",
|
||||
"Piperacillin",
|
||||
"Pivampicillin",
|
||||
"Pivmecillinam",
|
||||
"Ticarcillin",
|
||||
"Cefacetrile (cephacetrile)",
|
||||
"Cefadroxil (cefadroxyl)",
|
||||
"Cefalexin (cephalexin)",
|
||||
"Cefaloglycin (cephaloglycin)",
|
||||
"Cefalonium (cephalonium)",
|
||||
"Cefaloridine (cephaloradine)",
|
||||
"Cefalotin (cephalothin)",
|
||||
"Cefapirin (cephapirin)",
|
||||
"Cefatrizine",
|
||||
"Cefazaflur",
|
||||
"Cefazedone",
|
||||
"Cefazolin (cephazolin)",
|
||||
"Cefradine (cephradine)",
|
||||
"Cefroxadine",
|
||||
"Ceftezole",
|
||||
"Cefaclor",
|
||||
"Cefamandole",
|
||||
"Cefmetazole",
|
||||
"Cefonicid",
|
||||
"Cefotetan",
|
||||
"Cefoxitin",
|
||||
"Cefprozil (cefproxil)",
|
||||
"Cefuroxime",
|
||||
"Cefuzonam",
|
||||
"Cefcapene",
|
||||
"Cefdaloxime",
|
||||
"Cefdinir",
|
||||
"Cefditoren",
|
||||
"Cefetamet",
|
||||
"Cefixime",
|
||||
"Cefmenoxime",
|
||||
"Cefodizime",
|
||||
"Cefotaxime",
|
||||
"Cefpimizole",
|
||||
"Cefpodoxime",
|
||||
"Cefteram",
|
||||
"Ceftibuten",
|
||||
"Ceftiofur",
|
||||
"Ceftiolene",
|
||||
"Ceftizoxime",
|
||||
"Ceftriaxone",
|
||||
"Cefoperazone",
|
||||
"Ceftazidime",
|
||||
"Cefclidine",
|
||||
"Cefepime",
|
||||
"Cefluprenam",
|
||||
"Cefoselis",
|
||||
"Cefozopran",
|
||||
"Cefpirome",
|
||||
"Cefquinome",
|
||||
"Ceftobiprole",
|
||||
"Ceftaroline",
|
||||
"Cefaclomezine",
|
||||
"Cefaloram",
|
||||
"Cefaparole",
|
||||
"Cefcanel",
|
||||
"Cefedrolor",
|
||||
"Cefempidone",
|
||||
"Cefetrizole",
|
||||
"Cefivitril",
|
||||
"Cefmatilen",
|
||||
"Cefmepidium",
|
||||
"Cefovecin",
|
||||
"Cefoxazole",
|
||||
"Cefrotil",
|
||||
"Cefsumide",
|
||||
"Cefuracetime",
|
||||
"Ceftioxide",
|
||||
"Ceftazidime/Avibactam",
|
||||
"Ceftolozane/Tazobactam",
|
||||
"Aztreonam",
|
||||
"Imipenem",
|
||||
"Imipenem/cilastatin",
|
||||
"Doripenem",
|
||||
"Meropenem",
|
||||
"Ertapenem",
|
||||
"Azithromycin",
|
||||
"Erythromycin",
|
||||
"Clarithromycin",
|
||||
"Dirithromycin",
|
||||
"Roxithromycin",
|
||||
"Telithromycin",
|
||||
"Clindamycin",
|
||||
"Lincomycin",
|
||||
"Pristinamycin",
|
||||
"Quinupristin/dalfopristin",
|
||||
"Amikacin",
|
||||
"Gentamicin",
|
||||
"Kanamycin",
|
||||
"Neomycin",
|
||||
"Netilmicin",
|
||||
"Paromomycin",
|
||||
"Streptomycin",
|
||||
"Tobramycin",
|
||||
"Flumequine",
|
||||
"Nalidixic acid",
|
||||
"Oxolinic acid",
|
||||
"Piromidic acid",
|
||||
"Pipemidic acid",
|
||||
"Rosoxacin",
|
||||
"Ciprofloxacin",
|
||||
"Enoxacin",
|
||||
"Lomefloxacin",
|
||||
"Nadifloxacin",
|
||||
"Norfloxacin",
|
||||
"Ofloxacin",
|
||||
"Pefloxacin",
|
||||
"Rufloxacin",
|
||||
"Balofloxacin",
|
||||
"Gatifloxacin",
|
||||
"Grepafloxacin",
|
||||
"Levofloxacin",
|
||||
"Moxifloxacin",
|
||||
"Pazufloxacin",
|
||||
"Sparfloxacin",
|
||||
"Temafloxacin",
|
||||
"Tosufloxacin",
|
||||
"Besifloxacin",
|
||||
"Clinafloxacin",
|
||||
"Gemifloxacin",
|
||||
"Sitafloxacin",
|
||||
"Trovafloxacin",
|
||||
"Prulifloxacin",
|
||||
"Sulfamethizole",
|
||||
"Sulfamethoxazole",
|
||||
"Sulfisoxazole",
|
||||
"Trimethoprim-Sulfamethoxazole",
|
||||
"Demeclocycline",
|
||||
"Doxycycline",
|
||||
"Minocycline",
|
||||
"Oxytetracycline",
|
||||
"Tetracycline",
|
||||
"Tigecycline",
|
||||
"Chloramphenicol",
|
||||
"Metronidazole",
|
||||
"Tinidazole",
|
||||
"Nitrofurantoin",
|
||||
"Vancomycin",
|
||||
"Teicoplanin",
|
||||
"Telavancin",
|
||||
"Linezolid",
|
||||
"Cycloserine 2",
|
||||
"Rifampin",
|
||||
"Rifabutin",
|
||||
"Rifapentine",
|
||||
"Rifalazil",
|
||||
"Bacitracin",
|
||||
"Polymyxin B",
|
||||
"Viomycin",
|
||||
"Capreomycin",
|
||||
]
|
||||
|
||||
for a in abt:
|
||||
@@ -75,115 +231,259 @@ def create_antibiotics():
|
||||
except frappe.DuplicateEntryError:
|
||||
pass
|
||||
|
||||
|
||||
def create_lab_test_uom():
|
||||
records = [
|
||||
{"doctype": "Lab Test UOM", "name": "umol/L", "lab_test_uom": "umol/L", "uom_description": None },
|
||||
{"doctype": "Lab Test UOM", "name": "mg/L", "lab_test_uom": "mg/L", "uom_description": None },
|
||||
{"doctype": "Lab Test UOM", "name": "mg / dl", "lab_test_uom": "mg / dl", "uom_description": None },
|
||||
{"doctype": "Lab Test UOM", "name": "pg / ml", "lab_test_uom": "pg / ml", "uom_description": None },
|
||||
{"doctype": "Lab Test UOM", "name": "U/ml", "lab_test_uom": "U/ml", "uom_description": None },
|
||||
{"doctype": "Lab Test UOM", "name": "/HPF", "lab_test_uom": "/HPF", "uom_description": None },
|
||||
{"doctype": "Lab Test UOM", "name": "Million Cells / cumm", "lab_test_uom": "Million Cells / cumm", "uom_description": None },
|
||||
{"doctype": "Lab Test UOM", "name": "Lakhs Cells / cumm", "lab_test_uom": "Lakhs Cells / cumm", "uom_description": None },
|
||||
{"doctype": "Lab Test UOM", "name": "U / L", "lab_test_uom": "U / L", "uom_description": None },
|
||||
{"doctype": "Lab Test UOM", "name": "g / L", "lab_test_uom": "g / L", "uom_description": None },
|
||||
{"doctype": "Lab Test UOM", "name": "IU / ml", "lab_test_uom": "IU / ml", "uom_description": None },
|
||||
{"doctype": "Lab Test UOM", "name": "gm %", "lab_test_uom": "gm %", "uom_description": None },
|
||||
{"doctype": "Lab Test UOM", "name": "Microgram", "lab_test_uom": "Microgram", "uom_description": None },
|
||||
{"doctype": "Lab Test UOM", "name": "Micron", "lab_test_uom": "Micron", "uom_description": None },
|
||||
{"doctype": "Lab Test UOM", "name": "Cells / cumm", "lab_test_uom": "Cells / cumm", "uom_description": None },
|
||||
{"doctype": "Lab Test UOM", "name": "%", "lab_test_uom": "%", "uom_description": None },
|
||||
{"doctype": "Lab Test UOM", "name": "mm / dl", "lab_test_uom": "mm / dl", "uom_description": None },
|
||||
{"doctype": "Lab Test UOM", "name": "mm / hr", "lab_test_uom": "mm / hr", "uom_description": None },
|
||||
{"doctype": "Lab Test UOM", "name": "ulU / ml", "lab_test_uom": "ulU / ml", "uom_description": None },
|
||||
{"doctype": "Lab Test UOM", "name": "ng / ml", "lab_test_uom": "ng / ml", "uom_description": None },
|
||||
{"doctype": "Lab Test UOM", "name": "ng / dl", "lab_test_uom": "ng / dl", "uom_description": None },
|
||||
{"doctype": "Lab Test UOM", "name": "ug / dl", "lab_test_uom": "ug / dl", "uom_description": None }
|
||||
{"doctype": "Lab Test UOM", "name": "umol/L", "lab_test_uom": "umol/L", "uom_description": None},
|
||||
{"doctype": "Lab Test UOM", "name": "mg/L", "lab_test_uom": "mg/L", "uom_description": None},
|
||||
{
|
||||
"doctype": "Lab Test UOM",
|
||||
"name": "mg / dl",
|
||||
"lab_test_uom": "mg / dl",
|
||||
"uom_description": None,
|
||||
},
|
||||
{
|
||||
"doctype": "Lab Test UOM",
|
||||
"name": "pg / ml",
|
||||
"lab_test_uom": "pg / ml",
|
||||
"uom_description": None,
|
||||
},
|
||||
{"doctype": "Lab Test UOM", "name": "U/ml", "lab_test_uom": "U/ml", "uom_description": None},
|
||||
{"doctype": "Lab Test UOM", "name": "/HPF", "lab_test_uom": "/HPF", "uom_description": None},
|
||||
{
|
||||
"doctype": "Lab Test UOM",
|
||||
"name": "Million Cells / cumm",
|
||||
"lab_test_uom": "Million Cells / cumm",
|
||||
"uom_description": None,
|
||||
},
|
||||
{
|
||||
"doctype": "Lab Test UOM",
|
||||
"name": "Lakhs Cells / cumm",
|
||||
"lab_test_uom": "Lakhs Cells / cumm",
|
||||
"uom_description": None,
|
||||
},
|
||||
{"doctype": "Lab Test UOM", "name": "U / L", "lab_test_uom": "U / L", "uom_description": None},
|
||||
{"doctype": "Lab Test UOM", "name": "g / L", "lab_test_uom": "g / L", "uom_description": None},
|
||||
{
|
||||
"doctype": "Lab Test UOM",
|
||||
"name": "IU / ml",
|
||||
"lab_test_uom": "IU / ml",
|
||||
"uom_description": None,
|
||||
},
|
||||
{"doctype": "Lab Test UOM", "name": "gm %", "lab_test_uom": "gm %", "uom_description": None},
|
||||
{
|
||||
"doctype": "Lab Test UOM",
|
||||
"name": "Microgram",
|
||||
"lab_test_uom": "Microgram",
|
||||
"uom_description": None,
|
||||
},
|
||||
{"doctype": "Lab Test UOM", "name": "Micron", "lab_test_uom": "Micron", "uom_description": None},
|
||||
{
|
||||
"doctype": "Lab Test UOM",
|
||||
"name": "Cells / cumm",
|
||||
"lab_test_uom": "Cells / cumm",
|
||||
"uom_description": None,
|
||||
},
|
||||
{"doctype": "Lab Test UOM", "name": "%", "lab_test_uom": "%", "uom_description": None},
|
||||
{
|
||||
"doctype": "Lab Test UOM",
|
||||
"name": "mm / dl",
|
||||
"lab_test_uom": "mm / dl",
|
||||
"uom_description": None,
|
||||
},
|
||||
{
|
||||
"doctype": "Lab Test UOM",
|
||||
"name": "mm / hr",
|
||||
"lab_test_uom": "mm / hr",
|
||||
"uom_description": None,
|
||||
},
|
||||
{
|
||||
"doctype": "Lab Test UOM",
|
||||
"name": "ulU / ml",
|
||||
"lab_test_uom": "ulU / ml",
|
||||
"uom_description": None,
|
||||
},
|
||||
{
|
||||
"doctype": "Lab Test UOM",
|
||||
"name": "ng / ml",
|
||||
"lab_test_uom": "ng / ml",
|
||||
"uom_description": None,
|
||||
},
|
||||
{
|
||||
"doctype": "Lab Test UOM",
|
||||
"name": "ng / dl",
|
||||
"lab_test_uom": "ng / dl",
|
||||
"uom_description": None,
|
||||
},
|
||||
{
|
||||
"doctype": "Lab Test UOM",
|
||||
"name": "ug / dl",
|
||||
"lab_test_uom": "ug / dl",
|
||||
"uom_description": None,
|
||||
},
|
||||
]
|
||||
|
||||
insert_record(records)
|
||||
|
||||
|
||||
def create_duration():
|
||||
records = [
|
||||
{"doctype": "Prescription Duration", "name": "3 Month", "number": "3", "period": "Month" },
|
||||
{"doctype": "Prescription Duration", "name": "2 Month", "number": "2", "period": "Month" },
|
||||
{"doctype": "Prescription Duration", "name": "1 Month", "number": "1", "period": "Month" },
|
||||
{"doctype": "Prescription Duration", "name": "12 Hour", "number": "12", "period": "Hour" },
|
||||
{"doctype": "Prescription Duration", "name": "11 Hour", "number": "11", "period": "Hour" },
|
||||
{"doctype": "Prescription Duration", "name": "10 Hour", "number": "10", "period": "Hour" },
|
||||
{"doctype": "Prescription Duration", "name": "9 Hour", "number": "9", "period": "Hour" },
|
||||
{"doctype": "Prescription Duration", "name": "8 Hour", "number": "8", "period": "Hour" },
|
||||
{"doctype": "Prescription Duration", "name": "7 Hour", "number": "7", "period": "Hour" },
|
||||
{"doctype": "Prescription Duration", "name": "6 Hour", "number": "6", "period": "Hour" },
|
||||
{"doctype": "Prescription Duration", "name": "5 Hour", "number": "5", "period": "Hour" },
|
||||
{"doctype": "Prescription Duration", "name": "4 Hour", "number": "4", "period": "Hour" },
|
||||
{"doctype": "Prescription Duration", "name": "3 Hour", "number": "3", "period": "Hour" },
|
||||
{"doctype": "Prescription Duration", "name": "2 Hour", "number": "2", "period": "Hour" },
|
||||
{"doctype": "Prescription Duration", "name": "1 Hour", "number": "1", "period": "Hour" },
|
||||
{"doctype": "Prescription Duration", "name": "5 Week", "number": "5", "period": "Week" },
|
||||
{"doctype": "Prescription Duration", "name": "4 Week", "number": "4", "period": "Week" },
|
||||
{"doctype": "Prescription Duration", "name": "3 Week", "number": "3", "period": "Week" },
|
||||
{"doctype": "Prescription Duration", "name": "2 Week", "number": "2", "period": "Week" },
|
||||
{"doctype": "Prescription Duration", "name": "1 Week", "number": "1", "period": "Week" },
|
||||
{"doctype": "Prescription Duration", "name": "6 Day", "number": "6", "period": "Day" },
|
||||
{"doctype": "Prescription Duration", "name": "5 Day", "number": "5", "period": "Day" },
|
||||
{"doctype": "Prescription Duration", "name": "4 Day", "number": "4", "period": "Day" },
|
||||
{"doctype": "Prescription Duration", "name": "3 Day", "number": "3", "period": "Day" },
|
||||
{"doctype": "Prescription Duration", "name": "2 Day", "number": "2", "period": "Day" },
|
||||
{"doctype": "Prescription Duration", "name": "1 Day", "number": "1", "period": "Day" }
|
||||
{"doctype": "Prescription Duration", "name": "3 Month", "number": "3", "period": "Month"},
|
||||
{"doctype": "Prescription Duration", "name": "2 Month", "number": "2", "period": "Month"},
|
||||
{"doctype": "Prescription Duration", "name": "1 Month", "number": "1", "period": "Month"},
|
||||
{"doctype": "Prescription Duration", "name": "12 Hour", "number": "12", "period": "Hour"},
|
||||
{"doctype": "Prescription Duration", "name": "11 Hour", "number": "11", "period": "Hour"},
|
||||
{"doctype": "Prescription Duration", "name": "10 Hour", "number": "10", "period": "Hour"},
|
||||
{"doctype": "Prescription Duration", "name": "9 Hour", "number": "9", "period": "Hour"},
|
||||
{"doctype": "Prescription Duration", "name": "8 Hour", "number": "8", "period": "Hour"},
|
||||
{"doctype": "Prescription Duration", "name": "7 Hour", "number": "7", "period": "Hour"},
|
||||
{"doctype": "Prescription Duration", "name": "6 Hour", "number": "6", "period": "Hour"},
|
||||
{"doctype": "Prescription Duration", "name": "5 Hour", "number": "5", "period": "Hour"},
|
||||
{"doctype": "Prescription Duration", "name": "4 Hour", "number": "4", "period": "Hour"},
|
||||
{"doctype": "Prescription Duration", "name": "3 Hour", "number": "3", "period": "Hour"},
|
||||
{"doctype": "Prescription Duration", "name": "2 Hour", "number": "2", "period": "Hour"},
|
||||
{"doctype": "Prescription Duration", "name": "1 Hour", "number": "1", "period": "Hour"},
|
||||
{"doctype": "Prescription Duration", "name": "5 Week", "number": "5", "period": "Week"},
|
||||
{"doctype": "Prescription Duration", "name": "4 Week", "number": "4", "period": "Week"},
|
||||
{"doctype": "Prescription Duration", "name": "3 Week", "number": "3", "period": "Week"},
|
||||
{"doctype": "Prescription Duration", "name": "2 Week", "number": "2", "period": "Week"},
|
||||
{"doctype": "Prescription Duration", "name": "1 Week", "number": "1", "period": "Week"},
|
||||
{"doctype": "Prescription Duration", "name": "6 Day", "number": "6", "period": "Day"},
|
||||
{"doctype": "Prescription Duration", "name": "5 Day", "number": "5", "period": "Day"},
|
||||
{"doctype": "Prescription Duration", "name": "4 Day", "number": "4", "period": "Day"},
|
||||
{"doctype": "Prescription Duration", "name": "3 Day", "number": "3", "period": "Day"},
|
||||
{"doctype": "Prescription Duration", "name": "2 Day", "number": "2", "period": "Day"},
|
||||
{"doctype": "Prescription Duration", "name": "1 Day", "number": "1", "period": "Day"},
|
||||
]
|
||||
insert_record(records)
|
||||
|
||||
|
||||
def create_dosage():
|
||||
records = [
|
||||
{"doctype": "Prescription Dosage", "name": "1-1-1-1", "dosage": "1-1-1-1","dosage_strength":
|
||||
[{"strength": "1.0","strength_time": "9:00:00"}, {"strength": "1.0","strength_time": "13:00:00"},{"strength": "1.0","strength_time": "17:00:00"},{"strength": "1.0","strength_time": "21:00:00"}]
|
||||
{
|
||||
"doctype": "Prescription Dosage",
|
||||
"name": "1-1-1-1",
|
||||
"dosage": "1-1-1-1",
|
||||
"dosage_strength": [
|
||||
{"strength": "1.0", "strength_time": "9:00:00"},
|
||||
{"strength": "1.0", "strength_time": "13:00:00"},
|
||||
{"strength": "1.0", "strength_time": "17:00:00"},
|
||||
{"strength": "1.0", "strength_time": "21:00:00"},
|
||||
],
|
||||
},
|
||||
{"doctype": "Prescription Dosage", "name": "0-0-1", "dosage": "0-0-1","dosage_strength":
|
||||
[{"strength": "1.0","strength_time": "21:00:00"}]
|
||||
{
|
||||
"doctype": "Prescription Dosage",
|
||||
"name": "0-0-1",
|
||||
"dosage": "0-0-1",
|
||||
"dosage_strength": [{"strength": "1.0", "strength_time": "21:00:00"}],
|
||||
},
|
||||
{"doctype": "Prescription Dosage", "name": "1-0-0", "dosage": "1-0-0","dosage_strength":
|
||||
[{"strength": "1.0","strength_time": "9:00:00"}]
|
||||
{
|
||||
"doctype": "Prescription Dosage",
|
||||
"name": "1-0-0",
|
||||
"dosage": "1-0-0",
|
||||
"dosage_strength": [{"strength": "1.0", "strength_time": "9:00:00"}],
|
||||
},
|
||||
{"doctype": "Prescription Dosage", "name": "0-1-0", "dosage": "0-1-0","dosage_strength":
|
||||
[{"strength": "1.0","strength_time": "14:00:00"}]
|
||||
{
|
||||
"doctype": "Prescription Dosage",
|
||||
"name": "0-1-0",
|
||||
"dosage": "0-1-0",
|
||||
"dosage_strength": [{"strength": "1.0", "strength_time": "14:00:00"}],
|
||||
},
|
||||
{"doctype": "Prescription Dosage", "name": "1-1-1", "dosage": "1-1-1","dosage_strength":
|
||||
[{"strength": "1.0","strength_time": "9:00:00"}, {"strength": "1.0","strength_time": "14:00:00"},{"strength": "1.0","strength_time": "21:00:00"}]
|
||||
{
|
||||
"doctype": "Prescription Dosage",
|
||||
"name": "1-1-1",
|
||||
"dosage": "1-1-1",
|
||||
"dosage_strength": [
|
||||
{"strength": "1.0", "strength_time": "9:00:00"},
|
||||
{"strength": "1.0", "strength_time": "14:00:00"},
|
||||
{"strength": "1.0", "strength_time": "21:00:00"},
|
||||
],
|
||||
},
|
||||
{"doctype": "Prescription Dosage", "name": "1-0-1", "dosage": "1-0-1","dosage_strength":
|
||||
[{"strength": "1.0","strength_time": "9:00:00"}, {"strength": "1.0","strength_time": "21:00:00"}]
|
||||
{
|
||||
"doctype": "Prescription Dosage",
|
||||
"name": "1-0-1",
|
||||
"dosage": "1-0-1",
|
||||
"dosage_strength": [
|
||||
{"strength": "1.0", "strength_time": "9:00:00"},
|
||||
{"strength": "1.0", "strength_time": "21:00:00"},
|
||||
],
|
||||
},
|
||||
{"doctype": "Prescription Dosage", "name": "Once Bedtime", "dosage": "Once Bedtime","dosage_strength":
|
||||
[{"strength": "1.0","strength_time": "21:00:00"}]
|
||||
{
|
||||
"doctype": "Prescription Dosage",
|
||||
"name": "Once Bedtime",
|
||||
"dosage": "Once Bedtime",
|
||||
"dosage_strength": [{"strength": "1.0", "strength_time": "21:00:00"}],
|
||||
},
|
||||
{"doctype": "Prescription Dosage", "name": "5 times a day", "dosage": "5 times a day","dosage_strength":
|
||||
[{"strength": "1.0","strength_time": "5:00:00"}, {"strength": "1.0","strength_time": "9:00:00"}, {"strength": "1.0","strength_time": "13:00:00"},{"strength": "1.0","strength_time": "17:00:00"},{"strength": "1.0","strength_time": "21:00:00"}]
|
||||
{
|
||||
"doctype": "Prescription Dosage",
|
||||
"name": "5 times a day",
|
||||
"dosage": "5 times a day",
|
||||
"dosage_strength": [
|
||||
{"strength": "1.0", "strength_time": "5:00:00"},
|
||||
{"strength": "1.0", "strength_time": "9:00:00"},
|
||||
{"strength": "1.0", "strength_time": "13:00:00"},
|
||||
{"strength": "1.0", "strength_time": "17:00:00"},
|
||||
{"strength": "1.0", "strength_time": "21:00:00"},
|
||||
],
|
||||
},
|
||||
{"doctype": "Prescription Dosage", "name": "QID", "dosage": "QID","dosage_strength":
|
||||
[{"strength": "1.0","strength_time": "9:00:00"}, {"strength": "1.0","strength_time": "13:00:00"},{"strength": "1.0","strength_time": "17:00:00"},{"strength": "1.0","strength_time": "21:00:00"}]
|
||||
{
|
||||
"doctype": "Prescription Dosage",
|
||||
"name": "QID",
|
||||
"dosage": "QID",
|
||||
"dosage_strength": [
|
||||
{"strength": "1.0", "strength_time": "9:00:00"},
|
||||
{"strength": "1.0", "strength_time": "13:00:00"},
|
||||
{"strength": "1.0", "strength_time": "17:00:00"},
|
||||
{"strength": "1.0", "strength_time": "21:00:00"},
|
||||
],
|
||||
},
|
||||
{"doctype": "Prescription Dosage", "name": "TID", "dosage": "TID","dosage_strength":
|
||||
[{"strength": "1.0","strength_time": "9:00:00"}, {"strength": "1.0","strength_time": "14:00:00"},{"strength": "1.0","strength_time": "21:00:00"}]
|
||||
{
|
||||
"doctype": "Prescription Dosage",
|
||||
"name": "TID",
|
||||
"dosage": "TID",
|
||||
"dosage_strength": [
|
||||
{"strength": "1.0", "strength_time": "9:00:00"},
|
||||
{"strength": "1.0", "strength_time": "14:00:00"},
|
||||
{"strength": "1.0", "strength_time": "21:00:00"},
|
||||
],
|
||||
},
|
||||
{"doctype": "Prescription Dosage", "name": "BID", "dosage": "BID","dosage_strength":
|
||||
[{"strength": "1.0","strength_time": "9:00:00"}, {"strength": "1.0","strength_time": "21:00:00"}]
|
||||
{
|
||||
"doctype": "Prescription Dosage",
|
||||
"name": "BID",
|
||||
"dosage": "BID",
|
||||
"dosage_strength": [
|
||||
{"strength": "1.0", "strength_time": "9:00:00"},
|
||||
{"strength": "1.0", "strength_time": "21:00:00"},
|
||||
],
|
||||
},
|
||||
{
|
||||
"doctype": "Prescription Dosage",
|
||||
"name": "Once Daily",
|
||||
"dosage": "Once Daily",
|
||||
"dosage_strength": [{"strength": "1.0", "strength_time": "9:00:00"}],
|
||||
},
|
||||
{"doctype": "Prescription Dosage", "name": "Once Daily", "dosage": "Once Daily","dosage_strength":
|
||||
[{"strength": "1.0","strength_time": "9:00:00"}]
|
||||
}
|
||||
]
|
||||
insert_record(records)
|
||||
|
||||
|
||||
def create_healthcare_item_groups():
|
||||
records = [
|
||||
{'doctype': 'Item Group', 'item_group_name': _('Laboratory'),
|
||||
'is_group': 0, 'parent_item_group': _('All Item Groups') },
|
||||
{'doctype': 'Item Group', 'item_group_name': _('Drug'),
|
||||
'is_group': 0, 'parent_item_group': _('All Item Groups') }
|
||||
{
|
||||
"doctype": "Item Group",
|
||||
"item_group_name": _("Laboratory"),
|
||||
"is_group": 0,
|
||||
"parent_item_group": _("All Item Groups"),
|
||||
},
|
||||
{
|
||||
"doctype": "Item Group",
|
||||
"item_group_name": _("Drug"),
|
||||
"is_group": 0,
|
||||
"parent_item_group": _("All Item Groups"),
|
||||
},
|
||||
]
|
||||
insert_record(records)
|
||||
|
||||
|
||||
def create_sensitivity():
|
||||
records = [
|
||||
{"doctype": "Sensitivity", "sensitivity": _("Low Sensitivity")},
|
||||
@@ -191,21 +491,23 @@ def create_sensitivity():
|
||||
{"doctype": "Sensitivity", "sensitivity": _("Moderate Sensitivity")},
|
||||
{"doctype": "Sensitivity", "sensitivity": _("Susceptible")},
|
||||
{"doctype": "Sensitivity", "sensitivity": _("Resistant")},
|
||||
{"doctype": "Sensitivity", "sensitivity": _("Intermediate")}
|
||||
{"doctype": "Sensitivity", "sensitivity": _("Intermediate")},
|
||||
]
|
||||
insert_record(records)
|
||||
|
||||
|
||||
def add_healthcare_service_unit_tree_root():
|
||||
record = [
|
||||
{
|
||||
"doctype": "Healthcare Service Unit",
|
||||
"healthcare_service_unit_name": "All Healthcare Service Units",
|
||||
"is_group": 1,
|
||||
"company": get_company()
|
||||
}
|
||||
"company": get_company(),
|
||||
}
|
||||
]
|
||||
insert_record(record)
|
||||
|
||||
|
||||
def get_company():
|
||||
company = frappe.defaults.get_defaults().company
|
||||
if company:
|
||||
@@ -216,81 +518,108 @@ def get_company():
|
||||
return company[0].name
|
||||
return None
|
||||
|
||||
|
||||
def setup_patient_history_settings():
|
||||
import json
|
||||
|
||||
settings = frappe.get_single('Patient History Settings')
|
||||
settings = frappe.get_single("Patient History Settings")
|
||||
configuration = get_patient_history_config()
|
||||
for dt, config in configuration.items():
|
||||
settings.append("standard_doctypes", {
|
||||
"document_type": dt,
|
||||
"date_fieldname": config[0],
|
||||
"selected_fields": json.dumps(config[1])
|
||||
})
|
||||
settings.append(
|
||||
"standard_doctypes",
|
||||
{"document_type": dt, "date_fieldname": config[0], "selected_fields": json.dumps(config[1])},
|
||||
)
|
||||
settings.save()
|
||||
|
||||
|
||||
def get_patient_history_config():
|
||||
return {
|
||||
"Patient Encounter": ("encounter_date", [
|
||||
{"label": "Healthcare Practitioner", "fieldname": "practitioner", "fieldtype": "Link"},
|
||||
{"label": "Symptoms", "fieldname": "symptoms", "fieldtype": "Table Multiselect"},
|
||||
{"label": "Diagnosis", "fieldname": "diagnosis", "fieldtype": "Table Multiselect"},
|
||||
{"label": "Drug Prescription", "fieldname": "drug_prescription", "fieldtype": "Table"},
|
||||
{"label": "Lab Tests", "fieldname": "lab_test_prescription", "fieldtype": "Table"},
|
||||
{"label": "Clinical Procedures", "fieldname": "procedure_prescription", "fieldtype": "Table"},
|
||||
{"label": "Therapies", "fieldname": "therapies", "fieldtype": "Table"},
|
||||
{"label": "Review Details", "fieldname": "encounter_comment", "fieldtype": "Small Text"}
|
||||
]),
|
||||
"Clinical Procedure": ("start_date", [
|
||||
{"label": "Procedure Template", "fieldname": "procedure_template", "fieldtype": "Link"},
|
||||
{"label": "Healthcare Practitioner", "fieldname": "practitioner", "fieldtype": "Link"},
|
||||
{"label": "Notes", "fieldname": "notes", "fieldtype": "Small Text"},
|
||||
{"label": "Service Unit", "fieldname": "service_unit", "fieldtype": "Healthcare Service Unit"},
|
||||
{"label": "Start Time", "fieldname": "start_time", "fieldtype": "Time"},
|
||||
{"label": "Sample", "fieldname": "sample", "fieldtype": "Link"}
|
||||
]),
|
||||
"Lab Test": ("result_date", [
|
||||
{"label": "Test Template", "fieldname": "template", "fieldtype": "Link"},
|
||||
{"label": "Healthcare Practitioner", "fieldname": "practitioner", "fieldtype": "Link"},
|
||||
{"label": "Test Name", "fieldname": "lab_test_name", "fieldtype": "Data"},
|
||||
{"label": "Lab Technician Name", "fieldname": "employee_name", "fieldtype": "Data"},
|
||||
{"label": "Sample ID", "fieldname": "sample", "fieldtype": "Link"},
|
||||
{"label": "Normal Test Result", "fieldname": "normal_test_items", "fieldtype": "Table"},
|
||||
{"label": "Descriptive Test Result", "fieldname": "descriptive_test_items", "fieldtype": "Table"},
|
||||
{"label": "Organism Test Result", "fieldname": "organism_test_items", "fieldtype": "Table"},
|
||||
{"label": "Sensitivity Test Result", "fieldname": "sensitivity_test_items", "fieldtype": "Table"},
|
||||
{"label": "Comments", "fieldname": "lab_test_comment", "fieldtype": "Table"}
|
||||
]),
|
||||
"Therapy Session": ("start_date", [
|
||||
{"label": "Therapy Type", "fieldname": "therapy_type", "fieldtype": "Link"},
|
||||
{"label": "Healthcare Practitioner", "fieldname": "practitioner", "fieldtype": "Link"},
|
||||
{"label": "Therapy Plan", "fieldname": "therapy_plan", "fieldtype": "Link"},
|
||||
{"label": "Duration", "fieldname": "duration", "fieldtype": "Int"},
|
||||
{"label": "Location", "fieldname": "location", "fieldtype": "Link"},
|
||||
{"label": "Healthcare Service Unit", "fieldname": "service_unit", "fieldtype": "Link"},
|
||||
{"label": "Start Time", "fieldname": "start_time", "fieldtype": "Time"},
|
||||
{"label": "Exercises", "fieldname": "exercises", "fieldtype": "Table"},
|
||||
{"label": "Total Counts Targeted", "fieldname": "total_counts_targeted", "fieldtype": "Int"},
|
||||
{"label": "Total Counts Completed", "fieldname": "total_counts_completed", "fieldtype": "Int"}
|
||||
]),
|
||||
"Vital Signs": ("signs_date", [
|
||||
{"label": "Body Temperature", "fieldname": "temperature", "fieldtype": "Data"},
|
||||
{"label": "Heart Rate / Pulse", "fieldname": "pulse", "fieldtype": "Data"},
|
||||
{"label": "Respiratory rate", "fieldname": "respiratory_rate", "fieldtype": "Data"},
|
||||
{"label": "Tongue", "fieldname": "tongue", "fieldtype": "Select"},
|
||||
{"label": "Abdomen", "fieldname": "abdomen", "fieldtype": "Select"},
|
||||
{"label": "Reflexes", "fieldname": "reflexes", "fieldtype": "Select"},
|
||||
{"label": "Blood Pressure", "fieldname": "bp", "fieldtype": "Data"},
|
||||
{"label": "Notes", "fieldname": "vital_signs_note", "fieldtype": "Small Text"},
|
||||
{"label": "Height (In Meter)", "fieldname": "height", "fieldtype": "Float"},
|
||||
{"label": "Weight (In Kilogram)", "fieldname": "weight", "fieldtype": "Float"},
|
||||
{"label": "BMI", "fieldname": "bmi", "fieldtype": "Float"}
|
||||
]),
|
||||
"Inpatient Medication Order": ("start_date", [
|
||||
{"label": "Healthcare Practitioner", "fieldname": "practitioner", "fieldtype": "Link"},
|
||||
{"label": "Start Date", "fieldname": "start_date", "fieldtype": "Date"},
|
||||
{"label": "End Date", "fieldname": "end_date", "fieldtype": "Date"},
|
||||
{"label": "Medication Orders", "fieldname": "medication_orders", "fieldtype": "Table"},
|
||||
{"label": "Total Orders", "fieldname": "total_orders", "fieldtype": "Float"}
|
||||
])
|
||||
"Patient Encounter": (
|
||||
"encounter_date",
|
||||
[
|
||||
{"label": "Healthcare Practitioner", "fieldname": "practitioner", "fieldtype": "Link"},
|
||||
{"label": "Symptoms", "fieldname": "symptoms", "fieldtype": "Table Multiselect"},
|
||||
{"label": "Diagnosis", "fieldname": "diagnosis", "fieldtype": "Table Multiselect"},
|
||||
{"label": "Drug Prescription", "fieldname": "drug_prescription", "fieldtype": "Table"},
|
||||
{"label": "Lab Tests", "fieldname": "lab_test_prescription", "fieldtype": "Table"},
|
||||
{"label": "Clinical Procedures", "fieldname": "procedure_prescription", "fieldtype": "Table"},
|
||||
{"label": "Therapies", "fieldname": "therapies", "fieldtype": "Table"},
|
||||
{"label": "Review Details", "fieldname": "encounter_comment", "fieldtype": "Small Text"},
|
||||
],
|
||||
),
|
||||
"Clinical Procedure": (
|
||||
"start_date",
|
||||
[
|
||||
{"label": "Procedure Template", "fieldname": "procedure_template", "fieldtype": "Link"},
|
||||
{"label": "Healthcare Practitioner", "fieldname": "practitioner", "fieldtype": "Link"},
|
||||
{"label": "Notes", "fieldname": "notes", "fieldtype": "Small Text"},
|
||||
{"label": "Service Unit", "fieldname": "service_unit", "fieldtype": "Healthcare Service Unit"},
|
||||
{"label": "Start Time", "fieldname": "start_time", "fieldtype": "Time"},
|
||||
{"label": "Sample", "fieldname": "sample", "fieldtype": "Link"},
|
||||
],
|
||||
),
|
||||
"Lab Test": (
|
||||
"result_date",
|
||||
[
|
||||
{"label": "Test Template", "fieldname": "template", "fieldtype": "Link"},
|
||||
{"label": "Healthcare Practitioner", "fieldname": "practitioner", "fieldtype": "Link"},
|
||||
{"label": "Test Name", "fieldname": "lab_test_name", "fieldtype": "Data"},
|
||||
{"label": "Lab Technician Name", "fieldname": "employee_name", "fieldtype": "Data"},
|
||||
{"label": "Sample ID", "fieldname": "sample", "fieldtype": "Link"},
|
||||
{"label": "Normal Test Result", "fieldname": "normal_test_items", "fieldtype": "Table"},
|
||||
{
|
||||
"label": "Descriptive Test Result",
|
||||
"fieldname": "descriptive_test_items",
|
||||
"fieldtype": "Table",
|
||||
},
|
||||
{"label": "Organism Test Result", "fieldname": "organism_test_items", "fieldtype": "Table"},
|
||||
{
|
||||
"label": "Sensitivity Test Result",
|
||||
"fieldname": "sensitivity_test_items",
|
||||
"fieldtype": "Table",
|
||||
},
|
||||
{"label": "Comments", "fieldname": "lab_test_comment", "fieldtype": "Table"},
|
||||
],
|
||||
),
|
||||
"Therapy Session": (
|
||||
"start_date",
|
||||
[
|
||||
{"label": "Therapy Type", "fieldname": "therapy_type", "fieldtype": "Link"},
|
||||
{"label": "Healthcare Practitioner", "fieldname": "practitioner", "fieldtype": "Link"},
|
||||
{"label": "Therapy Plan", "fieldname": "therapy_plan", "fieldtype": "Link"},
|
||||
{"label": "Duration", "fieldname": "duration", "fieldtype": "Int"},
|
||||
{"label": "Location", "fieldname": "location", "fieldtype": "Link"},
|
||||
{"label": "Healthcare Service Unit", "fieldname": "service_unit", "fieldtype": "Link"},
|
||||
{"label": "Start Time", "fieldname": "start_time", "fieldtype": "Time"},
|
||||
{"label": "Exercises", "fieldname": "exercises", "fieldtype": "Table"},
|
||||
{"label": "Total Counts Targeted", "fieldname": "total_counts_targeted", "fieldtype": "Int"},
|
||||
{"label": "Total Counts Completed", "fieldname": "total_counts_completed", "fieldtype": "Int"},
|
||||
],
|
||||
),
|
||||
"Vital Signs": (
|
||||
"signs_date",
|
||||
[
|
||||
{"label": "Body Temperature", "fieldname": "temperature", "fieldtype": "Data"},
|
||||
{"label": "Heart Rate / Pulse", "fieldname": "pulse", "fieldtype": "Data"},
|
||||
{"label": "Respiratory rate", "fieldname": "respiratory_rate", "fieldtype": "Data"},
|
||||
{"label": "Tongue", "fieldname": "tongue", "fieldtype": "Select"},
|
||||
{"label": "Abdomen", "fieldname": "abdomen", "fieldtype": "Select"},
|
||||
{"label": "Reflexes", "fieldname": "reflexes", "fieldtype": "Select"},
|
||||
{"label": "Blood Pressure", "fieldname": "bp", "fieldtype": "Data"},
|
||||
{"label": "Notes", "fieldname": "vital_signs_note", "fieldtype": "Small Text"},
|
||||
{"label": "Height (In Meter)", "fieldname": "height", "fieldtype": "Float"},
|
||||
{"label": "Weight (In Kilogram)", "fieldname": "weight", "fieldtype": "Float"},
|
||||
{"label": "BMI", "fieldname": "bmi", "fieldtype": "Float"},
|
||||
],
|
||||
),
|
||||
"Inpatient Medication Order": (
|
||||
"start_date",
|
||||
[
|
||||
{"label": "Healthcare Practitioner", "fieldname": "practitioner", "fieldtype": "Link"},
|
||||
{"label": "Start Date", "fieldname": "start_date", "fieldtype": "Date"},
|
||||
{"label": "End Date", "fieldname": "end_date", "fieldtype": "Date"},
|
||||
{"label": "Medication Orders", "fieldname": "medication_orders", "fieldtype": "Table"},
|
||||
{"label": "Total Orders", "fieldname": "total_orders", "fieldtype": "Float"},
|
||||
],
|
||||
),
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ from erpnext.healthcare.doctype.lab_test.lab_test import create_multiple
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_healthcare_services_to_invoice(patient, company):
|
||||
patient = frappe.get_doc('Patient', patient)
|
||||
patient = frappe.get_doc("Patient", patient)
|
||||
items_to_invoice = []
|
||||
if patient:
|
||||
validate_customer_created(patient)
|
||||
@@ -34,50 +34,62 @@ def get_healthcare_services_to_invoice(patient, company):
|
||||
|
||||
|
||||
def validate_customer_created(patient):
|
||||
if not frappe.db.get_value('Patient', patient.name, 'customer'):
|
||||
if not frappe.db.get_value("Patient", patient.name, "customer"):
|
||||
msg = _("Please set a Customer linked to the Patient")
|
||||
msg += " <b><a href='/app/Form/Patient/{0}'>{0}</a></b>".format(patient.name)
|
||||
frappe.throw(msg, title=_('Customer Not Found'))
|
||||
msg += " <b><a href='/app/Form/Patient/{0}'>{0}</a></b>".format(patient.name)
|
||||
frappe.throw(msg, title=_("Customer Not Found"))
|
||||
|
||||
|
||||
def get_appointments_to_invoice(patient, company):
|
||||
appointments_to_invoice = []
|
||||
patient_appointments = frappe.get_list(
|
||||
'Patient Appointment',
|
||||
fields = '*',
|
||||
filters = {'patient': patient.name, 'company': company, 'invoiced': 0, 'status': ['not in', 'Cancelled']},
|
||||
order_by = 'appointment_date'
|
||||
)
|
||||
"Patient Appointment",
|
||||
fields="*",
|
||||
filters={
|
||||
"patient": patient.name,
|
||||
"company": company,
|
||||
"invoiced": 0,
|
||||
"status": ["not in", "Cancelled"],
|
||||
},
|
||||
order_by="appointment_date",
|
||||
)
|
||||
|
||||
for appointment in patient_appointments:
|
||||
# Procedure Appointments
|
||||
if appointment.procedure_template:
|
||||
if frappe.db.get_value('Clinical Procedure Template', appointment.procedure_template, 'is_billable'):
|
||||
appointments_to_invoice.append({
|
||||
'reference_type': 'Patient Appointment',
|
||||
'reference_name': appointment.name,
|
||||
'service': appointment.procedure_template
|
||||
})
|
||||
if frappe.db.get_value(
|
||||
"Clinical Procedure Template", appointment.procedure_template, "is_billable"
|
||||
):
|
||||
appointments_to_invoice.append(
|
||||
{
|
||||
"reference_type": "Patient Appointment",
|
||||
"reference_name": appointment.name,
|
||||
"service": appointment.procedure_template,
|
||||
}
|
||||
)
|
||||
# Consultation Appointments, should check fee validity
|
||||
else:
|
||||
if frappe.db.get_single_value('Healthcare Settings', 'enable_free_follow_ups') and \
|
||||
frappe.db.exists('Fee Validity Reference', {'appointment': appointment.name}):
|
||||
continue # Skip invoicing, fee validty present
|
||||
if frappe.db.get_single_value(
|
||||
"Healthcare Settings", "enable_free_follow_ups"
|
||||
) and frappe.db.exists("Fee Validity Reference", {"appointment": appointment.name}):
|
||||
continue # Skip invoicing, fee validty present
|
||||
practitioner_charge = 0
|
||||
income_account = None
|
||||
service_item = None
|
||||
if appointment.practitioner:
|
||||
details = get_service_item_and_practitioner_charge(appointment)
|
||||
service_item = details.get('service_item')
|
||||
practitioner_charge = details.get('practitioner_charge')
|
||||
service_item = details.get("service_item")
|
||||
practitioner_charge = details.get("practitioner_charge")
|
||||
income_account = get_income_account(appointment.practitioner, appointment.company)
|
||||
appointments_to_invoice.append({
|
||||
'reference_type': 'Patient Appointment',
|
||||
'reference_name': appointment.name,
|
||||
'service': service_item,
|
||||
'rate': practitioner_charge,
|
||||
'income_account': income_account
|
||||
})
|
||||
appointments_to_invoice.append(
|
||||
{
|
||||
"reference_type": "Patient Appointment",
|
||||
"reference_name": appointment.name,
|
||||
"service": service_item,
|
||||
"rate": practitioner_charge,
|
||||
"income_account": income_account,
|
||||
}
|
||||
)
|
||||
|
||||
return appointments_to_invoice
|
||||
|
||||
@@ -87,9 +99,9 @@ def get_encounters_to_invoice(patient, company):
|
||||
patient = patient.name
|
||||
encounters_to_invoice = []
|
||||
encounters = frappe.get_list(
|
||||
'Patient Encounter',
|
||||
fields=['*'],
|
||||
filters={'patient': patient, 'company': company, 'invoiced': False, 'docstatus': 1}
|
||||
"Patient Encounter",
|
||||
fields=["*"],
|
||||
filters={"patient": patient, "company": company, "invoiced": False, "docstatus": 1},
|
||||
)
|
||||
if encounters:
|
||||
for encounter in encounters:
|
||||
@@ -98,22 +110,25 @@ def get_encounters_to_invoice(patient, company):
|
||||
income_account = None
|
||||
service_item = None
|
||||
if encounter.practitioner:
|
||||
if encounter.inpatient_record and \
|
||||
frappe.db.get_single_value('Healthcare Settings', 'do_not_bill_inpatient_encounters'):
|
||||
if encounter.inpatient_record and frappe.db.get_single_value(
|
||||
"Healthcare Settings", "do_not_bill_inpatient_encounters"
|
||||
):
|
||||
continue
|
||||
|
||||
details = get_service_item_and_practitioner_charge(encounter)
|
||||
service_item = details.get('service_item')
|
||||
practitioner_charge = details.get('practitioner_charge')
|
||||
service_item = details.get("service_item")
|
||||
practitioner_charge = details.get("practitioner_charge")
|
||||
income_account = get_income_account(encounter.practitioner, encounter.company)
|
||||
|
||||
encounters_to_invoice.append({
|
||||
'reference_type': 'Patient Encounter',
|
||||
'reference_name': encounter.name,
|
||||
'service': service_item,
|
||||
'rate': practitioner_charge,
|
||||
'income_account': income_account
|
||||
})
|
||||
encounters_to_invoice.append(
|
||||
{
|
||||
"reference_type": "Patient Encounter",
|
||||
"reference_name": encounter.name,
|
||||
"service": service_item,
|
||||
"rate": practitioner_charge,
|
||||
"income_account": income_account,
|
||||
}
|
||||
)
|
||||
|
||||
return encounters_to_invoice
|
||||
|
||||
@@ -121,21 +136,21 @@ def get_encounters_to_invoice(patient, company):
|
||||
def get_lab_tests_to_invoice(patient, company):
|
||||
lab_tests_to_invoice = []
|
||||
lab_tests = frappe.get_list(
|
||||
'Lab Test',
|
||||
fields=['name', 'template'],
|
||||
filters={'patient': patient.name, 'company': company, 'invoiced': False, 'docstatus': 1}
|
||||
"Lab Test",
|
||||
fields=["name", "template"],
|
||||
filters={"patient": patient.name, "company": company, "invoiced": False, "docstatus": 1},
|
||||
)
|
||||
for lab_test in lab_tests:
|
||||
item, is_billable = frappe.get_cached_value('Lab Test Template', lab_test.template, ['item', 'is_billable'])
|
||||
item, is_billable = frappe.get_cached_value(
|
||||
"Lab Test Template", lab_test.template, ["item", "is_billable"]
|
||||
)
|
||||
if is_billable:
|
||||
lab_tests_to_invoice.append({
|
||||
'reference_type': 'Lab Test',
|
||||
'reference_name': lab_test.name,
|
||||
'service': item
|
||||
})
|
||||
lab_tests_to_invoice.append(
|
||||
{"reference_type": "Lab Test", "reference_name": lab_test.name, "service": item}
|
||||
)
|
||||
|
||||
lab_prescriptions = frappe.db.sql(
|
||||
'''
|
||||
"""
|
||||
SELECT
|
||||
lp.name, lp.lab_test_code
|
||||
FROM
|
||||
@@ -145,16 +160,19 @@ def get_lab_tests_to_invoice(patient, company):
|
||||
and lp.parent=et.name
|
||||
and lp.lab_test_created=0
|
||||
and lp.invoiced=0
|
||||
''', (patient.name), as_dict=1)
|
||||
""",
|
||||
(patient.name),
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
for prescription in lab_prescriptions:
|
||||
item, is_billable = frappe.get_cached_value('Lab Test Template', prescription.lab_test_code, ['item', 'is_billable'])
|
||||
item, is_billable = frappe.get_cached_value(
|
||||
"Lab Test Template", prescription.lab_test_code, ["item", "is_billable"]
|
||||
)
|
||||
if prescription.lab_test_code and is_billable:
|
||||
lab_tests_to_invoice.append({
|
||||
'reference_type': 'Lab Prescription',
|
||||
'reference_name': prescription.name,
|
||||
'service': item
|
||||
})
|
||||
lab_tests_to_invoice.append(
|
||||
{"reference_type": "Lab Prescription", "reference_name": prescription.name, "service": item}
|
||||
)
|
||||
|
||||
return lab_tests_to_invoice
|
||||
|
||||
@@ -162,40 +180,51 @@ def get_lab_tests_to_invoice(patient, company):
|
||||
def get_clinical_procedures_to_invoice(patient, company):
|
||||
clinical_procedures_to_invoice = []
|
||||
procedures = frappe.get_list(
|
||||
'Clinical Procedure',
|
||||
fields='*',
|
||||
filters={'patient': patient.name, 'company': company, 'invoiced': False}
|
||||
"Clinical Procedure",
|
||||
fields="*",
|
||||
filters={"patient": patient.name, "company": company, "invoiced": False},
|
||||
)
|
||||
for procedure in procedures:
|
||||
if not procedure.appointment:
|
||||
item, is_billable = frappe.get_cached_value('Clinical Procedure Template', procedure.procedure_template, ['item', 'is_billable'])
|
||||
item, is_billable = frappe.get_cached_value(
|
||||
"Clinical Procedure Template", procedure.procedure_template, ["item", "is_billable"]
|
||||
)
|
||||
if procedure.procedure_template and is_billable:
|
||||
clinical_procedures_to_invoice.append({
|
||||
'reference_type': 'Clinical Procedure',
|
||||
'reference_name': procedure.name,
|
||||
'service': item
|
||||
})
|
||||
clinical_procedures_to_invoice.append(
|
||||
{"reference_type": "Clinical Procedure", "reference_name": procedure.name, "service": item}
|
||||
)
|
||||
|
||||
# consumables
|
||||
if procedure.invoice_separately_as_consumables and procedure.consume_stock \
|
||||
and procedure.status == 'Completed' and not procedure.consumption_invoiced:
|
||||
if (
|
||||
procedure.invoice_separately_as_consumables
|
||||
and procedure.consume_stock
|
||||
and procedure.status == "Completed"
|
||||
and not procedure.consumption_invoiced
|
||||
):
|
||||
|
||||
service_item = frappe.db.get_single_value('Healthcare Settings', 'clinical_procedure_consumable_item')
|
||||
service_item = frappe.db.get_single_value(
|
||||
"Healthcare Settings", "clinical_procedure_consumable_item"
|
||||
)
|
||||
if not service_item:
|
||||
frappe.throw(_('Please configure Clinical Procedure Consumable Item in {0}').format(
|
||||
frappe.utils.get_link_to_form('Healthcare Settings', 'Healthcare Settings')),
|
||||
title=_('Missing Configuration'))
|
||||
frappe.throw(
|
||||
_("Please configure Clinical Procedure Consumable Item in {0}").format(
|
||||
frappe.utils.get_link_to_form("Healthcare Settings", "Healthcare Settings")
|
||||
),
|
||||
title=_("Missing Configuration"),
|
||||
)
|
||||
|
||||
clinical_procedures_to_invoice.append({
|
||||
'reference_type': 'Clinical Procedure',
|
||||
'reference_name': procedure.name,
|
||||
'service': service_item,
|
||||
'rate': procedure.consumable_total_amount,
|
||||
'description': procedure.consumption_details
|
||||
})
|
||||
clinical_procedures_to_invoice.append(
|
||||
{
|
||||
"reference_type": "Clinical Procedure",
|
||||
"reference_name": procedure.name,
|
||||
"service": service_item,
|
||||
"rate": procedure.consumable_total_amount,
|
||||
"description": procedure.consumption_details,
|
||||
}
|
||||
)
|
||||
|
||||
procedure_prescriptions = frappe.db.sql(
|
||||
'''
|
||||
"""
|
||||
SELECT
|
||||
pp.name, pp.procedure
|
||||
FROM
|
||||
@@ -206,16 +235,23 @@ def get_clinical_procedures_to_invoice(patient, company):
|
||||
and pp.procedure_created=0
|
||||
and pp.invoiced=0
|
||||
and pp.appointment_booked=0
|
||||
''', (patient.name), as_dict=1)
|
||||
""",
|
||||
(patient.name),
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
for prescription in procedure_prescriptions:
|
||||
item, is_billable = frappe.get_cached_value('Clinical Procedure Template', prescription.procedure, ['item', 'is_billable'])
|
||||
item, is_billable = frappe.get_cached_value(
|
||||
"Clinical Procedure Template", prescription.procedure, ["item", "is_billable"]
|
||||
)
|
||||
if is_billable:
|
||||
clinical_procedures_to_invoice.append({
|
||||
'reference_type': 'Procedure Prescription',
|
||||
'reference_name': prescription.name,
|
||||
'service': item
|
||||
})
|
||||
clinical_procedures_to_invoice.append(
|
||||
{
|
||||
"reference_type": "Procedure Prescription",
|
||||
"reference_name": prescription.name,
|
||||
"service": item,
|
||||
}
|
||||
)
|
||||
|
||||
return clinical_procedures_to_invoice
|
||||
|
||||
@@ -223,7 +259,7 @@ def get_clinical_procedures_to_invoice(patient, company):
|
||||
def get_inpatient_services_to_invoice(patient, company):
|
||||
services_to_invoice = []
|
||||
inpatient_services = frappe.db.sql(
|
||||
'''
|
||||
"""
|
||||
SELECT
|
||||
io.*
|
||||
FROM
|
||||
@@ -234,11 +270,16 @@ def get_inpatient_services_to_invoice(patient, company):
|
||||
and io.parent=ip.name
|
||||
and io.left=1
|
||||
and io.invoiced=0
|
||||
''', (patient.name, company), as_dict=1)
|
||||
""",
|
||||
(patient.name, company),
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
for inpatient_occupancy in inpatient_services:
|
||||
service_unit_type = frappe.db.get_value('Healthcare Service Unit', inpatient_occupancy.service_unit, 'service_unit_type')
|
||||
service_unit_type = frappe.get_cached_doc('Healthcare Service Unit Type', service_unit_type)
|
||||
service_unit_type = frappe.db.get_value(
|
||||
"Healthcare Service Unit", inpatient_occupancy.service_unit, "service_unit_type"
|
||||
)
|
||||
service_unit_type = frappe.get_cached_doc("Healthcare Service Unit Type", service_unit_type)
|
||||
if service_unit_type and service_unit_type.is_billable:
|
||||
hours_occupied = time_diff_in_hours(inpatient_occupancy.check_out, inpatient_occupancy.check_in)
|
||||
qty = 0.5
|
||||
@@ -252,11 +293,14 @@ def get_inpatient_services_to_invoice(patient, company):
|
||||
qty = rounded(floor + 0.5, 1)
|
||||
if qty <= 0:
|
||||
qty = 0.5
|
||||
services_to_invoice.append({
|
||||
'reference_type': 'Inpatient Occupancy',
|
||||
'reference_name': inpatient_occupancy.name,
|
||||
'service': service_unit_type.item, 'qty': qty
|
||||
})
|
||||
services_to_invoice.append(
|
||||
{
|
||||
"reference_type": "Inpatient Occupancy",
|
||||
"reference_name": inpatient_occupancy.name,
|
||||
"service": service_unit_type.item,
|
||||
"qty": qty,
|
||||
}
|
||||
)
|
||||
|
||||
return services_to_invoice
|
||||
|
||||
@@ -264,53 +308,62 @@ def get_inpatient_services_to_invoice(patient, company):
|
||||
def get_therapy_plans_to_invoice(patient, company):
|
||||
therapy_plans_to_invoice = []
|
||||
therapy_plans = frappe.get_list(
|
||||
'Therapy Plan',
|
||||
fields=['therapy_plan_template', 'name'],
|
||||
"Therapy Plan",
|
||||
fields=["therapy_plan_template", "name"],
|
||||
filters={
|
||||
'patient': patient.name,
|
||||
'invoiced': 0,
|
||||
'company': company,
|
||||
'therapy_plan_template': ('!=', '')
|
||||
}
|
||||
"patient": patient.name,
|
||||
"invoiced": 0,
|
||||
"company": company,
|
||||
"therapy_plan_template": ("!=", ""),
|
||||
},
|
||||
)
|
||||
for plan in therapy_plans:
|
||||
therapy_plans_to_invoice.append({
|
||||
'reference_type': 'Therapy Plan',
|
||||
'reference_name': plan.name,
|
||||
'service': frappe.db.get_value('Therapy Plan Template', plan.therapy_plan_template, 'linked_item')
|
||||
})
|
||||
therapy_plans_to_invoice.append(
|
||||
{
|
||||
"reference_type": "Therapy Plan",
|
||||
"reference_name": plan.name,
|
||||
"service": frappe.db.get_value(
|
||||
"Therapy Plan Template", plan.therapy_plan_template, "linked_item"
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
return therapy_plans_to_invoice
|
||||
|
||||
|
||||
def get_therapy_sessions_to_invoice(patient, company):
|
||||
therapy_sessions_to_invoice = []
|
||||
therapy_plans = frappe.db.get_all('Therapy Plan', {'therapy_plan_template': ('!=', '')})
|
||||
therapy_plans = frappe.db.get_all("Therapy Plan", {"therapy_plan_template": ("!=", "")})
|
||||
therapy_plans_created_from_template = []
|
||||
for entry in therapy_plans:
|
||||
therapy_plans_created_from_template.append(entry.name)
|
||||
|
||||
therapy_sessions = frappe.get_list(
|
||||
'Therapy Session',
|
||||
fields='*',
|
||||
"Therapy Session",
|
||||
fields="*",
|
||||
filters={
|
||||
'patient': patient.name,
|
||||
'invoiced': 0,
|
||||
'company': company,
|
||||
'therapy_plan': ('not in', therapy_plans_created_from_template)
|
||||
}
|
||||
"patient": patient.name,
|
||||
"invoiced": 0,
|
||||
"company": company,
|
||||
"therapy_plan": ("not in", therapy_plans_created_from_template),
|
||||
},
|
||||
)
|
||||
for therapy in therapy_sessions:
|
||||
if not therapy.appointment:
|
||||
if therapy.therapy_type and frappe.db.get_value('Therapy Type', therapy.therapy_type, 'is_billable'):
|
||||
therapy_sessions_to_invoice.append({
|
||||
'reference_type': 'Therapy Session',
|
||||
'reference_name': therapy.name,
|
||||
'service': frappe.db.get_value('Therapy Type', therapy.therapy_type, 'item')
|
||||
})
|
||||
if therapy.therapy_type and frappe.db.get_value(
|
||||
"Therapy Type", therapy.therapy_type, "is_billable"
|
||||
):
|
||||
therapy_sessions_to_invoice.append(
|
||||
{
|
||||
"reference_type": "Therapy Session",
|
||||
"reference_name": therapy.name,
|
||||
"service": frappe.db.get_value("Therapy Type", therapy.therapy_type, "item"),
|
||||
}
|
||||
)
|
||||
|
||||
return therapy_sessions_to_invoice
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_service_item_and_practitioner_charge(doc):
|
||||
if isinstance(doc, str):
|
||||
@@ -319,12 +372,14 @@ def get_service_item_and_practitioner_charge(doc):
|
||||
|
||||
service_item = None
|
||||
practitioner_charge = None
|
||||
department = doc.medical_department if doc.doctype == 'Patient Encounter' else doc.department
|
||||
department = doc.medical_department if doc.doctype == "Patient Encounter" else doc.department
|
||||
|
||||
is_inpatient = doc.inpatient_record
|
||||
|
||||
if doc.get('appointment_type'):
|
||||
service_item, practitioner_charge = get_appointment_type_service_item(doc.appointment_type, department, is_inpatient)
|
||||
if doc.get("appointment_type"):
|
||||
service_item, practitioner_charge = get_appointment_type_service_item(
|
||||
doc.appointment_type, department, is_inpatient
|
||||
)
|
||||
|
||||
if not service_item and not practitioner_charge:
|
||||
service_item, practitioner_charge = get_practitioner_service_item(doc.practitioner, is_inpatient)
|
||||
@@ -337,7 +392,7 @@ def get_service_item_and_practitioner_charge(doc):
|
||||
if not practitioner_charge:
|
||||
throw_config_practitioner_charge(is_inpatient, doc.practitioner)
|
||||
|
||||
return {'service_item': service_item, 'practitioner_charge': practitioner_charge}
|
||||
return {"service_item": service_item, "practitioner_charge": practitioner_charge}
|
||||
|
||||
|
||||
def get_appointment_type_service_item(appointment_type, department, is_inpatient):
|
||||
@@ -351,33 +406,37 @@ def get_appointment_type_service_item(appointment_type, department, is_inpatient
|
||||
|
||||
if item_list:
|
||||
if is_inpatient:
|
||||
service_item = item_list.get('inpatient_visit_charge_item')
|
||||
practitioner_charge = item_list.get('inpatient_visit_charge')
|
||||
service_item = item_list.get("inpatient_visit_charge_item")
|
||||
practitioner_charge = item_list.get("inpatient_visit_charge")
|
||||
else:
|
||||
service_item = item_list.get('op_consulting_charge_item')
|
||||
practitioner_charge = item_list.get('op_consulting_charge')
|
||||
service_item = item_list.get("op_consulting_charge_item")
|
||||
practitioner_charge = item_list.get("op_consulting_charge")
|
||||
|
||||
return service_item, practitioner_charge
|
||||
|
||||
|
||||
def throw_config_service_item(is_inpatient):
|
||||
service_item_label = _('Out Patient Consulting Charge Item')
|
||||
service_item_label = _("Out Patient Consulting Charge Item")
|
||||
if is_inpatient:
|
||||
service_item_label = _('Inpatient Visit Charge Item')
|
||||
service_item_label = _("Inpatient Visit Charge Item")
|
||||
|
||||
msg = _(('Please Configure {0} in ').format(service_item_label) \
|
||||
+ '''<b><a href='/app/Form/Healthcare Settings'>Healthcare Settings</a></b>''')
|
||||
frappe.throw(msg, title=_('Missing Configuration'))
|
||||
msg = _(
|
||||
("Please Configure {0} in ").format(service_item_label)
|
||||
+ """<b><a href='/app/Form/Healthcare Settings'>Healthcare Settings</a></b>"""
|
||||
)
|
||||
frappe.throw(msg, title=_("Missing Configuration"))
|
||||
|
||||
|
||||
def throw_config_practitioner_charge(is_inpatient, practitioner):
|
||||
charge_name = _('OP Consulting Charge')
|
||||
charge_name = _("OP Consulting Charge")
|
||||
if is_inpatient:
|
||||
charge_name = _('Inpatient Visit Charge')
|
||||
charge_name = _("Inpatient Visit Charge")
|
||||
|
||||
msg = _(('Please Configure {0} for Healthcare Practitioner').format(charge_name) \
|
||||
+ ''' <b><a href='/app/Form/Healthcare Practitioner/{0}'>{0}</a></b>'''.format(practitioner))
|
||||
frappe.throw(msg, title=_('Missing Configuration'))
|
||||
msg = _(
|
||||
("Please Configure {0} for Healthcare Practitioner").format(charge_name)
|
||||
+ """ <b><a href='/app/Form/Healthcare Practitioner/{0}'>{0}</a></b>""".format(practitioner)
|
||||
)
|
||||
frappe.throw(msg, title=_("Missing Configuration"))
|
||||
|
||||
|
||||
def get_practitioner_service_item(practitioner, is_inpatient):
|
||||
@@ -385,9 +444,15 @@ def get_practitioner_service_item(practitioner, is_inpatient):
|
||||
practitioner_charge = None
|
||||
|
||||
if is_inpatient:
|
||||
service_item, practitioner_charge = frappe.db.get_value('Healthcare Practitioner', practitioner, ['inpatient_visit_charge_item', 'inpatient_visit_charge'])
|
||||
service_item, practitioner_charge = frappe.db.get_value(
|
||||
"Healthcare Practitioner",
|
||||
practitioner,
|
||||
["inpatient_visit_charge_item", "inpatient_visit_charge"],
|
||||
)
|
||||
else:
|
||||
service_item, practitioner_charge = frappe.db.get_value('Healthcare Practitioner', practitioner, ['op_consulting_charge_item', 'op_consulting_charge'])
|
||||
service_item, practitioner_charge = frappe.db.get_value(
|
||||
"Healthcare Practitioner", practitioner, ["op_consulting_charge_item", "op_consulting_charge"]
|
||||
)
|
||||
|
||||
return service_item, practitioner_charge
|
||||
|
||||
@@ -396,18 +461,22 @@ def get_healthcare_service_item(is_inpatient):
|
||||
service_item = None
|
||||
|
||||
if is_inpatient:
|
||||
service_item = frappe.db.get_single_value('Healthcare Settings', 'inpatient_visit_charge_item')
|
||||
service_item = frappe.db.get_single_value("Healthcare Settings", "inpatient_visit_charge_item")
|
||||
else:
|
||||
service_item = frappe.db.get_single_value('Healthcare Settings', 'op_consulting_charge_item')
|
||||
service_item = frappe.db.get_single_value("Healthcare Settings", "op_consulting_charge_item")
|
||||
|
||||
return service_item
|
||||
|
||||
|
||||
def get_practitioner_charge(practitioner, is_inpatient):
|
||||
if is_inpatient:
|
||||
practitioner_charge = frappe.db.get_value('Healthcare Practitioner', practitioner, 'inpatient_visit_charge')
|
||||
practitioner_charge = frappe.db.get_value(
|
||||
"Healthcare Practitioner", practitioner, "inpatient_visit_charge"
|
||||
)
|
||||
else:
|
||||
practitioner_charge = frappe.db.get_value('Healthcare Practitioner', practitioner, 'op_consulting_charge')
|
||||
practitioner_charge = frappe.db.get_value(
|
||||
"Healthcare Practitioner", practitioner, "op_consulting_charge"
|
||||
)
|
||||
if practitioner_charge:
|
||||
return practitioner_charge
|
||||
return False
|
||||
@@ -416,75 +485,92 @@ def get_practitioner_charge(practitioner, is_inpatient):
|
||||
def manage_invoice_submit_cancel(doc, method):
|
||||
if doc.items:
|
||||
for item in doc.items:
|
||||
if item.get('reference_dt') and item.get('reference_dn'):
|
||||
if frappe.get_meta(item.reference_dt).has_field('invoiced'):
|
||||
if item.get("reference_dt") and item.get("reference_dn"):
|
||||
if frappe.get_meta(item.reference_dt).has_field("invoiced"):
|
||||
set_invoiced(item, method, doc.name)
|
||||
|
||||
if method=='on_submit' and frappe.db.get_single_value('Healthcare Settings', 'create_lab_test_on_si_submit'):
|
||||
create_multiple('Sales Invoice', doc.name)
|
||||
if method == "on_submit" and frappe.db.get_single_value(
|
||||
"Healthcare Settings", "create_lab_test_on_si_submit"
|
||||
):
|
||||
create_multiple("Sales Invoice", doc.name)
|
||||
|
||||
|
||||
def set_invoiced(item, method, ref_invoice=None):
|
||||
invoiced = False
|
||||
if method=='on_submit':
|
||||
if method == "on_submit":
|
||||
validate_invoiced_on_submit(item)
|
||||
invoiced = True
|
||||
|
||||
if item.reference_dt == 'Clinical Procedure':
|
||||
service_item = frappe.db.get_single_value('Healthcare Settings', 'clinical_procedure_consumable_item')
|
||||
if item.reference_dt == "Clinical Procedure":
|
||||
service_item = frappe.db.get_single_value(
|
||||
"Healthcare Settings", "clinical_procedure_consumable_item"
|
||||
)
|
||||
if service_item == item.item_code:
|
||||
frappe.db.set_value(item.reference_dt, item.reference_dn, 'consumption_invoiced', invoiced)
|
||||
frappe.db.set_value(item.reference_dt, item.reference_dn, "consumption_invoiced", invoiced)
|
||||
else:
|
||||
frappe.db.set_value(item.reference_dt, item.reference_dn, 'invoiced', invoiced)
|
||||
frappe.db.set_value(item.reference_dt, item.reference_dn, "invoiced", invoiced)
|
||||
else:
|
||||
frappe.db.set_value(item.reference_dt, item.reference_dn, 'invoiced', invoiced)
|
||||
frappe.db.set_value(item.reference_dt, item.reference_dn, "invoiced", invoiced)
|
||||
|
||||
if item.reference_dt == 'Patient Appointment':
|
||||
if frappe.db.get_value('Patient Appointment', item.reference_dn, 'procedure_template'):
|
||||
dt_from_appointment = 'Clinical Procedure'
|
||||
if item.reference_dt == "Patient Appointment":
|
||||
if frappe.db.get_value("Patient Appointment", item.reference_dn, "procedure_template"):
|
||||
dt_from_appointment = "Clinical Procedure"
|
||||
else:
|
||||
dt_from_appointment = 'Patient Encounter'
|
||||
dt_from_appointment = "Patient Encounter"
|
||||
manage_doc_for_appointment(dt_from_appointment, item.reference_dn, invoiced)
|
||||
|
||||
elif item.reference_dt == 'Lab Prescription':
|
||||
manage_prescriptions(invoiced, item.reference_dt, item.reference_dn, 'Lab Test', 'lab_test_created')
|
||||
elif item.reference_dt == "Lab Prescription":
|
||||
manage_prescriptions(
|
||||
invoiced, item.reference_dt, item.reference_dn, "Lab Test", "lab_test_created"
|
||||
)
|
||||
|
||||
elif item.reference_dt == 'Procedure Prescription':
|
||||
manage_prescriptions(invoiced, item.reference_dt, item.reference_dn, 'Clinical Procedure', 'procedure_created')
|
||||
elif item.reference_dt == "Procedure Prescription":
|
||||
manage_prescriptions(
|
||||
invoiced, item.reference_dt, item.reference_dn, "Clinical Procedure", "procedure_created"
|
||||
)
|
||||
|
||||
|
||||
def validate_invoiced_on_submit(item):
|
||||
if item.reference_dt == 'Clinical Procedure' and \
|
||||
frappe.db.get_single_value('Healthcare Settings', 'clinical_procedure_consumable_item') == item.item_code:
|
||||
is_invoiced = frappe.db.get_value(item.reference_dt, item.reference_dn, 'consumption_invoiced')
|
||||
if (
|
||||
item.reference_dt == "Clinical Procedure"
|
||||
and frappe.db.get_single_value("Healthcare Settings", "clinical_procedure_consumable_item")
|
||||
== item.item_code
|
||||
):
|
||||
is_invoiced = frappe.db.get_value(item.reference_dt, item.reference_dn, "consumption_invoiced")
|
||||
else:
|
||||
is_invoiced = frappe.db.get_value(item.reference_dt, item.reference_dn, 'invoiced')
|
||||
is_invoiced = frappe.db.get_value(item.reference_dt, item.reference_dn, "invoiced")
|
||||
if is_invoiced:
|
||||
frappe.throw(_('The item referenced by {0} - {1} is already invoiced').format(
|
||||
item.reference_dt, item.reference_dn))
|
||||
frappe.throw(
|
||||
_("The item referenced by {0} - {1} is already invoiced").format(
|
||||
item.reference_dt, item.reference_dn
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def manage_prescriptions(invoiced, ref_dt, ref_dn, dt, created_check_field):
|
||||
created = frappe.db.get_value(ref_dt, ref_dn, created_check_field)
|
||||
if created:
|
||||
# Fetch the doc created for the prescription
|
||||
doc_created = frappe.db.get_value(dt, {'prescription': ref_dn})
|
||||
frappe.db.set_value(dt, doc_created, 'invoiced', invoiced)
|
||||
doc_created = frappe.db.get_value(dt, {"prescription": ref_dn})
|
||||
frappe.db.set_value(dt, doc_created, "invoiced", invoiced)
|
||||
|
||||
|
||||
def check_fee_validity(appointment):
|
||||
if not frappe.db.get_single_value('Healthcare Settings', 'enable_free_follow_ups'):
|
||||
if not frappe.db.get_single_value("Healthcare Settings", "enable_free_follow_ups"):
|
||||
return
|
||||
|
||||
validity = frappe.db.exists('Fee Validity', {
|
||||
'practitioner': appointment.practitioner,
|
||||
'patient': appointment.patient,
|
||||
'valid_till': ('>=', appointment.appointment_date)
|
||||
})
|
||||
validity = frappe.db.exists(
|
||||
"Fee Validity",
|
||||
{
|
||||
"practitioner": appointment.practitioner,
|
||||
"patient": appointment.patient,
|
||||
"valid_till": (">=", appointment.appointment_date),
|
||||
},
|
||||
)
|
||||
if not validity:
|
||||
return
|
||||
|
||||
validity = frappe.get_doc('Fee Validity', validity)
|
||||
validity = frappe.get_doc("Fee Validity", validity)
|
||||
return validity
|
||||
|
||||
|
||||
@@ -492,16 +578,14 @@ def manage_fee_validity(appointment):
|
||||
fee_validity = check_fee_validity(appointment)
|
||||
|
||||
if fee_validity:
|
||||
if appointment.status == 'Cancelled' and fee_validity.visited > 0:
|
||||
if appointment.status == "Cancelled" and fee_validity.visited > 0:
|
||||
fee_validity.visited -= 1
|
||||
frappe.db.delete('Fee Validity Reference', {'appointment': appointment.name})
|
||||
elif fee_validity.status == 'Completed':
|
||||
frappe.db.delete("Fee Validity Reference", {"appointment": appointment.name})
|
||||
elif fee_validity.status == "Completed":
|
||||
return
|
||||
else:
|
||||
fee_validity.visited += 1
|
||||
fee_validity.append('ref_appointments', {
|
||||
'appointment': appointment.name
|
||||
})
|
||||
fee_validity.append("ref_appointments", {"appointment": appointment.name})
|
||||
fee_validity.save(ignore_permissions=True)
|
||||
else:
|
||||
fee_validity = create_fee_validity(appointment)
|
||||
@@ -510,36 +594,33 @@ def manage_fee_validity(appointment):
|
||||
|
||||
def manage_doc_for_appointment(dt_from_appointment, appointment, invoiced):
|
||||
dn_from_appointment = frappe.db.get_value(
|
||||
dt_from_appointment,
|
||||
filters={'appointment': appointment}
|
||||
dt_from_appointment, filters={"appointment": appointment}
|
||||
)
|
||||
if dn_from_appointment:
|
||||
frappe.db.set_value(dt_from_appointment, dn_from_appointment, 'invoiced', invoiced)
|
||||
frappe.db.set_value(dt_from_appointment, dn_from_appointment, "invoiced", invoiced)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_drugs_to_invoice(encounter):
|
||||
encounter = frappe.get_doc('Patient Encounter', encounter)
|
||||
encounter = frappe.get_doc("Patient Encounter", encounter)
|
||||
if encounter:
|
||||
patient = frappe.get_doc('Patient', encounter.patient)
|
||||
patient = frappe.get_doc("Patient", encounter.patient)
|
||||
if patient:
|
||||
if patient.customer:
|
||||
items_to_invoice = []
|
||||
for drug_line in encounter.drug_prescription:
|
||||
if drug_line.drug_code:
|
||||
qty = 1
|
||||
if frappe.db.get_value('Item', drug_line.drug_code, 'stock_uom') == 'Nos':
|
||||
if frappe.db.get_value("Item", drug_line.drug_code, "stock_uom") == "Nos":
|
||||
qty = drug_line.get_quantity()
|
||||
|
||||
description = ''
|
||||
description = ""
|
||||
if drug_line.dosage and drug_line.period:
|
||||
description = _('{0} for {1}').format(drug_line.dosage, drug_line.period)
|
||||
description = _("{0} for {1}").format(drug_line.dosage, drug_line.period)
|
||||
|
||||
items_to_invoice.append({
|
||||
'drug_code': drug_line.drug_code,
|
||||
'quantity': qty,
|
||||
'description': description
|
||||
})
|
||||
items_to_invoice.append(
|
||||
{"drug_code": drug_line.drug_code, "quantity": qty, "description": description}
|
||||
)
|
||||
return items_to_invoice
|
||||
else:
|
||||
validate_customer_created(patient)
|
||||
@@ -547,52 +628,56 @@ def get_drugs_to_invoice(encounter):
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_children(doctype, parent=None, company=None, is_root=False):
|
||||
parent_fieldname = 'parent_' + doctype.lower().replace(' ', '_')
|
||||
fields = [
|
||||
'name as value',
|
||||
'is_group as expandable',
|
||||
'lft',
|
||||
'rgt'
|
||||
]
|
||||
parent_fieldname = "parent_" + doctype.lower().replace(" ", "_")
|
||||
fields = ["name as value", "is_group as expandable", "lft", "rgt"]
|
||||
|
||||
filters = [["ifnull(`{0}`,'')".format(parent_fieldname),
|
||||
'=', '' if is_root else parent]]
|
||||
filters = [["ifnull(`{0}`,'')".format(parent_fieldname), "=", "" if is_root else parent]]
|
||||
|
||||
if is_root:
|
||||
fields += ['service_unit_type'] if doctype == 'Healthcare Service Unit' else []
|
||||
filters.append(['company', '=', company])
|
||||
fields += ["service_unit_type"] if doctype == "Healthcare Service Unit" else []
|
||||
filters.append(["company", "=", company])
|
||||
else:
|
||||
fields += ['service_unit_type', 'allow_appointments', 'inpatient_occupancy',
|
||||
'occupancy_status'] if doctype == 'Healthcare Service Unit' else []
|
||||
fields += [parent_fieldname + ' as parent']
|
||||
fields += (
|
||||
["service_unit_type", "allow_appointments", "inpatient_occupancy", "occupancy_status"]
|
||||
if doctype == "Healthcare Service Unit"
|
||||
else []
|
||||
)
|
||||
fields += [parent_fieldname + " as parent"]
|
||||
|
||||
service_units = frappe.get_list(doctype, fields=fields, filters=filters)
|
||||
for each in service_units:
|
||||
if each['expandable'] == 1: # group node
|
||||
available_count = frappe.db.count('Healthcare Service Unit', filters={
|
||||
'parent_healthcare_service_unit': each['value'],
|
||||
'inpatient_occupancy': 1})
|
||||
if each["expandable"] == 1: # group node
|
||||
available_count = frappe.db.count(
|
||||
"Healthcare Service Unit",
|
||||
filters={"parent_healthcare_service_unit": each["value"], "inpatient_occupancy": 1},
|
||||
)
|
||||
|
||||
if available_count > 0:
|
||||
occupied_count = frappe.db.count('Healthcare Service Unit', {
|
||||
'parent_healthcare_service_unit': each['value'],
|
||||
'inpatient_occupancy': 1,
|
||||
'occupancy_status': 'Occupied'})
|
||||
occupied_count = frappe.db.count(
|
||||
"Healthcare Service Unit",
|
||||
{
|
||||
"parent_healthcare_service_unit": each["value"],
|
||||
"inpatient_occupancy": 1,
|
||||
"occupancy_status": "Occupied",
|
||||
},
|
||||
)
|
||||
# set occupancy status of group node
|
||||
each['occupied_of_available'] = str(
|
||||
occupied_count) + ' Occupied of ' + str(available_count)
|
||||
each["occupied_of_available"] = str(occupied_count) + " Occupied of " + str(available_count)
|
||||
|
||||
return service_units
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_patient_vitals(patient, from_date=None, to_date=None):
|
||||
if not patient: return
|
||||
if not patient:
|
||||
return
|
||||
|
||||
vitals = frappe.db.get_all('Vital Signs', filters={
|
||||
'docstatus': 1,
|
||||
'patient': patient
|
||||
}, order_by='signs_date, signs_time', fields=['*'])
|
||||
vitals = frappe.db.get_all(
|
||||
"Vital Signs",
|
||||
filters={"docstatus": 1, "patient": patient},
|
||||
order_by="signs_date, signs_time",
|
||||
fields=["*"],
|
||||
)
|
||||
|
||||
if len(vitals):
|
||||
return vitals
|
||||
@@ -604,14 +689,14 @@ def render_docs_as_html(docs):
|
||||
# docs key value pair {doctype: docname}
|
||||
docs_html = "<div class='col-md-12 col-sm-12 text-muted'>"
|
||||
for doc in docs:
|
||||
docs_html += render_doc_as_html(doc['doctype'], doc['docname'])['html'] + '<br/>'
|
||||
return {'html': docs_html}
|
||||
docs_html += render_doc_as_html(doc["doctype"], doc["docname"])["html"] + "<br/>"
|
||||
return {"html": docs_html}
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def render_doc_as_html(doctype, docname, exclude_fields = None):
|
||||
def render_doc_as_html(doctype, docname, exclude_fields=None):
|
||||
"""
|
||||
Render document as HTML
|
||||
Render document as HTML
|
||||
"""
|
||||
|
||||
doc = frappe.get_doc(doctype, docname)
|
||||
@@ -642,7 +727,9 @@ def render_doc_as_html(doctype, docname, exclude_fields = None):
|
||||
{1} {2}
|
||||
</div>
|
||||
</div>
|
||||
""".format(section_label, section_html, html)
|
||||
""".format(
|
||||
section_label, section_html, html
|
||||
)
|
||||
|
||||
# close divs for columns
|
||||
while col_on:
|
||||
@@ -672,7 +759,9 @@ def render_doc_as_html(doctype, docname, exclude_fields = None):
|
||||
<div class='col-md-4 col-sm-4'>
|
||||
{1}
|
||||
</div>
|
||||
""".format(section_label, html)
|
||||
""".format(
|
||||
section_label, html
|
||||
)
|
||||
elif col_on == 1 and has_data:
|
||||
section_html += "<div class='col-md-4 col-sm-4'>" + html + "</div>"
|
||||
elif col_on > 1 and has_data:
|
||||
@@ -684,7 +773,9 @@ def render_doc_as_html(doctype, docname, exclude_fields = None):
|
||||
{0}
|
||||
</div>
|
||||
</div>
|
||||
""".format(html)
|
||||
""".format(
|
||||
html
|
||||
)
|
||||
|
||||
html = ""
|
||||
col_on += 1
|
||||
@@ -726,21 +817,31 @@ def render_doc_as_html(doctype, docname, exclude_fields = None):
|
||||
<table class='table table-condensed bordered'>
|
||||
{0} {1}
|
||||
</table>
|
||||
""".format(table_head, table_row)
|
||||
""".format(
|
||||
table_head, table_row
|
||||
)
|
||||
else:
|
||||
html += """
|
||||
<table class='table table-condensed table-bordered'>
|
||||
{0} {1}
|
||||
</table>
|
||||
""".format(table_head, table_row)
|
||||
""".format(
|
||||
table_head, table_row
|
||||
)
|
||||
continue
|
||||
|
||||
# on any other field type add label and value to html
|
||||
if not df.hidden and not df.print_hide and doc.get(df.fieldname) and df.fieldname not in exclude_fields:
|
||||
if (
|
||||
not df.hidden
|
||||
and not df.print_hide
|
||||
and doc.get(df.fieldname)
|
||||
and df.fieldname not in exclude_fields
|
||||
):
|
||||
formatted_value = format_value(doc.get(df.fieldname), meta.get_field(df.fieldname), doc)
|
||||
html += "<br>{0} : {1}".format(df.label or df.fieldname, formatted_value)
|
||||
|
||||
if not has_data : has_data = True
|
||||
if not has_data:
|
||||
has_data = True
|
||||
|
||||
if sec_on and col_on and has_data:
|
||||
doc_html += section_html + html + "</div></div>"
|
||||
@@ -751,49 +852,53 @@ def render_doc_as_html(doctype, docname, exclude_fields = None):
|
||||
{0} {1}
|
||||
</div>
|
||||
</div>
|
||||
""".format(section_html, html)
|
||||
""".format(
|
||||
section_html, html
|
||||
)
|
||||
|
||||
return {"html": doc_html}
|
||||
|
||||
|
||||
def update_address_links(address, method):
|
||||
'''
|
||||
"""
|
||||
Hook validate Address
|
||||
If Patient is linked in Address, also link the associated Customer
|
||||
'''
|
||||
if 'Healthcare' not in frappe.get_active_domains():
|
||||
"""
|
||||
if "Healthcare" not in frappe.get_active_domains():
|
||||
return
|
||||
|
||||
patient_links = list(filter(lambda link: link.get('link_doctype') == 'Patient', address.links))
|
||||
patient_links = list(filter(lambda link: link.get("link_doctype") == "Patient", address.links))
|
||||
|
||||
for link in patient_links:
|
||||
customer = frappe.db.get_value('Patient', link.get('link_name'), 'customer')
|
||||
if customer and not address.has_link('Customer', customer):
|
||||
address.append('links', dict(link_doctype = 'Customer', link_name = customer))
|
||||
customer = frappe.db.get_value("Patient", link.get("link_name"), "customer")
|
||||
if customer and not address.has_link("Customer", customer):
|
||||
address.append("links", dict(link_doctype="Customer", link_name=customer))
|
||||
|
||||
|
||||
def update_patient_email_and_phone_numbers(contact, method):
|
||||
'''
|
||||
"""
|
||||
Hook validate Contact
|
||||
Update linked Patients' primary mobile and phone numbers
|
||||
'''
|
||||
if 'Healthcare' not in frappe.get_active_domains() or contact.flags.skip_patient_update:
|
||||
"""
|
||||
if "Healthcare" not in frappe.get_active_domains() or contact.flags.skip_patient_update:
|
||||
return
|
||||
|
||||
if contact.is_primary_contact and (contact.email_id or contact.mobile_no or contact.phone):
|
||||
patient_links = list(filter(lambda link: link.get('link_doctype') == 'Patient', contact.links))
|
||||
patient_links = list(filter(lambda link: link.get("link_doctype") == "Patient", contact.links))
|
||||
|
||||
for link in patient_links:
|
||||
contact_details = frappe.db.get_value('Patient', link.get('link_name'), ['email', 'mobile', 'phone'], as_dict=1)
|
||||
contact_details = frappe.db.get_value(
|
||||
"Patient", link.get("link_name"), ["email", "mobile", "phone"], as_dict=1
|
||||
)
|
||||
|
||||
new_contact_details = {}
|
||||
|
||||
if contact.email_id and contact.email_id != contact_details.get('email'):
|
||||
new_contact_details.update({'email': contact.email_id})
|
||||
if contact.mobile_no and contact.mobile_no != contact_details.get('mobile'):
|
||||
new_contact_details.update({'mobile': contact.mobile_no})
|
||||
if contact.phone and contact.phone != contact_details.get('phone'):
|
||||
new_contact_details.update({'phone': contact.phone})
|
||||
if contact.email_id and contact.email_id != contact_details.get("email"):
|
||||
new_contact_details.update({"email": contact.email_id})
|
||||
if contact.mobile_no and contact.mobile_no != contact_details.get("mobile"):
|
||||
new_contact_details.update({"mobile": contact.mobile_no})
|
||||
if contact.phone and contact.phone != contact_details.get("phone"):
|
||||
new_contact_details.update({"phone": contact.phone})
|
||||
|
||||
if new_contact_details:
|
||||
frappe.db.set_value('Patient', link.get('link_name'), new_contact_details)
|
||||
frappe.db.set_value("Patient", link.get("link_name"), new_contact_details)
|
||||
|
||||
@@ -1,22 +1,31 @@
|
||||
|
||||
import frappe
|
||||
|
||||
|
||||
def get_context(context):
|
||||
context.read_only = 1
|
||||
|
||||
|
||||
def get_list_context(context):
|
||||
context.row_template = "erpnext/templates/includes/healthcare/lab_test_row_template.html"
|
||||
context.get_list = get_lab_test_list
|
||||
|
||||
def get_lab_test_list(doctype, txt, filters, limit_start, limit_page_length = 20, order_by='modified desc'):
|
||||
|
||||
def get_lab_test_list(
|
||||
doctype, txt, filters, limit_start, limit_page_length=20, order_by="modified desc"
|
||||
):
|
||||
patient = get_patient()
|
||||
lab_tests = frappe.db.sql("""select * from `tabLab Test`
|
||||
where patient = %s order by result_date""", patient, as_dict = True)
|
||||
lab_tests = frappe.db.sql(
|
||||
"""select * from `tabLab Test`
|
||||
where patient = %s order by result_date""",
|
||||
patient,
|
||||
as_dict=True,
|
||||
)
|
||||
return lab_tests
|
||||
|
||||
|
||||
def get_patient():
|
||||
return frappe.get_value("Patient",{"email": frappe.session.user}, "name")
|
||||
return frappe.get_value("Patient", {"email": frappe.session.user}, "name")
|
||||
|
||||
|
||||
def has_website_permission(doc, ptype, user, verbose=False):
|
||||
if doc.patient == get_patient():
|
||||
|
||||
@@ -1,22 +1,31 @@
|
||||
|
||||
import frappe
|
||||
|
||||
|
||||
def get_context(context):
|
||||
context.read_only = 1
|
||||
|
||||
|
||||
def get_list_context(context):
|
||||
context.row_template = "erpnext/templates/includes/healthcare/appointment_row_template.html"
|
||||
context.get_list = get_appointment_list
|
||||
|
||||
def get_appointment_list(doctype, txt, filters, limit_start, limit_page_length = 20, order_by='modified desc'):
|
||||
|
||||
def get_appointment_list(
|
||||
doctype, txt, filters, limit_start, limit_page_length=20, order_by="modified desc"
|
||||
):
|
||||
patient = get_patient()
|
||||
lab_tests = frappe.db.sql("""select * from `tabPatient Appointment`
|
||||
where patient = %s and (status = 'Open' or status = 'Scheduled') order by appointment_date""", patient, as_dict = True)
|
||||
lab_tests = frappe.db.sql(
|
||||
"""select * from `tabPatient Appointment`
|
||||
where patient = %s and (status = 'Open' or status = 'Scheduled') order by appointment_date""",
|
||||
patient,
|
||||
as_dict=True,
|
||||
)
|
||||
return lab_tests
|
||||
|
||||
|
||||
def get_patient():
|
||||
return frappe.get_value("Patient",{"email": frappe.session.user}, "name")
|
||||
return frappe.get_value("Patient", {"email": frappe.session.user}, "name")
|
||||
|
||||
|
||||
def has_website_permission(doc, ptype, user, verbose=False):
|
||||
if doc.patient == get_patient():
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
def get_context(context):
|
||||
# do your magic here
|
||||
pass
|
||||
|
||||
@@ -1,23 +1,25 @@
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
|
||||
no_cache = 1
|
||||
|
||||
|
||||
def get_context(context):
|
||||
if frappe.session.user=='Guest':
|
||||
if frappe.session.user == "Guest":
|
||||
frappe.throw(_("You need to be logged in to access this page"), frappe.PermissionError)
|
||||
|
||||
context.show_sidebar=True
|
||||
context.show_sidebar = True
|
||||
|
||||
if frappe.db.exists("Patient", {'email': frappe.session.user}):
|
||||
patient = frappe.get_doc("Patient", {'email': frappe.session.user})
|
||||
if frappe.db.exists("Patient", {"email": frappe.session.user}):
|
||||
patient = frappe.get_doc("Patient", {"email": frappe.session.user})
|
||||
context.doc = patient
|
||||
frappe.form_dict.new = 0
|
||||
frappe.form_dict.name = patient.name
|
||||
|
||||
|
||||
def get_patient():
|
||||
return frappe.get_value("Patient",{"email": frappe.session.user}, "name")
|
||||
return frappe.get_value("Patient", {"email": frappe.session.user}, "name")
|
||||
|
||||
|
||||
def has_website_permission(doc, ptype, user, verbose=False):
|
||||
if doc.name == get_patient():
|
||||
|
||||
@@ -1,22 +1,31 @@
|
||||
|
||||
import frappe
|
||||
|
||||
|
||||
def get_context(context):
|
||||
context.read_only = 1
|
||||
|
||||
|
||||
def get_list_context(context):
|
||||
context.row_template = "erpnext/templates/includes/healthcare/prescription_row_template.html"
|
||||
context.get_list = get_encounter_list
|
||||
|
||||
def get_encounter_list(doctype, txt, filters, limit_start, limit_page_length = 20, order_by='modified desc'):
|
||||
|
||||
def get_encounter_list(
|
||||
doctype, txt, filters, limit_start, limit_page_length=20, order_by="modified desc"
|
||||
):
|
||||
patient = get_patient()
|
||||
encounters = frappe.db.sql("""select * from `tabPatient Encounter`
|
||||
where patient = %s order by creation desc""", patient, as_dict = True)
|
||||
encounters = frappe.db.sql(
|
||||
"""select * from `tabPatient Encounter`
|
||||
where patient = %s order by creation desc""",
|
||||
patient,
|
||||
as_dict=True,
|
||||
)
|
||||
return encounters
|
||||
|
||||
|
||||
def get_patient():
|
||||
return frappe.get_value("Patient",{"email": frappe.session.user}, "name")
|
||||
return frappe.get_value("Patient", {"email": frappe.session.user}, "name")
|
||||
|
||||
|
||||
def has_website_permission(doc, ptype, user, verbose=False):
|
||||
if doc.patient == get_patient():
|
||||
|
||||
Reference in New Issue
Block a user