Skip to content

Commit

Permalink
feat: add patient_filter to base effect's payload (#192)
Browse files Browse the repository at this point in the history
  • Loading branch information
mbiannaccone authored Nov 19, 2024
1 parent 5e139c8 commit 1757447
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 21 deletions.
21 changes: 12 additions & 9 deletions canvas_sdk/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,18 @@ def _get_error_details(self, method: Any) -> list[InitErrorDetails]:
class_name = self.__repr_name__() # type: ignore[misc]

class_name_article = "an" if class_name.startswith(("A", "E", "I", "O", "U")) else "a"
return [
self._create_error_detail(
"missing",
f"Field '{field}' is required to {method.replace('_', ' ')} {class_name_article} {class_name}",
v,
)
for field in required_fields
if (v := getattr(self, field)) is None
]

error_details = []
for field in required_fields:
fields = field.split("|")
if not all(getattr(self, f) is None for f in fields):
continue
field_description = " or ".join([f"'{f}'" for f in fields])
message = f"Field {field_description} is required to {method.replace('_', ' ')} {class_name_article} {class_name}"
error = self._create_error_detail("missing", message, None)
error_details.append(error)

return error_details

def _validate_before_effect(self, method: str) -> None:
self.model_validate(self)
Expand Down
15 changes: 13 additions & 2 deletions canvas_sdk/effects/banner_alert/add_banner_alert.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ class AddBannerAlert(_BaseEffect):

class Meta:
effect_type = EffectType.ADD_BANNER_ALERT
apply_required_fields = ("patient_id", "key", "narrative", "placement", "intent")
apply_required_fields = (
"patient_id|patient_filter",
"key",
"narrative",
"placement",
"intent",
)

class Placement(Enum):
CHART = "chart"
Expand Down Expand Up @@ -47,4 +53,9 @@ def values(self) -> dict[str, Any]:
@property
def effect_payload(self) -> dict[str, Any]:
"""The payload of the effect."""
return {"patient": self.patient_id, "key": self.key, "data": self.values}
return {
"patient": self.patient_id,
"patient_filter": self.patient_filter,
"key": self.key,
"data": self.values,
}
4 changes: 2 additions & 2 deletions canvas_sdk/effects/banner_alert/remove_banner_alert.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ class RemoveBannerAlert(_BaseEffect):

class Meta:
effect_type = EffectType.REMOVE_BANNER_ALERT
apply_required_fields = ("patient_id", "key")
apply_required_fields = ("patient_id|patient_filter", "key")

patient_id: str | None = None
key: str | None = None

@property
def effect_payload(self) -> dict[str, Any]:
"""The payload of the effect."""
return {"patient": self.patient_id, "key": self.key}
return {"patient": self.patient_id, "patient_filter": self.patient_filter, "key": self.key}
24 changes: 20 additions & 4 deletions canvas_sdk/effects/banner_alert/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,12 +178,28 @@ def test_protocol_that_adds_banner_alert(
"placement": [AddBannerAlert.Placement.APPOINTMENT_CARD],
"intent": AddBannerAlert.Intent.INFO,
},
'{"patient": "uuid", "key": "test-key", "data": {"narrative": "hellooo", "placement": ["appointment_card"], "intent": "info", "href": null}}',
'{"patient": "uuid", "patient_filter": null, "key": "test-key", "data": {"narrative": "hellooo", "placement": ["appointment_card"], "intent": "info", "href": null}}',
),
(
AddBannerAlert,
{
"patient_filter": {"active": True},
"key": "test-key",
"narrative": "hellooo",
"placement": [AddBannerAlert.Placement.APPOINTMENT_CARD],
"intent": AddBannerAlert.Intent.INFO,
},
'{"patient": null, "patient_filter": {"active": true}, "key": "test-key", "data": {"narrative": "hellooo", "placement": ["appointment_card"], "intent": "info", "href": null}}',
),
(
RemoveBannerAlert,
{"patient_id": "uuid", "key": "testeroo"},
'{"patient": "uuid", "key": "testeroo"}',
'{"patient": "uuid", "patient_filter": null, "key": "testeroo"}',
),
(
RemoveBannerAlert,
{"patient_filter": {"active": True}, "key": "testeroo"},
'{"patient": null, "patient_filter": {"active": true}, "key": "testeroo"}',
),
],
)
Expand All @@ -204,7 +220,7 @@ def test_banner_alert_apply_method_succeeds_with_all_required_fields(
AddBannerAlert,
[
"5 validation errors for AddBannerAlert",
"Field 'patient_id' is required to apply an AddBannerAlert [type=missing",
"Field 'patient_id' or 'patient_filter' is required to apply an AddBannerAlert [type=missing",
"Field 'key' is required to apply an AddBannerAlert [type=missing",
"Field 'narrative' is required to apply an AddBannerAlert [type=missing",
"Field 'placement' is required to apply an AddBannerAlert [type=missing",
Expand All @@ -215,7 +231,7 @@ def test_banner_alert_apply_method_succeeds_with_all_required_fields(
RemoveBannerAlert,
[
"2 validation errors for RemoveBannerAlert",
"Field 'patient_id' is required to apply a RemoveBannerAlert [type=missing",
"Field 'patient_id' or 'patient_filter' is required to apply a RemoveBannerAlert [type=missing",
"Field 'key' is required to apply a RemoveBannerAlert [type=missing",
],
),
Expand Down
2 changes: 2 additions & 0 deletions canvas_sdk/effects/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ class _BaseEffect(Model):
A Canvas Effect that changes user behavior or autonomously performs activities on behalf of users.
"""

patient_filter: dict | None = None

class Meta:
effect_type = EffectType.UNKNOWN_EFFECT

Expand Down
9 changes: 7 additions & 2 deletions canvas_sdk/effects/protocol_card/protocol_card.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class Status(Enum):

class Meta:
effect_type = EffectType.ADD_OR_UPDATE_PROTOCOL_CARD
apply_required_fields = ("patient_id", "key")
apply_required_fields = ("patient_id|patient_filter", "key")

patient_id: str | None = None
key: str | None = None
Expand All @@ -68,7 +68,12 @@ def values(self) -> dict[str, Any]:
@property
def effect_payload(self) -> dict[str, Any]:
"""The payload of the effect."""
return {"patient": self.patient_id, "key": self.key, "data": self.values}
return {
"patient": self.patient_id,
"patient_filter": self.patient_filter,
"key": self.key,
"data": self.values,
}

def add_recommendation(
self,
Expand Down
4 changes: 2 additions & 2 deletions canvas_sdk/effects/protocol_card/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def test_apply_method_succeeds_with_patient_id_and_key() -> None:
applied = p.apply()
assert (
applied.payload
== '{"patient": "uuid", "key": "something-unique", "data": {"title": "", "narrative": "", "recommendations": [], "status": "due", "feedback_enabled": false}}'
== '{"patient": "uuid", "patient_filter": null, "key": "something-unique", "data": {"title": "", "narrative": "", "recommendations": [], "status": "due", "feedback_enabled": false}}'
)


Expand All @@ -38,7 +38,7 @@ def test_apply_method_raises_error_without_patient_id_and_key() -> None:

assert "2 validation errors for ProtocolCard" in err_msg
assert (
"Field 'patient_id' is required to apply a ProtocolCard [type=missing, input_value=None, input_type=NoneType]"
"Field 'patient_id' or 'patient_filter' is required to apply a ProtocolCard [type=missing, input_value=None, input_type=NoneType]"
in err_msg
)
assert (
Expand Down

0 comments on commit 1757447

Please sign in to comment.