canvas 0.21.0__py3-none-any.whl → 0.22.1__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.21.0.dist-info → canvas-0.22.1.dist-info}/METADATA +1 -1
- {canvas-0.21.0.dist-info → canvas-0.22.1.dist-info}/RECORD +31 -25
- canvas_generated/messages/effects_pb2.py +2 -2
- canvas_generated/messages/effects_pb2.pyi +40 -0
- canvas_generated/messages/events_pb2.py +2 -2
- canvas_generated/messages/events_pb2.pyi +108 -0
- canvas_sdk/commands/__init__.py +8 -0
- canvas_sdk/commands/base.py +1 -0
- canvas_sdk/commands/commands/__init__.py +0 -0
- canvas_sdk/commands/commands/adjust_prescription.py +24 -0
- canvas_sdk/commands/commands/imaging_order.py +39 -0
- canvas_sdk/commands/commands/instruct.py +17 -1
- canvas_sdk/commands/commands/lab_order.py +11 -6
- canvas_sdk/commands/commands/prescribe.py +1 -1
- canvas_sdk/commands/commands/questionnaire/__init__.py +102 -0
- canvas_sdk/commands/commands/questionnaire/question.py +134 -0
- canvas_sdk/commands/commands/refer.py +50 -0
- canvas_sdk/commands/commands/refill.py +28 -0
- canvas_sdk/commands/commands/resolve_condition.py +43 -0
- canvas_sdk/commands/constants.py +34 -0
- canvas_sdk/commands/tests/protocol/tests.py +10 -1
- canvas_sdk/commands/tests/test_utils.py +4 -1
- canvas_sdk/effects/banner_alert/tests.py +10 -2
- canvas_sdk/v1/data/condition.py +4 -2
- canvas_sdk/v1/data/medication.py +4 -2
- plugin_runner/installation.py +1 -2
- plugin_runner/plugin_runner.py +34 -2
- protobufs/canvas_generated/messages/effects.proto +25 -1
- protobufs/canvas_generated/messages/events.proto +54 -36
- canvas_sdk/commands/commands/questionnaire.py +0 -16
- {canvas-0.21.0.dist-info → canvas-0.22.1.dist-info}/WHEEL +0 -0
- {canvas-0.21.0.dist-info → canvas-0.22.1.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from typing import Literal
|
|
2
|
+
from uuid import UUID
|
|
3
|
+
|
|
4
|
+
from django.db.models.expressions import Subquery
|
|
5
|
+
from pydantic import Field
|
|
6
|
+
from pydantic_core import InitErrorDetails
|
|
7
|
+
|
|
8
|
+
from canvas_sdk.commands.base import _BaseCommand as BaseCommand
|
|
9
|
+
from canvas_sdk.v1.data import Condition, Note
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ResolveConditionCommand(BaseCommand):
|
|
13
|
+
"""A class for managing a ResolveCondition command within a specific note."""
|
|
14
|
+
|
|
15
|
+
class Meta:
|
|
16
|
+
key = "resolveCondition"
|
|
17
|
+
commit_required_fields = ("condition_id",)
|
|
18
|
+
|
|
19
|
+
condition_id: UUID | str | None = None
|
|
20
|
+
show_in_condition_list: bool = False
|
|
21
|
+
rationale: str | None = Field(max_length=1024, default=None)
|
|
22
|
+
|
|
23
|
+
def _get_error_details(
|
|
24
|
+
self, method: Literal["originate", "edit", "delete", "commit", "enter_in_error"]
|
|
25
|
+
) -> list[InitErrorDetails]:
|
|
26
|
+
errors = super()._get_error_details(method)
|
|
27
|
+
|
|
28
|
+
if self.condition_id:
|
|
29
|
+
subquery = Subquery(Note.objects.filter(id=self.note_uuid).values("patient_id")[:1])
|
|
30
|
+
if (
|
|
31
|
+
not Condition.objects.active()
|
|
32
|
+
.filter(id=self.condition_id, patient=subquery)
|
|
33
|
+
.exists()
|
|
34
|
+
):
|
|
35
|
+
errors.append(
|
|
36
|
+
self._create_error_detail(
|
|
37
|
+
"value",
|
|
38
|
+
f"Condition with id {self.condition_id} does not exist.",
|
|
39
|
+
self.condition_id,
|
|
40
|
+
)
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
return errors
|
canvas_sdk/commands/constants.py
CHANGED
|
@@ -1,7 +1,28 @@
|
|
|
1
|
+
from enum import StrEnum
|
|
1
2
|
from typing import NotRequired
|
|
2
3
|
|
|
4
|
+
from pydantic import Field
|
|
3
5
|
from typing_extensions import TypedDict
|
|
4
6
|
|
|
7
|
+
from canvas_sdk.base import Model
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class CodeSystems(StrEnum):
|
|
11
|
+
"""A class representing different code systems and their URLs."""
|
|
12
|
+
|
|
13
|
+
SNOMED = "http://snomed.info/sct"
|
|
14
|
+
RXNORM = "http://www.nlm.nih.gov/research/umls/rxnorm"
|
|
15
|
+
LOINC = "http://loinc.org"
|
|
16
|
+
FDB = "http://www.fdbhealth.com/"
|
|
17
|
+
ICD10 = "ICD-10"
|
|
18
|
+
CVX = "http://hl7.org/fhir/sid/cvx"
|
|
19
|
+
CPT = "http://www.ama-assn.org/go/cpt"
|
|
20
|
+
NUCC = "http://www.nucc.org/"
|
|
21
|
+
NDC = "http://hl7.org/fhir/sid/ndc"
|
|
22
|
+
HCPCS = "http://www.cms.gov/medicare/coding/medhcpcsgeninfo"
|
|
23
|
+
UNITS_OF_MEASURE = "http://unitsofmeasure.org"
|
|
24
|
+
UNSTRUCTURED = "UNSTRUCTURED"
|
|
25
|
+
|
|
5
26
|
|
|
6
27
|
class Coding(TypedDict):
|
|
7
28
|
"""Coding object in Canvas."""
|
|
@@ -16,3 +37,16 @@ class ClinicalQuantity(TypedDict):
|
|
|
16
37
|
|
|
17
38
|
representative_ndc: str
|
|
18
39
|
ncpdp_quantity_qualifier_code: str
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class ServiceProvider(Model):
|
|
43
|
+
"""ServiceProvider model."""
|
|
44
|
+
|
|
45
|
+
first_name: str = Field(max_length=512)
|
|
46
|
+
last_name: str = Field(max_length=512)
|
|
47
|
+
specialty: str = Field(max_length=512)
|
|
48
|
+
practice_name: str = Field(max_length=512)
|
|
49
|
+
business_fax: str | None = Field(max_length=512, default=None)
|
|
50
|
+
business_phone: str | None = Field(max_length=512, default=None)
|
|
51
|
+
business_address: str | None = Field(max_length=512, default=None)
|
|
52
|
+
notes: str | None = Field(max_length=512, default=None)
|
|
@@ -49,7 +49,16 @@ def write_and_install_protocol_and_clean_up(
|
|
|
49
49
|
f"Loading plugin '{plugin_name}",
|
|
50
50
|
)
|
|
51
51
|
install_plugin(plugin_name, token)
|
|
52
|
-
message_received_event.wait(timeout=
|
|
52
|
+
message_received_event.wait(timeout=15.0)
|
|
53
|
+
|
|
54
|
+
# unfortunately sometimes the log websocket just doesn't return any
|
|
55
|
+
# messages, so asserting on the state of the timeout here causes failures
|
|
56
|
+
# even though the delay itself will cause the waiting test to pass (because
|
|
57
|
+
# the plugin has been loaded).
|
|
58
|
+
# timeout_not_hit = message_received_event.wait(timeout=15.0)
|
|
59
|
+
# if not timeout_not_hit:
|
|
60
|
+
# ws.close()
|
|
61
|
+
# assert timeout_not_hit, f"plugin loading message timeout hit: Loading plugin '{plugin_name}"
|
|
53
62
|
|
|
54
63
|
yield
|
|
55
64
|
|
|
@@ -367,6 +367,9 @@ def wait_for_log(
|
|
|
367
367
|
thread = threading.Thread(target=ws.run_forever)
|
|
368
368
|
thread.start()
|
|
369
369
|
|
|
370
|
-
connected_event.wait(timeout=5.0)
|
|
370
|
+
timeout_not_hit = connected_event.wait(timeout=5.0)
|
|
371
|
+
if not timeout_not_hit:
|
|
372
|
+
ws.close()
|
|
373
|
+
assert timeout_not_hit, "connection timeout hit"
|
|
371
374
|
|
|
372
375
|
return message_received_event, thread, ws
|
|
@@ -107,8 +107,16 @@ class Protocol(BaseProtocol):
|
|
|
107
107
|
)
|
|
108
108
|
response.raise_for_status()
|
|
109
109
|
|
|
110
|
-
message_received_event.wait(timeout=
|
|
111
|
-
|
|
110
|
+
message_received_event.wait(timeout=15.0)
|
|
111
|
+
|
|
112
|
+
# unfortunately sometimes the log websocket just doesn't return any
|
|
113
|
+
# messages, so asserting on the state of the timeout here causes failures
|
|
114
|
+
# even though the delay itself will cause the waiting test to pass (because
|
|
115
|
+
# the plugin has been loaded).
|
|
116
|
+
# timeout_not_hit = message_received_event.wait(timeout=15.0)
|
|
117
|
+
# if not timeout_not_hit:
|
|
118
|
+
# ws.close()
|
|
119
|
+
# assert timeout_not_hit, f"plugin loading message timeout hit: Loading plugin '{plugin_name}"
|
|
112
120
|
yield
|
|
113
121
|
|
|
114
122
|
ws.close()
|
canvas_sdk/v1/data/condition.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import cast
|
|
1
|
+
from typing import Self, cast
|
|
2
2
|
|
|
3
3
|
from django.db import models
|
|
4
4
|
from django.db.models import TextChoices
|
|
@@ -30,7 +30,9 @@ class ConditionQuerySet(
|
|
|
30
30
|
):
|
|
31
31
|
"""ConditionQuerySet."""
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
def active(self) -> Self:
|
|
34
|
+
"""Return a queryset that filters for active conditions."""
|
|
35
|
+
return self.committed().filter(clinical_status=ClinicalStatus.ACTIVE)
|
|
34
36
|
|
|
35
37
|
|
|
36
38
|
ConditionManager = BaseModelManager.from_queryset(ConditionQuerySet)
|
canvas_sdk/v1/data/medication.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import cast
|
|
1
|
+
from typing import Self, cast
|
|
2
2
|
|
|
3
3
|
from django.db import models
|
|
4
4
|
from django.db.models import TextChoices
|
|
@@ -21,7 +21,9 @@ class Status(TextChoices):
|
|
|
21
21
|
class MedicationQuerySet(ValueSetLookupQuerySet, CommittableQuerySetMixin, ForPatientQuerySetMixin):
|
|
22
22
|
"""MedicationQuerySet."""
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
def active(self) -> Self:
|
|
25
|
+
"""Filter by active medications."""
|
|
26
|
+
return self.committed().filter(status=Status.ACTIVE)
|
|
25
27
|
|
|
26
28
|
|
|
27
29
|
MedicationManager = BaseModelManager.from_queryset(MedicationQuerySet)
|
plugin_runner/installation.py
CHANGED
|
@@ -137,7 +137,7 @@ def download_plugin(plugin_package: str) -> Generator[Path, None, None]:
|
|
|
137
137
|
def install_plugin(plugin_name: str, attributes: PluginAttributes) -> None:
|
|
138
138
|
"""Install the given Plugin's package into the runtime."""
|
|
139
139
|
try:
|
|
140
|
-
log.info(f'Installing plugin "{plugin_name}"')
|
|
140
|
+
log.info(f'Installing plugin "{plugin_name}", version {attributes["version"]}')
|
|
141
141
|
|
|
142
142
|
plugin_installation_path = Path(PLUGIN_DIRECTORY) / plugin_name
|
|
143
143
|
|
|
@@ -224,7 +224,6 @@ def install_plugins() -> None:
|
|
|
224
224
|
|
|
225
225
|
for plugin_name, attributes in enabled_plugins().items():
|
|
226
226
|
try:
|
|
227
|
-
log.info(f'Installing plugin "{plugin_name}", version {attributes["version"]}')
|
|
228
227
|
install_plugin(plugin_name, attributes)
|
|
229
228
|
except PluginInstallationError:
|
|
230
229
|
disable_plugin(plugin_name)
|
plugin_runner/plugin_runner.py
CHANGED
|
@@ -13,6 +13,8 @@ from typing import Any, TypedDict
|
|
|
13
13
|
|
|
14
14
|
import grpc
|
|
15
15
|
import redis.asyncio as redis
|
|
16
|
+
from asgiref.sync import sync_to_async
|
|
17
|
+
from django.db import connections
|
|
16
18
|
|
|
17
19
|
from canvas_generated.messages.effects_pb2 import EffectType
|
|
18
20
|
from canvas_generated.messages.plugins_pb2 import ReloadPluginsRequest, ReloadPluginsResponse
|
|
@@ -30,6 +32,7 @@ from plugin_runner.installation import install_plugins
|
|
|
30
32
|
from plugin_runner.sandbox import Sandbox
|
|
31
33
|
from settings import (
|
|
32
34
|
CHANNEL_NAME,
|
|
35
|
+
IS_TESTING,
|
|
33
36
|
MANIFEST_FILE_NAME,
|
|
34
37
|
PLUGIN_DIRECTORY,
|
|
35
38
|
REDIS_ENDPOINT,
|
|
@@ -103,6 +106,25 @@ class PluginManifest(TypedDict):
|
|
|
103
106
|
readme: str
|
|
104
107
|
|
|
105
108
|
|
|
109
|
+
@sync_to_async
|
|
110
|
+
def reconnect_if_needed() -> None:
|
|
111
|
+
"""
|
|
112
|
+
Reconnect to the database if the connection has been closed.
|
|
113
|
+
|
|
114
|
+
NOTE: Django database functions are not async-safe and must be called
|
|
115
|
+
via e.g. sync_to_async. They will silently fail and block the handler
|
|
116
|
+
if called in an async context directly.
|
|
117
|
+
"""
|
|
118
|
+
if IS_TESTING:
|
|
119
|
+
return
|
|
120
|
+
|
|
121
|
+
connection = connections["default"]
|
|
122
|
+
|
|
123
|
+
if not connection.is_usable():
|
|
124
|
+
log.debug("Connection was unusable, reconnecting...")
|
|
125
|
+
connection.connect()
|
|
126
|
+
|
|
127
|
+
|
|
106
128
|
class PluginRunner(PluginRunnerServicer):
|
|
107
129
|
"""This process runs provided plugins that register interest in incoming events."""
|
|
108
130
|
|
|
@@ -118,6 +140,11 @@ class PluginRunner(PluginRunnerServicer):
|
|
|
118
140
|
event_name = event.name
|
|
119
141
|
relevant_plugins = EVENT_HANDLER_MAP[event_name]
|
|
120
142
|
|
|
143
|
+
log.debug(f"Processing {relevant_plugins} for {event_name}")
|
|
144
|
+
|
|
145
|
+
if relevant_plugins:
|
|
146
|
+
await reconnect_if_needed()
|
|
147
|
+
|
|
121
148
|
if event_type in [EventType.PLUGIN_CREATED, EventType.PLUGIN_UPDATED]:
|
|
122
149
|
plugin_name = event.target.id
|
|
123
150
|
# filter only for the plugin(s) that were created/updated
|
|
@@ -126,6 +153,8 @@ class PluginRunner(PluginRunnerServicer):
|
|
|
126
153
|
effect_list = []
|
|
127
154
|
|
|
128
155
|
for plugin_name in relevant_plugins:
|
|
156
|
+
log.debug(f"Processing {plugin_name}")
|
|
157
|
+
|
|
129
158
|
plugin = LOADED_PLUGINS[plugin_name]
|
|
130
159
|
handler_class = plugin["class"]
|
|
131
160
|
base_plugin_name = plugin_name.split(":")[0]
|
|
@@ -142,7 +171,7 @@ class PluginRunner(PluginRunnerServicer):
|
|
|
142
171
|
)
|
|
143
172
|
|
|
144
173
|
compute_start_time = time.time()
|
|
145
|
-
_effects = await
|
|
174
|
+
_effects = await sync_to_async(handler.compute)()
|
|
146
175
|
effects = [
|
|
147
176
|
Effect(
|
|
148
177
|
type=effect.type,
|
|
@@ -166,9 +195,12 @@ class PluginRunner(PluginRunnerServicer):
|
|
|
166
195
|
tags={"plugin": plugin_name},
|
|
167
196
|
)
|
|
168
197
|
except Exception as e:
|
|
198
|
+
log.error(f"Encountered exception in plugin {plugin_name}:")
|
|
199
|
+
|
|
169
200
|
for error_line_with_newlines in traceback.format_exception(e):
|
|
170
201
|
for error_line in error_line_with_newlines.split("\n"):
|
|
171
202
|
log.error(error_line)
|
|
203
|
+
|
|
172
204
|
continue
|
|
173
205
|
|
|
174
206
|
effect_list += effects
|
|
@@ -204,7 +236,7 @@ async def synchronize_plugins(run_once: bool = False) -> None:
|
|
|
204
236
|
"""
|
|
205
237
|
log.info(f'synchronize_plugins: listening for messages on pubsub channel "{CHANNEL_NAME}"')
|
|
206
238
|
|
|
207
|
-
|
|
239
|
+
_, pubsub = get_client()
|
|
208
240
|
await pubsub.psubscribe(CHANNEL_NAME)
|
|
209
241
|
|
|
210
242
|
while True:
|
|
@@ -163,6 +163,12 @@ enum EffectType {
|
|
|
163
163
|
COMMIT_CLOSE_GOAL_COMMAND = 131;
|
|
164
164
|
ENTER_IN_ERROR_CLOSE_GOAL_COMMAND = 132;
|
|
165
165
|
|
|
166
|
+
ORIGINATE_REFER_COMMAND = 139;
|
|
167
|
+
EDIT_REFER_COMMAND = 140;
|
|
168
|
+
DELETE_REFER_COMMAND = 141;
|
|
169
|
+
COMMIT_REFER_COMMAND = 142;
|
|
170
|
+
ENTER_IN_ERROR_REFER_COMMAND = 143;
|
|
171
|
+
|
|
166
172
|
CREATE_QUESTIONNAIRE_RESULT = 138;
|
|
167
173
|
|
|
168
174
|
ANNOTATE_PATIENT_CHART_CONDITION_RESULTS = 200;
|
|
@@ -203,6 +209,24 @@ enum EffectType {
|
|
|
203
209
|
COMMIT_FOLLOW_UP_COMMAND = 908;
|
|
204
210
|
ENTER_IN_ERROR_FOLLOW_UP_COMMAND = 909;
|
|
205
211
|
|
|
212
|
+
ORIGINATE_IMAGING_ORDER_COMMAND = 1100;
|
|
213
|
+
EDIT_IMAGING_ORDER_COMMAND = 1101;
|
|
214
|
+
DELETE_IMAGING_ORDER_COMMAND = 1102;
|
|
215
|
+
COMMIT_IMAGING_ORDER_COMMAND = 1103;
|
|
216
|
+
ENTER_IN_ERROR_IMAGING_ORDER_COMMAND = 1104;
|
|
217
|
+
|
|
218
|
+
ORIGINATE_RESOLVE_CONDITION_COMMAND = 1200;
|
|
219
|
+
EDIT_RESOLVE_CONDITION_COMMAND = 1201;
|
|
220
|
+
DELETE_RESOLVE_CONDITION_COMMAND = 1202;
|
|
221
|
+
COMMIT_RESOLVE_CONDITION_COMMAND = 1203;
|
|
222
|
+
ENTER_IN_ERROR_RESOLVE_CONDITION_COMMAND = 1204;
|
|
223
|
+
|
|
224
|
+
ORIGINATE_ADJUST_PRESCRIPTION_COMMAND = 1300;
|
|
225
|
+
EDIT_ADJUST_PRESCRIPTION_COMMAND = 1301;
|
|
226
|
+
DELETE_ADJUST_PRESCRIPTION_COMMAND = 1302;
|
|
227
|
+
COMMIT_ADJUST_PRESCRIPTION_COMMAND = 1303;
|
|
228
|
+
ENTER_IN_ERROR_ADJUST_PRESCRIPTION_COMMAND = 1304;
|
|
229
|
+
|
|
206
230
|
SHOW_ACTION_BUTTON = 1000;
|
|
207
231
|
|
|
208
232
|
PATIENT_PORTAL__INTAKE_FORM_RESULTS = 2000;
|
|
@@ -232,4 +256,4 @@ message Effect {
|
|
|
232
256
|
//Oneof effect_payload {
|
|
233
257
|
// ...
|
|
234
258
|
//}
|
|
235
|
-
}
|
|
259
|
+
}
|
|
@@ -136,18 +136,26 @@ enum EventType {
|
|
|
136
136
|
// ADJUST_DIAGNOSIS_COMMAND__PRE_EXECUTE_ACTION = 1010;
|
|
137
137
|
// ADJUST_DIAGNOSIS_COMMAND__POST_EXECUTE_ACTION = 1011;
|
|
138
138
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
139
|
+
ADJUST_PRESCRIPTION_COMMAND__PRE_ORIGINATE = 2000;
|
|
140
|
+
ADJUST_PRESCRIPTION_COMMAND__POST_ORIGINATE = 2001;
|
|
141
|
+
ADJUST_PRESCRIPTION_COMMAND__PRE_UPDATE = 2002;
|
|
142
|
+
ADJUST_PRESCRIPTION_COMMAND__POST_UPDATE = 2003;
|
|
143
|
+
ADJUST_PRESCRIPTION_COMMAND__PRE_COMMIT = 2004;
|
|
144
|
+
ADJUST_PRESCRIPTION_COMMAND__POST_COMMIT = 2005;
|
|
145
|
+
ADJUST_PRESCRIPTION_COMMAND__PRE_DELETE = 2006;
|
|
146
|
+
ADJUST_PRESCRIPTION_COMMAND__POST_DELETE = 2007;
|
|
147
|
+
ADJUST_PRESCRIPTION_COMMAND__PRE_ENTER_IN_ERROR = 2008;
|
|
148
|
+
ADJUST_PRESCRIPTION_COMMAND__POST_ENTER_IN_ERROR = 2009;
|
|
149
|
+
ADJUST_PRESCRIPTION_COMMAND__PRE_EXECUTE_ACTION = 2010;
|
|
150
|
+
ADJUST_PRESCRIPTION_COMMAND__POST_EXECUTE_ACTION = 2011;
|
|
151
|
+
ADJUST_PRESCRIPTION__PRESCRIBE__POST_SEARCH = 2012;
|
|
152
|
+
ADJUST_PRESCRIPTION__PRESCRIBE__PRE_SEARCH = 2013;
|
|
153
|
+
ADJUST_PRESCRIPTION__INDICATIONS__PRE_SEARCH = 2014;
|
|
154
|
+
ADJUST_PRESCRIPTION__INDICATIONS__POST_SEARCH = 2015;
|
|
155
|
+
ADJUST_PRESCRIPTION__PHARMACY__PRE_SEARCH = 2016;
|
|
156
|
+
ADJUST_PRESCRIPTION__PHARMACY__POST_SEARCH = 2017;
|
|
157
|
+
ADJUST_PRESCRIPTION__CHANGE_MEDICATION_TO__PRE_SEARCH = 2018;
|
|
158
|
+
ADJUST_PRESCRIPTION__CHANGE_MEDICATION_TO__POST_SEARCH = 2019;
|
|
151
159
|
|
|
152
160
|
// ADJUST_PROTOCOL_COMMAND__PRE_ORIGINATE = 3000;
|
|
153
161
|
// ADJUST_PROTOCOL_COMMAND__POST_ORIGINATE = 3001;
|
|
@@ -683,18 +691,26 @@ enum EventType {
|
|
|
683
691
|
REASON_FOR_VISIT__CODING__POST_SEARCH = 35012;
|
|
684
692
|
REASON_FOR_VISIT__CODING__PRE_SEARCH = 35013;
|
|
685
693
|
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
694
|
+
REFER_COMMAND__PRE_ORIGINATE = 36000;
|
|
695
|
+
REFER_COMMAND__POST_ORIGINATE = 36001;
|
|
696
|
+
REFER_COMMAND__PRE_UPDATE = 36002;
|
|
697
|
+
REFER_COMMAND__POST_UPDATE = 36003;
|
|
698
|
+
REFER_COMMAND__PRE_COMMIT = 36004;
|
|
699
|
+
REFER_COMMAND__POST_COMMIT = 36005;
|
|
700
|
+
REFER_COMMAND__PRE_DELETE = 36006;
|
|
701
|
+
REFER_COMMAND__POST_DELETE = 36007;
|
|
702
|
+
REFER_COMMAND__PRE_ENTER_IN_ERROR = 36008;
|
|
703
|
+
REFER_COMMAND__POST_ENTER_IN_ERROR = 36009;
|
|
704
|
+
REFER_COMMAND__PRE_EXECUTE_ACTION = 36010;
|
|
705
|
+
REFER_COMMAND__POST_EXECUTE_ACTION = 36011;
|
|
706
|
+
REFER_COMMAND__REFER_TO__POST_SEARCH = 36012;
|
|
707
|
+
REFER_COMMAND__REFER_TO__PRE_SEARCH = 36013;
|
|
708
|
+
REFER_COMMAND__INDICATIONS__POST_SEARCH = 36014;
|
|
709
|
+
REFER_COMMAND__INDICATIONS__PRE_SEARCH = 36015;
|
|
710
|
+
REFER_COMMAND__DOCUMENTS_TO_INCLUDE__POST_SEARCH = 36016;
|
|
711
|
+
REFER_COMMAND__DOCUMENTS_TO_INCLUDE__PRE_SEARCH = 36017;
|
|
712
|
+
REFER_COMMAND__LINKED_ITEMS__POST_SEARCH = 36018;
|
|
713
|
+
REFER_COMMAND__LINKED_ITEMS_INCLUDE__PRE_SEARCH = 36019;
|
|
698
714
|
|
|
699
715
|
// REFERENCE_COMMAND__PRE_ORIGINATE = 37000;
|
|
700
716
|
// REFERENCE_COMMAND__POST_ORIGINATE = 37001;
|
|
@@ -758,18 +774,20 @@ enum EventType {
|
|
|
758
774
|
REMOVE_ALLERGY__ALLERGY__PRE_SEARCH = 40012;
|
|
759
775
|
REMOVE_ALLERGY__ALLERGY__POST_SEARCH = 40013;
|
|
760
776
|
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
777
|
+
RESOLVE_CONDITION_COMMAND__PRE_ORIGINATE = 41000;
|
|
778
|
+
RESOLVE_CONDITION_COMMAND__POST_ORIGINATE = 41001;
|
|
779
|
+
RESOLVE_CONDITION_COMMAND__PRE_UPDATE = 41002;
|
|
780
|
+
RESOLVE_CONDITION_COMMAND__POST_UPDATE = 41003;
|
|
781
|
+
RESOLVE_CONDITION_COMMAND__PRE_COMMIT = 41004;
|
|
782
|
+
RESOLVE_CONDITION_COMMAND__POST_COMMIT = 41005;
|
|
783
|
+
RESOLVE_CONDITION_COMMAND__PRE_DELETE = 41006;
|
|
784
|
+
RESOLVE_CONDITION_COMMAND__POST_DELETE = 41007;
|
|
785
|
+
RESOLVE_CONDITION_COMMAND__PRE_ENTER_IN_ERROR = 41008;
|
|
786
|
+
RESOLVE_CONDITION_COMMAND__POST_ENTER_IN_ERROR = 41009;
|
|
787
|
+
RESOLVE_CONDITION_COMMAND__PRE_EXECUTE_ACTION = 41010;
|
|
788
|
+
RESOLVE_CONDITION_COMMAND__POST_EXECUTE_ACTION = 41011;
|
|
789
|
+
RESOLVE_CONDITION__CONDITION__PRE_SEARCH = 41012;
|
|
790
|
+
RESOLVE_CONDITION__CONDITION__POST_SEARCH = 41013;
|
|
773
791
|
|
|
774
792
|
ROS_COMMAND__PRE_ORIGINATE = 42000;
|
|
775
793
|
ROS_COMMAND__POST_ORIGINATE = 42001;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
from pydantic import Field
|
|
2
|
-
|
|
3
|
-
from canvas_sdk.commands.base import _BaseCommand
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class QuestionnaireCommand(_BaseCommand):
|
|
7
|
-
"""A class for managing a Questionnaire command within a specific note."""
|
|
8
|
-
|
|
9
|
-
class Meta:
|
|
10
|
-
key = "questionnaire"
|
|
11
|
-
commit_required_fields = ("questionnaire_id",)
|
|
12
|
-
|
|
13
|
-
questionnaire_id: str | None = Field(
|
|
14
|
-
default=None, json_schema_extra={"commands_api_name": "questionnaire"}
|
|
15
|
-
)
|
|
16
|
-
result: str | None = None
|
|
File without changes
|
|
File without changes
|