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
Merged

Conversation

aduane
Copy link
Collaborator

@aduane aduane commented Jun 23, 2024

https://canvasmedical.atlassian.net/browse/KOALA-1632

With this PR, I was able to originate the following commands:

  • AssessCommand
  • DiagnoseCommand
    • Issue with specifying the onset date
  • GoalCommand
  • HistoryOfPresentIllnessCommand
  • MedicationStatementCommand
  • PlanCommand
  • PrescribeCommand
    • Issue with specifying the indications and dosage form
  • QuestionnaireCommand
  • ReasonForVisitCommand
  • StopMedicationCommand
  • UpdateGoalCommand

This won't have an effect until we write the interpreters, however.

@aduane aduane requested review from jrwils and mbiannaccone June 23, 2024 17:34
@aduane aduane self-assigned this Jun 23, 2024
},
}
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.


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.

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

@aduane
Copy link
Collaborator Author

aduane commented Jun 29, 2024

Here is a sample protocol I was using for development:

import json

from datetime import datetime

from canvas_sdk.effects import Effect, EffectType
from canvas_sdk.commands import (
    AssessCommand,
    DiagnoseCommand,
    GoalCommand,
    HistoryOfPresentIllnessCommand,
    MedicationStatementCommand,
    PlanCommand,
    PrescribeCommand,
    QuestionnaireCommand,
    ReasonForVisitCommand,
    StopMedicationCommand,
    UpdateGoalCommand,
)
from canvas_sdk.events import EventType
from canvas_sdk.protocols import BaseProtocol
from logger import log


class Protocol(BaseProtocol):
    RESPONDS_TO = EventType.Name(EventType.ASSESS_COMMAND__CONDITION_SELECTED)
    #RESPONDS_TO = EventType.Name(EventType.UPDATE_GOAL_COMMAND__POST_DELETE)
    #RESPONDS_TO = EventType.Name(EventType.MEDICATION_STATEMENT_COMMAND__POST_DELETE)

    def compute(self):
        ## assess = AssessCommand(
        ##     user_id=0,
        ##     note_uuid=self.context["note"]["uuid"],
        ##     narrative="Let's assess",
        ##     status=AssessCommand.Status.STABLE,
        ##     background="this is the background",
        ##     condition_id=self.context["data"]["condition"]["id"]
        ## )
        ## diagnose = DiagnoseCommand(
        ##     user_id=0,
        ##     note_uuid=self.context["note"]["uuid"],
        ##     icd10_code="F419",
        ##     background="In today's modern world...",
        ##     approximate_date_of_onset=datetime.strptime("2024-06-23", "%Y-%m-%d"),
        ##     today_assessment="Pt needs to log off for at least a month.",
        ## )
        ## goal = GoalCommand(
        ##     user_id=0,
        ##     note_uuid=self.context["note"]["uuid"],
        ##     goal_statement="Eat a ton of tacos",
        ##     start_date=datetime.strptime("2024-06-23", "%Y-%m-%d"),
        ##     due_date=datetime.strptime("2024-07-23", "%Y-%m-%d"),
        ##     achievement_status=GoalCommand.AchievementStatus.NO_PROGRESS,
        ##     priority=GoalCommand.Priority.HIGH,
        ##     progress="Pt is researching local taquerias.",
        ## )
        ## hpi = HistoryOfPresentIllnessCommand(
        ##     user_id=0,
        ##     note_uuid=self.context["note"]["uuid"],
        ##     narrative="Read too much twitter, got sad."
        ## )
        ## medication_statement = MedicationStatementCommand(
        ##     user_id=0,
        ##     note_uuid=self.context["note"]["uuid"],
        ##     fdb_code="218832",
        ##     sig="A flintstone a day keeps the scurvy away."
        ## )
        ## plan = PlanCommand(
        ##     user_id=0,
        ##     note_uuid=self.context["note"]["uuid"],
        ##     narrative="What's the plan?"
        ## )
        ## unstructured_reason_for_visit = ReasonForVisitCommand(
        ##     user_id=0,
        ##     note_uuid=self.context["note"]["uuid"],
        ##     structured=False,
        ##     comment="Dropped in for yearly exam",
        ## )
        ## structured_reason_for_visit = ReasonForVisitCommand(
        ##     user_id=0,
        ##     note_uuid=self.context["note"]["uuid"],
        ##     structured=True,
        ##     coding={
        ##         "code": "129007",
        ##         "system": "http://snomed.info/sct",
        ##     },
        ##     comment="Dropped in for daily exam",
        ## )
        ## stop_medication = StopMedicationCommand(
        ##     user_id=0,
        ##     note_uuid=self.context["note"]["uuid"],
        ##     medication_id=self.context["data"]["medication"]["id"],
        ##     rationale="I'm sorry Dave, I'm afraid I can't do that",
        ## )
        ## questionnaire = QuestionnaireCommand(
        ##     user_id=0,
        ##     note_uuid=self.context["note"]["uuid"],
        ##     questionnaire_id="678b901b-a50d-4dfa-bc77-78f1142362fe"
        ## )
        ## update_goal = UpdateGoalCommand(
        ##     user_id=0,
        ##     note_uuid=self.context["note"]["uuid"],
        ##     goal_id=self.context["data"]["goal"]["id"],
        ##     due_date=datetime.strptime("2030-01-22", "%Y-%m-%d"),
        ##     achievement_status=UpdateGoalCommand.AchievementStatus.IN_PROGRESS,
        ##     priority=UpdateGoalCommand.Priority.LOW,
        ##     progress="hello to this update goal command",
        ## )
        ## prescribe = PrescribeCommand(
        ##     user_id=0,
        ##     note_uuid=self.context["note"]["uuid"],
        ##     fdb_code='197702',
        ##     icd10_codes=['W5621XA'],  # TODO: needs to be condition uuids
        ##     sig='i po qhs',
        ##     days_supply=90,
        ##     quantity_to_dispense=90,
        ##     type_to_dispense='tablet',  # TODO: needs some work
        ##     refills=2,
        ##     substitutions=PrescribeCommand.Substitutions.ALLOWED,
        ##     pharmacy='1051008',
        ##     prescriber_id='3640cd20de8a470aa570a852859ac87e',
        ##     note_to_pharmacist='Hello',
        ## )

        return [
            ## assess.originate(),
            ## diagnose.originate(),
            ## goal.originate(),
            ## hpi.originate(),
            ## medication_statement.originate(),
            ## plan.originate(),
            ## unstructured_reason_for_visit.originate(),
            ## structured_reason_for_visit.originate(),
            ## stop_medication.originate(),
            ## questionnaire.originate(),
            ## prescribe.originate(),
            ## update_goal.originate(),
        ]

"quantity_to_dispense": str(Decimal(self.quantity_to_dispense))
if self.quantity_to_dispense
else None,
# "type_to_dispense": self.type_to_dispense,
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This breaks the interpreter if sent. Suppressing until the interpreter works.

@aduane
Copy link
Collaborator Author

aduane commented Jul 3, 2024

@jrwils @mbiannaccone This is ready for review

@aduane aduane changed the title Add many more command events. Add many command origination events. Jul 3, 2024
@aduane aduane merged commit 2a3ecb5 into main Jul 3, 2024
2 checks passed
@aduane aduane deleted the ad/add-many-more-command-events branch July 3, 2024 20:51
@aduane aduane changed the title Add many command origination events. Add many command origination effects. Jul 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants