Skip to content

Commit

Permalink
fix(Observation): observation results based on calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
akashkrishna619 committed Apr 25, 2024
1 parent 9258c1c commit 4a41a44
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 4 deletions.
121 changes: 120 additions & 1 deletion healthcare/healthcare/doctype/observation/observation.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from frappe import _
from frappe.model.document import Document
from frappe.model.workflow import get_workflow_name, get_workflow_state_field
from frappe.utils import now_datetime
from frappe.utils import flt, get_link_to_form, getdate, now_datetime, nowdate

from erpnext.setup.doctype.terms_and_conditions.terms_and_conditions import (
get_terms_and_conditions,
Expand All @@ -25,6 +25,12 @@ def validate(self):

def on_update(self):
set_diagnostic_report_status(self)
if (
self.parent_observation
and self.result_data
and self.permitted_data_type in ["Quantity", "Numeric"]
):
set_calculated_result(self)

def before_insert(self):
set_observation_idx(self)
Expand Down Expand Up @@ -482,3 +488,116 @@ def set_diagnostic_report_status(doc):
frappe.db.set_value(
"Diagnostic Report", diagnostic_report.get("name"), set_value_dict, update_modified=False
)


def set_calculated_result(doc):
if doc.parent_observation:
parent_template = frappe.db.get_value(
"Observation", doc.parent_observation, "observation_template"
)
parent_template_doc = frappe.get_cached_doc("Observation Template", parent_template)

data = frappe._dict()
patient_doc = frappe.get_cached_doc("Patient", doc.patient).as_dict()
settings = frappe.get_cached_doc("Healthcare Settings").as_dict()

data.update(doc.as_dict())
data.update(parent_template_doc.as_dict())
data.update(patient_doc)
data.update(settings)

for component in parent_template_doc.observation_component:
"""
Data retrieval from observations has been moved into the loop
to accommodate component observations, which may contain formulas
utilizing results from previous iterations.
"""
if component.based_on_formula and component.formula:
obs_data = get_data(doc, parent_template_doc)
else:
continue

if obs_data and len(obs_data) > 0:
data.update(obs_data)
result = eval_condition_and_formula(component, data)
if not result:
continue

result_observation_name, result_data = frappe.db.get_value(
"Observation",
{
"parent_observation": doc.parent_observation,
"observation_template": component.get("observation_template"),
},
["name", "result_data"],
)
if result_observation_name and result_data != str(result):
frappe.db.set_value(
"Observation",
result_observation_name,
"result_data",
str(result),
)


def get_data(doc, parent_template_doc):
data = frappe._dict()
observation_details = frappe.get_all(
"Observation",
{"parent_observation": doc.parent_observation},
["observation_template", "result_data"],
)

# to get all result_data to map against abbs of all table rows
for component in parent_template_doc.observation_component:
result = [
d["result_data"]
for d in observation_details
if (d["observation_template"] == component.get("observation_template") and d["result_data"])
]
data[component.get("abbr")] = flt(result[0]) if (result and len(result) > 0 and result[0]) else 0
return data


def eval_condition_and_formula(d, data):
try:
if d.get("condition"):
cond = d.get("condition")
parts = cond.strip().splitlines()
condition = " ".join(parts)
if condition:
if not frappe.safe_eval(condition, data):
return None

if d.based_on_formula:
amount = None
formula = d.formula.strip().replace("\n", " ") if d.formula else None
operands = re.split(r"\W+", formula)
abbrs = [operand for operand in operands if re.search(r"[a-zA-Z]", operand)]
if "age" in abbrs and data.get("dob"):
age = (
getdate(nowdate()).year
- data.get("dob").year
- (
(getdate(nowdate()).month, getdate(nowdate()).day)
< (data.get("dob").month, data.get("dob").day)
)
)
if age > 0:
data["age"] = age

# check the formula abbrs has result value
abbrs_present = all(abbr in data and data[abbr] != 0 for abbr in abbrs)
if formula and abbrs_present:
amount = flt(frappe.safe_eval(formula, {}, data))

return amount

except Exception as err:
description = _("This error can be due to invalid formula.")
message = _(
"""Error while evaluating the {0} {1} at row {2}. <br><br> <b>Error:</b> {3}
<br><br> <b>Hint:</b> {4}"""
).format(d.parenttype, get_link_to_form(d.parenttype, d.parent), d.idx, err, description)
frappe.throw(message, title=_("Error in formula"))
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
"field_order": [
"observation_template",
"abbr",
"condition",
"column_break_seht",
"based_on_formula",
"formula"
"formula",
"note"
],
"fields": [
{
Expand All @@ -30,7 +32,7 @@
"fieldname": "based_on_formula",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Based On Formula"
"label": "Based on Condition and Formula"
},
{
"depends_on": "based_on_formula",
Expand All @@ -47,12 +49,24 @@
"in_list_view": 1,
"label": "Abbr",
"read_only": 1
},
{
"depends_on": "based_on_formula",
"fieldname": "condition",
"fieldtype": "Code",
"label": "Condition"
},
{
"depends_on": "based_on_formula",
"fieldname": "note",
"fieldtype": "HTML",
"options": "<p>Notes:</p>\n\n<ol>\n<li>Keywords Available : \n<code>age</code></li>\n<li>Tables Available : <code>Patient, Healthcare Settings, Observation, Observation Template</code></li>\n</ol>"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2023-07-16 19:13:13.918443",
"modified": "2024-04-09 11:52:55.556596",
"modified_by": "Administrator",
"module": "Healthcare",
"name": "Observation Component",
Expand Down

0 comments on commit 4a41a44

Please sign in to comment.