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.

Files changed (32) hide show
  1. {canvas-0.21.0.dist-info → canvas-0.22.1.dist-info}/METADATA +1 -1
  2. {canvas-0.21.0.dist-info → canvas-0.22.1.dist-info}/RECORD +31 -25
  3. canvas_generated/messages/effects_pb2.py +2 -2
  4. canvas_generated/messages/effects_pb2.pyi +40 -0
  5. canvas_generated/messages/events_pb2.py +2 -2
  6. canvas_generated/messages/events_pb2.pyi +108 -0
  7. canvas_sdk/commands/__init__.py +8 -0
  8. canvas_sdk/commands/base.py +1 -0
  9. canvas_sdk/commands/commands/__init__.py +0 -0
  10. canvas_sdk/commands/commands/adjust_prescription.py +24 -0
  11. canvas_sdk/commands/commands/imaging_order.py +39 -0
  12. canvas_sdk/commands/commands/instruct.py +17 -1
  13. canvas_sdk/commands/commands/lab_order.py +11 -6
  14. canvas_sdk/commands/commands/prescribe.py +1 -1
  15. canvas_sdk/commands/commands/questionnaire/__init__.py +102 -0
  16. canvas_sdk/commands/commands/questionnaire/question.py +134 -0
  17. canvas_sdk/commands/commands/refer.py +50 -0
  18. canvas_sdk/commands/commands/refill.py +28 -0
  19. canvas_sdk/commands/commands/resolve_condition.py +43 -0
  20. canvas_sdk/commands/constants.py +34 -0
  21. canvas_sdk/commands/tests/protocol/tests.py +10 -1
  22. canvas_sdk/commands/tests/test_utils.py +4 -1
  23. canvas_sdk/effects/banner_alert/tests.py +10 -2
  24. canvas_sdk/v1/data/condition.py +4 -2
  25. canvas_sdk/v1/data/medication.py +4 -2
  26. plugin_runner/installation.py +1 -2
  27. plugin_runner/plugin_runner.py +34 -2
  28. protobufs/canvas_generated/messages/effects.proto +25 -1
  29. protobufs/canvas_generated/messages/events.proto +54 -36
  30. canvas_sdk/commands/commands/questionnaire.py +0 -16
  31. {canvas-0.21.0.dist-info → canvas-0.22.1.dist-info}/WHEEL +0 -0
  32. {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
@@ -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=5.0)
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=5.0)
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()
@@ -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
- pass
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)
@@ -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
- pass
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)
@@ -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)
@@ -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 asyncio.get_running_loop().run_in_executor(None, handler.compute)
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
- client, pubsub = get_client()
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
- // 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;
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
- // REFER_COMMAND__PRE_ORIGINATE = 36000;
687
- // REFER_COMMAND__POST_ORIGINATE = 36001;
688
- // REFER_COMMAND__PRE_UPDATE = 36002;
689
- // REFER_COMMAND__POST_UPDATE = 36003;
690
- // REFER_COMMAND__PRE_COMMIT = 36004;
691
- // REFER_COMMAND__POST_COMMIT = 36005;
692
- // REFER_COMMAND__PRE_DELETE = 36006;
693
- // REFER_COMMAND__POST_DELETE = 36007;
694
- // REFER_COMMAND__PRE_ENTER_IN_ERROR = 36008;
695
- // REFER_COMMAND__POST_ENTER_IN_ERROR = 36009;
696
- // REFER_COMMAND__PRE_EXECUTE_ACTION = 36010;
697
- // REFER_COMMAND__POST_EXECUTE_ACTION = 36011;
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
- // RESOLVE_CONDITION_COMMAND__PRE_ORIGINATE = 41000;
762
- // RESOLVE_CONDITION_COMMAND__POST_ORIGINATE = 41001;
763
- // RESOLVE_CONDITION_COMMAND__PRE_UPDATE = 41002;
764
- // RESOLVE_CONDITION_COMMAND__POST_UPDATE = 41003;
765
- // RESOLVE_CONDITION_COMMAND__PRE_COMMIT = 41004;
766
- // RESOLVE_CONDITION_COMMAND__POST_COMMIT = 41005;
767
- // RESOLVE_CONDITION_COMMAND__PRE_DELETE = 41006;
768
- // RESOLVE_CONDITION_COMMAND__POST_DELETE = 41007;
769
- // RESOLVE_CONDITION_COMMAND__PRE_ENTER_IN_ERROR = 41008;
770
- // RESOLVE_CONDITION_COMMAND__POST_ENTER_IN_ERROR = 41009;
771
- // RESOLVE_CONDITION_COMMAND__PRE_EXECUTE_ACTION = 41010;
772
- // RESOLVE_CONDITION_COMMAND__POST_EXECUTE_ACTION = 41011;
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