canvas 0.2.5__py3-none-any.whl → 0.2.10__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of canvas might be problematic. Click here for more details.

Files changed (85) hide show
  1. {canvas-0.2.5.dist-info → canvas-0.2.10.dist-info}/METADATA +4 -1
  2. canvas-0.2.10.dist-info/RECORD +143 -0
  3. canvas_cli/apps/plugin/plugin.py +51 -9
  4. canvas_cli/apps/plugin/tests.py +51 -0
  5. canvas_cli/tests.py +193 -4
  6. canvas_cli/utils/validators/manifest_schema.py +1 -0
  7. canvas_generated/messages/effects_pb2.py +2 -2
  8. canvas_generated/messages/effects_pb2.pyi +136 -0
  9. canvas_generated/messages/events_pb2.py +3 -3
  10. canvas_generated/messages/events_pb2.pyi +614 -0
  11. canvas_sdk/__init__.py +7 -0
  12. canvas_sdk/base.py +6 -2
  13. canvas_sdk/commands/__init__.py +26 -0
  14. canvas_sdk/commands/base.py +35 -32
  15. canvas_sdk/commands/commands/allergy.py +49 -0
  16. canvas_sdk/commands/commands/assess.py +1 -1
  17. canvas_sdk/commands/commands/close_goal.py +22 -0
  18. canvas_sdk/commands/commands/diagnose.py +3 -3
  19. canvas_sdk/commands/commands/family_history.py +18 -0
  20. canvas_sdk/commands/commands/goal.py +3 -3
  21. canvas_sdk/commands/commands/history_present_illness.py +1 -1
  22. canvas_sdk/commands/commands/instruct.py +17 -0
  23. canvas_sdk/commands/commands/lab_order.py +33 -0
  24. canvas_sdk/commands/commands/medical_history.py +34 -0
  25. canvas_sdk/commands/commands/medication_statement.py +1 -1
  26. canvas_sdk/commands/commands/past_surgical_history.py +28 -0
  27. canvas_sdk/commands/commands/perform.py +17 -0
  28. canvas_sdk/commands/commands/plan.py +2 -2
  29. canvas_sdk/commands/commands/prescribe.py +10 -7
  30. canvas_sdk/commands/commands/questionnaire.py +1 -1
  31. canvas_sdk/commands/commands/refill.py +16 -0
  32. canvas_sdk/commands/commands/remove_allergy.py +26 -0
  33. canvas_sdk/commands/commands/stop_medication.py +1 -1
  34. canvas_sdk/commands/commands/task.py +52 -0
  35. canvas_sdk/commands/commands/update_diagnosis.py +27 -0
  36. canvas_sdk/commands/commands/update_goal.py +1 -1
  37. canvas_sdk/commands/commands/vitals.py +78 -0
  38. canvas_sdk/commands/constants.py +7 -0
  39. canvas_sdk/commands/tests/protocol/__init__.py +0 -0
  40. canvas_sdk/commands/tests/protocol/tests.py +55 -0
  41. canvas_sdk/commands/tests/schema/__init__.py +0 -0
  42. canvas_sdk/commands/tests/schema/tests.py +104 -0
  43. canvas_sdk/commands/tests/test_utils.py +170 -6
  44. canvas_sdk/commands/tests/unit/__init__.py +0 -0
  45. canvas_sdk/commands/tests/{tests.py → unit/tests.py} +20 -194
  46. canvas_sdk/effects/banner_alert/add_banner_alert.py +8 -7
  47. canvas_sdk/effects/banner_alert/remove_banner_alert.py +3 -2
  48. canvas_sdk/effects/banner_alert/tests.py +224 -0
  49. canvas_sdk/effects/base.py +3 -5
  50. canvas_sdk/effects/patient_chart_summary_configuration.py +39 -0
  51. canvas_sdk/effects/protocol_card/__init__.py +1 -0
  52. canvas_sdk/effects/protocol_card/protocol_card.py +83 -0
  53. canvas_sdk/effects/protocol_card/tests.py +184 -0
  54. canvas_sdk/protocols/clinical_quality_measure.py +41 -0
  55. canvas_sdk/utils/db.py +17 -0
  56. canvas_sdk/v1/__init__.py +0 -0
  57. canvas_sdk/v1/data/__init__.py +3 -0
  58. canvas_sdk/v1/data/allergy_intolerance.py +63 -0
  59. canvas_sdk/v1/data/base.py +47 -0
  60. canvas_sdk/v1/data/condition.py +48 -0
  61. canvas_sdk/v1/data/lab.py +96 -0
  62. canvas_sdk/v1/data/medication.py +54 -0
  63. canvas_sdk/v1/data/patient.py +49 -0
  64. canvas_sdk/v1/data/user.py +10 -0
  65. canvas_sdk/value_set/tests/test_value_sets.py +65 -0
  66. canvas_sdk/value_set/v2022/adverse_event.py +33 -0
  67. canvas_sdk/value_set/v2022/allergy.py +232 -0
  68. canvas_sdk/value_set/v2022/assessment.py +215 -0
  69. canvas_sdk/value_set/v2022/communication.py +325 -0
  70. canvas_sdk/value_set/v2022/condition.py +40654 -0
  71. canvas_sdk/value_set/v2022/device.py +174 -0
  72. canvas_sdk/value_set/v2022/diagnostic_study.py +4967 -0
  73. canvas_sdk/value_set/v2022/encounter.py +2564 -0
  74. canvas_sdk/value_set/v2022/immunization.py +341 -0
  75. canvas_sdk/value_set/v2022/individual_characteristic.py +307 -0
  76. canvas_sdk/value_set/v2022/intervention.py +1356 -0
  77. canvas_sdk/value_set/v2022/laboratory_test.py +1250 -0
  78. canvas_sdk/value_set/v2022/medication.py +5130 -0
  79. canvas_sdk/value_set/v2022/physical_exam.py +201 -0
  80. canvas_sdk/value_set/v2022/procedure.py +4037 -0
  81. canvas_sdk/value_set/v2022/symptom.py +176 -0
  82. canvas_sdk/value_set/value_set.py +91 -0
  83. canvas-0.2.5.dist-info/RECORD +0 -91
  84. {canvas-0.2.5.dist-info → canvas-0.2.10.dist-info}/WHEEL +0 -0
  85. {canvas-0.2.5.dist-info → canvas-0.2.10.dist-info}/entry_points.txt +0 -0
