canvas 0.2.5__py3-none-any.whl → 0.2.11__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.5.dist-info → canvas-0.2.11.dist-info}/METADATA +4 -1
- canvas-0.2.11.dist-info/RECORD +144 -0
- canvas_cli/apps/plugin/plugin.py +51 -9
- canvas_cli/apps/plugin/tests.py +51 -0
- canvas_cli/tests.py +193 -4
- canvas_cli/utils/validators/manifest_schema.py +1 -0
- canvas_generated/messages/effects_pb2.py +2 -2
- canvas_generated/messages/effects_pb2.pyi +136 -0
- canvas_generated/messages/events_pb2.py +3 -3
- canvas_generated/messages/events_pb2.pyi +614 -0
- canvas_sdk/__init__.py +7 -0
- canvas_sdk/base.py +6 -2
- canvas_sdk/commands/__init__.py +26 -0
- canvas_sdk/commands/base.py +35 -32
- canvas_sdk/commands/commands/allergy.py +49 -0
- canvas_sdk/commands/commands/assess.py +1 -1
- canvas_sdk/commands/commands/close_goal.py +22 -0
- canvas_sdk/commands/commands/diagnose.py +3 -3
- canvas_sdk/commands/commands/family_history.py +18 -0
- canvas_sdk/commands/commands/goal.py +3 -3
- canvas_sdk/commands/commands/history_present_illness.py +1 -1
- canvas_sdk/commands/commands/instruct.py +17 -0
- canvas_sdk/commands/commands/lab_order.py +33 -0
- canvas_sdk/commands/commands/medical_history.py +34 -0
- canvas_sdk/commands/commands/medication_statement.py +1 -1
- canvas_sdk/commands/commands/past_surgical_history.py +28 -0
- canvas_sdk/commands/commands/perform.py +17 -0
- canvas_sdk/commands/commands/plan.py +2 -2
- canvas_sdk/commands/commands/prescribe.py +10 -7
- canvas_sdk/commands/commands/questionnaire.py +1 -1
- canvas_sdk/commands/commands/refill.py +16 -0
- canvas_sdk/commands/commands/remove_allergy.py +26 -0
- canvas_sdk/commands/commands/stop_medication.py +1 -1
- canvas_sdk/commands/commands/task.py +52 -0
- canvas_sdk/commands/commands/update_diagnosis.py +27 -0
- canvas_sdk/commands/commands/update_goal.py +1 -1
- canvas_sdk/commands/commands/vitals.py +78 -0
- canvas_sdk/commands/constants.py +7 -0
- canvas_sdk/commands/tests/protocol/__init__.py +0 -0
- canvas_sdk/commands/tests/protocol/tests.py +55 -0
- canvas_sdk/commands/tests/schema/__init__.py +0 -0
- canvas_sdk/commands/tests/schema/tests.py +104 -0
- canvas_sdk/commands/tests/test_utils.py +170 -6
- canvas_sdk/commands/tests/unit/__init__.py +0 -0
- canvas_sdk/commands/tests/{tests.py → unit/tests.py} +20 -194
- canvas_sdk/effects/banner_alert/add_banner_alert.py +8 -7
- canvas_sdk/effects/banner_alert/remove_banner_alert.py +3 -2
- canvas_sdk/effects/banner_alert/tests.py +224 -0
- canvas_sdk/effects/base.py +3 -5
- canvas_sdk/effects/patient_chart_summary_configuration.py +39 -0
- canvas_sdk/effects/protocol_card/__init__.py +1 -0
- canvas_sdk/effects/protocol_card/protocol_card.py +83 -0
- canvas_sdk/effects/protocol_card/tests.py +184 -0
- canvas_sdk/protocols/clinical_quality_measure.py +41 -0
- canvas_sdk/utils/db.py +17 -0
- canvas_sdk/v1/__init__.py +0 -0
- canvas_sdk/v1/data/__init__.py +3 -0
- canvas_sdk/v1/data/allergy_intolerance.py +63 -0
- canvas_sdk/v1/data/base.py +47 -0
- canvas_sdk/v1/data/condition.py +48 -0
- canvas_sdk/v1/data/lab.py +96 -0
- canvas_sdk/v1/data/medication.py +54 -0
- canvas_sdk/v1/data/patient.py +49 -0
- canvas_sdk/v1/data/user.py +10 -0
- canvas_sdk/value_set/tests/test_value_sets.py +65 -0
- canvas_sdk/value_set/v2022/adverse_event.py +33 -0
- canvas_sdk/value_set/v2022/allergy.py +232 -0
- canvas_sdk/value_set/v2022/assessment.py +215 -0
- canvas_sdk/value_set/v2022/communication.py +325 -0
- canvas_sdk/value_set/v2022/condition.py +40654 -0
- canvas_sdk/value_set/v2022/device.py +174 -0
- canvas_sdk/value_set/v2022/diagnostic_study.py +4967 -0
- canvas_sdk/value_set/v2022/encounter.py +2564 -0
- canvas_sdk/value_set/v2022/immunization.py +341 -0
- canvas_sdk/value_set/v2022/individual_characteristic.py +307 -0
- canvas_sdk/value_set/v2022/intervention.py +1356 -0
- canvas_sdk/value_set/v2022/laboratory_test.py +1250 -0
- canvas_sdk/value_set/v2022/medication.py +5130 -0
- canvas_sdk/value_set/v2022/physical_exam.py +201 -0
- canvas_sdk/value_set/v2022/procedure.py +4037 -0
- canvas_sdk/value_set/v2022/symptom.py +176 -0
- canvas_sdk/value_set/value_set.py +91 -0
- settings.py +43 -0
- canvas-0.2.5.dist-info/RECORD +0 -91
- {canvas-0.2.5.dist-info → canvas-0.2.11.dist-info}/WHEEL +0 -0
- {canvas-0.2.5.dist-info → canvas-0.2.11.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel, ConfigDict
|
|
5
|
+
|
|
6
|
+
from canvas_sdk.effects.base import EffectType, _BaseEffect
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Recommendation(BaseModel):
|
|
10
|
+
"""
|
|
11
|
+
A Recommendation for a Protocol Card.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
model_config = ConfigDict(strict=True, validate_assignment=True)
|
|
15
|
+
|
|
16
|
+
title: str = ""
|
|
17
|
+
button: str = ""
|
|
18
|
+
href: str | None = None
|
|
19
|
+
command: str | None = None
|
|
20
|
+
context: dict | None = None
|
|
21
|
+
|
|
22
|
+
@property
|
|
23
|
+
def values(self) -> dict:
|
|
24
|
+
"""The ProtocolCard recommendation's values."""
|
|
25
|
+
return {
|
|
26
|
+
"title": self.title,
|
|
27
|
+
"button": self.button,
|
|
28
|
+
"href": self.href,
|
|
29
|
+
"command": {"type": self.command} if self.command else {},
|
|
30
|
+
"context": self.context or {},
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ProtocolCard(_BaseEffect):
|
|
35
|
+
"""
|
|
36
|
+
An Effect that will result in a protocol card in Canvas.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
class Status(Enum):
|
|
40
|
+
DUE = "due"
|
|
41
|
+
SATISFIED = "satisfied"
|
|
42
|
+
|
|
43
|
+
class Meta:
|
|
44
|
+
effect_type = EffectType.ADD_OR_UPDATE_PROTOCOL_CARD
|
|
45
|
+
apply_required_fields = ("patient_id", "key")
|
|
46
|
+
|
|
47
|
+
patient_id: str | None = None
|
|
48
|
+
key: str | None = None
|
|
49
|
+
title: str = ""
|
|
50
|
+
narrative: str = ""
|
|
51
|
+
recommendations: list[Recommendation] = []
|
|
52
|
+
status: Status = Status.DUE # type: ignore
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def values(self) -> dict[str, Any]:
|
|
56
|
+
"""The ProtocolCard's values."""
|
|
57
|
+
return {
|
|
58
|
+
"title": self.title,
|
|
59
|
+
"narrative": self.narrative,
|
|
60
|
+
"recommendations": [
|
|
61
|
+
rec.values | {"key": i} for i, rec in enumerate(self.recommendations)
|
|
62
|
+
],
|
|
63
|
+
"status": self.status.value,
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def effect_payload(self) -> dict[str, Any]:
|
|
68
|
+
"""The payload of the effect."""
|
|
69
|
+
return {"patient": self.patient_id, "key": self.key, "data": self.values}
|
|
70
|
+
|
|
71
|
+
def add_recommendation(
|
|
72
|
+
self,
|
|
73
|
+
title: str = "",
|
|
74
|
+
button: str = "",
|
|
75
|
+
href: str | None = None,
|
|
76
|
+
command: str | None = None,
|
|
77
|
+
context: dict | None = None,
|
|
78
|
+
) -> None:
|
|
79
|
+
"""Adds a recommendation to the protocol card's list of recommendations."""
|
|
80
|
+
recommendation = Recommendation(
|
|
81
|
+
title=title, button=button, href=href, command=command, context=context
|
|
82
|
+
)
|
|
83
|
+
self.recommendations.append(recommendation)
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from pydantic import ValidationError
|
|
3
|
+
|
|
4
|
+
from canvas_sdk.commands import (
|
|
5
|
+
AssessCommand,
|
|
6
|
+
DiagnoseCommand,
|
|
7
|
+
GoalCommand,
|
|
8
|
+
HistoryOfPresentIllnessCommand,
|
|
9
|
+
MedicationStatementCommand,
|
|
10
|
+
PlanCommand,
|
|
11
|
+
PrescribeCommand,
|
|
12
|
+
QuestionnaireCommand,
|
|
13
|
+
ReasonForVisitCommand,
|
|
14
|
+
StopMedicationCommand,
|
|
15
|
+
UpdateGoalCommand,
|
|
16
|
+
)
|
|
17
|
+
from canvas_sdk.commands.base import _BaseCommand
|
|
18
|
+
from canvas_sdk.effects.protocol_card import ProtocolCard, Recommendation
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_apply_method_succeeds_with_patient_id_and_key() -> None:
|
|
22
|
+
p = ProtocolCard(patient_id="uuid", key="something-unique")
|
|
23
|
+
applied = p.apply()
|
|
24
|
+
assert (
|
|
25
|
+
applied.payload
|
|
26
|
+
== '{"patient": "uuid", "key": "something-unique", "data": {"title": "", "narrative": "", "recommendations": [], "status": "due"}}'
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_apply_method_raises_error_without_patient_id_and_key() -> None:
|
|
31
|
+
p = ProtocolCard()
|
|
32
|
+
|
|
33
|
+
with pytest.raises(ValidationError) as e:
|
|
34
|
+
p.apply()
|
|
35
|
+
err_msg = repr(e.value)
|
|
36
|
+
|
|
37
|
+
assert "2 validation errors for ProtocolCard" in err_msg
|
|
38
|
+
assert (
|
|
39
|
+
"Field 'patient_id' is required to apply a ProtocolCard [type=missing, input_value=None, input_type=NoneType]"
|
|
40
|
+
in err_msg
|
|
41
|
+
)
|
|
42
|
+
assert (
|
|
43
|
+
"Field 'key' is required to apply a ProtocolCard [type=missing, input_value=None, input_type=NoneType]"
|
|
44
|
+
in err_msg
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@pytest.mark.parametrize(
|
|
49
|
+
"init_params,rec1_params,rec2_params",
|
|
50
|
+
[
|
|
51
|
+
(
|
|
52
|
+
{
|
|
53
|
+
"key": "link_rec",
|
|
54
|
+
"patient_id": "patientuuid",
|
|
55
|
+
"title": "This is a test!",
|
|
56
|
+
"narrative": "we should only expect a link and a button",
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"title": "this is a link",
|
|
60
|
+
"button": "click this",
|
|
61
|
+
"href": "https://canvasmedical.com/",
|
|
62
|
+
},
|
|
63
|
+
{"title": "second link", "button": "don't click this", "href": "https://google.com/"},
|
|
64
|
+
),
|
|
65
|
+
(
|
|
66
|
+
{
|
|
67
|
+
"key": "command_rec",
|
|
68
|
+
"patient_id": "patientuuid",
|
|
69
|
+
"title": "This is a test for command recommendations!",
|
|
70
|
+
"narrative": "we should only expect buttons to insert commands",
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"title": "this is a command",
|
|
74
|
+
"button": "click this",
|
|
75
|
+
"command": "updategoal",
|
|
76
|
+
"context": {"progress": "none"},
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"title": "another command",
|
|
80
|
+
"button": "hypertension",
|
|
81
|
+
"command": "diagnose",
|
|
82
|
+
"context": {"background": "stuff"},
|
|
83
|
+
},
|
|
84
|
+
),
|
|
85
|
+
(
|
|
86
|
+
{
|
|
87
|
+
"patient_id": "patientuuid",
|
|
88
|
+
"key": "command_rec_with_coding_filter",
|
|
89
|
+
"title": "This is a test for command recommendations with coding filters!",
|
|
90
|
+
"narrative": "we should only expect buttons to insert commands",
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"title": "hypertension",
|
|
94
|
+
"button": "diagnose",
|
|
95
|
+
"command": "diagnose",
|
|
96
|
+
"context": {"background": "hey", "icd10_code": "I10"},
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"title": "fake medication",
|
|
100
|
+
"button": "prescribe",
|
|
101
|
+
"command": "prescribe",
|
|
102
|
+
"context": {"sig": "1pobid"},
|
|
103
|
+
},
|
|
104
|
+
),
|
|
105
|
+
],
|
|
106
|
+
)
|
|
107
|
+
def test_add_recommendations(
|
|
108
|
+
init_params: dict[str, str], rec1_params: dict[str, str], rec2_params: dict[str, str]
|
|
109
|
+
) -> None:
|
|
110
|
+
p = ProtocolCard(**init_params)
|
|
111
|
+
p.add_recommendation(**rec1_params)
|
|
112
|
+
p.recommendations.append(Recommendation(**rec2_params))
|
|
113
|
+
|
|
114
|
+
assert p.values == {
|
|
115
|
+
"title": init_params["title"],
|
|
116
|
+
"narrative": init_params["narrative"],
|
|
117
|
+
"recommendations": [
|
|
118
|
+
{
|
|
119
|
+
"title": rec1_params.get("title", None),
|
|
120
|
+
"button": rec1_params.get("button", None),
|
|
121
|
+
"href": rec1_params.get("href", None),
|
|
122
|
+
"command": {"type": rec1_params["command"]} if "command" in rec1_params else {},
|
|
123
|
+
"context": rec1_params.get("context", {}),
|
|
124
|
+
"key": 0,
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"title": rec2_params.get("title", None),
|
|
128
|
+
"button": rec2_params.get("button", None),
|
|
129
|
+
"href": rec2_params.get("href", None),
|
|
130
|
+
"command": {"type": rec2_params["command"]} if "command" in rec2_params else {},
|
|
131
|
+
"context": rec2_params.get("context", {}),
|
|
132
|
+
"key": 1,
|
|
133
|
+
},
|
|
134
|
+
],
|
|
135
|
+
"status": "due",
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@pytest.mark.parametrize(
|
|
140
|
+
"Command,init_params",
|
|
141
|
+
[
|
|
142
|
+
(AssessCommand, {}),
|
|
143
|
+
(DiagnoseCommand, {"icd10_code": "I10"}),
|
|
144
|
+
(GoalCommand, {}),
|
|
145
|
+
(HistoryOfPresentIllnessCommand, {}),
|
|
146
|
+
(MedicationStatementCommand, {"fdb_code": "fakeroo"}),
|
|
147
|
+
(PlanCommand, {}),
|
|
148
|
+
(PrescribeCommand, {"fdb_code": "fake"}),
|
|
149
|
+
(QuestionnaireCommand, {}),
|
|
150
|
+
(ReasonForVisitCommand, {}),
|
|
151
|
+
(StopMedicationCommand, {}),
|
|
152
|
+
(UpdateGoalCommand, {}),
|
|
153
|
+
],
|
|
154
|
+
)
|
|
155
|
+
def test_add_recommendations_from_commands(
|
|
156
|
+
Command: _BaseCommand, init_params: dict[str, str]
|
|
157
|
+
) -> None:
|
|
158
|
+
cmd = Command(**init_params)
|
|
159
|
+
p = ProtocolCard(patient_id="uuid", key="commands")
|
|
160
|
+
p.recommendations.append(cmd.recommend())
|
|
161
|
+
p.recommendations.append(cmd.recommend(title="hello", button="click"))
|
|
162
|
+
p.add_recommendation(
|
|
163
|
+
title="yeehaw", button="click here", command=cmd.Meta.key.lower(), context=init_params
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
rec1, rec2, rec3 = p.values["recommendations"]
|
|
167
|
+
assert rec1["title"] == ""
|
|
168
|
+
assert rec1["button"] == cmd.constantized_key().lower().replace("_", " ")
|
|
169
|
+
assert rec1["href"] is None
|
|
170
|
+
assert rec1["context"] == cmd.values
|
|
171
|
+
assert rec1["command"]["type"] == cmd.Meta.key.lower()
|
|
172
|
+
|
|
173
|
+
assert rec2["title"] == "hello"
|
|
174
|
+
assert rec2["button"] == "click"
|
|
175
|
+
assert rec2["href"] is None
|
|
176
|
+
assert rec2["context"] == cmd.values
|
|
177
|
+
assert rec2["command"]["type"] == cmd.Meta.key.lower()
|
|
178
|
+
|
|
179
|
+
assert rec3["title"] == "yeehaw"
|
|
180
|
+
assert rec3["button"] == "click here"
|
|
181
|
+
assert rec3["href"] is None
|
|
182
|
+
assert rec3["command"]["type"] == cmd.Meta.key.lower()
|
|
183
|
+
for k, v in init_params.items():
|
|
184
|
+
assert rec3["context"][k] == v
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from canvas_sdk.protocols.base import BaseProtocol
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ClinicalQualityMeasure(BaseProtocol):
|
|
7
|
+
"""
|
|
8
|
+
The class that ClinicalQualityMeasure protocols inherit from.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
class Meta:
|
|
12
|
+
title: str = ""
|
|
13
|
+
identifiers: list[str] = []
|
|
14
|
+
description: str = ""
|
|
15
|
+
information: str = ""
|
|
16
|
+
references: list[str] = []
|
|
17
|
+
types: list[str] = []
|
|
18
|
+
authors: list[str] = []
|
|
19
|
+
show_in_chart: bool = True
|
|
20
|
+
show_in_population: bool = True
|
|
21
|
+
can_be_snoozed: bool = True
|
|
22
|
+
is_abstract: bool = False
|
|
23
|
+
|
|
24
|
+
@classmethod
|
|
25
|
+
def _meta(cls) -> dict[str, Any]:
|
|
26
|
+
"""
|
|
27
|
+
Meta properties of the protocol in dictionary form.
|
|
28
|
+
"""
|
|
29
|
+
base_meta = {
|
|
30
|
+
k: v for k, v in ClinicalQualityMeasure.Meta.__dict__.items() if not k.startswith("__")
|
|
31
|
+
}
|
|
32
|
+
class_meta = {k: v for k, v in cls.Meta.__dict__.items() if not k.startswith("__")}
|
|
33
|
+
|
|
34
|
+
return base_meta | class_meta
|
|
35
|
+
|
|
36
|
+
@classmethod
|
|
37
|
+
def protocol_key(cls) -> str:
|
|
38
|
+
"""
|
|
39
|
+
External key used to identify the protocol.
|
|
40
|
+
"""
|
|
41
|
+
return cls.__name__
|
canvas_sdk/utils/db.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from typing import Any
|
|
3
|
+
from urllib import parse
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def get_database_dict_from_url() -> dict[str, Any]:
|
|
7
|
+
"""Retrieves the database URL for the data module connection formatted for Django settings."""
|
|
8
|
+
parsed_url = parse.urlparse(os.getenv("DATABASE_URL"))
|
|
9
|
+
db_name = parsed_url.path[1:]
|
|
10
|
+
return {
|
|
11
|
+
"ENGINE": "django.db.backends.postgresql",
|
|
12
|
+
"NAME": db_name,
|
|
13
|
+
"USER": os.getenv("CANVAS_SDK_DATABASE_ROLE"),
|
|
14
|
+
"PASSWORD": os.getenv("CANVAS_SDK_DATABASE_ROLE_PASSWORD"),
|
|
15
|
+
"HOST": parsed_url.hostname,
|
|
16
|
+
"PORT": parsed_url.port,
|
|
17
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
from django.contrib.postgres.fields import ArrayField
|
|
2
|
+
from django.db import models
|
|
3
|
+
|
|
4
|
+
from canvas_sdk.v1.data.base import CommittableModelManager
|
|
5
|
+
from canvas_sdk.v1.data.patient import Patient
|
|
6
|
+
from canvas_sdk.v1.data.user import CanvasUser
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class AllergyIntolerance(models.Model):
|
|
10
|
+
"""AllergyIntolerance."""
|
|
11
|
+
|
|
12
|
+
class Meta:
|
|
13
|
+
managed = False
|
|
14
|
+
app_label = "canvas_sdk"
|
|
15
|
+
db_table = "canvas_sdk_data_api_allergyintolerance_001"
|
|
16
|
+
|
|
17
|
+
objects = CommittableModelManager()
|
|
18
|
+
|
|
19
|
+
id = models.UUIDField()
|
|
20
|
+
dbid = models.BigIntegerField(primary_key=True)
|
|
21
|
+
created = models.DateTimeField()
|
|
22
|
+
modified = models.DateTimeField()
|
|
23
|
+
editors = ArrayField(models.IntegerField())
|
|
24
|
+
deleted = models.BooleanField()
|
|
25
|
+
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
26
|
+
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
27
|
+
patient = models.ForeignKey(
|
|
28
|
+
Patient,
|
|
29
|
+
on_delete=models.DO_NOTHING,
|
|
30
|
+
related_name="allergy_intolerances",
|
|
31
|
+
)
|
|
32
|
+
note_id = models.BigIntegerField()
|
|
33
|
+
allergy_intolerance_type = models.CharField()
|
|
34
|
+
category = models.IntegerField()
|
|
35
|
+
status = models.CharField()
|
|
36
|
+
severity = models.CharField()
|
|
37
|
+
onset_date = models.DateField()
|
|
38
|
+
onset_date_original_input = models.CharField()
|
|
39
|
+
last_occurrence = models.DateField()
|
|
40
|
+
last_occurrence_original_input = models.CharField()
|
|
41
|
+
recorded_date = models.DateTimeField()
|
|
42
|
+
narrative = models.CharField()
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class AllergyIntoleranceCoding(models.Model):
|
|
46
|
+
"""AllergyIntoleranceCoding."""
|
|
47
|
+
|
|
48
|
+
class Meta:
|
|
49
|
+
managed = False
|
|
50
|
+
app_label = "canvas_sdk"
|
|
51
|
+
db_table = "canvas_sdk_data_api_allergyintolerancecoding_001"
|
|
52
|
+
|
|
53
|
+
dbid = models.BigIntegerField(primary_key=True)
|
|
54
|
+
system = models.CharField()
|
|
55
|
+
version = models.CharField()
|
|
56
|
+
code = models.CharField()
|
|
57
|
+
display = models.CharField()
|
|
58
|
+
user_selected = models.BooleanField()
|
|
59
|
+
allergy_intolerance = models.ForeignKey(
|
|
60
|
+
AllergyIntolerance,
|
|
61
|
+
on_delete=models.DO_NOTHING,
|
|
62
|
+
related_name="codings",
|
|
63
|
+
)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Type
|
|
2
|
+
|
|
3
|
+
from django.db import models
|
|
4
|
+
from django.db.models import Q
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from canvas_sdk.value_set.value_set import ValueSet
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class CommittableModelManager(models.Manager):
|
|
11
|
+
def get_queryset(self) -> "models.QuerySet":
|
|
12
|
+
# TODO: Should we just filter these out at the view level?
|
|
13
|
+
return super().get_queryset().filter(deleted=False)
|
|
14
|
+
|
|
15
|
+
def committed(self) -> "models.QuerySet":
|
|
16
|
+
# The committer_id IS set, and the entered_in_error_id IS NOT set
|
|
17
|
+
return self.filter(committer_id__isnull=False, entered_in_error_id__isnull=True)
|
|
18
|
+
|
|
19
|
+
def for_patient(self, patient_id: str) -> "models.QuerySet":
|
|
20
|
+
return self.filter(patient__id=patient_id)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ValueSetLookupQuerySet(models.QuerySet):
|
|
24
|
+
def find(self, value_set: Type["ValueSet"]) -> models.QuerySet:
|
|
25
|
+
"""
|
|
26
|
+
Filters conditions, medications, etc. to those found in the inherited ValueSet class that is passed.
|
|
27
|
+
|
|
28
|
+
For example:
|
|
29
|
+
|
|
30
|
+
from canvas_sdk.v1.data.condition import Condition
|
|
31
|
+
from canvas_sdk.value_set.v2022.condition import MorbidObesity
|
|
32
|
+
morbid_obesity_conditions = Condition.objects.find(MorbidObesity)
|
|
33
|
+
|
|
34
|
+
This method can also be chained like so:
|
|
35
|
+
|
|
36
|
+
Condition.objects.find(MorbidObesity).find(AnaphylacticReactionToCommonBakersYeast)
|
|
37
|
+
"""
|
|
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
|
+
q_filter = Q()
|
|
45
|
+
for system, codes in uri_codes:
|
|
46
|
+
q_filter |= Q(codings__system=system, codings__code__in=codes)
|
|
47
|
+
return self.filter(q_filter).distinct()
|
|
@@ -0,0 +1,48 @@
|
|
|
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 ConditionQuerySet(ValueSetLookupQuerySet):
|
|
9
|
+
"""ConditionQuerySet."""
|
|
10
|
+
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Condition(models.Model):
|
|
15
|
+
"""Condition."""
|
|
16
|
+
|
|
17
|
+
class Meta:
|
|
18
|
+
managed = False
|
|
19
|
+
app_label = "canvas_sdk"
|
|
20
|
+
db_table = "canvas_sdk_data_api_condition_001"
|
|
21
|
+
|
|
22
|
+
objects = CommittableModelManager.from_queryset(ConditionQuerySet)()
|
|
23
|
+
|
|
24
|
+
id = models.UUIDField()
|
|
25
|
+
dbid = models.BigIntegerField(primary_key=True)
|
|
26
|
+
onset_date = models.DateField()
|
|
27
|
+
resolution_date = models.DateField()
|
|
28
|
+
deleted = models.BooleanField()
|
|
29
|
+
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
30
|
+
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
31
|
+
patient = models.ForeignKey(Patient, on_delete=models.DO_NOTHING, related_name="conditions")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ConditionCoding(models.Model):
|
|
35
|
+
"""ConditionCoding."""
|
|
36
|
+
|
|
37
|
+
class Meta:
|
|
38
|
+
managed = False
|
|
39
|
+
app_label = "canvas_sdk"
|
|
40
|
+
db_table = "canvas_sdk_data_api_conditioncoding_001"
|
|
41
|
+
|
|
42
|
+
dbid = models.BigIntegerField(primary_key=True)
|
|
43
|
+
system = models.CharField()
|
|
44
|
+
version = models.CharField()
|
|
45
|
+
code = models.CharField()
|
|
46
|
+
display = models.CharField()
|
|
47
|
+
user_selected = models.BooleanField()
|
|
48
|
+
condition = models.ForeignKey(Condition, on_delete=models.DO_NOTHING, related_name="codings")
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
|
|
3
|
+
from canvas_sdk.v1.data.base import CommittableModelManager
|
|
4
|
+
from canvas_sdk.v1.data.patient import Patient
|
|
5
|
+
from canvas_sdk.v1.data.user import CanvasUser
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class LabReport(models.Model):
|
|
9
|
+
class Meta:
|
|
10
|
+
managed = False
|
|
11
|
+
app_label = "canvas_sdk"
|
|
12
|
+
db_table = "canvas_sdk_data_api_labreport_001"
|
|
13
|
+
|
|
14
|
+
objects = CommittableModelManager()
|
|
15
|
+
|
|
16
|
+
id = models.UUIDField()
|
|
17
|
+
dbid = models.BigIntegerField(primary_key=True)
|
|
18
|
+
created = models.DateTimeField()
|
|
19
|
+
modified = models.DateTimeField()
|
|
20
|
+
review_mode = models.CharField()
|
|
21
|
+
junked = models.BooleanField()
|
|
22
|
+
requires_signature = models.BooleanField()
|
|
23
|
+
assigned_date = models.DateTimeField()
|
|
24
|
+
patient = models.ForeignKey(Patient, on_delete=models.DO_NOTHING, related_name="lab_reports")
|
|
25
|
+
transmission_type = models.CharField()
|
|
26
|
+
for_test_only = models.BooleanField()
|
|
27
|
+
external_id = models.CharField()
|
|
28
|
+
version = models.IntegerField()
|
|
29
|
+
requisition_number = models.CharField()
|
|
30
|
+
review = models.ForeignKey("LabReview", related_name="reports", on_delete=models.DO_NOTHING)
|
|
31
|
+
original_date = models.DateTimeField()
|
|
32
|
+
date_performed = models.DateTimeField()
|
|
33
|
+
custom_document_name = models.CharField()
|
|
34
|
+
originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
35
|
+
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
36
|
+
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
37
|
+
deleted = models.BooleanField()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class LabReview(models.Model):
|
|
41
|
+
class Meta:
|
|
42
|
+
managed = False
|
|
43
|
+
app_label = "canvas_sdk"
|
|
44
|
+
db_table = "canvas_sdk_data_api_labreview_001"
|
|
45
|
+
|
|
46
|
+
objects = CommittableModelManager()
|
|
47
|
+
|
|
48
|
+
id = models.UUIDField()
|
|
49
|
+
dbid = models.BigIntegerField(primary_key=True)
|
|
50
|
+
created = models.DateTimeField()
|
|
51
|
+
modified = models.DateTimeField()
|
|
52
|
+
originator = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
53
|
+
deleted = models.BooleanField()
|
|
54
|
+
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
55
|
+
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
56
|
+
internal_comment = models.TextField()
|
|
57
|
+
message_to_patient = models.CharField()
|
|
58
|
+
status = models.CharField()
|
|
59
|
+
patient = models.ForeignKey(Patient, on_delete=models.DO_NOTHING)
|
|
60
|
+
patient_communication_method = models.CharField()
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class LabValue(models.Model):
|
|
64
|
+
class Meta:
|
|
65
|
+
managed = False
|
|
66
|
+
app_label = "canvas_sdk"
|
|
67
|
+
db_table = "canvas_sdk_data_api_labvalue_001"
|
|
68
|
+
|
|
69
|
+
id = models.UUIDField()
|
|
70
|
+
dbid = models.BigIntegerField(primary_key=True)
|
|
71
|
+
created = models.DateTimeField()
|
|
72
|
+
modified = models.DateTimeField()
|
|
73
|
+
report = models.ForeignKey("LabReport", related_name="values", on_delete=models.DO_NOTHING)
|
|
74
|
+
value = models.TextField()
|
|
75
|
+
units = models.CharField()
|
|
76
|
+
abnormal_flag = models.CharField()
|
|
77
|
+
reference_range = models.CharField()
|
|
78
|
+
low_threshold = models.CharField()
|
|
79
|
+
high_threshold = models.CharField()
|
|
80
|
+
comment = models.TextField()
|
|
81
|
+
observation_status = models.CharField()
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class LabValueCoding(models.Model):
|
|
85
|
+
class Meta:
|
|
86
|
+
managed = False
|
|
87
|
+
app_label = "canvas_sdk"
|
|
88
|
+
db_table = "canvas_sdk_data_api_labvaluecoding_001"
|
|
89
|
+
|
|
90
|
+
dbid = models.BigIntegerField(primary_key=True)
|
|
91
|
+
created = models.DateTimeField()
|
|
92
|
+
modified = models.DateTimeField()
|
|
93
|
+
value = models.ForeignKey(LabValue, on_delete=models.DO_NOTHING, related_name="codings")
|
|
94
|
+
code = models.CharField()
|
|
95
|
+
name = models.CharField()
|
|
96
|
+
system = models.CharField()
|
|
@@ -0,0 +1,54 @@
|
|
|
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 MedicationQuerySet(ValueSetLookupQuerySet):
|
|
9
|
+
"""MedicationQuerySet."""
|
|
10
|
+
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Medication(models.Model):
|
|
15
|
+
"""Medication."""
|
|
16
|
+
|
|
17
|
+
class Meta:
|
|
18
|
+
managed = False
|
|
19
|
+
app_label = "canvas_sdk"
|
|
20
|
+
db_table = "canvas_sdk_data_api_medication_001"
|
|
21
|
+
|
|
22
|
+
objects = CommittableModelManager.from_queryset(MedicationQuerySet)()
|
|
23
|
+
|
|
24
|
+
id = models.UUIDField()
|
|
25
|
+
dbid = models.BigIntegerField(primary_key=True)
|
|
26
|
+
patient = models.ForeignKey(Patient, on_delete=models.DO_NOTHING, related_name="medications")
|
|
27
|
+
deleted = models.BooleanField()
|
|
28
|
+
entered_in_error = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
29
|
+
committer = models.ForeignKey(CanvasUser, on_delete=models.DO_NOTHING)
|
|
30
|
+
status = models.CharField()
|
|
31
|
+
start_date = models.DateField()
|
|
32
|
+
end_date = models.DateField()
|
|
33
|
+
quantity_qualifier_description = models.CharField()
|
|
34
|
+
clinical_quantity_description = models.CharField()
|
|
35
|
+
potency_unit_code = models.CharField()
|
|
36
|
+
national_drug_code = models.CharField()
|
|
37
|
+
erx_quantity = models.CharField()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class MedicationCoding(models.Model):
|
|
41
|
+
"""MedicationCoding."""
|
|
42
|
+
|
|
43
|
+
class Meta:
|
|
44
|
+
managed = False
|
|
45
|
+
app_label = "canvas_sdk"
|
|
46
|
+
db_table = "canvas_sdk_data_api_medicationcoding_001"
|
|
47
|
+
|
|
48
|
+
dbid = models.BigIntegerField(primary_key=True)
|
|
49
|
+
system = models.CharField()
|
|
50
|
+
version = models.CharField()
|
|
51
|
+
code = models.CharField()
|
|
52
|
+
display = models.CharField()
|
|
53
|
+
user_selected = models.BooleanField()
|
|
54
|
+
medication = models.ForeignKey(Medication, on_delete=models.DO_NOTHING, related_name="codings")
|