style: bulk format code with black

v13 port because otherwise backports will result in conflicts always
This commit is contained in:
Ankush Menat
2022-03-29 17:29:34 +05:30
parent 7cc84dcbb4
commit c07713b860
1555 changed files with 96709 additions and 66138 deletions

View File

@@ -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",
}

View File

@@ -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)

View File

@@ -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"]},
],
}

View File

@@ -5,5 +5,6 @@ import unittest
# test_records = frappe.get_test_records('Appointment Type')
class TestAppointmentType(unittest.TestCase):
pass

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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"]}],
}

View File

@@ -5,5 +5,6 @@ import unittest
# test_records = frappe.get_test_records('Diagnosis')
class TestDiagnosis(unittest.TestCase):
pass

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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`""")

View File

@@ -1,5 +1,3 @@
def get_data():
return []

View File

@@ -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,
)

View File

@@ -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"]},
],
}

View File

@@ -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

View File

@@ -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)

View File

@@ -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"]},
],
}

View File

@@ -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()

View File

@@ -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"
)

View File

@@ -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

View File

@@ -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"]}],
}

View File

@@ -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

View File

@@ -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]

View File

@@ -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()

View File

@@ -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},
)

View File

@@ -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"],
},
],
}

View File

@@ -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

View File

@@ -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),
)

View File

@@ -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)

View File

@@ -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

View File

@@ -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"]}],
}

View File

@@ -5,5 +5,6 @@ import unittest
# test_records = frappe.get_test_records('Lab Test Template')
class TestLabTestTemplate(unittest.TestCase):
pass

View File

@@ -5,5 +5,6 @@ import unittest
# test_records = frappe.get_test_records('Lab Test UOM')
class TestLabTestUOM(unittest.TestCase):
pass

View File

@@ -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

View File

@@ -5,5 +5,6 @@ import unittest
# test_records = frappe.get_test_records('Medical Department')
class TestMedicalDepartment(unittest.TestCase):
pass

View File

@@ -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

View File

@@ -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"]},
],
}

View File

@@ -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)

View File

@@ -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()

View File

@@ -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"],
}
]
],
}

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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"],
}

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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()

View File

@@ -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

View File

@@ -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"))

View File

@@ -5,5 +5,6 @@ import unittest
# test_records = frappe.get_test_records('Sample Collection')
class TestSampleCollection(unittest.TestCase):
pass

View File

@@ -5,5 +5,6 @@ import unittest
# test_records = frappe.get_test_records('Sensitivity')
class TestSensitivity(unittest.TestCase):
pass

View File

@@ -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

View File

@@ -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

View File

@@ -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"],
}

View File

@@ -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

View File

@@ -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"]}],
}

View File

@@ -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

View File

@@ -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"]}],
}

View File

@@ -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

View File

@@ -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

View File

@@ -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"))

View File

@@ -5,5 +5,6 @@ import unittest
# test_records = frappe.get_test_records('Vital Signs')
class TestVitalSigns(unittest.TestCase):
pass

View File

@@ -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]

View File

@@ -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

View File

@@ -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)

View File

@@ -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"

View File

@@ -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)

View File

@@ -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",
},
]

View File

@@ -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"}

View File

@@ -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"},
],
),
}

View File

@@ -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)

View File

@@ -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():

View File

@@ -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():

View File

@@ -1,5 +1,3 @@
def get_context(context):
# do your magic here
pass

View File

@@ -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():

View File

@@ -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():