canvas 0.13.2__py3-none-any.whl → 0.14.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.13.2.dist-info → canvas-0.14.0.dist-info}/METADATA +1 -3
- {canvas-0.13.2.dist-info → canvas-0.14.0.dist-info}/RECORD +32 -30
- canvas_generated/messages/effects_pb2.py +2 -2
- canvas_generated/messages/effects_pb2.pyi +2 -0
- canvas_sdk/effects/questionnaire_result.py +29 -0
- canvas_sdk/models/__init__.py +1 -0
- canvas_sdk/v1/data/allergy_intolerance.py +4 -2
- canvas_sdk/v1/data/billing.py +4 -2
- canvas_sdk/v1/data/command.py +17 -4
- canvas_sdk/v1/data/condition.py +8 -4
- canvas_sdk/v1/data/detected_issue.py +8 -5
- canvas_sdk/v1/data/device.py +6 -4
- canvas_sdk/v1/data/imaging.py +15 -13
- canvas_sdk/v1/data/lab.py +19 -13
- canvas_sdk/v1/data/medication.py +8 -4
- canvas_sdk/v1/data/note.py +8 -6
- canvas_sdk/v1/data/observation.py +11 -9
- canvas_sdk/v1/data/practicelocation.py +2 -2
- canvas_sdk/v1/data/protocol_override.py +3 -5
- canvas_sdk/v1/data/questionnaire.py +15 -13
- canvas_sdk/v1/data/staff.py +4 -4
- canvas_sdk/v1/data/task.py +12 -8
- plugin_runner/aws_headers.py +77 -0
- plugin_runner/plugin_installer.py +25 -7
- plugin_runner/plugin_runner.py +0 -1
- plugin_runner/plugin_synchronizer.py +3 -1
- plugin_runner/tests/test_plugin_installer.py +10 -12
- plugin_runner/tests/test_plugin_runner.py +0 -14
- plugin_runner/tests/test_sandbox.py +13 -1
- settings.py +4 -0
- {canvas-0.13.2.dist-info → canvas-0.14.0.dist-info}/WHEEL +0 -0
- {canvas-0.13.2.dist-info → canvas-0.14.0.dist-info}/entry_points.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: canvas
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.14.0
|
|
4
4
|
Summary: SDK to customize event-driven actions in your Canvas instance
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: Canvas Team
|
|
@@ -10,8 +10,6 @@ Classifier: License :: OSI Approved :: MIT License
|
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.11
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
-
Requires-Dist: boto3 (>=1.35.88,<2.0.0)
|
|
14
|
-
Requires-Dist: boto3-stubs[s3] (>=1.35.88,<2.0.0)
|
|
15
13
|
Requires-Dist: cookiecutter
|
|
16
14
|
Requires-Dist: cron-converter (>=1.2.1,<2.0.0)
|
|
17
15
|
Requires-Dist: deprecation (>=2.1.0,<3.0.0)
|
|
@@ -97,8 +97,8 @@ canvas_cli/utils/validators/__init__.py,sha256=rBvSR2O1hWkNAnUBdcr-zUkmqT796_A61
|
|
|
97
97
|
canvas_cli/utils/validators/manifest_schema.py,sha256=6PQmK2AdMWxrziBtv6jcpyoNk3SQEZsJCt3PrI0ZYm4,3961
|
|
98
98
|
canvas_cli/utils/validators/tests.py,sha256=KhaOdbxGUK2QwL2KnycAJJkqclYQSXF7CKg-scSf0DU,1259
|
|
99
99
|
canvas_cli/utils/validators/validators.py,sha256=lrUBQ0sF7seTe_pNGsNgASdr2BGp6g-Qui58V4H9qfQ,1598
|
|
100
|
-
canvas_generated/messages/effects_pb2.py,sha256=
|
|
101
|
-
canvas_generated/messages/effects_pb2.pyi,sha256=
|
|
100
|
+
canvas_generated/messages/effects_pb2.py,sha256=_fAq_TZ_82aC1qNdilFTZ53glzUJhqZ8ze19qnOJJqU,9082
|
|
101
|
+
canvas_generated/messages/effects_pb2.pyi,sha256=UraC7VQ8GeymsfiMl5q8e0csHOKq2xv47vagCPTSe9o,15683
|
|
102
102
|
canvas_generated/messages/effects_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
|
|
103
103
|
canvas_generated/messages/events_pb2.py,sha256=5xnMRMlqBTkxM3h8EVUW3EiNZ1LNoBGvMWFlwdf2epI,39868
|
|
104
104
|
canvas_generated/messages/events_pb2.pyi,sha256=HVqS44OgMYGL47svBJE9iQbLXaOm-EoMvBYvdP6Ha3c,71175
|
|
@@ -162,6 +162,7 @@ canvas_sdk/effects/patient_profile_configuration.py,sha256=ZXBx_PnJP-KKRIwuDI4tS
|
|
|
162
162
|
canvas_sdk/effects/protocol_card/__init__.py,sha256=AwXAARybFhVIfYwqiRThG6Ne3ARnKgvuvuGUknWpwTo,134
|
|
163
163
|
canvas_sdk/effects/protocol_card/protocol_card.py,sha256=aL8lXRBm1ByU-X0xzgBepxKnUTLvmr-OC7G-C-EBjy8,2596
|
|
164
164
|
canvas_sdk/effects/protocol_card/tests.py,sha256=ZiDZTjn-Z6UpEfR1S-6XDcJXlPlTPpLbg2PgvkQD8Uk,6815
|
|
165
|
+
canvas_sdk/effects/questionnaire_result.py,sha256=dXJE6la5aP5xLCnT9iMCOS6PiKu0Zz733Ku2lqa4CnM,816
|
|
165
166
|
canvas_sdk/effects/show_button.py,sha256=JnW9nM8S_GUXIOufs-uef3pg0HPDxSbF0l51Wh1Xxgw,715
|
|
166
167
|
canvas_sdk/effects/surescripts/surescripts_messages.py,sha256=tMG5ry2mZA5pwO0uGJfYZnJuVpj5MVhS2lYT5IRsb1Y,2582
|
|
167
168
|
canvas_sdk/effects/task/task.py,sha256=olG7gJN3CC1JKrGU4SdVvRq8qLduPuiNz80C_dTaY58,2837
|
|
@@ -172,7 +173,7 @@ canvas_sdk/handlers/action_button.py,sha256=8q7zo96k_4SV4JUHc_GoqbBksXW2dk_EE33H
|
|
|
172
173
|
canvas_sdk/handlers/application.py,sha256=8HwgJeHThCpif-vLAfgQU0En3Y07AEyONPIWkLUoqyM,910
|
|
173
174
|
canvas_sdk/handlers/base.py,sha256=E5UCnckZJM2N7G-NEWh5Wj2BmSARM6dNxS26Ly8AKug,1277
|
|
174
175
|
canvas_sdk/handlers/cron_task.py,sha256=Q4_D3bDKE5hyEpCf0JnGSgZlnLh_g9RSP3oEfIuLJ9Y,945
|
|
175
|
-
canvas_sdk/models/__init__.py,sha256=
|
|
176
|
+
canvas_sdk/models/__init__.py,sha256=o2axmFmIcYihBwPCeErDyjiEKCdN1rVuJWr7P81AXnM,376
|
|
176
177
|
canvas_sdk/protocols/__init__.py,sha256=3u9zet5D4DX4V953tLCoN1xhaOhAUCwGwscMv-7IIxo,186
|
|
177
178
|
canvas_sdk/protocols/base.py,sha256=sbm0uOk3PPfPemqBmHh2hawE5utC6no46EmvyMN8Y7Q,179
|
|
178
179
|
canvas_sdk/protocols/clinical_quality_measure.py,sha256=39ddtSIBCFB4DF7Kpuh2uDwSxH-mV7sjrsVrQY7tEuo,4835
|
|
@@ -185,26 +186,26 @@ canvas_sdk/utils/stats.py,sha256=sJhIW_IssUVefQN6rrUAt1P0KvVIUIYcnpZlMHLibNA,732
|
|
|
185
186
|
canvas_sdk/utils/tests.py,sha256=0Buh_7PvDU1D081_rSJoYSJwIHMOBbL0gtGS3bSKe7s,2285
|
|
186
187
|
canvas_sdk/v1/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
187
188
|
canvas_sdk/v1/data/__init__.py,sha256=Ea0apSYEz2UEhlZT9bmLH0rqmh75-2C0AsxbqDIfYnU,567
|
|
188
|
-
canvas_sdk/v1/data/allergy_intolerance.py,sha256=
|
|
189
|
+
canvas_sdk/v1/data/allergy_intolerance.py,sha256=BJD8eDVpdwxPTM2ebdZeCLG8-lafS_kxFHhPJsnZY7g,2099
|
|
189
190
|
canvas_sdk/v1/data/base.py,sha256=ZMZEpwkeg3ewl3QsbPAF7-z1MqqWu5hCR-IibWQCiHI,6189
|
|
190
|
-
canvas_sdk/v1/data/billing.py,sha256=
|
|
191
|
-
canvas_sdk/v1/data/command.py,sha256=
|
|
191
|
+
canvas_sdk/v1/data/billing.py,sha256=sAC5IMV526pdEZ9FwEmN7dz30F0kOHqH7Rh_JBwReuQ,2076
|
|
192
|
+
canvas_sdk/v1/data/command.py,sha256=Tk4oA-QBhq8p38xUClrv6Wp0uaIbpFW1iHDZV356_Y0,1636
|
|
192
193
|
canvas_sdk/v1/data/common.py,sha256=OvF4Oxo3BqE1Cv2lfyA1MXp_q_VHwoihyiJ0ETfa5lY,3459
|
|
193
|
-
canvas_sdk/v1/data/condition.py,sha256=
|
|
194
|
-
canvas_sdk/v1/data/detected_issue.py,sha256=
|
|
195
|
-
canvas_sdk/v1/data/device.py,sha256=
|
|
196
|
-
canvas_sdk/v1/data/imaging.py,sha256=
|
|
197
|
-
canvas_sdk/v1/data/lab.py,sha256=
|
|
198
|
-
canvas_sdk/v1/data/medication.py,sha256=
|
|
199
|
-
canvas_sdk/v1/data/note.py,sha256=
|
|
200
|
-
canvas_sdk/v1/data/observation.py,sha256=
|
|
194
|
+
canvas_sdk/v1/data/condition.py,sha256=g_kBv5zV3ynUg8fZbBqIrVTUBbl70r7pED-YxmnZ540,1930
|
|
195
|
+
canvas_sdk/v1/data/detected_issue.py,sha256=IvxHrBa2YK_ylHNi2HGSK0ji2yk92C_6EDDnsMh6CnY,1790
|
|
196
|
+
canvas_sdk/v1/data/device.py,sha256=PkRPKhMOA848O2gzgb1_LL0-YxUp-hPMQ_B0JKAQIvw,1713
|
|
197
|
+
canvas_sdk/v1/data/imaging.py,sha256=IOavBqdKDQAa6Tzcbl9GUVrkMOCMoCqIt5Tr9AV-qLc,4430
|
|
198
|
+
canvas_sdk/v1/data/lab.py,sha256=yYSCgqrMuAD-ebG-1oAiFaImyPnn3RE0ynqXJbrjTy8,11061
|
|
199
|
+
canvas_sdk/v1/data/medication.py,sha256=c33tsmUnVsehmdIDr1VNP_2Q56UNZoaoja3oV35Y898,2070
|
|
200
|
+
canvas_sdk/v1/data/note.py,sha256=tT0tHC2KtDP6QHFKtfJLYF45zb0P1GJAk90OAPPuoWE,6642
|
|
201
|
+
canvas_sdk/v1/data/observation.py,sha256=iY6FaQahN1sa0yIRGqLHJGDKhtJu_rLiv0C8yJr4-Ak,3812
|
|
201
202
|
canvas_sdk/v1/data/organization.py,sha256=SsRcBZfExmr87Wq2aU54AoTZzXJjfvHoV4XVF7oqvRA,995
|
|
202
203
|
canvas_sdk/v1/data/patient.py,sha256=iUSTAsEB_cVEUP12mkvJ7J5DkYhUZWmHTDw4JPdB6pc,3090
|
|
203
|
-
canvas_sdk/v1/data/practicelocation.py,sha256=
|
|
204
|
-
canvas_sdk/v1/data/protocol_override.py,sha256=
|
|
205
|
-
canvas_sdk/v1/data/questionnaire.py,sha256=
|
|
206
|
-
canvas_sdk/v1/data/staff.py,sha256=
|
|
207
|
-
canvas_sdk/v1/data/task.py,sha256=
|
|
204
|
+
canvas_sdk/v1/data/practicelocation.py,sha256=nM2T4rzkutIZWQCTULvMNGpvTuWOvOrvISNWjOPe2Io,4264
|
|
205
|
+
canvas_sdk/v1/data/protocol_override.py,sha256=FQBMaKTKCCnr4ZYgsorAYKSWh_YVuFAW_UqHmHifUTY,1851
|
|
206
|
+
canvas_sdk/v1/data/questionnaire.py,sha256=xTqZUfTjz5eyRdP2xh_bJ8YPc5pWxevsto_U0uf1v0I,7068
|
|
207
|
+
canvas_sdk/v1/data/staff.py,sha256=GFTdRB_FlpssB44kPDNJ8-S-cK14mm9banDZcv-wyuk,2819
|
|
208
|
+
canvas_sdk/v1/data/task.py,sha256=hQHJstXntQjCK3Fgg0C7ktqvaqmTmvUCy2PeyfkStGU,3668
|
|
208
209
|
canvas_sdk/v1/data/user.py,sha256=DmA8fNNGwiNOmuR-RYxQw1NpxN5yYhgwtRtRBRJ_22g,309
|
|
209
210
|
canvas_sdk/value_set/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
210
211
|
canvas_sdk/value_set/custom.py,sha256=0xzGP86ioCGcsx8wwf46SXfe9IefLSGVq7Z4yrHbEUU,19709
|
|
@@ -232,10 +233,11 @@ logger/__init__.py,sha256=9o2iRCjzFEhfULgXvrrECRFK-4IslWJTqKKjTCEUbq8,61
|
|
|
232
233
|
logger/logger.py,sha256=axf7UffBJtETjwDCtmi1IaaJKsvcFj8zaLfouGsq68A,1847
|
|
233
234
|
plugin_runner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
234
235
|
plugin_runner/authentication.py,sha256=SDPso2AogtLAV_H0LuMDp99IMZuF3oTq-Q_AXAvJ8uc,1116
|
|
236
|
+
plugin_runner/aws_headers.py,sha256=DenX_nAMVhXMJZw88PLZbqJsi5_XriNtr3jE-eJqHY4,2773
|
|
235
237
|
plugin_runner/exceptions.py,sha256=YnRZiQVzbU3HrVlmEXLje_np99009YnhTRVHHyBCtqc,433
|
|
236
|
-
plugin_runner/plugin_installer.py,sha256=
|
|
237
|
-
plugin_runner/plugin_runner.py,sha256=
|
|
238
|
-
plugin_runner/plugin_synchronizer.py,sha256=
|
|
238
|
+
plugin_runner/plugin_installer.py,sha256=QNc222WQHJk9d8YE8Npi3mlkCApbYVH4M9VZX5-AYxw,7676
|
|
239
|
+
plugin_runner/plugin_runner.py,sha256=EZ3snfYZ5kirlELY0LH6stcz6NuaJQ_WJE8aKi59EVU,15269
|
|
240
|
+
plugin_runner/plugin_synchronizer.py,sha256=GcY2oKwJc8beDoAJwo-0MkY4rxNzoF-Bk1bF9MOtO6U,2851
|
|
239
241
|
plugin_runner/sandbox.py,sha256=JUbphdu1iY0rPU6DdMEjFA32BBsZXHUz1KguCYpmrug,9384
|
|
240
242
|
plugin_runner/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
241
243
|
plugin_runner/tests/data/plugins/.gitkeep,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -269,13 +271,13 @@ plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/other_module/bas
|
|
|
269
271
|
plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/protocols/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
270
272
|
plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/protocols/my_protocol.py,sha256=V_6DPXsJaD12zGyKqGjYY2JFtKEk4E0eIAgBWax_MGc,629
|
|
271
273
|
plugin_runner/tests/test_application.py,sha256=ZirW14UGorfkQ_VSbnoKtmTvx6lHFS2EqndYNczIQfo,2391
|
|
272
|
-
plugin_runner/tests/test_plugin_installer.py,sha256=
|
|
273
|
-
plugin_runner/tests/test_plugin_runner.py,sha256=
|
|
274
|
-
plugin_runner/tests/test_sandbox.py,sha256=
|
|
274
|
+
plugin_runner/tests/test_plugin_installer.py,sha256=JNzLTAl7K8vFYe_WIt-_-VxuxoD_EdLnkceJWVfFvYA,3999
|
|
275
|
+
plugin_runner/tests/test_plugin_runner.py,sha256=htO1Pu-73AusrBP1EPeaeVPXcDYyHSEb-aHpSZFTz04,7029
|
|
276
|
+
plugin_runner/tests/test_sandbox.py,sha256=GX_nKgpU2R6s3V__dogkqEhLOXcqsQlic2kjwSwl_30,3835
|
|
275
277
|
pubsub/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
276
278
|
pubsub/pubsub.py,sha256=pyTW0JU8mtaqiAV6g6xjZwel1CVy2EonPMU-_vkmhUM,1044
|
|
277
|
-
settings.py,sha256=
|
|
278
|
-
canvas-0.
|
|
279
|
-
canvas-0.
|
|
280
|
-
canvas-0.
|
|
281
|
-
canvas-0.
|
|
279
|
+
settings.py,sha256=S_nlo7S2UxJUXrKRCv2hRXXysKrjJ9pxjT2Amb-JSao,2392
|
|
280
|
+
canvas-0.14.0.dist-info/METADATA,sha256=SQTZ2hB4GgCqEI8hSV_QsRNJXpnsjzmlpkzjerlkaaM,4703
|
|
281
|
+
canvas-0.14.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
282
|
+
canvas-0.14.0.dist-info/entry_points.txt,sha256=VSmSo1IZ3aEfL7enmLmlWSraS_IIkoXNVeyXzgRxFiY,46
|
|
283
|
+
canvas-0.14.0.dist-info/RECORD,,
|
|
@@ -14,7 +14,7 @@ _sym_db = _symbol_database.Default()
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\'canvas_generated/messages/effects.proto\x12\x06\x63\x61nvas\"c\n\x06\x45\x66\x66\x65\x63t\x12 \n\x04type\x18\x01 \x01(\x0e\x32\x12.canvas.EffectType\x12\x0f\n\x07payload\x18\x02 \x01(\t\x12\x13\n\x0bplugin_name\x18\x03 \x01(\t\x12\x11\n\tclassname\x18\x04 \x01(\t*\
|
|
17
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\'canvas_generated/messages/effects.proto\x12\x06\x63\x61nvas\"c\n\x06\x45\x66\x66\x65\x63t\x12 \n\x04type\x18\x01 \x01(\x0e\x32\x12.canvas.EffectType\x12\x0f\n\x07payload\x18\x02 \x01(\t\x12\x13\n\x0bplugin_name\x18\x03 \x01(\t\x12\x11\n\tclassname\x18\x04 \x01(\t*\xa5(\n\nEffectType\x12\x12\n\x0eUNKNOWN_EFFECT\x10\x00\x12\x07\n\x03LOG\x10\x01\x12\x14\n\x10\x41\x44\x44_PLAN_COMMAND\x10\x02\x12\x1f\n\x1b\x41UTOCOMPLETE_SEARCH_RESULTS\x10\x03\x12\x14\n\x10\x41\x44\x44_BANNER_ALERT\x10\x04\x12\x17\n\x13REMOVE_BANNER_ALERT\x10\x05\x12\x1c\n\x18ORIGINATE_ASSESS_COMMAND\x10\x06\x12\x17\n\x13\x45\x44IT_ASSESS_COMMAND\x10\x07\x12\x19\n\x15\x44\x45LETE_ASSESS_COMMAND\x10\x08\x12\x19\n\x15\x43OMMIT_ASSESS_COMMAND\x10\t\x12!\n\x1d\x45NTER_IN_ERROR_ASSESS_COMMAND\x10\n\x12\x1e\n\x1aORIGINATE_DIAGNOSE_COMMAND\x10\x0b\x12\x19\n\x15\x45\x44IT_DIAGNOSE_COMMAND\x10\x0c\x12\x1b\n\x17\x44\x45LETE_DIAGNOSE_COMMAND\x10\r\x12\x1b\n\x17\x43OMMIT_DIAGNOSE_COMMAND\x10\x0e\x12#\n\x1f\x45NTER_IN_ERROR_DIAGNOSE_COMMAND\x10\x0f\x12\x1a\n\x16ORIGINATE_GOAL_COMMAND\x10\x10\x12\x15\n\x11\x45\x44IT_GOAL_COMMAND\x10\x11\x12\x17\n\x13\x44\x45LETE_GOAL_COMMAND\x10\x12\x12\x17\n\x13\x43OMMIT_GOAL_COMMAND\x10\x13\x12\x1f\n\x1b\x45NTER_IN_ERROR_GOAL_COMMAND\x10\x14\x12\x19\n\x15ORIGINATE_HPI_COMMAND\x10\x15\x12\x14\n\x10\x45\x44IT_HPI_COMMAND\x10\x16\x12\x16\n\x12\x44\x45LETE_HPI_COMMAND\x10\x17\x12\x16\n\x12\x43OMMIT_HPI_COMMAND\x10\x18\x12\x1e\n\x1a\x45NTER_IN_ERROR_HPI_COMMAND\x10\x19\x12*\n&ORIGINATE_MEDICATION_STATEMENT_COMMAND\x10\x1a\x12%\n!EDIT_MEDICATION_STATEMENT_COMMAND\x10\x1b\x12\'\n#DELETE_MEDICATION_STATEMENT_COMMAND\x10\x1c\x12\'\n#COMMIT_MEDICATION_STATEMENT_COMMAND\x10\x1d\x12/\n+ENTER_IN_ERROR_MEDICATION_STATEMENT_COMMAND\x10\x1e\x12\x1a\n\x16ORIGINATE_PLAN_COMMAND\x10\x1f\x12\x15\n\x11\x45\x44IT_PLAN_COMMAND\x10 \x12\x17\n\x13\x44\x45LETE_PLAN_COMMAND\x10!\x12\x17\n\x13\x43OMMIT_PLAN_COMMAND\x10\"\x12\x1f\n\x1b\x45NTER_IN_ERROR_PLAN_COMMAND\x10#\x12\x1f\n\x1bORIGINATE_PRESCRIBE_COMMAND\x10$\x12\x1a\n\x16\x45\x44IT_PRESCRIBE_COMMAND\x10%\x12\x1c\n\x18\x44\x45LETE_PRESCRIBE_COMMAND\x10&\x12\x1c\n\x18\x43OMMIT_PRESCRIBE_COMMAND\x10\'\x12$\n ENTER_IN_ERROR_PRESCRIBE_COMMAND\x10(\x12#\n\x1fORIGINATE_QUESTIONNAIRE_COMMAND\x10)\x12\x1e\n\x1a\x45\x44IT_QUESTIONNAIRE_COMMAND\x10*\x12 \n\x1c\x44\x45LETE_QUESTIONNAIRE_COMMAND\x10+\x12 \n\x1c\x43OMMIT_QUESTIONNAIRE_COMMAND\x10,\x12(\n$ENTER_IN_ERROR_QUESTIONNAIRE_COMMAND\x10-\x12&\n\"ORIGINATE_REASON_FOR_VISIT_COMMAND\x10.\x12!\n\x1d\x45\x44IT_REASON_FOR_VISIT_COMMAND\x10/\x12#\n\x1f\x44\x45LETE_REASON_FOR_VISIT_COMMAND\x10\x30\x12#\n\x1f\x43OMMIT_REASON_FOR_VISIT_COMMAND\x10\x31\x12+\n\'ENTER_IN_ERROR_REASON_FOR_VISIT_COMMAND\x10\x32\x12%\n!ORIGINATE_STOP_MEDICATION_COMMAND\x10\x33\x12 \n\x1c\x45\x44IT_STOP_MEDICATION_COMMAND\x10\x34\x12\"\n\x1e\x44\x45LETE_STOP_MEDICATION_COMMAND\x10\x35\x12\"\n\x1e\x43OMMIT_STOP_MEDICATION_COMMAND\x10\x36\x12*\n&ENTER_IN_ERROR_STOP_MEDICATION_COMMAND\x10\x37\x12!\n\x1dORIGINATE_UPDATE_GOAL_COMMAND\x10\x38\x12\x1c\n\x18\x45\x44IT_UPDATE_GOAL_COMMAND\x10\x39\x12\x1e\n\x1a\x44\x45LETE_UPDATE_GOAL_COMMAND\x10:\x12\x1e\n\x1a\x43OMMIT_UPDATE_GOAL_COMMAND\x10;\x12&\n\"ENTER_IN_ERROR_UPDATE_GOAL_COMMAND\x10<\x12\x1d\n\x19ORIGINATE_PERFORM_COMMAND\x10=\x12\x18\n\x14\x45\x44IT_PERFORM_COMMAND\x10>\x12\x1a\n\x16\x44\x45LETE_PERFORM_COMMAND\x10?\x12\x1a\n\x16\x43OMMIT_PERFORM_COMMAND\x10@\x12\"\n\x1e\x45NTER_IN_ERROR_PERFORM_COMMAND\x10\x41\x12\x1e\n\x1aORIGINATE_INSTRUCT_COMMAND\x10\x42\x12\x19\n\x15\x45\x44IT_INSTRUCT_COMMAND\x10\x43\x12\x1b\n\x17\x44\x45LETE_INSTRUCT_COMMAND\x10\x44\x12\x1b\n\x17\x43OMMIT_INSTRUCT_COMMAND\x10\x45\x12#\n\x1f\x45NTER_IN_ERROR_INSTRUCT_COMMAND\x10\x46\x12\x1f\n\x1bORIGINATE_LAB_ORDER_COMMAND\x10G\x12\x1a\n\x16\x45\x44IT_LAB_ORDER_COMMAND\x10H\x12\x1c\n\x18\x44\x45LETE_LAB_ORDER_COMMAND\x10I\x12\x1c\n\x18\x43OMMIT_LAB_ORDER_COMMAND\x10J\x12$\n ENTER_IN_ERROR_LAB_ORDER_COMMAND\x10K\x12$\n ORIGINATE_FAMILY_HISTORY_COMMAND\x10L\x12\x1f\n\x1b\x45\x44IT_FAMILY_HISTORY_COMMAND\x10M\x12!\n\x1d\x44\x45LETE_FAMILY_HISTORY_COMMAND\x10N\x12!\n\x1d\x43OMMIT_FAMILY_HISTORY_COMMAND\x10O\x12)\n%ENTER_IN_ERROR_FAMILY_HISTORY_COMMAND\x10P\x12\x1d\n\x19ORIGINATE_ALLERGY_COMMAND\x10Q\x12\x18\n\x14\x45\x44IT_ALLERGY_COMMAND\x10R\x12\x1a\n\x16\x44\x45LETE_ALLERGY_COMMAND\x10S\x12\x1a\n\x16\x43OMMIT_ALLERGY_COMMAND\x10T\x12\"\n\x1e\x45NTER_IN_ERROR_ALLERGY_COMMAND\x10U\x12$\n ORIGINATE_REMOVE_ALLERGY_COMMAND\x10V\x12\x1f\n\x1b\x45\x44IT_REMOVE_ALLERGY_COMMAND\x10W\x12!\n\x1d\x44\x45LETE_REMOVE_ALLERGY_COMMAND\x10X\x12!\n\x1d\x43OMMIT_REMOVE_ALLERGY_COMMAND\x10Y\x12)\n%ENTER_IN_ERROR_REMOVE_ALLERGY_COMMAND\x10Z\x12&\n\"ORIGINATE_SURGICAL_HISTORY_COMMAND\x10[\x12!\n\x1d\x45\x44IT_SURGICAL_HISTORY_COMMAND\x10\\\x12#\n\x1f\x44\x45LETE_SURGICAL_HISTORY_COMMAND\x10]\x12#\n\x1f\x43OMMIT_SURGICAL_HISTORY_COMMAND\x10^\x12+\n\'ENTER_IN_ERROR_SURGICAL_HISTORY_COMMAND\x10_\x12\x0f\n\x0b\x43REATE_TASK\x10\x64\x12\x0f\n\x0bUPDATE_TASK\x10\x65\x12\x17\n\x13\x43REATE_TASK_COMMENT\x10\x66\x12%\n!ORIGINATE_MEDICAL_HISTORY_COMMAND\x10g\x12 \n\x1c\x45\x44IT_MEDICAL_HISTORY_COMMAND\x10h\x12\"\n\x1e\x44\x45LETE_MEDICAL_HISTORY_COMMAND\x10i\x12\"\n\x1e\x43OMMIT_MEDICAL_HISTORY_COMMAND\x10j\x12*\n&ENTER_IN_ERROR_MEDICAL_HISTORY_COMMAND\x10k\x12\x1f\n\x1b\x41\x44\x44_OR_UPDATE_PROTOCOL_CARD\x10n\x12\x1b\n\x16ORIGINATE_TASK_COMMAND\x10\x85\x01\x12\x16\n\x11\x45\x44IT_TASK_COMMAND\x10\x86\x01\x12\x18\n\x13\x44\x45LETE_TASK_COMMAND\x10\x87\x01\x12\x18\n\x13\x43OMMIT_TASK_COMMAND\x10\x88\x01\x12 \n\x1b\x45NTER_IN_ERROR_TASK_COMMAND\x10\x89\x01\x12\x1c\n\x18ORIGINATE_REFILL_COMMAND\x10q\x12\x17\n\x13\x45\x44IT_REFILL_COMMAND\x10r\x12\x19\n\x15\x44\x45LETE_REFILL_COMMAND\x10s\x12\x19\n\x15\x43OMMIT_REFILL_COMMAND\x10t\x12!\n\x1d\x45NTER_IN_ERROR_REFILL_COMMAND\x10u\x12\x1c\n\x18ORIGINATE_VITALS_COMMAND\x10v\x12\x17\n\x13\x45\x44IT_VITALS_COMMAND\x10w\x12\x19\n\x15\x44\x45LETE_VITALS_COMMAND\x10x\x12\x19\n\x15\x43OMMIT_VITALS_COMMAND\x10y\x12!\n\x1d\x45NTER_IN_ERROR_VITALS_COMMAND\x10z\x12&\n\"ORIGINATE_UPDATE_DIAGNOSIS_COMMAND\x10{\x12!\n\x1d\x45\x44IT_UPDATE_DIAGNOSIS_COMMAND\x10|\x12#\n\x1f\x44\x45LETE_UPDATE_DIAGNOSIS_COMMAND\x10}\x12#\n\x1f\x43OMMIT_UPDATE_DIAGNOSIS_COMMAND\x10~\x12+\n\'ENTER_IN_ERROR_UPDATE_DIAGNOSIS_COMMAND\x10\x7f\x12!\n\x1cORIGINATE_CLOSE_GOAL_COMMAND\x10\x80\x01\x12\x1c\n\x17\x45\x44IT_CLOSE_GOAL_COMMAND\x10\x81\x01\x12\x1e\n\x19\x44\x45LETE_CLOSE_GOAL_COMMAND\x10\x82\x01\x12\x1e\n\x19\x43OMMIT_CLOSE_GOAL_COMMAND\x10\x83\x01\x12&\n!ENTER_IN_ERROR_CLOSE_GOAL_COMMAND\x10\x84\x01\x12 \n\x1b\x43REATE_QUESTIONNAIRE_RESULT\x10\x8a\x01\x12-\n(ANNOTATE_PATIENT_CHART_CONDITION_RESULTS\x10\xc8\x01\x12%\n ANNOTATE_CLAIM_CONDITION_RESULTS\x10\xac\x02\x12(\n#SHOW_PATIENT_CHART_SUMMARY_SECTIONS\x10\x90\x03\x12\"\n\x1dSHOW_PATIENT_PROFILE_SECTIONS\x10\xf4\x03\x12\x37\n2PATIENT_PROFILE__ADD_PHARMACY__POST_SEARCH_RESULTS\x10\xf5\x03\x12)\n$SEND_SURESCRIPTS_ELIGIBILITY_REQUEST\x10\xd8\x04\x12\x30\n+SEND_SURESCRIPTS_MEDICATION_HISTORY_REQUEST\x10\xd9\x04\x12&\n!SEND_SURESCRIPTS_BENEFITS_REQUEST\x10\xda\x04\x12\x1b\n\x16ORIGINATE_EXAM_COMMAND\x10\xbc\x05\x12\x16\n\x11\x45\x44IT_EXAM_COMMAND\x10\xbd\x05\x12\x18\n\x13\x44\x45LETE_EXAM_COMMAND\x10\xbe\x05\x12\x18\n\x13\x43OMMIT_EXAM_COMMAND\x10\xbf\x05\x12 \n\x1b\x45NTER_IN_ERROR_EXAM_COMMAND\x10\xc0\x05\x12\x1a\n\x15ORIGINATE_ROS_COMMAND\x10\xa0\x06\x12\x15\n\x10\x45\x44IT_ROS_COMMAND\x10\xa1\x06\x12\x17\n\x12\x44\x45LETE_ROS_COMMAND\x10\xa2\x06\x12\x17\n\x12\x43OMMIT_ROS_COMMAND\x10\xa3\x06\x12\x1f\n\x1a\x45NTER_IN_ERROR_ROS_COMMAND\x10\xa4\x06\x12,\n\'ORIGINATE_STRUCTURED_ASSESSMENT_COMMAND\x10\x84\x07\x12\'\n\"EDIT_STRUCTURED_ASSESSMENT_COMMAND\x10\x85\x07\x12)\n$DELETE_STRUCTURED_ASSESSMENT_COMMAND\x10\x86\x07\x12)\n$COMMIT_STRUCTURED_ASSESSMENT_COMMAND\x10\x87\x07\x12\x31\n,ENTER_IN_ERROR_STRUCTURED_ASSESSMENT_COMMAND\x10\x88\x07\x12\x17\n\x12SHOW_ACTION_BUTTON\x10\xe8\x07\x12(\n#PATIENT_PORTAL__INTAKE_FORM_RESULTS\x10\xd0\x0f\x12\x11\n\x0cLAUNCH_MODAL\x10\xb8\x17\x62\x06proto3')
|
|
18
18
|
|
|
19
19
|
_globals = globals()
|
|
20
20
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
@@ -22,7 +22,7 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'canvas_generated.messages.e
|
|
|
22
22
|
if _descriptor._USE_C_DESCRIPTORS == False:
|
|
23
23
|
DESCRIPTOR._options = None
|
|
24
24
|
_globals['_EFFECTTYPE']._serialized_start=153
|
|
25
|
-
_globals['_EFFECTTYPE']._serialized_end=
|
|
25
|
+
_globals['_EFFECTTYPE']._serialized_end=5310
|
|
26
26
|
_globals['_EFFECT']._serialized_start=51
|
|
27
27
|
_globals['_EFFECT']._serialized_end=150
|
|
28
28
|
# @@protoc_insertion_point(module_scope)
|
|
@@ -137,6 +137,7 @@ class EffectType(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
|
|
|
137
137
|
DELETE_CLOSE_GOAL_COMMAND: _ClassVar[EffectType]
|
|
138
138
|
COMMIT_CLOSE_GOAL_COMMAND: _ClassVar[EffectType]
|
|
139
139
|
ENTER_IN_ERROR_CLOSE_GOAL_COMMAND: _ClassVar[EffectType]
|
|
140
|
+
CREATE_QUESTIONNAIRE_RESULT: _ClassVar[EffectType]
|
|
140
141
|
ANNOTATE_PATIENT_CHART_CONDITION_RESULTS: _ClassVar[EffectType]
|
|
141
142
|
ANNOTATE_CLAIM_CONDITION_RESULTS: _ClassVar[EffectType]
|
|
142
143
|
SHOW_PATIENT_CHART_SUMMARY_SECTIONS: _ClassVar[EffectType]
|
|
@@ -293,6 +294,7 @@ EDIT_CLOSE_GOAL_COMMAND: EffectType
|
|
|
293
294
|
DELETE_CLOSE_GOAL_COMMAND: EffectType
|
|
294
295
|
COMMIT_CLOSE_GOAL_COMMAND: EffectType
|
|
295
296
|
ENTER_IN_ERROR_CLOSE_GOAL_COMMAND: EffectType
|
|
297
|
+
CREATE_QUESTIONNAIRE_RESULT: EffectType
|
|
296
298
|
ANNOTATE_PATIENT_CHART_CONDITION_RESULTS: EffectType
|
|
297
299
|
ANNOTATE_CLAIM_CONDITION_RESULTS: EffectType
|
|
298
300
|
SHOW_PATIENT_CHART_SUMMARY_SECTIONS: EffectType
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from canvas_sdk.effects.base import EffectType, _BaseEffect
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class CreateQuestionnaireResult(_BaseEffect):
|
|
7
|
+
"""CreateQuestionnaireResult effect."""
|
|
8
|
+
|
|
9
|
+
class Meta:
|
|
10
|
+
effect_type = EffectType.CREATE_QUESTIONNAIRE_RESULT
|
|
11
|
+
|
|
12
|
+
interview_id: str | None = None
|
|
13
|
+
score: float | None = None
|
|
14
|
+
abnormal: bool | None = None
|
|
15
|
+
narrative: str | None = None
|
|
16
|
+
code_system: str | None = None
|
|
17
|
+
code: str | None = None
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def values(self) -> dict[str, Any]:
|
|
21
|
+
"""Make the payload."""
|
|
22
|
+
return {
|
|
23
|
+
"interview_id": self.interview_id,
|
|
24
|
+
"score": self.score,
|
|
25
|
+
"abnormal": self.abnormal or False,
|
|
26
|
+
"narrative": self.narrative or "",
|
|
27
|
+
"code_system": self.code_system,
|
|
28
|
+
"code": self.code,
|
|
29
|
+
}
|
canvas_sdk/models/__init__.py
CHANGED
|
@@ -20,12 +20,13 @@ class AllergyIntolerance(models.Model):
|
|
|
20
20
|
created = models.DateTimeField()
|
|
21
21
|
modified = models.DateTimeField()
|
|
22
22
|
deleted = models.BooleanField()
|
|
23
|
-
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
24
|
-
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
23
|
+
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
24
|
+
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
25
25
|
patient = models.ForeignKey(
|
|
26
26
|
Patient,
|
|
27
27
|
on_delete=models.DO_NOTHING,
|
|
28
28
|
related_name="allergy_intolerances",
|
|
29
|
+
null=True,
|
|
29
30
|
)
|
|
30
31
|
note_id = models.BigIntegerField()
|
|
31
32
|
allergy_intolerance_type = models.CharField()
|
|
@@ -58,4 +59,5 @@ class AllergyIntoleranceCoding(models.Model):
|
|
|
58
59
|
AllergyIntolerance,
|
|
59
60
|
on_delete=models.DO_NOTHING,
|
|
60
61
|
related_name="codings",
|
|
62
|
+
null=True,
|
|
61
63
|
)
|
canvas_sdk/v1/data/billing.py
CHANGED
|
@@ -46,9 +46,11 @@ class BillingLineItem(models.Model):
|
|
|
46
46
|
dbid = models.BigIntegerField(primary_key=True)
|
|
47
47
|
created = models.DateTimeField()
|
|
48
48
|
modified = models.DateTimeField()
|
|
49
|
-
note = models.ForeignKey(
|
|
49
|
+
note = models.ForeignKey(
|
|
50
|
+
Note, on_delete=models.DO_NOTHING, related_name="billing_line_items", null=True
|
|
51
|
+
)
|
|
50
52
|
patient = models.ForeignKey(
|
|
51
|
-
Patient, on_delete=models.DO_NOTHING, related_name="billing_line_items"
|
|
53
|
+
Patient, on_delete=models.DO_NOTHING, related_name="billing_line_items", null=True
|
|
52
54
|
)
|
|
53
55
|
cpt = models.CharField()
|
|
54
56
|
charge = models.DecimalField()
|
canvas_sdk/v1/data/command.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from django.apps import apps
|
|
1
2
|
from django.db import models
|
|
2
3
|
|
|
3
4
|
from canvas_sdk.v1.data.patient import Patient
|
|
@@ -16,12 +17,24 @@ class Command(models.Model):
|
|
|
16
17
|
dbid = models.BigIntegerField(primary_key=True)
|
|
17
18
|
created = models.DateTimeField()
|
|
18
19
|
modified = models.DateTimeField()
|
|
19
|
-
originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
20
|
-
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
21
|
-
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
20
|
+
originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
21
|
+
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
22
|
+
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
22
23
|
state = models.CharField()
|
|
23
|
-
patient = models.ForeignKey(Patient, on_delete=models.DO_NOTHING)
|
|
24
|
+
patient = models.ForeignKey(Patient, on_delete=models.DO_NOTHING, null=True)
|
|
24
25
|
note_id = models.BigIntegerField()
|
|
25
26
|
schema_key = models.TextField()
|
|
26
27
|
data = models.JSONField()
|
|
27
28
|
origination_source = models.CharField()
|
|
29
|
+
anchor_object_type = models.CharField()
|
|
30
|
+
anchor_object_dbid = models.BigIntegerField()
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def anchor_object(self) -> models.Model | None:
|
|
34
|
+
"""
|
|
35
|
+
Use the anchor_object_type and anchor_object_dbid to get the anchor object for the command.
|
|
36
|
+
"""
|
|
37
|
+
# TODO: Is the anchor object type enough here, or do we need a mapping? The home-app model
|
|
38
|
+
# names might not exactly match the plugins model names.
|
|
39
|
+
anchor_model = apps.get_model(app_label="canvas_sdk", model_name=self.anchor_object_type)
|
|
40
|
+
return anchor_model.objects.get(dbid=self.anchor_object_dbid)
|
canvas_sdk/v1/data/condition.py
CHANGED
|
@@ -35,9 +35,11 @@ class Condition(models.Model):
|
|
|
35
35
|
id = models.UUIDField()
|
|
36
36
|
dbid = models.BigIntegerField(primary_key=True)
|
|
37
37
|
deleted = models.BooleanField()
|
|
38
|
-
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
39
|
-
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
40
|
-
patient = models.ForeignKey(
|
|
38
|
+
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
39
|
+
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
40
|
+
patient = models.ForeignKey(
|
|
41
|
+
Patient, on_delete=models.DO_NOTHING, related_name="conditions", null=True
|
|
42
|
+
)
|
|
41
43
|
onset_date = models.DateField()
|
|
42
44
|
resolution_date = models.DateField()
|
|
43
45
|
clinical_status = models.CharField(choices=ClinicalStatus.choices)
|
|
@@ -57,4 +59,6 @@ class ConditionCoding(models.Model):
|
|
|
57
59
|
code = models.CharField()
|
|
58
60
|
display = models.CharField()
|
|
59
61
|
user_selected = models.BooleanField()
|
|
60
|
-
condition = models.ForeignKey(
|
|
62
|
+
condition = models.ForeignKey(
|
|
63
|
+
Condition, on_delete=models.DO_NOTHING, related_name="codings", null=True
|
|
64
|
+
)
|
|
@@ -18,11 +18,11 @@ class DetectedIssue(models.Model):
|
|
|
18
18
|
modified = models.DateTimeField()
|
|
19
19
|
identified = models.DateTimeField()
|
|
20
20
|
deleted = models.BooleanField()
|
|
21
|
-
originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
22
|
-
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
23
|
-
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
21
|
+
originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
22
|
+
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
23
|
+
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
24
24
|
patient = models.ForeignKey(
|
|
25
|
-
Patient, on_delete=models.DO_NOTHING, related_name="detected_issues"
|
|
25
|
+
Patient, on_delete=models.DO_NOTHING, related_name="detected_issues", null=True
|
|
26
26
|
)
|
|
27
27
|
code = models.CharField()
|
|
28
28
|
status = models.CharField()
|
|
@@ -48,5 +48,8 @@ class DetectedIssueEvidence(models.Model):
|
|
|
48
48
|
display = models.CharField()
|
|
49
49
|
user_selected = models.BooleanField()
|
|
50
50
|
detected_issue = models.ForeignKey(
|
|
51
|
-
DetectedIssue,
|
|
51
|
+
DetectedIssue,
|
|
52
|
+
on_delete=models.DO_NOTHING,
|
|
53
|
+
related_name="evidence",
|
|
54
|
+
null=True,
|
|
52
55
|
)
|
canvas_sdk/v1/data/device.py
CHANGED
|
@@ -16,10 +16,12 @@ class Device(models.Model):
|
|
|
16
16
|
dbid = models.BigIntegerField(primary_key=True)
|
|
17
17
|
created = models.DateTimeField()
|
|
18
18
|
modified = models.DateTimeField()
|
|
19
|
-
originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
20
|
-
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
21
|
-
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
22
|
-
patient = models.ForeignKey(
|
|
19
|
+
originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
20
|
+
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
21
|
+
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
22
|
+
patient = models.ForeignKey(
|
|
23
|
+
Patient, on_delete=models.DO_NOTHING, related_name="devices", null=True
|
|
24
|
+
)
|
|
23
25
|
note_id = models.BigIntegerField()
|
|
24
26
|
deleted = models.BooleanField()
|
|
25
27
|
labeled_contains_NRL = models.BooleanField()
|
canvas_sdk/v1/data/imaging.py
CHANGED
|
@@ -22,23 +22,25 @@ class ImagingOrder(models.Model):
|
|
|
22
22
|
dbid = models.BigIntegerField(primary_key=True)
|
|
23
23
|
created = models.DateTimeField()
|
|
24
24
|
modified = models.DateTimeField()
|
|
25
|
-
originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
25
|
+
originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
26
26
|
deleted = models.BooleanField()
|
|
27
|
-
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
27
|
+
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
28
28
|
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
29
|
-
patient = models.ForeignKey(
|
|
29
|
+
patient = models.ForeignKey(
|
|
30
|
+
Patient, on_delete=models.DO_NOTHING, related_name="imaging_orders", null=True
|
|
31
|
+
)
|
|
30
32
|
# TODO - uncomment when Note model is complete
|
|
31
|
-
# note = models.ForeigneKey(Note, on_delete=models.DO_NOTHING, related_name="imaging_orders")
|
|
33
|
+
# note = models.ForeigneKey(Note, on_delete=models.DO_NOTHING, related_name="imaging_orders", null=True)
|
|
32
34
|
imaging = models.CharField()
|
|
33
35
|
# TODO - uncomment when ServiceProvider model is complete
|
|
34
|
-
# imaging_center = models.ForeignKey(ServiceProvider, related_name="imaging_orders", null=True
|
|
36
|
+
# imaging_center = models.ForeignKey(ServiceProvider, on_delete=models.DO_NOTHING, related_name="imaging_orders", null=True)
|
|
35
37
|
note_to_radiologist = models.CharField()
|
|
36
38
|
internal_comment = models.CharField()
|
|
37
39
|
status = models.CharField(choices=OrderStatus)
|
|
38
40
|
date_time_ordered = models.DateTimeField()
|
|
39
41
|
priority = models.CharField()
|
|
40
42
|
# TODO - uncomment when Staff model is complete
|
|
41
|
-
# ordering_provider = models.ForeignKey(Staff, on_delete=models.
|
|
43
|
+
# ordering_provider = models.ForeignKey(Staff, on_delete=models.DO_NOTHING, related_name="imaging_orders", null=True)
|
|
42
44
|
delegated = models.BooleanField(default=False)
|
|
43
45
|
|
|
44
46
|
|
|
@@ -54,19 +56,19 @@ class ImagingReview(models.Model):
|
|
|
54
56
|
dbid = models.BigIntegerField(primary_key=True)
|
|
55
57
|
created = models.DateTimeField()
|
|
56
58
|
modified = models.DateTimeField()
|
|
57
|
-
originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
59
|
+
originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
58
60
|
deleted = models.BooleanField()
|
|
59
|
-
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
60
|
-
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
61
|
+
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
62
|
+
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
61
63
|
patient_communication_method = models.CharField(choices=ReviewPatientCommunicationMethod)
|
|
62
64
|
# TODO - uncomment when Note model is complete
|
|
63
|
-
# note = models.ForeignKey(Note, on_delete=models.DO_NOTHING, related_name="imaging_reviews")
|
|
65
|
+
# note = models.ForeignKey(Note, on_delete=models.DO_NOTHING, related_name="imaging_reviews", null=True)
|
|
64
66
|
internal_comment = models.CharField()
|
|
65
67
|
message_to_patient = models.CharField()
|
|
66
68
|
is_released_to_patient = models.BooleanField()
|
|
67
69
|
status = models.CharField(choices=ReviewStatus)
|
|
68
70
|
patient = models.ForeignKey(
|
|
69
|
-
Patient, on_delete=models.DO_NOTHING, related_name="imaging_reviews"
|
|
71
|
+
Patient, on_delete=models.DO_NOTHING, related_name="imaging_reviews", null=True
|
|
70
72
|
)
|
|
71
73
|
|
|
72
74
|
|
|
@@ -92,11 +94,11 @@ class ImagingReport(models.Model):
|
|
|
92
94
|
requires_signature = models.BooleanField()
|
|
93
95
|
assigned_date = models.DateTimeField()
|
|
94
96
|
patient = models.ForeignKey(
|
|
95
|
-
Patient, on_delete=models.DO_NOTHING, related_name="imaging_results"
|
|
97
|
+
Patient, on_delete=models.DO_NOTHING, related_name="imaging_results", null=True
|
|
96
98
|
)
|
|
97
99
|
order = models.ForeignKey(ImagingOrder, on_delete=models.DO_NOTHING, null=True)
|
|
98
100
|
source = models.CharField(choices=ImagingReportSource)
|
|
99
101
|
name = models.CharField()
|
|
100
102
|
result_date = models.DateField()
|
|
101
103
|
original_date = models.DateField()
|
|
102
|
-
review = models.ForeignKey(ImagingReview,
|
|
104
|
+
review = models.ForeignKey(ImagingReview, on_delete=models.DO_NOTHING, null=True)
|
canvas_sdk/v1/data/lab.py
CHANGED
|
@@ -47,12 +47,12 @@ class LabReport(models.Model):
|
|
|
47
47
|
version = models.IntegerField()
|
|
48
48
|
requisition_number = models.CharField()
|
|
49
49
|
review = models.ForeignKey(
|
|
50
|
-
"LabReview", related_name="reports",
|
|
50
|
+
"LabReview", on_delete=models.DO_NOTHING, related_name="reports", null=True
|
|
51
51
|
)
|
|
52
52
|
original_date = models.DateTimeField()
|
|
53
53
|
date_performed = models.DateTimeField()
|
|
54
54
|
custom_document_name = models.CharField()
|
|
55
|
-
originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
55
|
+
originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
56
56
|
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
57
57
|
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
58
58
|
deleted = models.BooleanField()
|
|
@@ -72,14 +72,16 @@ class LabReview(models.Model):
|
|
|
72
72
|
dbid = models.BigIntegerField(primary_key=True)
|
|
73
73
|
created = models.DateTimeField()
|
|
74
74
|
modified = models.DateTimeField()
|
|
75
|
-
originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
75
|
+
originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
76
76
|
deleted = models.BooleanField()
|
|
77
77
|
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
78
78
|
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
79
79
|
internal_comment = models.TextField()
|
|
80
80
|
message_to_patient = models.CharField()
|
|
81
81
|
status = models.CharField()
|
|
82
|
-
patient = models.ForeignKey(
|
|
82
|
+
patient = models.ForeignKey(
|
|
83
|
+
Patient, on_delete=models.DO_NOTHING, related_name="lab_reviews", null=True
|
|
84
|
+
)
|
|
83
85
|
patient_communication_method = models.CharField()
|
|
84
86
|
|
|
85
87
|
|
|
@@ -113,7 +115,7 @@ class LabValue(models.Model):
|
|
|
113
115
|
created = models.DateTimeField()
|
|
114
116
|
modified = models.DateTimeField()
|
|
115
117
|
report = models.ForeignKey(
|
|
116
|
-
"LabReport", related_name="values",
|
|
118
|
+
"LabReport", on_delete=models.DO_NOTHING, related_name="values", null=True
|
|
117
119
|
)
|
|
118
120
|
value = models.TextField()
|
|
119
121
|
units = models.CharField()
|
|
@@ -178,14 +180,16 @@ class LabOrder(models.Model):
|
|
|
178
180
|
dbid = models.BigIntegerField(primary_key=True)
|
|
179
181
|
created = models.DateTimeField()
|
|
180
182
|
modified = models.DateTimeField()
|
|
181
|
-
originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
183
|
+
originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
182
184
|
deleted = models.BooleanField()
|
|
183
185
|
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
184
186
|
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
185
|
-
patient = models.ForeignKey(
|
|
187
|
+
patient = models.ForeignKey(
|
|
188
|
+
Patient, on_delete=models.DO_NOTHING, related_name="lab_orders", null=True
|
|
189
|
+
)
|
|
186
190
|
ontology_lab_partner = models.CharField()
|
|
187
191
|
# TODO - uncomment when the Note model is finished
|
|
188
|
-
# note = models.ForeignKey("Note", on_delete=models.DO_NOTHING)
|
|
192
|
+
# note = models.ForeignKey("Note", on_delete=models.DO_NOTHING, null=True)
|
|
189
193
|
comment = models.CharField()
|
|
190
194
|
requisition_number = models.CharField()
|
|
191
195
|
is_patient_bill = models.BooleanField(null=True)
|
|
@@ -224,11 +228,13 @@ class LabOrderReason(models.Model):
|
|
|
224
228
|
dbid = models.BigIntegerField(primary_key=True)
|
|
225
229
|
created = models.DateTimeField()
|
|
226
230
|
modified = models.DateTimeField()
|
|
227
|
-
originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
231
|
+
originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
228
232
|
deleted = models.BooleanField()
|
|
229
|
-
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
230
|
-
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
231
|
-
order = models.ForeignKey(
|
|
233
|
+
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
234
|
+
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
235
|
+
order = models.ForeignKey(
|
|
236
|
+
LabOrder, on_delete=models.DO_NOTHING, related_name="reasons", null=True
|
|
237
|
+
)
|
|
232
238
|
mode = models.CharField(max_length=30, choices=LabReasonMode)
|
|
233
239
|
|
|
234
240
|
|
|
@@ -281,7 +287,7 @@ class LabTest(models.Model):
|
|
|
281
287
|
ontology_test_code = models.CharField(max_length=512, blank=True, default="")
|
|
282
288
|
status = models.CharField(max_length=30, choices=LabTestOrderStatus)
|
|
283
289
|
report = models.ForeignKey(
|
|
284
|
-
LabReport, on_delete=models.DO_NOTHING,
|
|
290
|
+
LabReport, on_delete=models.DO_NOTHING, related_name="tests", null=True
|
|
285
291
|
)
|
|
286
292
|
aoe_code = models.CharField(max_length=10, default="")
|
|
287
293
|
procedure_class = models.CharField(max_length=10, default="")
|
canvas_sdk/v1/data/medication.py
CHANGED
|
@@ -31,10 +31,12 @@ class Medication(models.Model):
|
|
|
31
31
|
|
|
32
32
|
id = models.UUIDField()
|
|
33
33
|
dbid = models.BigIntegerField(primary_key=True)
|
|
34
|
-
patient = models.ForeignKey(
|
|
34
|
+
patient = models.ForeignKey(
|
|
35
|
+
Patient, on_delete=models.DO_NOTHING, related_name="medications", null=True
|
|
36
|
+
)
|
|
35
37
|
deleted = models.BooleanField()
|
|
36
|
-
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
37
|
-
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
38
|
+
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
39
|
+
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
38
40
|
status = models.CharField(choices=Status.choices)
|
|
39
41
|
start_date = models.DateTimeField()
|
|
40
42
|
end_date = models.DateTimeField()
|
|
@@ -59,4 +61,6 @@ class MedicationCoding(models.Model):
|
|
|
59
61
|
code = models.CharField()
|
|
60
62
|
display = models.CharField()
|
|
61
63
|
user_selected = models.BooleanField()
|
|
62
|
-
medication = models.ForeignKey(
|
|
64
|
+
medication = models.ForeignKey(
|
|
65
|
+
Medication, on_delete=models.DO_NOTHING, related_name="codings", null=True
|
|
66
|
+
)
|
canvas_sdk/v1/data/note.py
CHANGED
|
@@ -140,21 +140,23 @@ class Note(models.Model):
|
|
|
140
140
|
dbid = models.BigIntegerField(db_column="dbid", primary_key=True)
|
|
141
141
|
created = models.DateTimeField()
|
|
142
142
|
modified = models.DateTimeField()
|
|
143
|
-
patient = models.ForeignKey(Patient, on_delete=models.DO_NOTHING)
|
|
144
|
-
provider = models.ForeignKey(
|
|
143
|
+
patient = models.ForeignKey(Patient, on_delete=models.DO_NOTHING, null=True)
|
|
144
|
+
provider = models.ForeignKey(
|
|
145
|
+
"Staff", on_delete=models.DO_NOTHING, related_name="notes", null=True
|
|
146
|
+
)
|
|
145
147
|
note_type = models.CharField(choices=NoteTypes.choices, null=True)
|
|
146
148
|
note_type_version = models.ForeignKey(
|
|
147
|
-
"NoteType", on_delete=models.DO_NOTHING, related_name="notes"
|
|
149
|
+
"NoteType", on_delete=models.DO_NOTHING, related_name="notes", null=True
|
|
148
150
|
)
|
|
149
151
|
title = models.TextField()
|
|
150
152
|
body = models.JSONField()
|
|
151
|
-
originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
153
|
+
originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
152
154
|
last_modified_by_staff = models.ForeignKey("Staff", on_delete=models.DO_NOTHING, null=True)
|
|
153
155
|
checksum = models.CharField()
|
|
154
156
|
billing_note = models.TextField()
|
|
155
157
|
# TODO -implement InpatientStay model
|
|
156
|
-
# inpatient_stay = models.ForeignKey("InpatientStay", on_delete=models.DO_NOTHING)
|
|
158
|
+
# inpatient_stay = models.ForeignKey("InpatientStay", on_delete=models.DO_NOTHING, null=True)
|
|
157
159
|
related_data = models.JSONField()
|
|
158
|
-
location = models.ForeignKey("PracticeLocation", on_delete=models.DO_NOTHING)
|
|
160
|
+
location = models.ForeignKey("PracticeLocation", on_delete=models.DO_NOTHING, null=True)
|
|
159
161
|
datetime_of_service = models.DateTimeField()
|
|
160
162
|
place_of_service = models.CharField()
|
|
@@ -25,13 +25,15 @@ class Observation(models.Model):
|
|
|
25
25
|
dbid = models.BigIntegerField(primary_key=True)
|
|
26
26
|
created = models.DateTimeField()
|
|
27
27
|
modified = models.DateTimeField()
|
|
28
|
-
originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
29
|
-
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
30
|
-
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
28
|
+
originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
29
|
+
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
30
|
+
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
31
31
|
deleted = models.BooleanField()
|
|
32
|
-
patient = models.ForeignKey(
|
|
32
|
+
patient = models.ForeignKey(
|
|
33
|
+
Patient, on_delete=models.DO_NOTHING, related_name="observations", null=True
|
|
34
|
+
)
|
|
33
35
|
is_member_of = models.ForeignKey(
|
|
34
|
-
"self", on_delete=models.DO_NOTHING,
|
|
36
|
+
"self", on_delete=models.DO_NOTHING, related_name="members", null=True
|
|
35
37
|
)
|
|
36
38
|
category = models.CharField()
|
|
37
39
|
units = models.TextField()
|
|
@@ -56,7 +58,7 @@ class ObservationCoding(models.Model):
|
|
|
56
58
|
display = models.CharField()
|
|
57
59
|
user_selected = models.BooleanField()
|
|
58
60
|
observation = models.ForeignKey(
|
|
59
|
-
Observation, on_delete=models.DO_NOTHING, related_name="codings"
|
|
61
|
+
Observation, on_delete=models.DO_NOTHING, related_name="codings", null=True
|
|
60
62
|
)
|
|
61
63
|
|
|
62
64
|
|
|
@@ -72,7 +74,7 @@ class ObservationComponent(models.Model):
|
|
|
72
74
|
created = models.DateTimeField()
|
|
73
75
|
modified = models.DateTimeField()
|
|
74
76
|
observation = models.ForeignKey(
|
|
75
|
-
Observation, on_delete=models.DO_NOTHING, related_name="components"
|
|
77
|
+
Observation, on_delete=models.DO_NOTHING, related_name="components", null=True
|
|
76
78
|
)
|
|
77
79
|
value_quantity = models.TextField()
|
|
78
80
|
value_quantity_unit = models.TextField()
|
|
@@ -94,7 +96,7 @@ class ObservationComponentCoding(models.Model):
|
|
|
94
96
|
display = models.CharField()
|
|
95
97
|
user_selected = models.BooleanField()
|
|
96
98
|
observation_component = models.ForeignKey(
|
|
97
|
-
ObservationComponent, on_delete=models.DO_NOTHING, related_name="codings"
|
|
99
|
+
ObservationComponent, on_delete=models.DO_NOTHING, related_name="codings", null=True
|
|
98
100
|
)
|
|
99
101
|
|
|
100
102
|
|
|
@@ -113,5 +115,5 @@ class ObservationValueCoding(models.Model):
|
|
|
113
115
|
display = models.CharField()
|
|
114
116
|
user_selected = models.BooleanField()
|
|
115
117
|
observation = models.ForeignKey(
|
|
116
|
-
Observation, on_delete=models.DO_NOTHING, related_name="value_codings"
|
|
118
|
+
Observation, on_delete=models.DO_NOTHING, related_name="value_codings", null=True
|
|
117
119
|
)
|
|
@@ -65,7 +65,7 @@ class PracticeLocation(models.Model):
|
|
|
65
65
|
created = models.DateTimeField()
|
|
66
66
|
modified = models.DateTimeField()
|
|
67
67
|
organization = models.ForeignKey(
|
|
68
|
-
"Organization", on_delete=models.DO_NOTHING, related_name="practice_locations"
|
|
68
|
+
"Organization", on_delete=models.DO_NOTHING, related_name="practice_locations", null=True
|
|
69
69
|
)
|
|
70
70
|
place_of_service_code = models.CharField(choices=PracticeLocationPOS.choices)
|
|
71
71
|
full_name = models.CharField()
|
|
@@ -96,7 +96,7 @@ class PracticeLocationSetting(models.Model):
|
|
|
96
96
|
|
|
97
97
|
dbid = models.BigIntegerField(primary_key=True)
|
|
98
98
|
practice_location = models.ForeignKey(
|
|
99
|
-
PracticeLocation, on_delete=models.DO_NOTHING, related_name="settings"
|
|
99
|
+
PracticeLocation, on_delete=models.DO_NOTHING, related_name="settings", null=True
|
|
100
100
|
)
|
|
101
101
|
name = models.CharField()
|
|
102
102
|
value = models.JSONField()
|
|
@@ -35,12 +35,10 @@ class ProtocolOverride(models.Model):
|
|
|
35
35
|
created = models.DateTimeField()
|
|
36
36
|
modified = models.DateTimeField()
|
|
37
37
|
deleted = models.BooleanField()
|
|
38
|
-
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
39
|
-
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
38
|
+
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
39
|
+
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
40
40
|
patient = models.ForeignKey(
|
|
41
|
-
Patient,
|
|
42
|
-
on_delete=models.DO_NOTHING,
|
|
43
|
-
related_name="protocol_overrides",
|
|
41
|
+
Patient, on_delete=models.DO_NOTHING, related_name="protocol_overrides", null=True
|
|
44
42
|
)
|
|
45
43
|
protocol_key = models.CharField()
|
|
46
44
|
is_adjustment = models.BooleanField()
|
|
@@ -47,7 +47,7 @@ class ResponseOption(models.Model):
|
|
|
47
47
|
code_description = models.CharField()
|
|
48
48
|
value = models.CharField()
|
|
49
49
|
response_option_set = models.ForeignKey(
|
|
50
|
-
ResponseOptionSet, on_delete=models.DO_NOTHING, related_name="options"
|
|
50
|
+
ResponseOptionSet, on_delete=models.DO_NOTHING, related_name="options", null=True
|
|
51
51
|
)
|
|
52
52
|
ordering = models.IntegerField()
|
|
53
53
|
|
|
@@ -67,7 +67,7 @@ class Question(models.Model):
|
|
|
67
67
|
status = models.CharField()
|
|
68
68
|
name = models.CharField()
|
|
69
69
|
response_option_set = models.ForeignKey(
|
|
70
|
-
ResponseOptionSet, on_delete=models.DO_NOTHING, related_name="questions"
|
|
70
|
+
ResponseOptionSet, on_delete=models.DO_NOTHING, related_name="questions", null=True
|
|
71
71
|
)
|
|
72
72
|
acknowledge_only = models.BooleanField()
|
|
73
73
|
show_prologue = models.BooleanField()
|
|
@@ -126,8 +126,8 @@ class QuestionnaireQuestionMap(models.Model):
|
|
|
126
126
|
created = models.DateTimeField()
|
|
127
127
|
modified = models.DateTimeField()
|
|
128
128
|
status = models.CharField()
|
|
129
|
-
questionnaire = models.ForeignKey(Questionnaire, on_delete=models.DO_NOTHING)
|
|
130
|
-
question = models.ForeignKey(Question, on_delete=models.DO_NOTHING)
|
|
129
|
+
questionnaire = models.ForeignKey(Questionnaire, on_delete=models.DO_NOTHING, null=True)
|
|
130
|
+
question = models.ForeignKey(Question, on_delete=models.DO_NOTHING, null=True)
|
|
131
131
|
|
|
132
132
|
|
|
133
133
|
class Interview(models.Model):
|
|
@@ -143,13 +143,15 @@ class Interview(models.Model):
|
|
|
143
143
|
id = models.UUIDField()
|
|
144
144
|
dbid = models.BigIntegerField(primary_key=True)
|
|
145
145
|
deleted = models.BooleanField()
|
|
146
|
-
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
147
|
-
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
146
|
+
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
147
|
+
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
148
148
|
status = models.CharField()
|
|
149
149
|
name = models.CharField()
|
|
150
150
|
language_id = models.BigIntegerField()
|
|
151
151
|
use_case_in_charting = models.CharField()
|
|
152
|
-
patient = models.ForeignKey(
|
|
152
|
+
patient = models.ForeignKey(
|
|
153
|
+
Patient, on_delete=models.DO_NOTHING, related_name="interviews", null=True
|
|
154
|
+
)
|
|
153
155
|
note_id = models.BigIntegerField()
|
|
154
156
|
appointment_id = models.BigIntegerField()
|
|
155
157
|
questionnaires = models.ManyToManyField( # type: ignore[var-annotated]
|
|
@@ -173,8 +175,8 @@ class InterviewQuestionnaireMap(models.Model):
|
|
|
173
175
|
created = models.DateTimeField()
|
|
174
176
|
modified = models.DateTimeField()
|
|
175
177
|
status = models.CharField()
|
|
176
|
-
interview = models.ForeignKey(Interview, on_delete=models.DO_NOTHING)
|
|
177
|
-
questionnaire = models.ForeignKey(Questionnaire, on_delete=models.
|
|
178
|
+
interview = models.ForeignKey(Interview, on_delete=models.DO_NOTHING, null=True)
|
|
179
|
+
questionnaire = models.ForeignKey(Questionnaire, on_delete=models.DO_NOTHING, null=True)
|
|
178
180
|
|
|
179
181
|
|
|
180
182
|
class InterviewQuestionResponse(models.Model):
|
|
@@ -190,16 +192,16 @@ class InterviewQuestionResponse(models.Model):
|
|
|
190
192
|
modified = models.DateTimeField()
|
|
191
193
|
status = models.CharField()
|
|
192
194
|
interview = models.ForeignKey(
|
|
193
|
-
Interview, on_delete=models.DO_NOTHING, related_name="interview_responses"
|
|
195
|
+
Interview, on_delete=models.DO_NOTHING, related_name="interview_responses", null=True
|
|
194
196
|
)
|
|
195
197
|
questionnaire = models.ForeignKey(
|
|
196
|
-
Questionnaire, on_delete=models.DO_NOTHING, related_name="interview_responses"
|
|
198
|
+
Questionnaire, on_delete=models.DO_NOTHING, related_name="interview_responses", null=True
|
|
197
199
|
)
|
|
198
200
|
question = models.ForeignKey(
|
|
199
|
-
Question, on_delete=models.DO_NOTHING, related_name="interview_responses"
|
|
201
|
+
Question, on_delete=models.DO_NOTHING, related_name="interview_responses", null=True
|
|
200
202
|
)
|
|
201
203
|
response_option = models.ForeignKey(
|
|
202
|
-
ResponseOption, on_delete=models.DO_NOTHING, related_name="interview_responses"
|
|
204
|
+
ResponseOption, on_delete=models.DO_NOTHING, related_name="interview_responses", null=True
|
|
203
205
|
)
|
|
204
206
|
response_option_value = models.TextField()
|
|
205
207
|
questionnaire_state = models.TextField()
|
canvas_sdk/v1/data/staff.py
CHANGED
|
@@ -54,12 +54,12 @@ class Staff(models.Model):
|
|
|
54
54
|
tax_id_type = models.CharField(choices=TaxIDType.choices)
|
|
55
55
|
spi_number = models.CharField()
|
|
56
56
|
# TODO - uncomment when Language is developed
|
|
57
|
-
# language = models.ForeignKey(Language, on_delete=models.DO_NOTHING, related_name="staff_speakers")
|
|
58
|
-
# language_secondary = models.ForeignKey(Language, on_delete=models.DO_NOTHING, related_name="staff_secondary_speakers")
|
|
57
|
+
# language = models.ForeignKey(Language, on_delete=models.DO_NOTHING, related_name="staff_speakers", null=True)
|
|
58
|
+
# language_secondary = models.ForeignKey(Language, on_delete=models.DO_NOTHING, related_name="staff_secondary_speakers", null=True)
|
|
59
59
|
personal_meeting_room_link = models.URLField(null=True)
|
|
60
60
|
state = models.JSONField()
|
|
61
|
-
user = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
61
|
+
user = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING, null=True)
|
|
62
62
|
schedule_column_ordering = models.IntegerField()
|
|
63
63
|
default_supervising_provider = models.ForeignKey(
|
|
64
|
-
"Staff", on_delete=models.DO_NOTHING,
|
|
64
|
+
"Staff", on_delete=models.DO_NOTHING, related_name="supervising_team", null=True
|
|
65
65
|
)
|
canvas_sdk/v1/data/task.py
CHANGED
|
@@ -46,14 +46,16 @@ class Task(models.Model):
|
|
|
46
46
|
dbid = models.BigIntegerField(primary_key=True)
|
|
47
47
|
created = models.DateTimeField()
|
|
48
48
|
modified = models.DateTimeField()
|
|
49
|
-
creator = models.ForeignKey(
|
|
49
|
+
creator = models.ForeignKey(
|
|
50
|
+
Staff, on_delete=models.DO_NOTHING, related_name="creator_tasks", null=True
|
|
51
|
+
)
|
|
50
52
|
assignee = models.ForeignKey(
|
|
51
|
-
Staff, related_name="assignee_tasks", null=True
|
|
53
|
+
Staff, on_delete=models.DO_NOTHING, related_name="assignee_tasks", null=True
|
|
52
54
|
)
|
|
53
55
|
# TODO - uncomment when Team model is created
|
|
54
|
-
# team = models.ForeignKey(Team, related_name="tasks", null=True
|
|
56
|
+
# team = models.ForeignKey(Team, on_delete=models.DO_NOTHING, related_name="tasks", null=True)
|
|
55
57
|
patient = models.ForeignKey(
|
|
56
|
-
Patient,
|
|
58
|
+
Patient, on_delete=models.DO_NOTHING, blank=True, related_name="tasks", null=True
|
|
57
59
|
)
|
|
58
60
|
task_type = models.CharField(choices=TaskType.choices)
|
|
59
61
|
tag = models.CharField()
|
|
@@ -75,8 +77,10 @@ class TaskComment(models.Model):
|
|
|
75
77
|
dbid = models.BigIntegerField(primary_key=True)
|
|
76
78
|
created = models.DateTimeField()
|
|
77
79
|
modified = models.DateTimeField()
|
|
78
|
-
creator = models.ForeignKey(
|
|
79
|
-
|
|
80
|
+
creator = models.ForeignKey(
|
|
81
|
+
Staff, on_delete=models.DO_NOTHING, related_name="comments", null=True
|
|
82
|
+
)
|
|
83
|
+
task = models.ForeignKey(Task, on_delete=models.DO_NOTHING, related_name="comments", null=True)
|
|
80
84
|
body = models.TextField()
|
|
81
85
|
|
|
82
86
|
|
|
@@ -108,5 +112,5 @@ class TaskTaskLabel(models.Model):
|
|
|
108
112
|
db_table = "canvas_sdk_data_api_tasktasklabel_001"
|
|
109
113
|
|
|
110
114
|
dbid = models.BigIntegerField(primary_key=True)
|
|
111
|
-
task_label = models.ForeignKey(TaskLabel, on_delete=models.DO_NOTHING)
|
|
112
|
-
task = models.ForeignKey(Task, on_delete=models.DO_NOTHING)
|
|
115
|
+
task_label = models.ForeignKey(TaskLabel, on_delete=models.DO_NOTHING, null=True)
|
|
116
|
+
task = models.ForeignKey(Task, on_delete=models.DO_NOTHING, null=True)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Shamelessly cribbed from https://charemza.name/blog/posts/aws/python/you-might-not-need-boto-3/
|
|
2
|
+
|
|
3
|
+
import datetime
|
|
4
|
+
import hashlib
|
|
5
|
+
import hmac
|
|
6
|
+
import urllib.parse
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def aws_sig_v4_headers(
|
|
10
|
+
access_key_id: str,
|
|
11
|
+
secret_access_key: str,
|
|
12
|
+
pre_auth_headers: dict[str, str],
|
|
13
|
+
service: str,
|
|
14
|
+
region: str,
|
|
15
|
+
host: str,
|
|
16
|
+
method: str,
|
|
17
|
+
path: str,
|
|
18
|
+
query: dict[str, str],
|
|
19
|
+
payload: bytes,
|
|
20
|
+
) -> dict[str, str]:
|
|
21
|
+
"""Constructs signed headers for use in requests made to AWS."""
|
|
22
|
+
algorithm = "AWS4-HMAC-SHA256"
|
|
23
|
+
now = datetime.datetime.utcnow()
|
|
24
|
+
amzdate = now.strftime("%Y%m%dT%H%M%SZ")
|
|
25
|
+
datestamp = now.strftime("%Y%m%d")
|
|
26
|
+
payload_hash = hashlib.sha256(payload).hexdigest()
|
|
27
|
+
credential_scope = f"{datestamp}/{region}/{service}/aws4_request"
|
|
28
|
+
|
|
29
|
+
pre_auth_headers_lower = {
|
|
30
|
+
header_key.lower(): " ".join(header_value.split())
|
|
31
|
+
for header_key, header_value in pre_auth_headers.items()
|
|
32
|
+
}
|
|
33
|
+
required_headers = {
|
|
34
|
+
"host": host,
|
|
35
|
+
"x-amz-content-sha256": payload_hash,
|
|
36
|
+
"x-amz-date": amzdate,
|
|
37
|
+
}
|
|
38
|
+
headers = {**pre_auth_headers_lower, **required_headers}
|
|
39
|
+
header_keys = sorted(headers.keys())
|
|
40
|
+
signed_headers = ";".join(header_keys)
|
|
41
|
+
|
|
42
|
+
def signature() -> str:
|
|
43
|
+
def canonical_request() -> str:
|
|
44
|
+
canonical_uri = urllib.parse.quote(path, safe="/~")
|
|
45
|
+
quoted_query = sorted(
|
|
46
|
+
(urllib.parse.quote(key, safe="~"), urllib.parse.quote(value, safe="~"))
|
|
47
|
+
for key, value in query.items()
|
|
48
|
+
)
|
|
49
|
+
canonical_querystring = "&".join(f"{key}={value}" for key, value in quoted_query)
|
|
50
|
+
canonical_headers = "".join(f"{key}:{headers[key]}\n" for key in header_keys)
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
f"{method}\n{canonical_uri}\n{canonical_querystring}\n"
|
|
54
|
+
+ f"{canonical_headers}\n{signed_headers}\n{payload_hash}"
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
def sign(key: bytes, msg: str) -> bytes:
|
|
58
|
+
return hmac.new(key, msg.encode("utf-8"), hashlib.sha256).digest()
|
|
59
|
+
|
|
60
|
+
string_to_sign = (
|
|
61
|
+
f"{algorithm}\n{amzdate}\n{credential_scope}\n"
|
|
62
|
+
+ hashlib.sha256(canonical_request().encode("utf-8")).hexdigest()
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
date_key = sign(("AWS4" + secret_access_key).encode("utf-8"), datestamp)
|
|
66
|
+
region_key = sign(date_key, region)
|
|
67
|
+
service_key = sign(region_key, service)
|
|
68
|
+
request_key = sign(service_key, "aws4_request")
|
|
69
|
+
return sign(request_key, string_to_sign).hex()
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
**pre_auth_headers,
|
|
73
|
+
"x-amz-date": amzdate,
|
|
74
|
+
"x-amz-content-sha256": payload_hash,
|
|
75
|
+
"Authorization": f"{algorithm} Credential={access_key_id}/{credential_scope}, "
|
|
76
|
+
f"SignedHeaders={signed_headers}, Signature=" + signature(),
|
|
77
|
+
}
|
|
@@ -9,12 +9,13 @@ from pathlib import Path
|
|
|
9
9
|
from typing import Any, TypedDict
|
|
10
10
|
from urllib import parse
|
|
11
11
|
|
|
12
|
-
import boto3
|
|
13
12
|
import psycopg
|
|
13
|
+
import requests
|
|
14
14
|
from psycopg import Connection
|
|
15
15
|
from psycopg.rows import dict_row
|
|
16
16
|
|
|
17
17
|
import settings
|
|
18
|
+
from plugin_runner.aws_headers import aws_sig_v4_headers
|
|
18
19
|
from plugin_runner.exceptions import InvalidPluginFormat, PluginInstallationError
|
|
19
20
|
|
|
20
21
|
# Plugin "packages" include this prefix in the database record for the plugin and the S3 bucket key.
|
|
@@ -98,17 +99,34 @@ def _extract_rows_to_dict(rows: list) -> dict[str, PluginAttributes]:
|
|
|
98
99
|
@contextmanager
|
|
99
100
|
def download_plugin(plugin_package: str) -> Generator:
|
|
100
101
|
"""Download the plugin package from the S3 bucket."""
|
|
101
|
-
|
|
102
|
+
method = "GET"
|
|
103
|
+
host = f"s3-{settings.AWS_REGION}.amazonaws.com"
|
|
104
|
+
bucket = settings.MEDIA_S3_BUCKET_NAME
|
|
105
|
+
customer_identifier = settings.CUSTOMER_IDENTIFIER
|
|
106
|
+
path = f"/{bucket}/{customer_identifier}/{plugin_package}"
|
|
107
|
+
payload = b"This is required for the AWS headers because it is part of the signature"
|
|
108
|
+
pre_auth_headers: dict[str, str] = {}
|
|
109
|
+
query: dict[str, str] = {}
|
|
110
|
+
headers = aws_sig_v4_headers(
|
|
111
|
+
settings.AWS_ACCESS_KEY_ID,
|
|
112
|
+
settings.AWS_SECRET_ACCESS_KEY,
|
|
113
|
+
pre_auth_headers,
|
|
114
|
+
"s3",
|
|
115
|
+
settings.AWS_REGION,
|
|
116
|
+
host,
|
|
117
|
+
method,
|
|
118
|
+
path,
|
|
119
|
+
query,
|
|
120
|
+
payload,
|
|
121
|
+
)
|
|
122
|
+
|
|
102
123
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
103
124
|
prefix_dir = Path(temp_dir) / UPLOAD_TO_PREFIX
|
|
104
125
|
prefix_dir.mkdir() # create an intermediate directory reflecting the prefix
|
|
105
126
|
download_path = Path(temp_dir) / plugin_package
|
|
106
127
|
with open(download_path, "wb") as download_file:
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
f"{settings.CUSTOMER_IDENTIFIER}/{plugin_package}",
|
|
110
|
-
download_file,
|
|
111
|
-
)
|
|
128
|
+
response = requests.request(method=method, url=f"https://{host}{path}", headers=headers)
|
|
129
|
+
download_file.write(response.content)
|
|
112
130
|
yield download_path
|
|
113
131
|
|
|
114
132
|
|
plugin_runner/plugin_runner.py
CHANGED
|
@@ -193,7 +193,6 @@ class PluginRunner(PluginRunnerServicer):
|
|
|
193
193
|
) -> AsyncGenerator[ReloadPluginsResponse, None]:
|
|
194
194
|
"""This is invoked when we need to reload plugins."""
|
|
195
195
|
try:
|
|
196
|
-
load_plugins()
|
|
197
196
|
publish_message({"action": "restart"})
|
|
198
197
|
except ImportError:
|
|
199
198
|
yield ReloadPluginsResponse(success=False)
|
|
@@ -48,6 +48,8 @@ def main() -> None:
|
|
|
48
48
|
try:
|
|
49
49
|
print("plugin-synchronizer: installing plugins after web container start")
|
|
50
50
|
install_plugins()
|
|
51
|
+
print("plugin-synchronizer: sending SIGHUP to plugin-runner")
|
|
52
|
+
check_output(["circusctl", "signal", "plugin-runner", "1"], cwd="/app", stderr=STDOUT)
|
|
51
53
|
except CalledProcessError as e:
|
|
52
54
|
print("plugin-synchronizer: `install_plugins` failed:", e)
|
|
53
55
|
|
|
@@ -67,7 +69,7 @@ def main() -> None:
|
|
|
67
69
|
data = pickle.loads(message.get("data", pickle.dumps({})))
|
|
68
70
|
|
|
69
71
|
if "action" not in data or "client_id" not in data:
|
|
70
|
-
|
|
72
|
+
continue
|
|
71
73
|
|
|
72
74
|
if data["action"] == "restart":
|
|
73
75
|
# Run the plugin installer process
|
|
@@ -2,11 +2,10 @@ import json
|
|
|
2
2
|
import tarfile
|
|
3
3
|
import tempfile
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from unittest.mock import MagicMock
|
|
5
|
+
from unittest.mock import MagicMock, patch
|
|
6
6
|
|
|
7
7
|
from pytest_mock import MockerFixture
|
|
8
8
|
|
|
9
|
-
import settings
|
|
10
9
|
from plugin_runner.plugin_installer import (
|
|
11
10
|
PluginAttributes,
|
|
12
11
|
_extract_rows_to_dict,
|
|
@@ -106,13 +105,12 @@ def test_plugin_installation_from_tarball(mocker: MockerFixture) -> None:
|
|
|
106
105
|
|
|
107
106
|
def test_download(mocker: MockerFixture) -> None:
|
|
108
107
|
"""Test that the plugin package can be written to disk, mocking out S3."""
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
)
|
|
108
|
+
mock_response = MagicMock()
|
|
109
|
+
mock_response.status_code = 200
|
|
110
|
+
mock_response.content = b"some content in a file"
|
|
111
|
+
with patch("requests.request", return_value=mock_response) as mock_request:
|
|
112
|
+
plugin_package = "plugins/plugin1.tar.gz"
|
|
113
|
+
with download_plugin(plugin_package) as plugin_path:
|
|
114
|
+
assert plugin_path.exists()
|
|
115
|
+
assert plugin_path.read_bytes() == b"some content in a file"
|
|
116
|
+
mock_request.assert_called_once()
|
|
@@ -191,17 +191,3 @@ async def test_reload_plugins_event_handler_successfully_loads_plugins(
|
|
|
191
191
|
assert len(result) == 1
|
|
192
192
|
assert result[0].success is True
|
|
193
193
|
assert "example_plugin:example_plugin.protocols.my_protocol:Protocol" in LOADED_PLUGINS
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
@pytest.mark.asyncio
|
|
197
|
-
async def test_reload_plugins_import_error(plugin_runner: PluginRunner) -> None:
|
|
198
|
-
"""Test ReloadPlugins response when an ImportError occurs."""
|
|
199
|
-
request = ReloadPluginsRequest()
|
|
200
|
-
|
|
201
|
-
with patch("plugin_runner.plugin_runner.load_plugins", side_effect=ImportError):
|
|
202
|
-
responses = []
|
|
203
|
-
async for response in plugin_runner.ReloadPlugins(request, None):
|
|
204
|
-
responses.append(response)
|
|
205
|
-
|
|
206
|
-
assert len(responses) == 1
|
|
207
|
-
assert responses[0].success is False
|
|
@@ -14,6 +14,11 @@ import os
|
|
|
14
14
|
result = os.listdir('.')
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
|
+
CODE_WITH_PLUGIN_RUNNER_SETTING_IMPORT = """
|
|
18
|
+
import settings
|
|
19
|
+
result = settings.AWS_SECRET_ACCESS_KEY
|
|
20
|
+
"""
|
|
21
|
+
|
|
17
22
|
CODE_WITH_ALLOWED_IMPORT = """
|
|
18
23
|
import json
|
|
19
24
|
result = json.dumps({"key": "value"})
|
|
@@ -39,7 +44,14 @@ def test_valid_code_execution() -> None:
|
|
|
39
44
|
def test_disallowed_import() -> None:
|
|
40
45
|
"""Test that restricted imports are not allowed."""
|
|
41
46
|
sandbox = Sandbox(CODE_WITH_RESTRICTED_IMPORT)
|
|
42
|
-
with pytest.raises(ImportError, match="os' is not an allowed import."):
|
|
47
|
+
with pytest.raises(ImportError, match="'os' is not an allowed import."):
|
|
48
|
+
sandbox.execute()
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def test_plugin_runner_settings_import() -> None:
|
|
52
|
+
"""Test that imports of plugin runner settings are not allowed."""
|
|
53
|
+
sandbox = Sandbox(CODE_WITH_PLUGIN_RUNNER_SETTING_IMPORT)
|
|
54
|
+
with pytest.raises(ImportError, match="'settings' is not an allowed import."):
|
|
43
55
|
sandbox.execute()
|
|
44
56
|
|
|
45
57
|
|
settings.py
CHANGED
|
@@ -49,6 +49,10 @@ else:
|
|
|
49
49
|
|
|
50
50
|
DATABASES = {"default": database_dict}
|
|
51
51
|
|
|
52
|
+
AWS_ACCESS_KEY_ID = os.getenv("AWS_ACCESS_KEY_ID", "")
|
|
53
|
+
AWS_SECRET_ACCESS_KEY = os.getenv("AWS_SECRET_ACCESS_KEY", "")
|
|
54
|
+
AWS_REGION = os.getenv("AWS_REGION", "us-west-2")
|
|
55
|
+
MEDIA_S3_BUCKET_NAME = os.getenv("MEDIA_S3_BUCKET_NAME", "canvas-client-media")
|
|
52
56
|
|
|
53
57
|
PLUGIN_RUNNER_SIGNING_KEY = os.getenv("PLUGIN_RUNNER_SIGNING_KEY", "")
|
|
54
58
|
|
|
File without changes
|
|
File without changes
|