canvas 0.2.11__py3-none-any.whl → 0.3.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.2.11.dist-info → canvas-0.3.1.dist-info}/METADATA +3 -3
- canvas-0.3.1.dist-info/RECORD +216 -0
- canvas_cli/apps/emit/__init__.py +3 -0
- canvas_cli/apps/emit/emit.py +67 -0
- canvas_cli/apps/emit/event_fixtures/ALLERGY_INTOLERANCE_CREATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/ALLERGY_INTOLERANCE_UPDATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/APPOINTMENT_CANCELED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/APPOINTMENT_CHECKED_IN.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/APPOINTMENT_CREATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/APPOINTMENT_NO_SHOWED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/APPOINTMENT_RESCHEDULED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/APPOINTMENT_RESTORED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/APPOINTMENT_UPDATED.ndjson +2 -0
- canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__CONDITION_SELECTED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__POST_COMMIT.ndjson +3 -0
- canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__POST_ORIGINATE.ndjson +4 -0
- canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__POST_UPDATE.ndjson +5 -0
- canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__PRE_COMMIT.ndjson +3 -0
- canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__PRE_ORIGINATE.ndjson +4 -0
- canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__PRE_UPDATE.ndjson +5 -0
- canvas_cli/apps/emit/event_fixtures/BILLING_LINE_ITEM_CREATED.ndjson +3 -0
- canvas_cli/apps/emit/event_fixtures/BILLING_LINE_ITEM_UPDATED.ndjson +2 -0
- canvas_cli/apps/emit/event_fixtures/CONDITION_ASSESSED.ndjson +2 -0
- canvas_cli/apps/emit/event_fixtures/CONDITION_CREATED.ndjson +4 -0
- canvas_cli/apps/emit/event_fixtures/CONDITION_UPDATED.ndjson +5 -0
- canvas_cli/apps/emit/event_fixtures/CRON.ndjson +3 -0
- canvas_cli/apps/emit/event_fixtures/ENCOUNTER_CREATED.ndjson +3 -0
- canvas_cli/apps/emit/event_fixtures/ENCOUNTER_UPDATED.ndjson +2 -0
- canvas_cli/apps/emit/event_fixtures/IMMUNIZATION_CREATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/IMMUNIZATION_STATEMENT_CREATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/IMMUNIZATION_STATEMENT_UPDATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/IMMUNIZATION_UPDATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/INTERVIEW_CREATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/INTERVIEW_UPDATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/LAB_ORDER_CREATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/LAB_ORDER_UPDATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/MEDICATION_LIST_ITEM_CREATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/MEDICATION_LIST_ITEM_UPDATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__POST_COMMIT.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__POST_ORIGINATE.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__POST_UPDATE.ndjson +2 -0
- canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__PRE_COMMIT.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__PRE_ORIGINATE.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__PRE_UPDATE.ndjson +2 -0
- canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT__MEDICATION__POST_SEARCH.ndjson +2 -0
- canvas_cli/apps/emit/event_fixtures/PATIENT_CREATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/PATIENT_UPDATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/PLAN_COMMAND__POST_ORIGINATE.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/PLAN_COMMAND__PRE_ORIGINATE.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__POST_COMMIT.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__POST_ORIGINATE.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__POST_UPDATE.ndjson +2 -0
- canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__PRE_COMMIT.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__PRE_ORIGINATE.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__PRE_UPDATE.ndjson +2 -0
- canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE__QUESTIONNAIRE__POST_SEARCH.ndjson +4 -0
- canvas_cli/apps/emit/event_fixtures/TASK_COMMENT_CREATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/TASK_CREATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/TASK_UPDATED.ndjson +1 -0
- canvas_cli/apps/emit/event_fixtures/VITAL_SIGN_CREATED.ndjson +14 -0
- canvas_cli/apps/emit/event_fixtures/VITAL_SIGN_UPDATED.ndjson +364 -0
- canvas_cli/apps/plugin/plugin.py +56 -23
- canvas_cli/apps/run_plugins/__init__.py +3 -0
- canvas_cli/apps/run_plugins/run_plugins.py +16 -0
- canvas_cli/main.py +8 -38
- canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/README.md +0 -1
- canvas_cli/utils/validators/validators.py +1 -1
- canvas_generated/messages/effects_pb2.py +5 -5
- canvas_generated/messages/effects_pb2.pyi +4 -2
- canvas_generated/messages/events_pb2.py +3 -3
- canvas_generated/messages/events_pb2.pyi +70 -0
- canvas_generated/messages/plugins_pb2.py +1 -1
- canvas_generated/services/plugin_runner_pb2.py +1 -1
- canvas_sdk/base.py +2 -2
- canvas_sdk/commands/__init__.py +3 -1
- canvas_sdk/commands/base.py +2 -2
- canvas_sdk/commands/commands/allergy.py +2 -0
- canvas_sdk/commands/commands/close_goal.py +3 -0
- canvas_sdk/commands/commands/prescribe.py +1 -3
- canvas_sdk/commands/commands/refill.py +1 -0
- canvas_sdk/commands/commands/task.py +1 -1
- canvas_sdk/commands/commands/vitals.py +15 -12
- canvas_sdk/commands/tests/schema/tests.py +1 -1
- canvas_sdk/commands/tests/test_utils.py +4 -2
- canvas_sdk/data/base.py +5 -1
- canvas_sdk/data/client.py +1 -1
- canvas_sdk/data/patient.py +2 -0
- canvas_sdk/data/staff.py +2 -0
- canvas_sdk/data/task.py +7 -0
- canvas_sdk/effects/protocol_card/protocol_card.py +2 -0
- canvas_sdk/effects/protocol_card/tests.py +5 -2
- canvas_sdk/protocols/__init__.py +1 -0
- canvas_sdk/protocols/clinical_quality_measure.py +1 -0
- canvas_sdk/utils/http.py +19 -18
- canvas_sdk/utils/stats.py +2 -1
- canvas_sdk/v1/data/allergy_intolerance.py +2 -3
- canvas_sdk/v1/data/base.py +55 -9
- canvas_sdk/v1/data/command.py +27 -0
- canvas_sdk/v1/data/device.py +44 -0
- canvas_sdk/v1/data/lab.py +8 -0
- canvas_sdk/v1/data/observation.py +117 -0
- canvas_sdk/v1/data/patient.py +3 -0
- canvas_sdk/v1/data/questionnaire.py +204 -0
- canvas_sdk/v1/data/user.py +2 -0
- canvas_sdk/value_set/v2022/condition.py +2 -2
- canvas_sdk/value_set/v2022/encounter.py +1 -1
- canvas_sdk/value_set/value_set.py +20 -5
- logger/__init__.py +1 -0
- logger/logger.py +17 -6
- plugin_runner/__init__.py +0 -0
- plugin_runner/authentication.py +48 -0
- plugin_runner/plugin_runner.py +338 -0
- plugin_runner/plugin_synchronizer.py +87 -0
- plugin_runner/sandbox.py +273 -0
- pubsub/__init__.py +0 -0
- pubsub/pubsub.py +38 -0
- canvas-0.2.11.dist-info/RECORD +0 -144
- {canvas-0.2.11.dist-info → canvas-0.3.1.dist-info}/WHEEL +0 -0
- {canvas-0.2.11.dist-info → canvas-0.3.1.dist-info}/entry_points.txt +0 -0
canvas_sdk/data/task.py
CHANGED
|
@@ -8,6 +8,8 @@ from canvas_sdk.effects import Effect, EffectType
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class Task(DataModel):
|
|
11
|
+
"""Data model for a task."""
|
|
12
|
+
|
|
11
13
|
class Meta(DataModel.Meta):
|
|
12
14
|
create_required_fields = ("title",)
|
|
13
15
|
|
|
@@ -26,15 +28,18 @@ class Task(DataModel):
|
|
|
26
28
|
labels: list[str] | None = None
|
|
27
29
|
|
|
28
30
|
def create(self) -> Effect:
|
|
31
|
+
"""Return an effect to create the task."""
|
|
29
32
|
self._validate_before_effect("create")
|
|
30
33
|
return Effect(type=EffectType.CREATE_TASK, payload=self.model_dump_json_nested())
|
|
31
34
|
|
|
32
35
|
def update(self) -> Effect:
|
|
36
|
+
"""Return an effect to update the task."""
|
|
33
37
|
self._validate_before_effect("update")
|
|
34
38
|
payload = self.model_dump_json_nested(exclude_unset=True)
|
|
35
39
|
return Effect(type=EffectType.UPDATE_TASK, payload=payload)
|
|
36
40
|
|
|
37
41
|
def add_comment(self, comment: str) -> Effect:
|
|
42
|
+
"""Return an effect to add a comment to the task."""
|
|
38
43
|
if not self.id:
|
|
39
44
|
raise ValueError("Cannot add a comment to a Task without an id")
|
|
40
45
|
task_comment = TaskComment(task=self, body=comment)
|
|
@@ -46,6 +51,8 @@ class Task(DataModel):
|
|
|
46
51
|
|
|
47
52
|
|
|
48
53
|
class TaskComment(DataModel):
|
|
54
|
+
"""Data model for a task comment."""
|
|
55
|
+
|
|
49
56
|
class Meta:
|
|
50
57
|
create_required_fields = (
|
|
51
58
|
"body",
|
|
@@ -50,6 +50,7 @@ class ProtocolCard(_BaseEffect):
|
|
|
50
50
|
narrative: str = ""
|
|
51
51
|
recommendations: list[Recommendation] = []
|
|
52
52
|
status: Status = Status.DUE # type: ignore
|
|
53
|
+
feedback_enabled: bool = False
|
|
53
54
|
|
|
54
55
|
@property
|
|
55
56
|
def values(self) -> dict[str, Any]:
|
|
@@ -61,6 +62,7 @@ class ProtocolCard(_BaseEffect):
|
|
|
61
62
|
rec.values | {"key": i} for i, rec in enumerate(self.recommendations)
|
|
62
63
|
],
|
|
63
64
|
"status": self.status.value,
|
|
65
|
+
"feedback_enabled": self.feedback_enabled,
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
@property
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
1
3
|
import pytest
|
|
2
4
|
from pydantic import ValidationError
|
|
3
5
|
|
|
@@ -23,7 +25,7 @@ def test_apply_method_succeeds_with_patient_id_and_key() -> None:
|
|
|
23
25
|
applied = p.apply()
|
|
24
26
|
assert (
|
|
25
27
|
applied.payload
|
|
26
|
-
== '{"patient": "uuid", "key": "something-unique", "data": {"title": "", "narrative": "", "recommendations": [], "status": "due"}}'
|
|
28
|
+
== '{"patient": "uuid", "key": "something-unique", "data": {"title": "", "narrative": "", "recommendations": [], "status": "due", "feedback_enabled": false}}'
|
|
27
29
|
)
|
|
28
30
|
|
|
29
31
|
|
|
@@ -105,7 +107,7 @@ def test_apply_method_raises_error_without_patient_id_and_key() -> None:
|
|
|
105
107
|
],
|
|
106
108
|
)
|
|
107
109
|
def test_add_recommendations(
|
|
108
|
-
init_params: dict[str, str], rec1_params: dict[
|
|
110
|
+
init_params: dict[str, str], rec1_params: dict[Any, Any], rec2_params: dict[str, str]
|
|
109
111
|
) -> None:
|
|
110
112
|
p = ProtocolCard(**init_params)
|
|
111
113
|
p.add_recommendation(**rec1_params)
|
|
@@ -133,6 +135,7 @@ def test_add_recommendations(
|
|
|
133
135
|
},
|
|
134
136
|
],
|
|
135
137
|
"status": "due",
|
|
138
|
+
"feedback_enabled": False,
|
|
136
139
|
}
|
|
137
140
|
|
|
138
141
|
|
canvas_sdk/protocols/__init__.py
CHANGED
canvas_sdk/utils/http.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import time
|
|
2
2
|
from functools import wraps
|
|
3
|
-
from typing import Any, Callable, TypeVar
|
|
3
|
+
from typing import Any, Callable, Mapping, TypeVar
|
|
4
4
|
|
|
5
5
|
import requests
|
|
6
6
|
import statsd
|
|
@@ -16,26 +16,27 @@ class Http:
|
|
|
16
16
|
self.statsd_client = statsd.StatsClient()
|
|
17
17
|
|
|
18
18
|
@staticmethod
|
|
19
|
-
def measure_time(fn: F
|
|
19
|
+
def measure_time(fn: F) -> F:
|
|
20
20
|
"""A decorator to store timing of HTTP calls."""
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return result
|
|
22
|
+
@wraps(fn)
|
|
23
|
+
def wrapper(self: "Http", *args: Any, **kwargs: Any) -> Any:
|
|
24
|
+
start_time = time.time()
|
|
25
|
+
result = fn(self, *args, **kwargs)
|
|
26
|
+
end_time = time.time()
|
|
27
|
+
timing = int((end_time - start_time) * 1000)
|
|
28
|
+
self.statsd_client.timing(f"http_{fn.__name__}", timing)
|
|
29
|
+
return result
|
|
31
30
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return _decorator(fn) if fn else _decorator
|
|
31
|
+
return wrapper
|
|
35
32
|
|
|
36
33
|
@measure_time
|
|
37
|
-
def get(
|
|
34
|
+
def get(
|
|
35
|
+
self, url: str, headers: Mapping[str, str | bytes | None] | None = None
|
|
36
|
+
) -> requests.Response:
|
|
38
37
|
"""Sends a GET request."""
|
|
38
|
+
if headers is None:
|
|
39
|
+
headers = {}
|
|
39
40
|
return self.session.get(url, headers=headers)
|
|
40
41
|
|
|
41
42
|
@measure_time
|
|
@@ -44,7 +45,7 @@ class Http:
|
|
|
44
45
|
url: str,
|
|
45
46
|
json: dict | None = None,
|
|
46
47
|
data: dict | str | list | bytes | None = None,
|
|
47
|
-
headers:
|
|
48
|
+
headers: Mapping[str, str | bytes | None] | None = None,
|
|
48
49
|
) -> requests.Response:
|
|
49
50
|
"""Sends a POST request."""
|
|
50
51
|
return self.session.post(url, json=json, data=data, headers=headers)
|
|
@@ -55,7 +56,7 @@ class Http:
|
|
|
55
56
|
url: str,
|
|
56
57
|
json: dict | None = None,
|
|
57
58
|
data: dict | str | list | bytes | None = None,
|
|
58
|
-
headers:
|
|
59
|
+
headers: Mapping[str, str | bytes | None] | None = None,
|
|
59
60
|
) -> requests.Response:
|
|
60
61
|
"""Sends a PUT request."""
|
|
61
62
|
return self.session.put(url, json=json, data=data, headers=headers)
|
|
@@ -66,7 +67,7 @@ class Http:
|
|
|
66
67
|
url: str,
|
|
67
68
|
json: dict | None = None,
|
|
68
69
|
data: dict | str | list | bytes | None = None,
|
|
69
|
-
headers:
|
|
70
|
+
headers: Mapping[str, str | bytes | None] | None = None,
|
|
70
71
|
) -> requests.Response:
|
|
71
72
|
"""Sends a PATCH request."""
|
|
72
73
|
return self.session.patch(url, json=json, data=data, headers=headers)
|
canvas_sdk/utils/stats.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from django.contrib.postgres.fields import ArrayField
|
|
2
2
|
from django.db import models
|
|
3
3
|
|
|
4
|
-
from canvas_sdk.v1.data.base import CommittableModelManager
|
|
4
|
+
from canvas_sdk.v1.data.base import CommittableModelManager, ValueSetLookupQuerySet
|
|
5
5
|
from canvas_sdk.v1.data.patient import Patient
|
|
6
6
|
from canvas_sdk.v1.data.user import CanvasUser
|
|
7
7
|
|
|
@@ -14,13 +14,12 @@ class AllergyIntolerance(models.Model):
|
|
|
14
14
|
app_label = "canvas_sdk"
|
|
15
15
|
db_table = "canvas_sdk_data_api_allergyintolerance_001"
|
|
16
16
|
|
|
17
|
-
objects = CommittableModelManager()
|
|
17
|
+
objects = CommittableModelManager().from_queryset(ValueSetLookupQuerySet)()
|
|
18
18
|
|
|
19
19
|
id = models.UUIDField()
|
|
20
20
|
dbid = models.BigIntegerField(primary_key=True)
|
|
21
21
|
created = models.DateTimeField()
|
|
22
22
|
modified = models.DateTimeField()
|
|
23
|
-
editors = ArrayField(models.IntegerField())
|
|
24
23
|
deleted = models.BooleanField()
|
|
25
24
|
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
26
25
|
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
canvas_sdk/v1/data/base.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from
|
|
1
|
+
from collections.abc import Container
|
|
2
|
+
from typing import TYPE_CHECKING, Type, cast
|
|
2
3
|
|
|
3
4
|
from django.db import models
|
|
4
5
|
from django.db.models import Q
|
|
@@ -8,19 +9,26 @@ if TYPE_CHECKING:
|
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
class CommittableModelManager(models.Manager):
|
|
12
|
+
"""A manager for commands that can be committed."""
|
|
13
|
+
|
|
11
14
|
def get_queryset(self) -> "models.QuerySet":
|
|
15
|
+
"""Return a queryset that filters out deleted objects."""
|
|
12
16
|
# TODO: Should we just filter these out at the view level?
|
|
13
17
|
return super().get_queryset().filter(deleted=False)
|
|
14
18
|
|
|
15
19
|
def committed(self) -> "models.QuerySet":
|
|
20
|
+
"""Return a queryset that filters for objects that have been committed."""
|
|
16
21
|
# The committer_id IS set, and the entered_in_error_id IS NOT set
|
|
17
22
|
return self.filter(committer_id__isnull=False, entered_in_error_id__isnull=True)
|
|
18
23
|
|
|
19
24
|
def for_patient(self, patient_id: str) -> "models.QuerySet":
|
|
25
|
+
"""Return a queryset that filters objects for a specific patient."""
|
|
20
26
|
return self.filter(patient__id=patient_id)
|
|
21
27
|
|
|
22
28
|
|
|
23
29
|
class ValueSetLookupQuerySet(models.QuerySet):
|
|
30
|
+
"""A QuerySet that can filter objects based on a ValueSet."""
|
|
31
|
+
|
|
24
32
|
def find(self, value_set: Type["ValueSet"]) -> models.QuerySet:
|
|
25
33
|
"""
|
|
26
34
|
Filters conditions, medications, etc. to those found in the inherited ValueSet class that is passed.
|
|
@@ -35,13 +43,51 @@ class ValueSetLookupQuerySet(models.QuerySet):
|
|
|
35
43
|
|
|
36
44
|
Condition.objects.find(MorbidObesity).find(AnaphylacticReactionToCommonBakersYeast)
|
|
37
45
|
"""
|
|
38
|
-
values_dict = value_set.values
|
|
39
|
-
uri_codes = [
|
|
40
|
-
(i[1], values_dict[i[0]])
|
|
41
|
-
for i in value_set.CODE_SYSTEM_MAPPING.items()
|
|
42
|
-
if i[0] in values_dict
|
|
43
|
-
]
|
|
44
46
|
q_filter = Q()
|
|
45
|
-
for system, codes in
|
|
46
|
-
q_filter |=
|
|
47
|
+
for system, codes in self.codings(value_set):
|
|
48
|
+
q_filter |= self.q_object(system, codes)
|
|
47
49
|
return self.filter(q_filter).distinct()
|
|
50
|
+
|
|
51
|
+
@staticmethod
|
|
52
|
+
def codings(value_set: Type["ValueSet"]) -> tuple[tuple[str, set[str]]]:
|
|
53
|
+
"""Provide a sequence of tuples where each tuple is a code system URL and a set of codes."""
|
|
54
|
+
values_dict = value_set.values
|
|
55
|
+
return cast(
|
|
56
|
+
tuple[tuple[str, set[str]]],
|
|
57
|
+
tuple(
|
|
58
|
+
(i[1], values_dict[i[0]])
|
|
59
|
+
for i in value_set.CODE_SYSTEM_MAPPING.items()
|
|
60
|
+
if i[0] in values_dict
|
|
61
|
+
),
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
@staticmethod
|
|
65
|
+
def q_object(system: str, codes: Container[str]) -> Q:
|
|
66
|
+
"""
|
|
67
|
+
This method can be overridden if a Q object with different filtering options is needed.
|
|
68
|
+
"""
|
|
69
|
+
return Q(codings__system=system, codings__code__in=codes)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class ValueSetLookupByNameQuerySet(ValueSetLookupQuerySet):
|
|
73
|
+
"""
|
|
74
|
+
QuerySet for ValueSet lookups using code system name rather than URL.
|
|
75
|
+
|
|
76
|
+
Some models, like Questionnaire, store the code system by name (e.g. "LOINC") rather than by the
|
|
77
|
+
url (e.g. "http://loinc.org"). This subclass accommodates these models.
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
@staticmethod
|
|
81
|
+
def codings(value_set: Type["ValueSet"]) -> tuple[tuple[str, set[str]]]:
|
|
82
|
+
"""
|
|
83
|
+
Provide a sequence of tuples where each tuple is a code system name and a set of codes.
|
|
84
|
+
"""
|
|
85
|
+
values_dict = value_set.values
|
|
86
|
+
return cast(
|
|
87
|
+
tuple[tuple[str, set[str]]],
|
|
88
|
+
tuple(
|
|
89
|
+
(i[0], values_dict[i[0]])
|
|
90
|
+
for i in value_set.CODE_SYSTEM_MAPPING.items()
|
|
91
|
+
if i[0] in values_dict
|
|
92
|
+
),
|
|
93
|
+
)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
|
|
3
|
+
from canvas_sdk.v1.data.patient import Patient
|
|
4
|
+
from canvas_sdk.v1.data.user import CanvasUser
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Command(models.Model):
|
|
8
|
+
"""Command."""
|
|
9
|
+
|
|
10
|
+
class Meta:
|
|
11
|
+
managed = False
|
|
12
|
+
app_label = "canvas_sdk"
|
|
13
|
+
db_table = "canvas_sdk_data_commands_command_001"
|
|
14
|
+
|
|
15
|
+
id = models.UUIDField()
|
|
16
|
+
dbid = models.BigIntegerField(primary_key=True)
|
|
17
|
+
created = models.DateTimeField()
|
|
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
|
+
state = models.CharField()
|
|
23
|
+
patient = models.ForeignKey(Patient, on_delete=models.DO_NOTHING)
|
|
24
|
+
note_id = models.BigIntegerField()
|
|
25
|
+
schema_key = models.TextField()
|
|
26
|
+
data = models.JSONField()
|
|
27
|
+
origination_source = models.CharField()
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
|
|
3
|
+
from canvas_sdk.v1.data import Patient
|
|
4
|
+
from canvas_sdk.v1.data.user import CanvasUser
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Device(models.Model):
|
|
8
|
+
"""Device."""
|
|
9
|
+
|
|
10
|
+
class Meta:
|
|
11
|
+
managed = False
|
|
12
|
+
app_label = "canvas_sdk"
|
|
13
|
+
db_table = "canvas_sdk_data_api_device_001"
|
|
14
|
+
|
|
15
|
+
id = models.UUIDField()
|
|
16
|
+
dbid = models.BigIntegerField(primary_key=True)
|
|
17
|
+
created = models.DateTimeField()
|
|
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(Patient, on_delete=models.DO_NOTHING, related_name="devices")
|
|
23
|
+
note_id = models.BigIntegerField()
|
|
24
|
+
deleted = models.BooleanField()
|
|
25
|
+
labeled_contains_NRL = models.BooleanField()
|
|
26
|
+
assigning_authority = models.CharField()
|
|
27
|
+
scoping_entity = models.CharField()
|
|
28
|
+
udi = models.CharField()
|
|
29
|
+
di = models.CharField()
|
|
30
|
+
issuing_agency = models.CharField()
|
|
31
|
+
lot_number = models.CharField()
|
|
32
|
+
brand_name = models.CharField()
|
|
33
|
+
mri_safety_status = models.CharField()
|
|
34
|
+
version_model_number = models.CharField()
|
|
35
|
+
company_name = models.CharField()
|
|
36
|
+
gmdnPTName = models.TextField()
|
|
37
|
+
status = models.CharField()
|
|
38
|
+
expiration_date = models.DateField()
|
|
39
|
+
expiration_date_original = models.CharField()
|
|
40
|
+
serial_number = models.CharField()
|
|
41
|
+
manufacturing_date_original = models.CharField()
|
|
42
|
+
manufacturing_date = models.DateField()
|
|
43
|
+
manufacturer = models.CharField()
|
|
44
|
+
procedure_id = models.BigIntegerField()
|
canvas_sdk/v1/data/lab.py
CHANGED
|
@@ -6,6 +6,8 @@ from canvas_sdk.v1.data.user import CanvasUser
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class LabReport(models.Model):
|
|
9
|
+
"""A class representing a lab report."""
|
|
10
|
+
|
|
9
11
|
class Meta:
|
|
10
12
|
managed = False
|
|
11
13
|
app_label = "canvas_sdk"
|
|
@@ -38,6 +40,8 @@ class LabReport(models.Model):
|
|
|
38
40
|
|
|
39
41
|
|
|
40
42
|
class LabReview(models.Model):
|
|
43
|
+
"""A class representing a lab review."""
|
|
44
|
+
|
|
41
45
|
class Meta:
|
|
42
46
|
managed = False
|
|
43
47
|
app_label = "canvas_sdk"
|
|
@@ -61,6 +65,8 @@ class LabReview(models.Model):
|
|
|
61
65
|
|
|
62
66
|
|
|
63
67
|
class LabValue(models.Model):
|
|
68
|
+
"""A class representing a lab value."""
|
|
69
|
+
|
|
64
70
|
class Meta:
|
|
65
71
|
managed = False
|
|
66
72
|
app_label = "canvas_sdk"
|
|
@@ -82,6 +88,8 @@ class LabValue(models.Model):
|
|
|
82
88
|
|
|
83
89
|
|
|
84
90
|
class LabValueCoding(models.Model):
|
|
91
|
+
"""A class representing a lab value coding."""
|
|
92
|
+
|
|
85
93
|
class Meta:
|
|
86
94
|
managed = False
|
|
87
95
|
app_label = "canvas_sdk"
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
|
|
3
|
+
from canvas_sdk.v1.data.base import CommittableModelManager, ValueSetLookupQuerySet
|
|
4
|
+
from canvas_sdk.v1.data.patient import Patient
|
|
5
|
+
from canvas_sdk.v1.data.user import CanvasUser
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ObservationQuerySet(ValueSetLookupQuerySet):
|
|
9
|
+
"""ObservationQuerySet."""
|
|
10
|
+
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Observation(models.Model):
|
|
15
|
+
"""Observation."""
|
|
16
|
+
|
|
17
|
+
class Meta:
|
|
18
|
+
managed = False
|
|
19
|
+
app_label = "canvas_sdk"
|
|
20
|
+
db_table = "canvas_sdk_data_api_observation_001"
|
|
21
|
+
|
|
22
|
+
objects = CommittableModelManager.from_queryset(ObservationQuerySet)()
|
|
23
|
+
|
|
24
|
+
id = models.UUIDField()
|
|
25
|
+
dbid = models.BigIntegerField(primary_key=True)
|
|
26
|
+
created = models.DateTimeField()
|
|
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)
|
|
31
|
+
deleted = models.BooleanField()
|
|
32
|
+
patient = models.ForeignKey(Patient, on_delete=models.DO_NOTHING, related_name="observations")
|
|
33
|
+
is_member_of = models.ForeignKey(
|
|
34
|
+
"self", on_delete=models.DO_NOTHING, null=True, related_name="members"
|
|
35
|
+
)
|
|
36
|
+
category = models.CharField()
|
|
37
|
+
units = models.TextField()
|
|
38
|
+
value = models.TextField()
|
|
39
|
+
note_id = models.BigIntegerField()
|
|
40
|
+
name = models.TextField()
|
|
41
|
+
effective_datetime = models.DateTimeField()
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class ObservationCoding(models.Model):
|
|
45
|
+
"""ObservationCoding."""
|
|
46
|
+
|
|
47
|
+
class Meta:
|
|
48
|
+
managed = False
|
|
49
|
+
app_label = "canvas_sdk"
|
|
50
|
+
db_table = "canvas_sdk_data_api_observationcoding_001"
|
|
51
|
+
|
|
52
|
+
dbid = models.BigIntegerField(primary_key=True)
|
|
53
|
+
system = models.CharField()
|
|
54
|
+
version = models.CharField()
|
|
55
|
+
code = models.CharField()
|
|
56
|
+
display = models.CharField()
|
|
57
|
+
user_selected = models.BooleanField()
|
|
58
|
+
observation = models.ForeignKey(
|
|
59
|
+
Observation, on_delete=models.DO_NOTHING, related_name="codings"
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class ObservationComponent(models.Model):
|
|
64
|
+
"""ObservationComponent."""
|
|
65
|
+
|
|
66
|
+
class Meta:
|
|
67
|
+
managed = False
|
|
68
|
+
app_label = "canvas_sdk"
|
|
69
|
+
db_table = "canvas_sdk_data_api_observationcomponent_001"
|
|
70
|
+
|
|
71
|
+
dbid = models.BigIntegerField(primary_key=True)
|
|
72
|
+
created = models.DateTimeField()
|
|
73
|
+
modified = models.DateTimeField()
|
|
74
|
+
observation = models.ForeignKey(
|
|
75
|
+
Observation, on_delete=models.DO_NOTHING, related_name="components"
|
|
76
|
+
)
|
|
77
|
+
value_quantity = models.TextField()
|
|
78
|
+
value_quantity_unit = models.TextField()
|
|
79
|
+
name = models.TextField()
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class ObservationComponentCoding(models.Model):
|
|
83
|
+
"""ObservationComponentCoding."""
|
|
84
|
+
|
|
85
|
+
class Meta:
|
|
86
|
+
managed = False
|
|
87
|
+
app_label = "canvas_sdk"
|
|
88
|
+
db_table = "canvas_sdk_data_api_observationcomponentcoding_001"
|
|
89
|
+
|
|
90
|
+
dbid = models.BigIntegerField(primary_key=True)
|
|
91
|
+
system = models.CharField()
|
|
92
|
+
version = models.CharField()
|
|
93
|
+
code = models.CharField()
|
|
94
|
+
display = models.CharField()
|
|
95
|
+
user_selected = models.BooleanField()
|
|
96
|
+
observation_component = models.ForeignKey(
|
|
97
|
+
ObservationComponent, on_delete=models.DO_NOTHING, related_name="codings"
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class ObservationValueCoding(models.Model):
|
|
102
|
+
"""ObservationValueCoding."""
|
|
103
|
+
|
|
104
|
+
class Meta:
|
|
105
|
+
managed = False
|
|
106
|
+
app_label = "canvas_sdk"
|
|
107
|
+
db_table = "canvas_sdk_data_api_observationvaluecoding_001"
|
|
108
|
+
|
|
109
|
+
dbid = models.BigIntegerField(primary_key=True)
|
|
110
|
+
system = models.CharField()
|
|
111
|
+
version = models.CharField()
|
|
112
|
+
code = models.CharField()
|
|
113
|
+
display = models.CharField()
|
|
114
|
+
user_selected = models.BooleanField()
|
|
115
|
+
observation = models.ForeignKey(
|
|
116
|
+
Observation, on_delete=models.DO_NOTHING, related_name="value_codings"
|
|
117
|
+
)
|
canvas_sdk/v1/data/patient.py
CHANGED
|
@@ -4,6 +4,8 @@ from django.db import models
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class Patient(models.Model):
|
|
7
|
+
"""A class representing a patient."""
|
|
8
|
+
|
|
7
9
|
class Meta:
|
|
8
10
|
managed = False
|
|
9
11
|
app_label = "canvas_sdk"
|
|
@@ -46,4 +48,5 @@ class Patient(models.Model):
|
|
|
46
48
|
|
|
47
49
|
@classmethod
|
|
48
50
|
def find(cls, id: str) -> Self:
|
|
51
|
+
"""Find a patient by id."""
|
|
49
52
|
return cls.objects.get(id=id)
|