Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add many command origination effects. #63

Merged
merged 10 commits into from
Jul 3, 2024
4 changes: 2 additions & 2 deletions canvas_generated/messages/effects_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

110 changes: 110 additions & 0 deletions canvas_generated/messages/effects_pb2.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,122 @@ class EffectType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
AUTOCOMPLETE_SEARCH_RESULTS: _ClassVar[EffectType]
ADD_BANNER_ALERT: _ClassVar[EffectType]
REMOVE_BANNER_ALERT: _ClassVar[EffectType]
ORIGINATE_ASSESS_COMMAND: _ClassVar[EffectType]
EDIT_ASSESS_COMMAND: _ClassVar[EffectType]
DELETE_ASSESS_COMMAND: _ClassVar[EffectType]
COMMIT_ASSESS_COMMAND: _ClassVar[EffectType]
ENTER_IN_ERROR_ASSESS_COMMAND: _ClassVar[EffectType]
ORIGINATE_DIAGNOSE_COMMAND: _ClassVar[EffectType]
EDIT_DIAGNOSE_COMMAND: _ClassVar[EffectType]
DELETE_DIAGNOSE_COMMAND: _ClassVar[EffectType]
COMMIT_DIAGNOSE_COMMAND: _ClassVar[EffectType]
ENTER_IN_ERROR_DIAGNOSE_COMMAND: _ClassVar[EffectType]
ORIGINATE_GOAL_COMMAND: _ClassVar[EffectType]
EDIT_GOAL_COMMAND: _ClassVar[EffectType]
DELETE_GOAL_COMMAND: _ClassVar[EffectType]
COMMIT_GOAL_COMMAND: _ClassVar[EffectType]
ENTER_IN_ERROR_GOAL_COMMAND: _ClassVar[EffectType]
ORIGINATE_HPI_COMMAND: _ClassVar[EffectType]
EDIT_HPI_COMMAND: _ClassVar[EffectType]
DELETE_HPI_COMMAND: _ClassVar[EffectType]
COMMIT_HPI_COMMAND: _ClassVar[EffectType]
ENTER_IN_ERROR_HPI_COMMAND: _ClassVar[EffectType]
ORIGINATE_MEDICATION_STATEMENT_COMMAND: _ClassVar[EffectType]
EDIT_MEDICATION_STATEMENT_COMMAND: _ClassVar[EffectType]
DELETE_MEDICATION_STATEMENT_COMMAND: _ClassVar[EffectType]
COMMIT_MEDICATION_STATEMENT_COMMAND: _ClassVar[EffectType]
ENTER_IN_ERROR_MEDICATION_STATEMENT_COMMAND: _ClassVar[EffectType]
ORIGINATE_PLAN_COMMAND: _ClassVar[EffectType]
EDIT_PLAN_COMMAND: _ClassVar[EffectType]
DELETE_PLAN_COMMAND: _ClassVar[EffectType]
COMMIT_PLAN_COMMAND: _ClassVar[EffectType]
ENTER_IN_ERROR_PLAN_COMMAND: _ClassVar[EffectType]
ORIGINATE_PRESCRIBE_COMMAND: _ClassVar[EffectType]
EDIT_PRESCRIBE_COMMAND: _ClassVar[EffectType]
DELETE_PRESCRIBE_COMMAND: _ClassVar[EffectType]
COMMIT_PRESCRIBE_COMMAND: _ClassVar[EffectType]
ENTER_IN_ERROR_PRESCRIBE_COMMAND: _ClassVar[EffectType]
ORIGINATE_QUESTIONNAIRE_COMMAND: _ClassVar[EffectType]
EDIT_QUESTIONNAIRE_COMMAND: _ClassVar[EffectType]
DELETE_QUESTIONNAIRE_COMMAND: _ClassVar[EffectType]
COMMIT_QUESTIONNAIRE_COMMAND: _ClassVar[EffectType]
ENTER_IN_ERROR_QUESTIONNAIRE_COMMAND: _ClassVar[EffectType]
ORIGINATE_REASON_FOR_VISIT_COMMAND: _ClassVar[EffectType]
EDIT_REASON_FOR_VISIT_COMMAND: _ClassVar[EffectType]
DELETE_REASON_FOR_VISIT_COMMAND: _ClassVar[EffectType]
COMMIT_REASON_FOR_VISIT_COMMAND: _ClassVar[EffectType]
ENTER_IN_ERROR_REASON_FOR_VISIT_COMMAND: _ClassVar[EffectType]
ORIGINATE_STOP_MEDICATION_COMMAND: _ClassVar[EffectType]
EDIT_STOP_MEDICATION_COMMAND: _ClassVar[EffectType]
DELETE_STOP_MEDICATION_COMMAND: _ClassVar[EffectType]
COMMIT_STOP_MEDICATION_COMMAND: _ClassVar[EffectType]
ENTER_IN_ERROR_STOP_MEDICATION_COMMAND: _ClassVar[EffectType]
ORIGINATE_UPDATE_GOAL_COMMAND: _ClassVar[EffectType]
EDIT_UPDATE_GOAL_COMMAND: _ClassVar[EffectType]
DELETE_UPDATE_GOAL_COMMAND: _ClassVar[EffectType]
COMMIT_UPDATE_GOAL_COMMAND: _ClassVar[EffectType]
ENTER_IN_ERROR_UPDATE_GOAL_COMMAND: _ClassVar[EffectType]
UNKNOWN_EFFECT: EffectType
LOG: EffectType
ADD_PLAN_COMMAND: EffectType
AUTOCOMPLETE_SEARCH_RESULTS: EffectType
ADD_BANNER_ALERT: EffectType
REMOVE_BANNER_ALERT: EffectType
ORIGINATE_ASSESS_COMMAND: EffectType
EDIT_ASSESS_COMMAND: EffectType
DELETE_ASSESS_COMMAND: EffectType
COMMIT_ASSESS_COMMAND: EffectType
ENTER_IN_ERROR_ASSESS_COMMAND: EffectType
ORIGINATE_DIAGNOSE_COMMAND: EffectType
EDIT_DIAGNOSE_COMMAND: EffectType
DELETE_DIAGNOSE_COMMAND: EffectType
COMMIT_DIAGNOSE_COMMAND: EffectType
ENTER_IN_ERROR_DIAGNOSE_COMMAND: EffectType
ORIGINATE_GOAL_COMMAND: EffectType
EDIT_GOAL_COMMAND: EffectType
DELETE_GOAL_COMMAND: EffectType
COMMIT_GOAL_COMMAND: EffectType
ENTER_IN_ERROR_GOAL_COMMAND: EffectType
ORIGINATE_HPI_COMMAND: EffectType
EDIT_HPI_COMMAND: EffectType
DELETE_HPI_COMMAND: EffectType
COMMIT_HPI_COMMAND: EffectType
ENTER_IN_ERROR_HPI_COMMAND: EffectType
ORIGINATE_MEDICATION_STATEMENT_COMMAND: EffectType
EDIT_MEDICATION_STATEMENT_COMMAND: EffectType
DELETE_MEDICATION_STATEMENT_COMMAND: EffectType
COMMIT_MEDICATION_STATEMENT_COMMAND: EffectType
ENTER_IN_ERROR_MEDICATION_STATEMENT_COMMAND: EffectType
ORIGINATE_PLAN_COMMAND: EffectType
EDIT_PLAN_COMMAND: EffectType
DELETE_PLAN_COMMAND: EffectType
COMMIT_PLAN_COMMAND: EffectType
ENTER_IN_ERROR_PLAN_COMMAND: EffectType
ORIGINATE_PRESCRIBE_COMMAND: EffectType
EDIT_PRESCRIBE_COMMAND: EffectType
DELETE_PRESCRIBE_COMMAND: EffectType
COMMIT_PRESCRIBE_COMMAND: EffectType
ENTER_IN_ERROR_PRESCRIBE_COMMAND: EffectType
ORIGINATE_QUESTIONNAIRE_COMMAND: EffectType
EDIT_QUESTIONNAIRE_COMMAND: EffectType
DELETE_QUESTIONNAIRE_COMMAND: EffectType
COMMIT_QUESTIONNAIRE_COMMAND: EffectType
ENTER_IN_ERROR_QUESTIONNAIRE_COMMAND: EffectType
ORIGINATE_REASON_FOR_VISIT_COMMAND: EffectType
EDIT_REASON_FOR_VISIT_COMMAND: EffectType
DELETE_REASON_FOR_VISIT_COMMAND: EffectType
COMMIT_REASON_FOR_VISIT_COMMAND: EffectType
ENTER_IN_ERROR_REASON_FOR_VISIT_COMMAND: EffectType
ORIGINATE_STOP_MEDICATION_COMMAND: EffectType
EDIT_STOP_MEDICATION_COMMAND: EffectType
DELETE_STOP_MEDICATION_COMMAND: EffectType
COMMIT_STOP_MEDICATION_COMMAND: EffectType
ENTER_IN_ERROR_STOP_MEDICATION_COMMAND: EffectType
ORIGINATE_UPDATE_GOAL_COMMAND: EffectType
EDIT_UPDATE_GOAL_COMMAND: EffectType
DELETE_UPDATE_GOAL_COMMAND: EffectType
COMMIT_UPDATE_GOAL_COMMAND: EffectType
ENTER_IN_ERROR_UPDATE_GOAL_COMMAND: EffectType

