canvas 0.34.1__py3-none-any.whl → 0.35.0__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.
- {canvas-0.34.1.dist-info → canvas-0.35.0.dist-info}/METADATA +1 -1
- {canvas-0.34.1.dist-info → canvas-0.35.0.dist-info}/RECORD +58 -50
- canvas_generated/messages/effects_pb2.py +4 -4
- canvas_generated/messages/effects_pb2.pyi +22 -2
- canvas_generated/messages/events_pb2.py +2 -2
- canvas_generated/messages/events_pb2.pyi +30 -0
- canvas_sdk/base.py +56 -0
- canvas_sdk/commands/base.py +22 -46
- canvas_sdk/commands/commands/adjust_prescription.py +0 -10
- canvas_sdk/commands/commands/allergy.py +0 -1
- canvas_sdk/commands/commands/assess.py +2 -2
- canvas_sdk/commands/commands/change_medication.py +58 -0
- canvas_sdk/commands/commands/close_goal.py +0 -1
- canvas_sdk/commands/commands/diagnose.py +0 -1
- canvas_sdk/commands/commands/exam.py +0 -1
- canvas_sdk/commands/commands/family_history.py +0 -1
- canvas_sdk/commands/commands/follow_up.py +4 -2
- canvas_sdk/commands/commands/goal.py +8 -7
- canvas_sdk/commands/commands/history_present_illness.py +0 -1
- canvas_sdk/commands/commands/imaging_order.py +9 -8
- canvas_sdk/commands/commands/instruct.py +2 -2
- canvas_sdk/commands/commands/lab_order.py +10 -9
- canvas_sdk/commands/commands/medical_history.py +0 -1
- canvas_sdk/commands/commands/medication_statement.py +0 -1
- canvas_sdk/commands/commands/past_surgical_history.py +0 -1
- canvas_sdk/commands/commands/perform.py +3 -2
- canvas_sdk/commands/commands/plan.py +0 -1
- canvas_sdk/commands/commands/prescribe.py +0 -9
- canvas_sdk/commands/commands/refer.py +10 -10
- canvas_sdk/commands/commands/refill.py +0 -9
- canvas_sdk/commands/commands/remove_allergy.py +0 -1
- canvas_sdk/commands/commands/resolve_condition.py +3 -2
- canvas_sdk/commands/commands/review_of_systems.py +0 -1
- canvas_sdk/commands/commands/stop_medication.py +0 -1
- canvas_sdk/commands/commands/structured_assessment.py +0 -1
- canvas_sdk/commands/commands/task.py +0 -4
- canvas_sdk/commands/commands/update_diagnosis.py +8 -6
- canvas_sdk/commands/commands/update_goal.py +0 -1
- canvas_sdk/commands/commands/vitals.py +0 -1
- canvas_sdk/effects/note/__init__.py +10 -0
- canvas_sdk/effects/note/appointment.py +148 -0
- canvas_sdk/effects/note/base.py +129 -0
- canvas_sdk/effects/note/note.py +79 -0
- canvas_sdk/effects/patient/__init__.py +3 -0
- canvas_sdk/effects/patient/base.py +123 -0
- canvas_sdk/utils/http.py +7 -26
- canvas_sdk/utils/metrics.py +192 -0
- canvas_sdk/utils/plugins.py +24 -0
- canvas_sdk/v1/data/__init__.py +4 -0
- canvas_sdk/v1/data/message.py +82 -0
- plugin_runner/load_all_plugins.py +0 -3
- plugin_runner/plugin_runner.py +107 -114
- plugin_runner/sandbox.py +3 -0
- protobufs/canvas_generated/messages/effects.proto +13 -0
- protobufs/canvas_generated/messages/events.proto +16 -0
- settings.py +4 -0
- canvas_sdk/utils/stats.py +0 -74
- {canvas-0.34.1.dist-info → canvas-0.35.0.dist-info}/WHEEL +0 -0
- {canvas-0.34.1.dist-info → canvas-0.35.0.dist-info}/entry_points.txt +0 -0
canvas_sdk/base.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from datetime import date, datetime
|
|
2
2
|
from enum import Enum
|
|
3
3
|
from typing import Any
|
|
4
|
+
from uuid import UUID
|
|
4
5
|
|
|
5
6
|
from pydantic import BaseModel, ConfigDict
|
|
6
7
|
from pydantic_core import InitErrorDetails, PydanticCustomError, ValidationError
|
|
@@ -51,3 +52,58 @@ class Model(BaseModel):
|
|
|
51
52
|
self.model_validate(self)
|
|
52
53
|
if error_details := self._get_error_details(method):
|
|
53
54
|
raise ValidationError.from_exception_data(self.__class__.__name__, error_details)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class TrackableFieldsModel(Model):
|
|
58
|
+
"""
|
|
59
|
+
A base model with additional functionality for tracking modified fields.
|
|
60
|
+
|
|
61
|
+
Attributes:
|
|
62
|
+
_dirty_keys (set[str]): A set to track which fields have been modified.
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
_dirty_excluded_keys: list[str] = [
|
|
66
|
+
"note_uuid",
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
_dirty_keys: set[str] = set()
|
|
70
|
+
|
|
71
|
+
def __init__(self, /, **data: Any) -> None:
|
|
72
|
+
"""Initialize the command and mark all provided keys as dirty."""
|
|
73
|
+
super().__init__(**data)
|
|
74
|
+
|
|
75
|
+
# Initialize a set to track which fields have been modified.
|
|
76
|
+
self._dirty_keys = set()
|
|
77
|
+
|
|
78
|
+
# Explicitly mark all keys provided in the constructor as dirty.
|
|
79
|
+
self._dirty_keys.update(data.keys())
|
|
80
|
+
|
|
81
|
+
def __setattr__(self, name: str, value: Any) -> None:
|
|
82
|
+
"""Set an attribute and mark it as dirty unless excluded."""
|
|
83
|
+
if not name.startswith("_") and name not in self._dirty_excluded_keys:
|
|
84
|
+
self._dirty_keys.add(name)
|
|
85
|
+
super().__setattr__(name, value)
|
|
86
|
+
|
|
87
|
+
def is_dirty(self, key: str) -> bool:
|
|
88
|
+
"""Returns True if the given property has been modified (i.e. marked as dirty), False otherwise."""
|
|
89
|
+
return key in self._dirty_keys
|
|
90
|
+
|
|
91
|
+
@property
|
|
92
|
+
def values(self) -> dict:
|
|
93
|
+
"""Return a dictionary of modified attributes with type-specific transformations."""
|
|
94
|
+
result = {}
|
|
95
|
+
for key in self._dirty_keys:
|
|
96
|
+
value = getattr(self, key)
|
|
97
|
+
if isinstance(value, Enum):
|
|
98
|
+
# If it's an enum, use its .value.
|
|
99
|
+
result[key] = value.value if value else None
|
|
100
|
+
elif isinstance(value, date | datetime):
|
|
101
|
+
# If it's a date/datetime, use isoformat().
|
|
102
|
+
result[key] = value.isoformat() if value else None
|
|
103
|
+
elif isinstance(value, UUID):
|
|
104
|
+
# If it's a UUID, use its string representation.
|
|
105
|
+
result[key] = str(value) if value else None
|
|
106
|
+
else:
|
|
107
|
+
# For strings, integers, or any other type, return as is.
|
|
108
|
+
result[key] = value
|
|
109
|
+
return result
|
canvas_sdk/commands/base.py
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import datetime
|
|
2
1
|
import json
|
|
3
2
|
import re
|
|
4
|
-
from enum import
|
|
3
|
+
from enum import EnumType
|
|
5
4
|
from types import NoneType, UnionType
|
|
6
5
|
from typing import Any, Union, get_args, get_origin
|
|
7
|
-
from uuid import UUID
|
|
8
6
|
|
|
9
|
-
from
|
|
7
|
+
from django.core.exceptions import ImproperlyConfigured
|
|
8
|
+
|
|
9
|
+
from canvas_sdk.base import TrackableFieldsModel
|
|
10
10
|
from canvas_sdk.commands.constants import Coding
|
|
11
11
|
from canvas_sdk.effects import Effect
|
|
12
12
|
from canvas_sdk.effects.protocol_card import Recommendation
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
class _BaseCommand(
|
|
15
|
+
class _BaseCommand(TrackableFieldsModel):
|
|
16
16
|
class Meta:
|
|
17
17
|
key = ""
|
|
18
18
|
originate_required_fields = ("note_uuid",)
|
|
@@ -21,34 +21,29 @@ class _BaseCommand(Model):
|
|
|
21
21
|
commit_required_fields = ("command_uuid",)
|
|
22
22
|
enter_in_error_required_fields = ("command_uuid",)
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
_dirty_excluded_keys = [
|
|
25
|
+
"note_uuid",
|
|
26
|
+
"command_uuid",
|
|
27
|
+
]
|
|
26
28
|
|
|
27
29
|
def __init__(self, /, **data: Any) -> None:
|
|
28
30
|
"""Initialize the command and mark all provided keys as dirty."""
|
|
29
31
|
super().__init__(**data)
|
|
30
32
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
self._dirty_keys.update(data.keys())
|
|
33
|
+
def __init_subclass__(cls, **kwargs: Any) -> None:
|
|
34
|
+
"""Validate that the command has a key and required fields."""
|
|
35
|
+
if not hasattr(cls.Meta, "key") or not cls.Meta.key:
|
|
36
|
+
raise ImproperlyConfigured(f"Command {cls.__name__!r} must specify Meta.key.")
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
):
|
|
43
|
-
self._dirty_keys.add(name)
|
|
44
|
-
super().__setattr__(name, value)
|
|
38
|
+
if hasattr(cls.Meta, "commit_required_fields"):
|
|
39
|
+
command_fields = set(cls.__pydantic_fields__.keys() | cls.__annotations__.keys())
|
|
40
|
+
for field in cls.Meta.commit_required_fields:
|
|
41
|
+
if field not in command_fields:
|
|
42
|
+
raise ImproperlyConfigured(f"Command {cls.__name__!r} must specify {field}.")
|
|
45
43
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return
|
|
49
|
-
|
|
50
|
-
def constantized_key(self) -> str:
|
|
51
|
-
return re.sub(r"(?<!^)(?=[A-Z])", "_", self.Meta.key).upper()
|
|
44
|
+
@classmethod
|
|
45
|
+
def constantized_key(cls) -> str:
|
|
46
|
+
return re.sub(r"(?<!^)(?=[A-Z])", "_", cls.Meta.key).upper()
|
|
52
47
|
|
|
53
48
|
note_uuid: str | None = None
|
|
54
49
|
command_uuid: str | None = None
|
|
@@ -58,26 +53,6 @@ class _BaseCommand(Model):
|
|
|
58
53
|
command_required_fields = super()._get_effect_method_required_fields(method)
|
|
59
54
|
return tuple(set(base_required_fields) | set(command_required_fields))
|
|
60
55
|
|
|
61
|
-
@property
|
|
62
|
-
def values(self) -> dict:
|
|
63
|
-
"""Return a dictionary of modified attributes with type-specific transformations."""
|
|
64
|
-
result = {}
|
|
65
|
-
for key in self._dirty_keys:
|
|
66
|
-
value = getattr(self, key)
|
|
67
|
-
if isinstance(value, Enum):
|
|
68
|
-
# If it's an enum, use its .value.
|
|
69
|
-
result[key] = value.value if value else None
|
|
70
|
-
elif isinstance(value, datetime.date | datetime.datetime):
|
|
71
|
-
# If it's a date/datetime, use isoformat().
|
|
72
|
-
result[key] = value.isoformat() if value else None
|
|
73
|
-
elif isinstance(value, UUID):
|
|
74
|
-
# If it's a UUID, use its string representation.
|
|
75
|
-
result[key] = str(value) if value else None
|
|
76
|
-
else:
|
|
77
|
-
# For strings, integers, or any other type, return as is.
|
|
78
|
-
result[key] = value
|
|
79
|
-
return result
|
|
80
|
-
|
|
81
56
|
@property
|
|
82
57
|
def coding_filter(self) -> Coding | None:
|
|
83
58
|
"""The coding filter used for command insertion in protocol cards."""
|
|
@@ -115,6 +90,7 @@ class _BaseCommand(Model):
|
|
|
115
90
|
base_properties = {"note_uuid", "command_uuid"}
|
|
116
91
|
schema = cls.model_json_schema()
|
|
117
92
|
required_fields: tuple = getattr(cls.Meta, "commit_required_fields", ())
|
|
93
|
+
|
|
118
94
|
return {
|
|
119
95
|
definition.get("commands_api_name", name): {
|
|
120
96
|
"required": name in required_fields,
|
|
@@ -8,16 +8,6 @@ class AdjustPrescriptionCommand(RefillCommand):
|
|
|
8
8
|
|
|
9
9
|
class Meta:
|
|
10
10
|
key = "adjustPrescription"
|
|
11
|
-
commit_required_fields = (
|
|
12
|
-
"fdb_code",
|
|
13
|
-
"sig",
|
|
14
|
-
"quantity_to_dispense",
|
|
15
|
-
"type_to_dispense",
|
|
16
|
-
"refills",
|
|
17
|
-
"substitutions",
|
|
18
|
-
"prescriber_id",
|
|
19
|
-
"new_fdb_code",
|
|
20
|
-
)
|
|
21
11
|
|
|
22
12
|
new_fdb_code: str | None = Field(
|
|
23
13
|
default=None, json_schema_extra={"commands_api_name": "change_medication_to"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
|
+
from uuid import UUID
|
|
2
3
|
|
|
3
4
|
from pydantic import Field
|
|
4
5
|
|
|
@@ -10,14 +11,13 @@ class AssessCommand(_BaseCommand):
|
|
|
10
11
|
|
|
11
12
|
class Meta:
|
|
12
13
|
key = "assess"
|
|
13
|
-
commit_required_fields = ("condition_id",)
|
|
14
14
|
|
|
15
15
|
class Status(Enum):
|
|
16
16
|
IMPROVED = "improved"
|
|
17
17
|
STABLE = "stable"
|
|
18
18
|
DETERIORATED = "deteriorated"
|
|
19
19
|
|
|
20
|
-
condition_id: str | None = Field(
|
|
20
|
+
condition_id: UUID | str | None = Field(
|
|
21
21
|
default=None, json_schema_extra={"commands_api_name": "condition"}
|
|
22
22
|
)
|
|
23
23
|
background: str | None = None
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
from typing import Literal
|
|
2
|
+
|
|
3
|
+
from pydantic import Field
|
|
4
|
+
from pydantic_core import InitErrorDetails
|
|
5
|
+
|
|
6
|
+
from canvas_sdk.commands.base import _BaseCommand as BaseCommand
|
|
7
|
+
from canvas_sdk.v1.data import Medication, Note
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ChangeMedicationCommand(BaseCommand):
|
|
11
|
+
"""A class for managing a ChangeMedication command within a specific note."""
|
|
12
|
+
|
|
13
|
+
class Meta:
|
|
14
|
+
key = "changeMedication"
|
|
15
|
+
commit_required_fields = ("medication_id",)
|
|
16
|
+
|
|
17
|
+
medication_id: str | None = Field(
|
|
18
|
+
default=None, json_schema_extra={"commands_api_name": "medication"}
|
|
19
|
+
)
|
|
20
|
+
sig: str | None = None
|
|
21
|
+
|
|
22
|
+
def _get_error_details(
|
|
23
|
+
self, method: Literal["originate", "edit", "delete", "commit", "enter_in_error"]
|
|
24
|
+
) -> list[InitErrorDetails]:
|
|
25
|
+
errors = super()._get_error_details(method)
|
|
26
|
+
|
|
27
|
+
note = None
|
|
28
|
+
|
|
29
|
+
if self.note_uuid:
|
|
30
|
+
note = Note.objects.filter(id=self.note_uuid).first()
|
|
31
|
+
|
|
32
|
+
if not note:
|
|
33
|
+
errors.append(
|
|
34
|
+
self._create_error_detail(
|
|
35
|
+
"value",
|
|
36
|
+
f"note with id {self.note_uuid} not found.",
|
|
37
|
+
self.note_uuid,
|
|
38
|
+
)
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
if self.medication_id and note:
|
|
42
|
+
medication = Medication.objects.filter(
|
|
43
|
+
id=self.medication_id, patient=note.patient
|
|
44
|
+
).first()
|
|
45
|
+
|
|
46
|
+
if not medication:
|
|
47
|
+
errors.append(
|
|
48
|
+
self._create_error_detail(
|
|
49
|
+
"value",
|
|
50
|
+
f"Medication with Id {self.medication_id} not found or not associated with the patient.",
|
|
51
|
+
self.medication_id,
|
|
52
|
+
)
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
return errors
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
__exports__ = ("ChangeMedicationCommand",)
|
|
@@ -2,6 +2,7 @@ from datetime import date
|
|
|
2
2
|
from typing import Literal
|
|
3
3
|
from uuid import UUID
|
|
4
4
|
|
|
5
|
+
from pydantic import Field
|
|
5
6
|
from pydantic_core import InitErrorDetails
|
|
6
7
|
|
|
7
8
|
from canvas_sdk.commands.base import _BaseCommand
|
|
@@ -14,11 +15,12 @@ class FollowUpCommand(_BaseCommand):
|
|
|
14
15
|
|
|
15
16
|
class Meta:
|
|
16
17
|
key = "followUp"
|
|
17
|
-
commit_required_fields = ("requested_date", "note_type")
|
|
18
18
|
|
|
19
19
|
structured: bool = False
|
|
20
20
|
requested_date: date | None = None
|
|
21
|
-
note_type_id: UUID | str | None =
|
|
21
|
+
note_type_id: UUID | str | None = Field(
|
|
22
|
+
default=None, json_schema_extra={"commands_api_name": "note_type"}
|
|
23
|
+
)
|
|
22
24
|
reason_for_visit: Coding | UUID | str | None = None
|
|
23
25
|
comment: str | None = None
|
|
24
26
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
from datetime import datetime
|
|
2
|
-
from enum import
|
|
1
|
+
from datetime import date, datetime
|
|
2
|
+
from enum import StrEnum
|
|
3
|
+
|
|
4
|
+
from pydantic import Field
|
|
3
5
|
|
|
4
6
|
from canvas_sdk.commands.base import _BaseCommand
|
|
5
7
|
|
|
@@ -9,14 +11,13 @@ class GoalCommand(_BaseCommand):
|
|
|
9
11
|
|
|
10
12
|
class Meta:
|
|
11
13
|
key = "goal"
|
|
12
|
-
commit_required_fields = ("goal_statement", "start_date")
|
|
13
14
|
|
|
14
|
-
class Priority(
|
|
15
|
+
class Priority(StrEnum):
|
|
15
16
|
HIGH = "high-priority"
|
|
16
17
|
MEDIUM = "medium-priority"
|
|
17
18
|
LOW = "low-priority"
|
|
18
19
|
|
|
19
|
-
class AchievementStatus(
|
|
20
|
+
class AchievementStatus(StrEnum):
|
|
20
21
|
IN_PROGRESS = "in-progress"
|
|
21
22
|
IMPROVING = "improving"
|
|
22
23
|
WORSENING = "worsening"
|
|
@@ -28,8 +29,8 @@ class GoalCommand(_BaseCommand):
|
|
|
28
29
|
NOT_ATTAINABLE = "not-attainable"
|
|
29
30
|
|
|
30
31
|
goal_statement: str = ""
|
|
31
|
-
start_date:
|
|
32
|
-
due_date:
|
|
32
|
+
start_date: date = Field(default_factory=lambda: datetime.now().date())
|
|
33
|
+
due_date: date | None = None
|
|
33
34
|
achievement_status: AchievementStatus | None = None
|
|
34
35
|
priority: Priority | None = None
|
|
35
36
|
progress: str | None = None
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
2
|
|
|
3
|
+
from pydantic import Field
|
|
4
|
+
|
|
3
5
|
from canvas_sdk.commands.base import _BaseCommand as BaseCommand
|
|
4
6
|
from canvas_sdk.commands.constants import ServiceProvider
|
|
5
7
|
|
|
@@ -9,21 +11,20 @@ class ImagingOrderCommand(BaseCommand):
|
|
|
9
11
|
|
|
10
12
|
class Meta:
|
|
11
13
|
key = "imagingOrder"
|
|
12
|
-
commit_required_fields = (
|
|
13
|
-
"image_code",
|
|
14
|
-
"diagnosis_codes",
|
|
15
|
-
"ordering_provider",
|
|
16
|
-
)
|
|
17
14
|
|
|
18
15
|
class Priority(Enum):
|
|
19
16
|
ROUTINE = "Routine"
|
|
20
17
|
URGENT = "Urgent"
|
|
21
18
|
|
|
22
|
-
image_code: str | None = None
|
|
23
|
-
diagnosis_codes: list[str] =
|
|
19
|
+
image_code: str | None = Field(default=None, json_schema_extra={"commands_api_name": "image"})
|
|
20
|
+
diagnosis_codes: list[str] | None = Field(
|
|
21
|
+
default=None, json_schema_extra={"commands_api_name": "indications"}
|
|
22
|
+
)
|
|
24
23
|
priority: Priority | None = None
|
|
25
24
|
additional_details: str | None = None
|
|
26
|
-
service_provider: ServiceProvider | None =
|
|
25
|
+
service_provider: ServiceProvider | None = Field(
|
|
26
|
+
default=None, json_schema_extra={"commands_api_name": "ordering_provider"}
|
|
27
|
+
)
|
|
27
28
|
comment: str | None = None
|
|
28
29
|
ordering_provider_key: str | None = None
|
|
29
30
|
linked_items_urns: list[str] | None = None
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from pydantic import Field
|
|
1
2
|
from pydantic_core import InitErrorDetails
|
|
2
3
|
|
|
3
4
|
from canvas_sdk.commands.base import _BaseCommand as BaseCommand
|
|
@@ -9,9 +10,8 @@ class InstructCommand(BaseCommand):
|
|
|
9
10
|
|
|
10
11
|
class Meta:
|
|
11
12
|
key = "instruct"
|
|
12
|
-
commit_required_fields = ("instruction",)
|
|
13
13
|
|
|
14
|
-
coding: Coding | None = None
|
|
14
|
+
coding: Coding | None = Field(default=None, json_schema_extra={"commands_api_name": "instruct"})
|
|
15
15
|
comment: str | None = None
|
|
16
16
|
|
|
17
17
|
def _get_error_details(self, method: str) -> list[InitErrorDetails]:
|
|
@@ -2,6 +2,7 @@ from typing import Literal
|
|
|
2
2
|
from uuid import UUID
|
|
3
3
|
|
|
4
4
|
from django.db.models.query_utils import Q
|
|
5
|
+
from pydantic import Field
|
|
5
6
|
from pydantic_core import InitErrorDetails
|
|
6
7
|
|
|
7
8
|
from canvas_sdk.commands.base import _BaseCommand as BaseCommand
|
|
@@ -13,17 +14,17 @@ class LabOrderCommand(BaseCommand):
|
|
|
13
14
|
|
|
14
15
|
class Meta:
|
|
15
16
|
key = "labOrder"
|
|
16
|
-
commit_required_fields = (
|
|
17
|
-
"lab_partner",
|
|
18
|
-
"tests_order_codes",
|
|
19
|
-
"ordering_provider",
|
|
20
|
-
"diagnosis_codes",
|
|
21
|
-
)
|
|
22
17
|
|
|
23
18
|
lab_partner: UUID | str | None = None
|
|
24
|
-
tests_order_codes: list[str] =
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
tests_order_codes: list[str] = Field(
|
|
20
|
+
default=[], json_schema_extra={"commands_api_name": "tests"}
|
|
21
|
+
)
|
|
22
|
+
ordering_provider_key: str | None = Field(
|
|
23
|
+
default=None, json_schema_extra={"commands_api_name": "ordering_provider"}
|
|
24
|
+
)
|
|
25
|
+
diagnosis_codes: list[str] = Field(
|
|
26
|
+
default=[], json_schema_extra={"commands_api_name": "diagnosis"}
|
|
27
|
+
)
|
|
27
28
|
fasting_required: bool = False
|
|
28
29
|
comment: str | None = None
|
|
29
30
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from pydantic import Field
|
|
2
|
+
|
|
1
3
|
from canvas_sdk.commands.base import _BaseCommand as BaseCommand
|
|
2
4
|
|
|
3
5
|
|
|
@@ -6,9 +8,8 @@ class PerformCommand(BaseCommand):
|
|
|
6
8
|
|
|
7
9
|
class Meta:
|
|
8
10
|
key = "perform"
|
|
9
|
-
commit_required_fields = ("cpt_code",)
|
|
10
11
|
|
|
11
|
-
cpt_code: str | None = None
|
|
12
|
+
cpt_code: str | None = Field(default=None, json_schema_extra={"commands_api_name": "perform"})
|
|
12
13
|
notes: str | None = None
|
|
13
14
|
|
|
14
15
|
|
|
@@ -12,15 +12,6 @@ class PrescribeCommand(_BaseCommand):
|
|
|
12
12
|
|
|
13
13
|
class Meta:
|
|
14
14
|
key = "prescribe"
|
|
15
|
-
commit_required_fields = (
|
|
16
|
-
"fdb_code",
|
|
17
|
-
"sig",
|
|
18
|
-
"quantity_to_dispense",
|
|
19
|
-
"type_to_dispense",
|
|
20
|
-
"refills",
|
|
21
|
-
"substitutions",
|
|
22
|
-
"prescriber_id",
|
|
23
|
-
)
|
|
24
15
|
|
|
25
16
|
class Substitutions(Enum):
|
|
26
17
|
ALLOWED = "allowed"
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
2
|
|
|
3
|
+
from pydantic import Field
|
|
4
|
+
|
|
3
5
|
from canvas_sdk.commands.base import _BaseCommand as BaseCommand
|
|
4
6
|
from canvas_sdk.commands.constants import ServiceProvider
|
|
5
7
|
|
|
@@ -9,12 +11,6 @@ class ReferCommand(BaseCommand):
|
|
|
9
11
|
|
|
10
12
|
class Meta:
|
|
11
13
|
key = "refer"
|
|
12
|
-
commit_required_fields = (
|
|
13
|
-
"service_provider",
|
|
14
|
-
"diagnosis_codes",
|
|
15
|
-
"clinical_question",
|
|
16
|
-
"notes_to_specialist",
|
|
17
|
-
)
|
|
18
14
|
|
|
19
15
|
class ClinicalQuestion(Enum):
|
|
20
16
|
"""Clinical question choices."""
|
|
@@ -30,8 +26,12 @@ class ReferCommand(BaseCommand):
|
|
|
30
26
|
ROUTINE = "Routine"
|
|
31
27
|
URGENT = "Urgent"
|
|
32
28
|
|
|
33
|
-
service_provider: ServiceProvider | None =
|
|
34
|
-
|
|
29
|
+
service_provider: ServiceProvider | None = Field(
|
|
30
|
+
default=None, json_schema_extra={"commands_api_name": "refer_to"}
|
|
31
|
+
)
|
|
32
|
+
diagnosis_codes: list[str] = Field(
|
|
33
|
+
default=[], json_schema_extra={"commands_api_name": "indications"}
|
|
34
|
+
)
|
|
35
35
|
clinical_question: ClinicalQuestion | None = None
|
|
36
36
|
priority: Priority | None = None
|
|
37
37
|
notes_to_specialist: str | None = None
|
|
@@ -44,8 +44,8 @@ class ReferCommand(BaseCommand):
|
|
|
44
44
|
"""The Refer command's field values."""
|
|
45
45
|
values = super().values
|
|
46
46
|
|
|
47
|
-
if self.is_dirty("service_provider"):
|
|
48
|
-
values["service_provider"] = self.service_provider.
|
|
47
|
+
if self.service_provider and self.is_dirty("service_provider"):
|
|
48
|
+
values["service_provider"] = self.service_provider.model_dump()
|
|
49
49
|
|
|
50
50
|
return values
|
|
51
51
|
|
|
@@ -12,15 +12,6 @@ class RefillCommand(PrescribeCommand):
|
|
|
12
12
|
|
|
13
13
|
class Meta:
|
|
14
14
|
key = "refill"
|
|
15
|
-
commit_required_fields = (
|
|
16
|
-
"fdb_code",
|
|
17
|
-
"sig",
|
|
18
|
-
"quantity_to_dispense",
|
|
19
|
-
"type_to_dispense",
|
|
20
|
-
"refills",
|
|
21
|
-
"substitutions",
|
|
22
|
-
"prescriber_id",
|
|
23
|
-
)
|
|
24
15
|
|
|
25
16
|
def _get_error_details(
|
|
26
17
|
self, method: Literal["originate", "edit", "delete", "commit", "enter_in_error"]
|
|
@@ -14,9 +14,10 @@ class ResolveConditionCommand(BaseCommand):
|
|
|
14
14
|
|
|
15
15
|
class Meta:
|
|
16
16
|
key = "resolveCondition"
|
|
17
|
-
commit_required_fields = ("condition_id",)
|
|
18
17
|
|
|
19
|
-
condition_id: UUID | str | None =
|
|
18
|
+
condition_id: UUID | str | None = Field(
|
|
19
|
+
default=None, json_schema_extra={"commands_api_name": "condition"}
|
|
20
|
+
)
|
|
20
21
|
show_in_condition_list: bool = False
|
|
21
22
|
rationale: str | None = Field(max_length=1024, default=None)
|
|
22
23
|
|