canvas_sdk/__init__.py CHANGED
@@ -0,0 +1,7 @@
1
+ import os
2
+
3
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
4
+
5
+ import django
6
+
7
+ django.setup()
canvas_sdk/base.py CHANGED
@@ -23,7 +23,7 @@ class Model(BaseModel):
23
23
  },
24
24
  )
25
25
 
26
- def _get_effect_method_required_fields(self, method: str) -> tuple[str]:
26
+ def _get_effect_method_required_fields(self, method: str) -> tuple[str] | tuple:
27
27
  return getattr(self.Meta, f"{method}_required_fields", tuple())
28
28
 
29
29
  def _create_error_detail(self, type: str, message: str, value: Any) -> InitErrorDetails:
@@ -31,9 +31,13 @@ class Model(BaseModel):
31
31
 
32
32
  def _get_error_details(self, method: str) -> list[InitErrorDetails]:
33
33
  required_fields = self._get_effect_method_required_fields(method)
34
+ class_name = self.__repr_name__()
35
+ class_name_article = "an" if class_name.startswith(("A", "E", "I", "O", "U")) else "a"
34
36
  return [
35
37
  self._create_error_detail(
36
- "missing", f"Field '{field}' is required to {method.replace('_', ' ')} a command", v
38
+ "missing",
39
+ f"Field '{field}' is required to {method.replace('_', ' ')} {class_name_article} {class_name}",
40
+ v,
37
41
  )
38
42
  for field in required_fields
39
43
  if (v := getattr(self, field)) is None
@@ -1,27 +1,53 @@
1
+ from canvas_sdk.commands.commands.allergy import AllergyCommand
1
2
  from canvas_sdk.commands.commands.assess import AssessCommand
3
+ from canvas_sdk.commands.commands.close_goal import CloseGoalCommand
2
4
  from canvas_sdk.commands.commands.diagnose import DiagnoseCommand
5
+ from canvas_sdk.commands.commands.family_history import FamilyHistoryCommand
3
6
  from canvas_sdk.commands.commands.goal import GoalCommand
4
7
  from canvas_sdk.commands.commands.history_present_illness import (
5
8
  HistoryOfPresentIllnessCommand,
6
9
  )
10
+ from canvas_sdk.commands.commands.instruct import InstructCommand
11
+ from canvas_sdk.commands.commands.lab_order import LabOrderCommand
12
+ from canvas_sdk.commands.commands.medical_history import MedicalHistoryCommand
7
13
  from canvas_sdk.commands.commands.medication_statement import MedicationStatementCommand
14
+ from canvas_sdk.commands.commands.past_surgical_history import PastSurgicalHistoryCommand
15
+ from canvas_sdk.commands.commands.perform import PerformCommand
8
16
  from canvas_sdk.commands.commands.plan import PlanCommand
9
17
  from canvas_sdk.commands.commands.prescribe import PrescribeCommand
10
18
  from canvas_sdk.commands.commands.questionnaire import QuestionnaireCommand
11
19
  from canvas_sdk.commands.commands.reason_for_visit import ReasonForVisitCommand
20
+ from canvas_sdk.commands.commands.refill import RefillCommand
21
+ from canvas_sdk.commands.commands.remove_allergy import RemoveAllergyCommand
12
22
  from canvas_sdk.commands.commands.stop_medication import StopMedicationCommand
23
+ from canvas_sdk.commands.commands.task import TaskCommand
24
+ from canvas_sdk.commands.commands.update_diagnosis import UpdateDiagnosisCommand
13
25
  from canvas_sdk.commands.commands.update_goal import UpdateGoalCommand
26
+ from canvas_sdk.commands.commands.vitals import VitalsCommand
14
27
 
15
28
  __all__ = (
29
+ "AllergyCommand",
16
30
  "AssessCommand",
31
+ "CloseGoalCommand",
17
32
  "DiagnoseCommand",
33
+ "FamilyHistoryCommand",
18
34
  "GoalCommand",
19
35
  "HistoryOfPresentIllnessCommand",
36
+ "InstructCommand",
37
+ "LabOrderCommand",
38
+ "MedicalHistoryCommand",
20
39
  "MedicationStatementCommand",
40
+ "PastSurgicalHistoryCommand",
41
+ "PerformCommand",
21
42
  "PlanCommand",
22
43
  "PrescribeCommand",
23
44
  "QuestionnaireCommand",
24
45
  "ReasonForVisitCommand",
46
+ "RefillCommand",
47
+ "RemoveAllergyCommand",
25
48
  "StopMedicationCommand",
49
+ "TaskCommand",
50
+ "UpdateDiagnosisCommand",
26
51
  "UpdateGoalCommand",
52
+ "VitalsCommand",
27
53
  )
@@ -1,42 +1,29 @@
1
1
  import json
2
2
  import re
3
3
  from enum import EnumType
4
- from typing import Literal, get_args
4
+ from types import NoneType, UnionType
5
+ from typing import Literal, get_args, get_origin, Union
5
6
 
6
7
  from canvas_sdk.base import Model
8
+ from canvas_sdk.commands.constants import Coding
7
9
  from canvas_sdk.effects import Effect, EffectType
10
+ from canvas_sdk.effects.protocol_card import Recommendation
8
11
 
9
12
 
10
13
  class _BaseCommand(Model):
11
14
  class Meta:
12
15
  key = ""
13
- originate_required_fields = (
14
- "user_id",
15
- "note_uuid",
16
- )
17
- edit_required_fields = (
18
- "user_id",
19
- "command_uuid",
20
- )
21
- delete_required_fields = (
22
- "user_id",
23
- "command_uuid",
24
- )
25
- commit_required_fields = (
26
- "user_id",
27
- "command_uuid",
28
- )
29
- enter_in_error_required_fields = (
30
- "user_id",
31
- "command_uuid",
32
- )
16
+ originate_required_fields = ("note_uuid",)
17
+ edit_required_fields = ("command_uuid",)
18
+ delete_required_fields = ("command_uuid",)
19
+ commit_required_fields = ("command_uuid",)
20
+ enter_in_error_required_fields = ("command_uuid",)
33
21
 
34
22
  def constantized_key(self) -> str:
35
23
  return re.sub(r"(?<!^)(?=[A-Z])", "_", self.Meta.key).upper()
36
24
 
37
25
  note_uuid: str | None = None
38
26
  command_uuid: str | None = None
39
- user_id: int | None = None
40
27
 
41
28
  def _get_effect_method_required_fields(
42
29
  self, method: Literal["originate", "edit", "delete", "commit", "enter_in_error"]
@@ -51,6 +38,11 @@ class _BaseCommand(Model):
51
38
  def values(self) -> dict:
52
39
  return {}
53
40
 
41
+ @property
42
+ def coding_filter(self) -> Coding | None:
43
+ """The coding filter used for command insertion in protocol cards."""
44
+ return None
45
+
54
46
  @classmethod
55
47
  def _get_property_choices(cls, name: str, schema: dict) -> list[dict] | None:
56
48
  definition = schema.get("properties", {}).get(name, {})
@@ -62,9 +54,15 @@ class _BaseCommand(Model):
62
54
  @classmethod
63
55
  def _get_property_type(cls, name: str) -> type:
64
56
  annotation = cls.model_fields[name].annotation
65
- if annotation_args := get_args(annotation):
66
- # if its a union, take the first one (which is not None)
67
- annotation = annotation_args[0]
57
+ origin = get_origin(annotation)
58
+
59
+ # Handle Union types
60
+ if origin is UnionType or origin is Union:
61
+ annotation_args = get_args(annotation)
62
+ # Filter out NoneType and take the first valid type
63
+ annotation = next(
64
+ (arg for arg in annotation_args if arg is not NoneType), annotation_args[0]
65
+ )
68
66
 
69
67
  if type(annotation) is EnumType:
70
68
  return str
@@ -74,9 +72,9 @@ class _BaseCommand(Model):
74
72
  @classmethod
75
73
  def command_schema(cls) -> dict:
76
74
  """The schema of the command."""
77
- base_properties = {"note_uuid", "command_uuid", "user_id"}
75
+ base_properties = {"note_uuid", "command_uuid"}
78
76
  schema = cls.model_json_schema()
79
- required_fields: tuple = getattr(cls.Meta, "originate_required_fields", tuple())
77
+ required_fields: tuple = getattr(cls.Meta, "commit_required_fields", tuple())
80
78
  return {
81
79
  definition.get("commands_api_name", name): {
82
80
  "required": name in required_fields,
@@ -94,7 +92,6 @@ class _BaseCommand(Model):
94
92
  type=EffectType.Value(f"ORIGINATE_{self.constantized_key()}_COMMAND"),
95
93
  payload=json.dumps(
96
94
  {
97
- "user": self.user_id,
98
95
  "note": self.note_uuid,
99
96
  "data": self.values,
100
97
  }
@@ -107,7 +104,6 @@ class _BaseCommand(Model):
107
104
  return {
108
105
  "type": f"EDIT_{self.constantized_key()}_COMMAND",
109
106
  "payload": {
110
- "user": self.user_id,
111
107
  "command": self.command_uuid,
112
108
  "data": self.values,
113
109
  },
@@ -118,7 +114,7 @@ class _BaseCommand(Model):
118
114
  self._validate_before_effect("delete")
119
115
  return {
120
116
  "type": f"DELETE_{self.constantized_key()}_COMMAND",
121
- "payload": {"command": self.command_uuid, "user": self.user_id},
117
+ "payload": {"command": self.command_uuid},
122
118
  }
123
119
 
124
120
  def commit(self) -> Effect:
@@ -126,7 +122,7 @@ class _BaseCommand(Model):
126
122
  self._validate_before_effect("commit")
127
123
  return {
128
124
  "type": f"COMMIT_{self.constantized_key()}_COMMAND",
129
- "payload": {"command": self.command_uuid, "user": self.user_id},
125
+ "payload": {"command": self.command_uuid},
130
126
  }
131
127
 
132
128
  def enter_in_error(self) -> Effect:
@@ -134,5 +130,12 @@ class _BaseCommand(Model):
134
130
  self._validate_before_effect("enter_in_error")
135
131
  return {
136
132
  "type": f"ENTER_IN_ERROR_{self.constantized_key()}_COMMAND",
137
- "payload": {"command": self.command_uuid, "user": self.user_id},
133
+ "payload": {"command": self.command_uuid},
138
134
  }
135
+
136
+ def recommend(self, title: str = "", button: str | None = None) -> Recommendation:
137
+ """Returns a command recommendation to be inserted via Protocol Card."""
138
+ if button is None:
139
+ button = self.constantized_key().lower().replace("_", " ")
140
+ command = self.Meta.key.lower()
141
+ return Recommendation(title=title, button=button, command=command, context=self.values)
@@ -0,0 +1,49 @@
1
+ from datetime import date
2
+ from enum import Enum, IntEnum
3
+
4
+ from typing_extensions import TypedDict
5
+
6
+ from canvas_sdk.commands.base import _BaseCommand as BaseCommand
7
+
8
+
9
+ class AllergenType(IntEnum):
10
+ ALLERGEN_GROUP = 1
11
+ MEDICATION = 2
12
+ INGREDIENT = 6
13
+
14
+
15
+ class Allergen(TypedDict):
16
+ """A TypedDict representing an allergen."""
17
+
18
+ concept_id: int
19
+ concept_type: AllergenType
20
+
21
+
22
+ class AllergyCommand(BaseCommand):
23
+ """A class for managing an Allergy command within a specific note."""
24
+
25
+ class Meta:
26
+ key = "allergy"
27
+ commit_required_fields = ("allergy",)
28
+
29
+ class Severity(Enum):
30
+ MILD = "mild"
31
+ MODERATE = "moderate"
32
+ SEVERE = "severe"
33
+
34
+ allergy: Allergen | None = None
35
+ severity: Severity | None = None
36
+ narrative: str | None = None
37
+ approximate_date: date | None = None
38
+
39
+ @property
40
+ def values(self) -> dict:
41
+ """The Allergy command's field values."""
42
+ return {
43
+ "allergy": self.allergy,
44
+ "severity": self.severity.value if self.severity else None,
45
+ "narrative": self.narrative,
46
+ "approximate_date": (
47
+ self.approximate_date.isoformat() if self.approximate_date else None
48
+ ),
49
+ }
@@ -10,7 +10,7 @@ class AssessCommand(_BaseCommand):
10
10
 
11
11
  class Meta:
12
12
  key = "assess"
13
- originate_required_fields = ("condition_id",)
13
+ commit_required_fields = ("condition_id",)
14
14
 
15
15
  class Status(Enum):
16
16
  IMPROVED = "improved"
@@ -0,0 +1,22 @@
1
+ from canvas_sdk.commands.base import _BaseCommand as BaseCommand
2
+ from canvas_sdk.commands.commands.goal import GoalCommand
3
+
4
+
5
+ class CloseGoalCommand(BaseCommand):
6
+ class Meta:
7
+ key = "closeGoal"
8
+ commit_required_fields = ("goal_id",)
9
+
10
+ goal_id: int | None = None
11
+ achievement_status: GoalCommand.AchievementStatus | None = None
12
+ progress: str | None = None
13
+
14
+ @property
15
+ def values(self) -> dict:
16
+ return {
17
+ "goal_id": self.goal_id,
18
+ "achievement_status": (
19
+ self.achievement_status.value if self.achievement_status else None
20
+ ),
21
+ "progress": self.progress,
22
+ }
@@ -1,4 +1,4 @@
1
- from datetime import datetime
1
+ from datetime import date
2
2
 
3
3
  from pydantic import Field
4
4
 
@@ -10,13 +10,13 @@ class DiagnoseCommand(_BaseCommand):
10
10
 
11
11
  class Meta:
12
12
  key = "diagnose"
13
- originate_required_fields = ("icd10_code",)
13
+ commit_required_fields = ("icd10_code",)
14
14
 
15
15
  icd10_code: str | None = Field(
16
16
  default=None, json_schema_extra={"commands_api_name": "diagnose"}
17
17
  )
18
18
  background: str | None = None
19
- approximate_date_of_onset: datetime | None = None
19
+ approximate_date_of_onset: date | None = None
20
20
  today_assessment: str | None = None
21
21
 
22
22
  @property
@@ -0,0 +1,18 @@
1
+ from canvas_sdk.commands.base import _BaseCommand as BaseCommand
2
+
3
+
4
+ class FamilyHistoryCommand(BaseCommand):
5
+ """A class for managing a Family History command within a specific note."""
6
+
7
+ class Meta:
8
+ key = "familyHistory"
9
+ commit_required_fields = ("family_history",)
10
+
11
+ family_history: str | None = None
12
+ relative: str | None = None
13
+ note: str | None = None
14
+
15
+ @property
16
+ def values(self) -> dict:
17
+ """The Family History command's field values."""
18
+ return {"family_history": self.family_history, "relative": self.relative, "note": self.note}
@@ -9,7 +9,7 @@ class GoalCommand(_BaseCommand):
9
9
 
10
10
  class Meta:
11
11
  key = "goal"
12
- originate_required_fields = ("goal_statement", "start_date")
12
+ commit_required_fields = ("goal_statement", "start_date")
13
13
 
14
14
  class Priority(Enum):
15
15
  HIGH = "high-priority"
@@ -27,8 +27,8 @@ class GoalCommand(_BaseCommand):
27
27
  NO_PROGRESS = "no-progress"
28
28
  NOT_ATTAINABLE = "not-attainable"
29
29
 
30
- goal_statement: str | None = None
31
- start_date: datetime | None = None
30
+ goal_statement: str = ""
31
+ start_date: datetime = datetime.now()
32
32
  due_date: datetime | None = None
33
33
  achievement_status: AchievementStatus | None = None
34
34
  priority: Priority | None = None
@@ -6,7 +6,7 @@ class HistoryOfPresentIllnessCommand(_BaseCommand):
6
6
 
7
7
  class Meta:
8
8
  key = "hpi"
9
- originate_required_fields = ("narrative",)
9
+ commit_required_fields = ("narrative",)
10
10
 
11
11
  narrative: str | None = None
12
12
 
@@ -0,0 +1,17 @@
1
+ from canvas_sdk.commands.base import _BaseCommand as BaseCommand
2
+
3
+
4
+ class InstructCommand(BaseCommand):
5
+ """A class for managing an Instruct command within a specific note."""
6
+
7
+ class Meta:
8
+ key = "instruct"
9
+ commit_required_fields = ("instruction",)
10
+
11
+ instruction: str | None = None
12
+ comment: str | None = None
13
+
14
+ @property
15
+ def values(self) -> dict:
16
+ """The Instruct command's field values."""
17
+ return {"instruction": self.instruction, "comment": self.comment}
@@ -0,0 +1,33 @@
1
+ from canvas_sdk.commands.base import _BaseCommand as BaseCommand
2
+
3
+
4
+ class LabOrderCommand(BaseCommand):
5
+ """A class for managing a Lab Order command within a specific note."""
6
+
7
+ class Meta:
8
+ key = "labOrder"
9
+ commit_required_fields = (
10
+ "lab_partner",
11
+ "tests_order_codes",
12
+ "ordering_provider",
13
+ "diagnosis_codes",
14
+ )
15
+
16
+ lab_partner: str | None = None
17
+ tests_order_codes: list[str] = []
18
+ ordering_provider_key: str | None = None
19
+ diagnosis_codes: list[str] = []
20
+ fasting_required: bool = False
21
+ comment: str | None = None
22
+
23
+ @property
24
+ def values(self) -> dict:
25
+ """The Lab Order command's field values."""
26
+ return {
27
+ "lab_partner": self.lab_partner,
28
+ "tests_order_codes": self.tests_order_codes,
29
+ "ordering_provider_key": self.ordering_provider_key,
30
+ "diagnosis_codes": self.diagnosis_codes,
31
+ "fasting_required": self.fasting_required,
32
+ "comment": self.comment,
33
+ }
@@ -0,0 +1,34 @@
1
+ from datetime import date
2
+
3
+ from pydantic import Field
4
+
5
+ from canvas_sdk.commands.base import _BaseCommand as BaseCommand
6
+
7
+
8
+ class MedicalHistoryCommand(BaseCommand):
9
+ """A class for managing a Medical History command within a specific note."""
10
+
11
+ class Meta:
12
+ key = "medicalHistory"
13
+ commit_required_fields = ("past_medical_history",)
14
+
15
+ past_medical_history: str | None = None
16
+ approximate_start_date: date | None = None
17
+ approximate_end_date: date | None = None
18
+ show_on_condition_list: bool = True
19
+ comments: str | None = Field(max_length=1000, default=None)
20
+
21
+ @property
22
+ def values(self) -> dict:
23
+ """The Medical History command's field values."""
24
+ return {
25
+ "past_medical_history": self.past_medical_history,
26
+ "approximate_start_date": (
27
+ self.approximate_start_date.isoformat() if self.approximate_start_date else None
28
+ ),
29
+ "approximate_end_date": (
30
+ self.approximate_end_date.isoformat() if self.approximate_end_date else None
31
+ ),
32
+ "show_on_condition_list": self.show_on_condition_list,
33
+ "comments": self.comments,
34
+ }
@@ -8,7 +8,7 @@ class MedicationStatementCommand(_BaseCommand):
8
8
 
9
9
  class Meta:
10
10
  key = "medicationStatement"
11
- originate_required_fields = ("fdb_code",)
11
+ commit_required_fields = ("fdb_code",)
12
12
 
13
13
  fdb_code: str | None = Field(
14
14
  default=None, json_schema_extra={"commands_api_name": "medication"}
@@ -0,0 +1,28 @@
1
+ from datetime import date
2
+
3
+ from pydantic import Field
4
+
5
+ from canvas_sdk.commands.base import _BaseCommand as BaseCommand
6
+
7
+
8
+ class PastSurgicalHistoryCommand(BaseCommand):
9
+ """A class for managing a Past Surgical History command within a specific note."""
10
+
11
+ class Meta:
12
+ key = "surgicalHistory"
13
+ commit_required_fields = ("past_surgical_history",)
14
+
15
+ past_surgical_history: str | None = None
16
+ approximate_date: date | None = None
17
+ comment: str | None = Field(max_length=1000, default=None)
18
+
19
+ @property
20
+ def values(self) -> dict:
21
+ """The Past Surgical History command's field values."""
22
+ return {
23
+ "past_surgical_history": self.past_surgical_history,
24
+ "approximate_date": (
25
+ self.approximate_date.isoformat() if self.approximate_date else None
26
+ ),
27
+ "comment": self.comment,
28
+ }
@@ -0,0 +1,17 @@
1
+ from canvas_sdk.commands.base import _BaseCommand as BaseCommand
2
+
3
+
4
+ class PerformCommand(BaseCommand):
5
+ """A class for managing a Perform command within a specific note."""
6
+
7
+ class Meta:
8
+ key = "perform"
9
+ commit_required_fields = ("cpt_code",)
10
+
11
+ cpt_code: str
12
+ notes: str | None = None
13
+
14
+ @property
15
+ def values(self) -> dict:
16
+ """The Perform command's field values."""
17
+ return {"cpt_code": self.cpt_code, "notes": self.notes}
@@ -6,9 +6,9 @@ class PlanCommand(_BaseCommand):
6
6
 
7
7
  class Meta:
8
8
  key = "plan"
9
- originate_required_fields = ("narrative",)
9
+ commit_required_fields = ("narrative",)
10
10
 
11
- narrative: str | None = None
11
+ narrative: str = ""
12
12
 
13
13
  @property
14
14
  def values(self) -> dict:
@@ -1,9 +1,12 @@
1
+ from dataclasses import dataclass
1
2
  from decimal import Decimal
2
3
  from enum import Enum
4
+ from typing import TypeVar
3
5
 
4
- from pydantic import Field
6
+ from pydantic import Field, conlist
5
7
 
6
8
  from canvas_sdk.commands.base import _BaseCommand
9
+ from canvas_sdk.commands.constants import ClinicalQuantity
7
10
 
8
11
 
9
12
  class PrescribeCommand(_BaseCommand):
@@ -11,7 +14,7 @@ class PrescribeCommand(_BaseCommand):
11
14
 
12
15
  class Meta:
13
16
  key = "prescribe"
14
- originate_required_fields = (
17
+ commit_required_fields = (
15
18
  "fdb_code",
16
19
  "sig",
17
20
  "quantity_to_dispense",
@@ -26,13 +29,13 @@ class PrescribeCommand(_BaseCommand):
26
29
  NOT_ALLOWED = "not_allowed"
27
30
 
28
31
  fdb_code: str | None = Field(default=None, json_schema_extra={"commands_api_name": "prescribe"})
29
- icd10_codes: list[str] | None = Field(
30
- None, json_schema_extra={"commands_api_name": "indications"}
32
+ icd10_codes: conlist(str, max_length=2) = Field(
33
+ [], json_schema_extra={"commands_api_name": "indications"}
31
34
  )
32
- sig: str | None = None
35
+ sig: str = ""
33
36
  days_supply: int | None = None
34
37
  quantity_to_dispense: Decimal | float | int | None = None
35
- type_to_dispense: str | None = None
38
+ type_to_dispense: ClinicalQuantity | None = None
36
39
  refills: int | None = None
37
40
  substitutions: Substitutions | None = None
38
41
  pharmacy: str | None = None
@@ -52,7 +55,7 @@ class PrescribeCommand(_BaseCommand):
52
55
  "quantity_to_dispense": (
53
56
  str(Decimal(self.quantity_to_dispense)) if self.quantity_to_dispense else None
54
57
  ),
55
- # "type_to_dispense": self.type_to_dispense,
58
+ "type_to_dispense": self.type_to_dispense if self.type_to_dispense else None,
56
59
  "refills": self.refills,
57
60
  "substitutions": self.substitutions.value if self.substitutions else None,
58
61
  "pharmacy": self.pharmacy,
@@ -8,7 +8,7 @@ class QuestionnaireCommand(_BaseCommand):
8
8
 
9
9
  class Meta:
10
10
  key = "questionnaire"
11
- originate_required_fields = ("questionnaire_id",)
11
+ commit_required_fields = ("questionnaire_id",)
12
12
 
13
13
  questionnaire_id: str | None = Field(
14
14
  default=None, json_schema_extra={"commands_api_name": "questionnaire"}
@@ -0,0 +1,16 @@
1
+ from canvas_sdk.commands.commands.prescribe import PrescribeCommand
2
+
3
+
4
+ class RefillCommand(PrescribeCommand):
5
+
6
+ class Meta:
7
+ key = "refill"
8
+ commit_required_fields = (
9
+ "fdb_code",
10
+ "sig",
11
+ "quantity_to_dispense",
12
+ "type_to_dispense",
13
+ "refills",
14
+ "substitutions",
15
+ "prescriber_id",
16
+ )
@@ -0,0 +1,26 @@
1
+ from pydantic import Field
2
+
3
+ from canvas_sdk.commands.base import _BaseCommand as BaseCommand
4
+
5
+
6
+ class RemoveAllergyCommand(BaseCommand):
7
+ """A class for managing a Remove Allergy command within a specific note."""
8
+
9
+ class Meta:
10
+ key = "removeAllergy"
11
+ commit_required_fields = ("allergy_id",)
12
+
13
+ allergy_id: str | None = Field(
14
+ description="The external ID of the allergy to remove.",
15
+ default=None,
16
+ json_schema_extra={"commands_api_name": "allergy"},
17
+ )
18
+ narrative: str | None = None
19
+
20
+ @property
21
+ def values(self) -> dict:
22
+ """The Remove Allergy command's field values."""
23
+ return {
24
+ "allergy_id": self.allergy_id,
25
+ "narrative": self.narrative,
26
+ }
@@ -8,7 +8,7 @@ class StopMedicationCommand(_BaseCommand):
8
8
 
9
9
  class Meta:
10
10
  key = "stopMedication"
11
- originate_required_fields = ("medication_id",)
11
+ commit_required_fields = ("medication_id",)
12
12
 
13
13
  # how do we make sure this is a valid medication_id for the patient?
14
14
  medication_id: str | None = Field(