class Effect(_message.Message):
__slots__ = ("type", "payload", "plugin_name")
Expand Down
44 changes: 25 additions & 19 deletions canvas_sdk/commands/base.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import json
import re
from enum import EnumType
from typing import get_args

from pydantic import BaseModel, ConfigDict, model_validator
from typing_extensions import Self

from canvas_sdk.effects import Effect
from canvas_sdk.effects import Effect, EffectType


class _BaseCommand(BaseModel):
Expand All @@ -14,15 +15,18 @@ class _BaseCommand(BaseModel):
class Meta:
key = ""

def constantized_key(self) -> str:
return re.sub(r"(?<!^)(?=[A-Z])", "_", self.Meta.key).upper()

# todo: update int to str as we should use external identifiers
note_id: int | None = None
note_uuid: str | None = None
command_uuid: str | None = None
user_id: int

@model_validator(mode="after")
def _verify_has_note_id_or_command_id(self) -> Self:
if not self.note_id and not self.command_uuid:
raise ValueError("Command should have either a note_id or a command_uuid.")
def _verify_has_note_uuid_or_command_id(self) -> Self:
if not self.note_uuid and not self.command_uuid:
raise ValueError("Command should have either a note_uuid or a command_uuid.")
return self

@property
Expand Down Expand Up @@ -52,7 +56,7 @@ def _get_property_type(cls, name: str) -> type:
@classmethod
def command_schema(cls) -> dict:
"""The schema of the command."""
base_properties = {"note_id", "command_uuid", "user_id"}
base_properties = {"note_uuid", "command_uuid", "user_id"}
schema = cls.model_json_schema()
return {
definition.get("commands_api_name", name): {
Expand All @@ -66,23 +70,25 @@ def command_schema(cls) -> dict:

def originate(self) -> Effect:
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should run the pydantic validators when these effect methods are called rather than on assignment. This should allow us to set the attributes individually instead of only in the constructor.
Example:

plan = PlanCommand()
plan.narrative = "This is my narrative"
plan.originate()  # <-- only validate here

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea. want me to tackle that?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, once this gets merged. We should chat about other priorities soon too.

"""Originate a new command in the note body."""
if not self.note_id:
if not self.note_uuid:
raise AttributeError("Note id is required to originate a command")
return {
"type": f"ADD_{self.Meta.key.upper()}_COMMAND",
"payload": {
"user": self.user_id,
"note": self.note_id,
"data": self.values,
},
}
return Effect(
type=EffectType.Value(f"ORIGINATE_{self.constantized_key()}_COMMAND"),
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed ADD to ORIGINATE.

payload=json.dumps(
{
"user": self.user_id,
"note": self.note_uuid,
"data": self.values,
}
),
)

def edit(self) -> Effect:
"""Edit the command."""
if not self.command_uuid:
raise AttributeError("Command uuid is required to edit a command")
return {
"type": f"EDIT_{self.Meta.key.upper()}_COMMAND",
"type": f"EDIT_{self.constantized_key()}_COMMAND",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed these from self.Meta.key.upper() to a call to the new method constantized_key to account for multi-word command types. Instead of EDIT_MEDICATIONSTATEMENT_COMMAND we want the more readable EDIT_MEDICATION_STATEMENT_COMMAND.

"payload": {
"user": self.user_id,
"command": self.command_uuid,
Expand All @@ -95,7 +101,7 @@ def delete(self) -> Effect:
if not self.command_uuid:
raise AttributeError("Command uuid is required to delete a command")
return {
"type": f"DELETE_{self.Meta.key.upper()}_COMMAND",
"type": f"DELETE_{self.constantized_key()}_COMMAND",
"payload": {"command": self.command_uuid, "user": self.user_id},
}

Expand All @@ -104,7 +110,7 @@ def commit(self) -> Effect:
if not self.command_uuid:
raise AttributeError("Command uuid is required to commit a command")
return {
"type": f"COMMIT_{self.Meta.key.upper()}_COMMAND",
"type": f"COMMIT_{self.constantized_key()}_COMMAND",
"payload": {"command": self.command_uuid, "user": self.user_id},
}

Expand All @@ -113,6 +119,6 @@ def enter_in_error(self) -> Effect:
if not self.command_uuid:
raise AttributeError("Command uuid is required to enter in error a command")
return {
"type": f"ENTER_IN_ERROR_{self.Meta.key.upper()}_COMMAND",
"type": f"ENTER_IN_ERROR_{self.constantized_key()}_COMMAND",
"payload": {"command": self.command_uuid, "user": self.user_id},
}
11 changes: 6 additions & 5 deletions canvas_sdk/commands/commands/diagnose.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,13 @@ class Meta:
@property
def values(self) -> dict:
"""The Diagnose command's field values."""
approximate_date_of_onset = None
if self.approximate_date_of_onset:
approximate_date_of_onset = self.approximate_date_of_onset.isoformat()
return {
"icd10_code": self.icd10_code,
"background": self.background,
"approximate_date_of_onset": (
self.approximate_date_of_onset.isoformat()
if self.approximate_date_of_onset
else None
),
"approximate_date_of_onset": approximate_date_of_onset,
"today_assessment": self.today_assessment,
}

Expand All @@ -42,3 +41,5 @@ def values(self) -> dict:
# see if we can get ValueSets to play nicely with pydantic

# idea3: runtime warning after pinging ontologies

# idea4: garbage in, garbage out
aduane marked this conversation as resolved.
Show resolved Hide resolved
2 changes: 1 addition & 1 deletion canvas_sdk/commands/commands/goal.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def values(self) -> dict:
return {
"goal_statement": self.goal_statement,
"start_date": (self.start_date.isoformat() if self.start_date else None),
"due_date": (self.due_date.isoformat() if self.start_date else None),
"due_date": (self.due_date.isoformat() if self.due_date else None),
aduane marked this conversation as resolved.
Show resolved Hide resolved
"achievement_status": (
self.achievement_status.value if self.achievement_status else None
),
Expand Down
Loading
Loading