canvas 0.63.0__py3-none-any.whl → 0.89.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.
- {canvas-0.63.0.dist-info → canvas-0.89.0.dist-info}/METADATA +4 -1
- {canvas-0.63.0.dist-info → canvas-0.89.0.dist-info}/RECORD +184 -98
- {canvas-0.63.0.dist-info → canvas-0.89.0.dist-info}/WHEEL +1 -1
- canvas_cli/apps/emit/event_fixtures/UNKNOWN.ndjson +1 -0
- canvas_cli/apps/logs/logs.py +386 -22
- canvas_cli/main.py +3 -1
- canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/tests/test_models.py +46 -4
- canvas_cli/utils/context/context.py +13 -13
- canvas_cli/utils/validators/manifest_schema.py +26 -1
- canvas_generated/messages/effects_pb2.py +5 -5
- canvas_generated/messages/effects_pb2.pyi +108 -2
- canvas_generated/messages/events_pb2.py +6 -6
- canvas_generated/messages/events_pb2.pyi +282 -2
- canvas_sdk/clients/__init__.py +1 -0
- canvas_sdk/clients/llms/__init__.py +17 -0
- canvas_sdk/clients/llms/libraries/__init__.py +11 -0
- canvas_sdk/clients/llms/libraries/llm_anthropic.py +87 -0
- canvas_sdk/clients/llms/libraries/llm_api.py +143 -0
- canvas_sdk/clients/llms/libraries/llm_google.py +92 -0
- canvas_sdk/clients/llms/libraries/llm_openai.py +98 -0
- canvas_sdk/clients/llms/structures/__init__.py +9 -0
- canvas_sdk/clients/llms/structures/llm_response.py +33 -0
- canvas_sdk/clients/llms/structures/llm_tokens.py +53 -0
- canvas_sdk/clients/llms/structures/llm_turn.py +47 -0
- canvas_sdk/clients/llms/structures/settings/__init__.py +13 -0
- canvas_sdk/clients/llms/structures/settings/llm_settings.py +27 -0
- canvas_sdk/clients/llms/structures/settings/llm_settings_anthropic.py +43 -0
- canvas_sdk/clients/llms/structures/settings/llm_settings_gemini.py +40 -0
- canvas_sdk/clients/llms/structures/settings/llm_settings_gpt4.py +40 -0
- canvas_sdk/clients/llms/structures/settings/llm_settings_gpt5.py +48 -0
- canvas_sdk/clients/third_party.py +3 -0
- canvas_sdk/commands/__init__.py +12 -0
- canvas_sdk/commands/base.py +33 -2
- canvas_sdk/commands/commands/adjust_prescription.py +4 -0
- canvas_sdk/commands/commands/custom_command.py +86 -0
- canvas_sdk/commands/commands/family_history.py +17 -1
- canvas_sdk/commands/commands/immunization_statement.py +42 -2
- canvas_sdk/commands/commands/medication_statement.py +16 -1
- canvas_sdk/commands/commands/past_surgical_history.py +16 -1
- canvas_sdk/commands/commands/perform.py +18 -1
- canvas_sdk/commands/commands/prescribe.py +8 -9
- canvas_sdk/commands/commands/refill.py +5 -5
- canvas_sdk/commands/commands/resolve_condition.py +5 -5
- canvas_sdk/commands/commands/review/__init__.py +3 -0
- canvas_sdk/commands/commands/review/base.py +72 -0
- canvas_sdk/commands/commands/review/imaging.py +13 -0
- canvas_sdk/commands/commands/review/lab.py +13 -0
- canvas_sdk/commands/commands/review/referral.py +13 -0
- canvas_sdk/commands/commands/review/uncategorized_document.py +13 -0
- canvas_sdk/commands/validation.py +43 -0
- canvas_sdk/effects/batch_originate.py +22 -0
- canvas_sdk/effects/calendar/__init__.py +13 -3
- canvas_sdk/effects/calendar/{create_calendar.py → calendar.py} +19 -5
- canvas_sdk/effects/calendar/event.py +172 -0
- canvas_sdk/effects/claim_label.py +93 -0
- canvas_sdk/effects/claim_line_item.py +47 -0
- canvas_sdk/effects/claim_queue.py +49 -0
- canvas_sdk/effects/fax/__init__.py +3 -0
- canvas_sdk/effects/fax/base.py +77 -0
- canvas_sdk/effects/fax/note.py +42 -0
- canvas_sdk/effects/metadata.py +15 -1
- canvas_sdk/effects/note/__init__.py +8 -1
- canvas_sdk/effects/note/appointment.py +135 -7
- canvas_sdk/effects/note/base.py +17 -0
- canvas_sdk/effects/note/message.py +22 -14
- canvas_sdk/effects/note/note.py +150 -1
- canvas_sdk/effects/observation/__init__.py +11 -0
- canvas_sdk/effects/observation/base.py +206 -0
- canvas_sdk/effects/patient/__init__.py +2 -0
- canvas_sdk/effects/patient/base.py +8 -0
- canvas_sdk/effects/payment/__init__.py +11 -0
- canvas_sdk/effects/payment/base.py +355 -0
- canvas_sdk/effects/payment/post_claim_payment.py +49 -0
- canvas_sdk/effects/send_contact_verification.py +42 -0
- canvas_sdk/effects/task/__init__.py +2 -1
- canvas_sdk/effects/task/task.py +30 -0
- canvas_sdk/effects/validation/__init__.py +3 -0
- canvas_sdk/effects/validation/base.py +92 -0
- canvas_sdk/events/base.py +15 -0
- canvas_sdk/handlers/application.py +7 -7
- canvas_sdk/handlers/simple_api/api.py +1 -4
- canvas_sdk/handlers/simple_api/websocket.py +1 -4
- canvas_sdk/handlers/utils.py +14 -0
- canvas_sdk/questionnaires/utils.py +1 -0
- canvas_sdk/templates/utils.py +17 -4
- canvas_sdk/test_utils/factories/FACTORY_GUIDE.md +362 -0
- canvas_sdk/test_utils/factories/__init__.py +115 -0
- canvas_sdk/test_utils/factories/calendar.py +24 -0
- canvas_sdk/test_utils/factories/claim.py +81 -0
- canvas_sdk/test_utils/factories/claim_diagnosis_code.py +16 -0
- canvas_sdk/test_utils/factories/coverage.py +17 -0
- canvas_sdk/test_utils/factories/imaging.py +74 -0
- canvas_sdk/test_utils/factories/lab.py +192 -0
- canvas_sdk/test_utils/factories/medication_history.py +75 -0
- canvas_sdk/test_utils/factories/note.py +52 -0
- canvas_sdk/test_utils/factories/organization.py +50 -0
- canvas_sdk/test_utils/factories/practicelocation.py +88 -0
- canvas_sdk/test_utils/factories/referral.py +81 -0
- canvas_sdk/test_utils/factories/staff.py +111 -0
- canvas_sdk/test_utils/factories/task.py +66 -0
- canvas_sdk/test_utils/factories/uncategorized_clinical_document.py +48 -0
- canvas_sdk/utils/metrics.py +4 -1
- canvas_sdk/v1/data/__init__.py +66 -7
- canvas_sdk/v1/data/allergy_intolerance.py +5 -11
- canvas_sdk/v1/data/appointment.py +18 -4
- canvas_sdk/v1/data/assessment.py +2 -12
- canvas_sdk/v1/data/banner_alert.py +2 -4
- canvas_sdk/v1/data/base.py +53 -14
- canvas_sdk/v1/data/billing.py +8 -11
- canvas_sdk/v1/data/calendar.py +64 -0
- canvas_sdk/v1/data/care_team.py +4 -10
- canvas_sdk/v1/data/claim.py +172 -66
- canvas_sdk/v1/data/claim_diagnosis_code.py +19 -0
- canvas_sdk/v1/data/claim_line_item.py +2 -5
- canvas_sdk/v1/data/coding.py +19 -0
- canvas_sdk/v1/data/command.py +2 -4
- canvas_sdk/v1/data/common.py +10 -0
- canvas_sdk/v1/data/compound_medication.py +3 -4
- canvas_sdk/v1/data/condition.py +4 -9
- canvas_sdk/v1/data/coverage.py +66 -26
- canvas_sdk/v1/data/detected_issue.py +20 -20
- canvas_sdk/v1/data/device.py +2 -14
- canvas_sdk/v1/data/discount.py +2 -5
- canvas_sdk/v1/data/encounter.py +44 -0
- canvas_sdk/v1/data/facility.py +1 -0
- canvas_sdk/v1/data/goal.py +2 -14
- canvas_sdk/v1/data/imaging.py +4 -30
- canvas_sdk/v1/data/immunization.py +7 -15
- canvas_sdk/v1/data/lab.py +12 -65
- canvas_sdk/v1/data/line_item_transaction.py +2 -5
- canvas_sdk/v1/data/medication.py +3 -8
- canvas_sdk/v1/data/medication_history.py +142 -0
- canvas_sdk/v1/data/medication_statement.py +41 -0
- canvas_sdk/v1/data/message.py +4 -8
- canvas_sdk/v1/data/note.py +37 -38
- canvas_sdk/v1/data/observation.py +9 -36
- canvas_sdk/v1/data/organization.py +70 -9
- canvas_sdk/v1/data/patient.py +8 -12
- canvas_sdk/v1/data/patient_consent.py +4 -14
- canvas_sdk/v1/data/payment_collection.py +2 -5
- canvas_sdk/v1/data/posting.py +3 -9
- canvas_sdk/v1/data/practicelocation.py +66 -7
- canvas_sdk/v1/data/protocol_override.py +3 -4
- canvas_sdk/v1/data/protocol_result.py +3 -3
- canvas_sdk/v1/data/questionnaire.py +10 -26
- canvas_sdk/v1/data/reason_for_visit.py +2 -6
- canvas_sdk/v1/data/referral.py +41 -17
- canvas_sdk/v1/data/staff.py +34 -26
- canvas_sdk/v1/data/stop_medication_event.py +27 -0
- canvas_sdk/v1/data/task.py +30 -11
- canvas_sdk/v1/data/team.py +2 -4
- canvas_sdk/v1/data/uncategorized_clinical_document.py +84 -0
- canvas_sdk/v1/data/user.py +14 -0
- canvas_sdk/v1/data/utils.py +5 -0
- canvas_sdk/value_set/v2026/__init__.py +1 -0
- canvas_sdk/value_set/v2026/adverse_event.py +157 -0
- canvas_sdk/value_set/v2026/allergy.py +116 -0
- canvas_sdk/value_set/v2026/assessment.py +466 -0
- canvas_sdk/value_set/v2026/communication.py +496 -0
- canvas_sdk/value_set/v2026/condition.py +52934 -0
- canvas_sdk/value_set/v2026/device.py +315 -0
- canvas_sdk/value_set/v2026/diagnostic_study.py +5243 -0
- canvas_sdk/value_set/v2026/encounter.py +2714 -0
- canvas_sdk/value_set/v2026/immunization.py +297 -0
- canvas_sdk/value_set/v2026/individual_characteristic.py +339 -0
- canvas_sdk/value_set/v2026/intervention.py +1703 -0
- canvas_sdk/value_set/v2026/laboratory_test.py +1831 -0
- canvas_sdk/value_set/v2026/medication.py +8218 -0
- canvas_sdk/value_set/v2026/no_qdm_category_assigned.py +26493 -0
- canvas_sdk/value_set/v2026/physical_exam.py +342 -0
- canvas_sdk/value_set/v2026/procedure.py +27869 -0
- canvas_sdk/value_set/v2026/symptom.py +625 -0
- logger/logger.py +30 -31
- logger/logstash.py +282 -0
- logger/pubsub.py +26 -0
- plugin_runner/allowed-module-imports.json +940 -9
- plugin_runner/generate_allowed_imports.py +1 -0
- plugin_runner/installation.py +2 -2
- plugin_runner/plugin_runner.py +21 -24
- plugin_runner/sandbox.py +34 -0
- protobufs/canvas_generated/messages/effects.proto +65 -0
- protobufs/canvas_generated/messages/events.proto +150 -51
- settings.py +27 -11
- canvas_sdk/effects/calendar/create_event.py +0 -43
- {canvas-0.63.0.dist-info → canvas-0.89.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
import factory
|
|
4
|
+
from django.utils import timezone
|
|
5
|
+
|
|
6
|
+
from canvas_sdk.v1.data import (
|
|
7
|
+
LabOrder,
|
|
8
|
+
LabOrderReason,
|
|
9
|
+
LabOrderReasonCondition,
|
|
10
|
+
LabPartner,
|
|
11
|
+
LabPartnerTest,
|
|
12
|
+
LabReport,
|
|
13
|
+
LabReview,
|
|
14
|
+
LabTest,
|
|
15
|
+
LabValue,
|
|
16
|
+
LabValueCoding,
|
|
17
|
+
)
|
|
18
|
+
from canvas_sdk.v1.data.common import (
|
|
19
|
+
DocumentReviewMode,
|
|
20
|
+
ReviewPatientCommunicationMethod,
|
|
21
|
+
ReviewStatus,
|
|
22
|
+
)
|
|
23
|
+
from canvas_sdk.v1.data.lab import TransmissionType
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class LabReportFactory(factory.django.DjangoModelFactory[LabReport]):
|
|
27
|
+
"""Factory for creating a LabReport."""
|
|
28
|
+
|
|
29
|
+
class Meta:
|
|
30
|
+
model = LabReport
|
|
31
|
+
|
|
32
|
+
review_mode = DocumentReviewMode.REVIEW_REQUIRED
|
|
33
|
+
junked = False
|
|
34
|
+
requires_signature = False
|
|
35
|
+
assigned_date = factory.LazyFunction(lambda: timezone.now())
|
|
36
|
+
patient = factory.SubFactory("canvas_sdk.test_utils.factories.PatientFactory")
|
|
37
|
+
transmission_type = TransmissionType.HL7
|
|
38
|
+
for_test_only = False
|
|
39
|
+
external_id = factory.Faker("uuid4")
|
|
40
|
+
version = 1
|
|
41
|
+
requisition_number = factory.Faker("bothify", text="REQ-########")
|
|
42
|
+
review = None # Optional field
|
|
43
|
+
original_date = factory.LazyFunction(lambda: timezone.now())
|
|
44
|
+
date_performed = factory.LazyFunction(lambda: timezone.now())
|
|
45
|
+
custom_document_name = factory.Faker("text", max_nb_chars=500)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class LabReviewFactory(factory.django.DjangoModelFactory[LabReview]):
|
|
49
|
+
"""Factory for creating a LabReview."""
|
|
50
|
+
|
|
51
|
+
class Meta:
|
|
52
|
+
model = LabReview
|
|
53
|
+
|
|
54
|
+
internal_comment = factory.Faker("paragraph")
|
|
55
|
+
message_to_patient = factory.Faker("text", max_nb_chars=2048)
|
|
56
|
+
status = ReviewStatus.STATUS_REVIEWING
|
|
57
|
+
patient = factory.SubFactory("canvas_sdk.test_utils.factories.PatientFactory")
|
|
58
|
+
patient_communication_method = ReviewPatientCommunicationMethod.DELEGATED_CALL_CAN_LEAVE_MESSAGE
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class LabValueFactory(factory.django.DjangoModelFactory[LabValue]):
|
|
62
|
+
"""Factory for creating a LabValue."""
|
|
63
|
+
|
|
64
|
+
class Meta:
|
|
65
|
+
model = LabValue
|
|
66
|
+
|
|
67
|
+
report = factory.SubFactory(LabReportFactory)
|
|
68
|
+
value = factory.Faker("bothify", text="##.#")
|
|
69
|
+
units = factory.Faker("random_element", elements=["mg/dL", "mmol/L", "g/dL", "%", "U/L"])
|
|
70
|
+
abnormal_flag = factory.Faker("random_element", elements=["", "H", "L", "HH", "LL"])
|
|
71
|
+
reference_range = factory.Faker("bothify", text="#.#-##.#")
|
|
72
|
+
low_threshold = factory.Faker("bothify", text="#.#")
|
|
73
|
+
high_threshold = factory.Faker("bothify", text="##.#")
|
|
74
|
+
comment = factory.Faker("sentence")
|
|
75
|
+
observation_status = factory.Faker(
|
|
76
|
+
"random_element", elements=["final", "preliminary", "corrected"]
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class LabValueCodingFactory(factory.django.DjangoModelFactory[LabValueCoding]):
|
|
81
|
+
"""Factory for creating a LabValueCoding."""
|
|
82
|
+
|
|
83
|
+
class Meta:
|
|
84
|
+
model = LabValueCoding
|
|
85
|
+
|
|
86
|
+
value = factory.SubFactory(LabValueFactory)
|
|
87
|
+
code = factory.Faker("bothify", text="#####-#")
|
|
88
|
+
name = factory.Faker("text", max_nb_chars=256)
|
|
89
|
+
system = factory.Faker("random_element", elements=["LOINC", "SNOMED", "CPT"])
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class LabOrderFactory(factory.django.DjangoModelFactory[LabOrder]):
|
|
93
|
+
"""Factory for creating a LabOrder."""
|
|
94
|
+
|
|
95
|
+
class Meta:
|
|
96
|
+
model = LabOrder
|
|
97
|
+
skip_postgeneration_save = True
|
|
98
|
+
|
|
99
|
+
patient = factory.SubFactory("canvas_sdk.test_utils.factories.PatientFactory")
|
|
100
|
+
ontology_lab_partner = factory.Faker("company")
|
|
101
|
+
note = factory.SubFactory("canvas_sdk.test_utils.factories.NoteFactory")
|
|
102
|
+
comment = factory.Faker("text", max_nb_chars=128)
|
|
103
|
+
requisition_number = factory.Faker("bothify", text="REQ-########")
|
|
104
|
+
is_patient_bill = False
|
|
105
|
+
date_ordered = factory.LazyFunction(lambda: timezone.now())
|
|
106
|
+
fasting_status = None # Optional field
|
|
107
|
+
specimen_collection_type = LabOrder.SpecimenCollectionType.ON_LOCATION
|
|
108
|
+
transmission_type = TransmissionType.HL7
|
|
109
|
+
courtesy_copy_type = None # Optional field
|
|
110
|
+
courtesy_copy_number = ""
|
|
111
|
+
courtesy_copy_text = ""
|
|
112
|
+
ordering_provider = factory.SubFactory("canvas_sdk.test_utils.factories.StaffFactory")
|
|
113
|
+
parent_order = None # Optional field
|
|
114
|
+
healthgorilla_id = ""
|
|
115
|
+
manual_processing_status = None # Optional field
|
|
116
|
+
manual_processing_comment = None # Optional field
|
|
117
|
+
labcorp_abn_url = ""
|
|
118
|
+
|
|
119
|
+
@factory.post_generation
|
|
120
|
+
def reports(self, create: Any, extracted: Any, **kwargs: Any) -> None:
|
|
121
|
+
"""Handle many-to-many relationship for reports."""
|
|
122
|
+
if not create:
|
|
123
|
+
return
|
|
124
|
+
|
|
125
|
+
if extracted:
|
|
126
|
+
for report in extracted:
|
|
127
|
+
self.reports.add(report)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class LabOrderReasonFactory(factory.django.DjangoModelFactory[LabOrderReason]):
|
|
131
|
+
"""Factory for creating a LabOrderReason."""
|
|
132
|
+
|
|
133
|
+
class Meta:
|
|
134
|
+
model = LabOrderReason
|
|
135
|
+
|
|
136
|
+
order = factory.SubFactory(LabOrderFactory)
|
|
137
|
+
mode = LabOrderReason.LabReasonMode.MONITOR
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class LabOrderReasonConditionFactory(factory.django.DjangoModelFactory[LabOrderReasonCondition]):
|
|
141
|
+
"""Factory for creating a LabOrderReasonCondition."""
|
|
142
|
+
|
|
143
|
+
class Meta:
|
|
144
|
+
model = LabOrderReasonCondition
|
|
145
|
+
|
|
146
|
+
reason = factory.SubFactory(LabOrderReasonFactory)
|
|
147
|
+
condition = None # Optional field - would need a ConditionFactory
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class LabTestFactory(factory.django.DjangoModelFactory[LabTest]):
|
|
151
|
+
"""Factory for creating a LabTest."""
|
|
152
|
+
|
|
153
|
+
class Meta:
|
|
154
|
+
model = LabTest
|
|
155
|
+
|
|
156
|
+
ontology_test_name = factory.Faker("text", max_nb_chars=512)
|
|
157
|
+
ontology_test_code = factory.Faker("bothify", text="####-#")
|
|
158
|
+
status = LabTest.LabTestOrderStatus.NEW
|
|
159
|
+
report = factory.SubFactory(LabReportFactory)
|
|
160
|
+
aoe_code = ""
|
|
161
|
+
procedure_class = ""
|
|
162
|
+
specimen_type = factory.Faker("random_element", elements=["blood", "urine", "serum", "plasma"])
|
|
163
|
+
specimen_source_code = factory.Faker("bothify", text="###")
|
|
164
|
+
specimen_source_description = factory.Faker("text", max_nb_chars=255)
|
|
165
|
+
specimen_source_coding_system = factory.Faker("random_element", elements=["LOINC", "SNOMED"])
|
|
166
|
+
order = factory.SubFactory(LabOrderFactory)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
class LabPartnerFactory(factory.django.DjangoModelFactory[LabPartner]):
|
|
170
|
+
"""Factory for creating a LabPartner."""
|
|
171
|
+
|
|
172
|
+
class Meta:
|
|
173
|
+
model = LabPartner
|
|
174
|
+
|
|
175
|
+
name = factory.Faker("company")
|
|
176
|
+
active = True
|
|
177
|
+
electronic_ordering_enabled = True
|
|
178
|
+
keywords = factory.Faker("words", nb=5)
|
|
179
|
+
default_lab_account_number = factory.Faker("bothify", text="LAB-######")
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
class LabPartnerTestFactory(factory.django.DjangoModelFactory[LabPartnerTest]):
|
|
183
|
+
"""Factory for creating a LabPartnerTest."""
|
|
184
|
+
|
|
185
|
+
class Meta:
|
|
186
|
+
model = LabPartnerTest
|
|
187
|
+
|
|
188
|
+
lab_partner = factory.SubFactory(LabPartnerFactory)
|
|
189
|
+
order_code = factory.Faker("bothify", text="####")
|
|
190
|
+
order_name = factory.Faker("text", max_nb_chars=256)
|
|
191
|
+
keywords = factory.Faker("words", nb=5)
|
|
192
|
+
cpt_code = factory.Faker("bothify", text="#####")
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
|
|
3
|
+
import factory
|
|
4
|
+
from django.utils import timezone
|
|
5
|
+
from factory.fuzzy import FuzzyDate, FuzzyDateTime
|
|
6
|
+
|
|
7
|
+
from canvas_sdk.test_utils.factories.patient import PatientFactory
|
|
8
|
+
from canvas_sdk.v1.data.medication_history import (
|
|
9
|
+
MedicationHistoryMedication,
|
|
10
|
+
MedicationHistoryMedicationCoding,
|
|
11
|
+
MedicationHistoryResponse,
|
|
12
|
+
MedicationHistoryResponseStatus,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class MedicationHistoryMedicationFactory(
|
|
17
|
+
factory.django.DjangoModelFactory[MedicationHistoryMedication]
|
|
18
|
+
):
|
|
19
|
+
"""Factory for creating a MedicationHistoryMedication."""
|
|
20
|
+
|
|
21
|
+
class Meta:
|
|
22
|
+
model = MedicationHistoryMedication
|
|
23
|
+
|
|
24
|
+
patient = factory.SubFactory(PatientFactory)
|
|
25
|
+
last_fill_date = FuzzyDateTime(
|
|
26
|
+
start_dt=timezone.now() - datetime.timedelta(days=365), end_dt=timezone.now()
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
drug_description = factory.Faker("word")
|
|
30
|
+
strength_value = "10"
|
|
31
|
+
strength_form = "tablet"
|
|
32
|
+
strength_unit_of_measure = "mg"
|
|
33
|
+
quantity = 30.0
|
|
34
|
+
quantity_unit_of_measure = "tablets"
|
|
35
|
+
days_supply = 30
|
|
36
|
+
sig = factory.Faker("sentence", nb_words=4)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class MedicationHistoryMedicationCodingFactory(
|
|
40
|
+
factory.django.DjangoModelFactory[MedicationHistoryMedicationCoding]
|
|
41
|
+
):
|
|
42
|
+
"""Factory for creating a MedicationHistoryMedicationCoding."""
|
|
43
|
+
|
|
44
|
+
class Meta:
|
|
45
|
+
model = MedicationHistoryMedicationCoding
|
|
46
|
+
|
|
47
|
+
medication = factory.SubFactory(MedicationHistoryMedicationFactory)
|
|
48
|
+
|
|
49
|
+
system = "http://www.nlm.nih.gov/research/umls/rxnorm"
|
|
50
|
+
version = "1.0"
|
|
51
|
+
code = factory.Faker("numerify", text="######")
|
|
52
|
+
display = factory.Faker("word")
|
|
53
|
+
user_selected = False
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class MedicationHistoryResponseFactory(
|
|
57
|
+
factory.django.DjangoModelFactory[MedicationHistoryResponse]
|
|
58
|
+
):
|
|
59
|
+
"""Factory for creating a MedicationHistoryResponse."""
|
|
60
|
+
|
|
61
|
+
class Meta:
|
|
62
|
+
model = MedicationHistoryResponse
|
|
63
|
+
|
|
64
|
+
patient = factory.SubFactory(PatientFactory)
|
|
65
|
+
status = MedicationHistoryResponseStatus.STATUS_APPROVED
|
|
66
|
+
start_date = FuzzyDate(
|
|
67
|
+
start_date=datetime.date.today() - datetime.timedelta(days=365),
|
|
68
|
+
end_date=datetime.date.today(),
|
|
69
|
+
)
|
|
70
|
+
end_date = FuzzyDate(
|
|
71
|
+
start_date=datetime.date.today(),
|
|
72
|
+
end_date=datetime.date.today() + datetime.timedelta(days=365),
|
|
73
|
+
)
|
|
74
|
+
message_id = factory.Faker("uuid4")
|
|
75
|
+
related_to_message_id = factory.Faker("uuid4")
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
import factory
|
|
4
|
+
|
|
5
|
+
from canvas_sdk.v1.data import Note, NoteStateChangeEvent, NoteType
|
|
6
|
+
from canvas_sdk.v1.data.note import NoteStates
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class NoteFactory(factory.django.DjangoModelFactory[Note]):
|
|
10
|
+
"""Factory for creating Note."""
|
|
11
|
+
|
|
12
|
+
class Meta:
|
|
13
|
+
model = Note
|
|
14
|
+
|
|
15
|
+
location = factory.SubFactory("canvas_sdk.test_utils.factories.PracticeLocationFactory")
|
|
16
|
+
originator = factory.SelfAttribute("provider.user")
|
|
17
|
+
provider = factory.SubFactory("canvas_sdk.test_utils.factories.StaffFactory")
|
|
18
|
+
patient = factory.SubFactory("canvas_sdk.test_utils.factories.PatientFactory")
|
|
19
|
+
note_type_version = factory.SubFactory("canvas_sdk.test_utils.factories.NoteTypeFactory")
|
|
20
|
+
|
|
21
|
+
@factory.post_generation
|
|
22
|
+
def create_initial_state_change_event(self, create: Any, extracted: Any, **kwargs: Any) -> None:
|
|
23
|
+
"""Create an initial NoteStateChangeEvent when a Note is created."""
|
|
24
|
+
if not create:
|
|
25
|
+
return
|
|
26
|
+
|
|
27
|
+
NoteStateChangeEventFactory.create(note=self, state=NoteStates.NEW)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class NoteStateChangeEventFactory(factory.django.DjangoModelFactory[NoteStateChangeEvent]):
|
|
31
|
+
"""Factory for creating NoteStateChangeEvent."""
|
|
32
|
+
|
|
33
|
+
class Meta:
|
|
34
|
+
model = NoteStateChangeEvent
|
|
35
|
+
|
|
36
|
+
note = factory.SubFactory(NoteFactory)
|
|
37
|
+
state = NoteStates.NEW
|
|
38
|
+
originator = factory.SelfAttribute("note.originator")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class NoteTypeFactory(factory.django.DjangoModelFactory[NoteType]):
|
|
42
|
+
"""Factory for creating NoteType."""
|
|
43
|
+
|
|
44
|
+
class Meta:
|
|
45
|
+
model = NoteType
|
|
46
|
+
|
|
47
|
+
available_places_of_service = ["01"]
|
|
48
|
+
name = factory.Faker("sentence", nb_words=1)
|
|
49
|
+
code = factory.Faker("sentence", nb_words=1)
|
|
50
|
+
system = factory.Faker("sentence", nb_words=1)
|
|
51
|
+
icon = factory.Faker("sentence", nb_words=1)
|
|
52
|
+
display = factory.Faker("sentence", nb_words=1)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import factory
|
|
2
|
+
|
|
3
|
+
from canvas_sdk.v1.data import Organization, OrganizationAddress, OrganizationContactPoint
|
|
4
|
+
from canvas_sdk.v1.data.common import ContactPointSystem, ContactPointUse
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class OrganizationFactory(factory.django.DjangoModelFactory[Organization]):
|
|
8
|
+
"""Factory for creating Organization."""
|
|
9
|
+
|
|
10
|
+
class Meta:
|
|
11
|
+
model = Organization
|
|
12
|
+
|
|
13
|
+
short_name = "Canvas Medical"
|
|
14
|
+
full_name = "Canvas Medical, Inc."
|
|
15
|
+
logo_url = "https://s3-us-west-2.amazonaws.com/canvas-pcp-assets/canvas_logo_large.png"
|
|
16
|
+
background_image_url = "https://s3-us-west-2.amazonaws.com/canvas-pcp-assets/santa-cruz-low.jpg"
|
|
17
|
+
background_gradient = (
|
|
18
|
+
"linear-gradient(to top, rgb(231, 201, 154) 0%, rgb(220, 210, 192) 29%, "
|
|
19
|
+
"rgb(156, 175, 191) 90%, rgb(147, 166, 189) 100%)"
|
|
20
|
+
)
|
|
21
|
+
tax_id = "123456"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class OrganizationAddressFactory(factory.django.DjangoModelFactory[OrganizationAddress]):
|
|
25
|
+
"""Factory for creating OrganizationAddress."""
|
|
26
|
+
|
|
27
|
+
class Meta:
|
|
28
|
+
model = OrganizationAddress
|
|
29
|
+
|
|
30
|
+
organization = factory.SubFactory(OrganizationFactory)
|
|
31
|
+
line1 = "456 Organization Ave"
|
|
32
|
+
line2 = "#2"
|
|
33
|
+
city = "San Francisco"
|
|
34
|
+
district = "Sunset"
|
|
35
|
+
state_code = "CA"
|
|
36
|
+
postal_code = "94112"
|
|
37
|
+
country = "USA"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class OrganizationContactPointFactory(factory.django.DjangoModelFactory[OrganizationContactPoint]):
|
|
41
|
+
"""Factory for creating OrganizationContactPoint."""
|
|
42
|
+
|
|
43
|
+
class Meta:
|
|
44
|
+
model = OrganizationContactPoint
|
|
45
|
+
|
|
46
|
+
organization = factory.SubFactory(OrganizationFactory)
|
|
47
|
+
system = ContactPointSystem.PHONE
|
|
48
|
+
value = "8003701416"
|
|
49
|
+
use = ContactPointUse.WORK
|
|
50
|
+
rank = 1
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
from datetime import date
|
|
2
|
+
|
|
3
|
+
import factory
|
|
4
|
+
|
|
5
|
+
from canvas_sdk.v1.data import (
|
|
6
|
+
PracticeLocation,
|
|
7
|
+
PracticeLocationAddress,
|
|
8
|
+
PracticeLocationContactPoint,
|
|
9
|
+
PracticeLocationSetting,
|
|
10
|
+
)
|
|
11
|
+
from canvas_sdk.v1.data.common import (
|
|
12
|
+
AddressState,
|
|
13
|
+
AddressType,
|
|
14
|
+
AddressUse,
|
|
15
|
+
ContactPointSystem,
|
|
16
|
+
ContactPointUse,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class PracticeLocationSettingFactory(factory.django.DjangoModelFactory[PracticeLocationSetting]):
|
|
21
|
+
"""Factory for PracticeLocationSetting."""
|
|
22
|
+
|
|
23
|
+
class Meta:
|
|
24
|
+
model = PracticeLocationSetting
|
|
25
|
+
django_get_or_create = ("name",)
|
|
26
|
+
|
|
27
|
+
name = factory.Sequence(lambda n: f"location_setting_{n}")
|
|
28
|
+
value = {"random": "json"}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class PracticeLocationFactory(factory.django.DjangoModelFactory[PracticeLocation]):
|
|
32
|
+
"""Factory for PracticeLocation."""
|
|
33
|
+
|
|
34
|
+
class Meta:
|
|
35
|
+
model = PracticeLocation
|
|
36
|
+
|
|
37
|
+
organization = factory.SubFactory(
|
|
38
|
+
"canvas_sdk.test_utils.factories.organization.OrganizationFactory"
|
|
39
|
+
)
|
|
40
|
+
short_name = "Family Doctors of SF"
|
|
41
|
+
full_name = "Family Doctors of San Francisco"
|
|
42
|
+
setting = factory.RelatedFactory(PracticeLocationSettingFactory, "practice_location")
|
|
43
|
+
bill_through_organization = True
|
|
44
|
+
billing_location_name = "Billing Location Name"
|
|
45
|
+
tax_id = "123456789"
|
|
46
|
+
tax_id_type = "E"
|
|
47
|
+
npi_number = "1234567890"
|
|
48
|
+
group_npi_number = "112233445"
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class PracticeLocationAddressFactory(factory.django.DjangoModelFactory[PracticeLocationAddress]):
|
|
52
|
+
"""Factory for PracticeLocationAddress."""
|
|
53
|
+
|
|
54
|
+
class Meta:
|
|
55
|
+
model = PracticeLocationAddress
|
|
56
|
+
|
|
57
|
+
practice_location = factory.SubFactory(
|
|
58
|
+
"canvas_sdk.test_utils.factories.PracticeLocationFactory"
|
|
59
|
+
)
|
|
60
|
+
line1 = "1234 Golden Gate Ave."
|
|
61
|
+
line2 = "Suite 456"
|
|
62
|
+
city = "San Francisco"
|
|
63
|
+
district = ""
|
|
64
|
+
state_code = "CA"
|
|
65
|
+
postal_code = "94100"
|
|
66
|
+
use = AddressUse.WORK
|
|
67
|
+
type = AddressType.BOTH
|
|
68
|
+
longitude = -122.476944
|
|
69
|
+
latitude = 37.769722
|
|
70
|
+
start = date(year=2015, month=10, day=10)
|
|
71
|
+
end = None
|
|
72
|
+
country = "USA"
|
|
73
|
+
state = AddressState.ACTIVE
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class PracticeLocationContactPointFactory(
|
|
77
|
+
factory.django.DjangoModelFactory[PracticeLocationContactPoint]
|
|
78
|
+
):
|
|
79
|
+
"""Factory for creating PracticeLocationContactPoint."""
|
|
80
|
+
|
|
81
|
+
class Meta:
|
|
82
|
+
model = PracticeLocationContactPoint
|
|
83
|
+
|
|
84
|
+
practice_location = factory.SubFactory(PracticeLocationFactory)
|
|
85
|
+
system = ContactPointSystem.PHONE
|
|
86
|
+
value = "8003701416"
|
|
87
|
+
use = ContactPointUse.WORK
|
|
88
|
+
rank = 1
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import json
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
import factory
|
|
6
|
+
from django.utils import timezone
|
|
7
|
+
from factory.fuzzy import FuzzyDate
|
|
8
|
+
|
|
9
|
+
from canvas_sdk.v1.data import Referral, ReferralReport, ReferralReview
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ReferralFactory(factory.django.DjangoModelFactory[Referral]):
|
|
13
|
+
"""Factory for creating a Referral."""
|
|
14
|
+
|
|
15
|
+
class Meta:
|
|
16
|
+
model = Referral
|
|
17
|
+
|
|
18
|
+
patient = factory.SubFactory("canvas_sdk.test_utils.factories.PatientFactory")
|
|
19
|
+
note = factory.SubFactory("canvas_sdk.test_utils.factories.NoteFactory")
|
|
20
|
+
service_provider = None # Optional field
|
|
21
|
+
clinical_question = factory.Faker("text", max_nb_chars=50)
|
|
22
|
+
priority = factory.Faker("random_element", elements=["routine", "urgent", "stat"])
|
|
23
|
+
include_visit_note = False
|
|
24
|
+
notes = factory.Faker("paragraph")
|
|
25
|
+
date_referred = factory.LazyFunction(lambda: timezone.now())
|
|
26
|
+
forwarded = False
|
|
27
|
+
internal_comment = factory.Faker("paragraph")
|
|
28
|
+
internal_task_comment = None # Optional field
|
|
29
|
+
ignored = False
|
|
30
|
+
task_ids = factory.LazyFunction(lambda: json.dumps([]))
|
|
31
|
+
|
|
32
|
+
@factory.post_generation
|
|
33
|
+
def assessments(self, create: Any, extracted: Any, **kwargs: Any) -> None:
|
|
34
|
+
"""Handle many-to-many relationship for assessments."""
|
|
35
|
+
if not create:
|
|
36
|
+
return
|
|
37
|
+
|
|
38
|
+
if extracted:
|
|
39
|
+
for assessment in extracted:
|
|
40
|
+
self.assessments.add(assessment)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class ReferralReviewFactory(factory.django.DjangoModelFactory[ReferralReview]):
|
|
44
|
+
"""Factory for creating a ReferralReview."""
|
|
45
|
+
|
|
46
|
+
class Meta:
|
|
47
|
+
model = ReferralReview
|
|
48
|
+
|
|
49
|
+
internal_comment = factory.Faker("paragraph")
|
|
50
|
+
message_to_patient = factory.Faker("sentence", nb_words=20)
|
|
51
|
+
status = factory.Faker("random_element", elements=["pending", "reviewed", "completed"])
|
|
52
|
+
patient = factory.SubFactory("canvas_sdk.test_utils.factories.PatientFactory")
|
|
53
|
+
patient_communication_method = factory.Faker(
|
|
54
|
+
"random_element", elements=["email", "phone", "portal", "mail"]
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class ReferralReportFactory(factory.django.DjangoModelFactory[ReferralReport]):
|
|
59
|
+
"""Factory for creating a ReferralReport."""
|
|
60
|
+
|
|
61
|
+
class Meta:
|
|
62
|
+
model = ReferralReport
|
|
63
|
+
|
|
64
|
+
originator = factory.SubFactory("canvas_sdk.test_utils.factories.CanvasUserFactory")
|
|
65
|
+
review_mode = factory.Faker("random_element", elements=["IN", "OT"])
|
|
66
|
+
assigned_by = factory.SubFactory("canvas_sdk.test_utils.factories.CanvasUserFactory")
|
|
67
|
+
junked = False
|
|
68
|
+
requires_signature = factory.Faker("boolean")
|
|
69
|
+
assigned_date = factory.LazyFunction(lambda: timezone.now())
|
|
70
|
+
team_assigned_date = None
|
|
71
|
+
team = None
|
|
72
|
+
patient = factory.SubFactory("canvas_sdk.test_utils.factories.PatientFactory")
|
|
73
|
+
referral = factory.SubFactory(ReferralFactory)
|
|
74
|
+
specialty = factory.Faker("job")
|
|
75
|
+
review = None
|
|
76
|
+
original_date = FuzzyDate(
|
|
77
|
+
start_date=datetime.date.today() - datetime.timedelta(days=365),
|
|
78
|
+
end_date=datetime.date.today(),
|
|
79
|
+
)
|
|
80
|
+
comment = factory.Faker("paragraph")
|
|
81
|
+
priority = False
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
|
|
3
|
+
import factory
|
|
4
|
+
from dateutil.relativedelta import relativedelta
|
|
5
|
+
|
|
6
|
+
from canvas_sdk.v1.data import (
|
|
7
|
+
Staff,
|
|
8
|
+
StaffAddress,
|
|
9
|
+
StaffContactPoint,
|
|
10
|
+
StaffLicense,
|
|
11
|
+
StaffPhoto,
|
|
12
|
+
StaffRole,
|
|
13
|
+
)
|
|
14
|
+
from canvas_sdk.v1.data.common import ContactPointSystem, ContactPointUse
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class StaffAddressFactory(factory.django.DjangoModelFactory[StaffAddress]):
|
|
18
|
+
"""Factory for creating StaffAddress."""
|
|
19
|
+
|
|
20
|
+
class Meta:
|
|
21
|
+
model = StaffAddress
|
|
22
|
+
|
|
23
|
+
line1 = "1234 Main Street"
|
|
24
|
+
line2 = "Apt 3"
|
|
25
|
+
city = "San Francisco"
|
|
26
|
+
district = "Sunset"
|
|
27
|
+
state_code = "CA"
|
|
28
|
+
postal_code = "94112"
|
|
29
|
+
country = "USA"
|
|
30
|
+
staff = factory.SubFactory("canvas_sdk.test_utils.factories.StaffFactory")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class StaffPhotoFactory(factory.django.DjangoModelFactory[StaffPhoto]):
|
|
34
|
+
"""Factory for creating StaffPhoto."""
|
|
35
|
+
|
|
36
|
+
class Meta:
|
|
37
|
+
model = StaffPhoto
|
|
38
|
+
|
|
39
|
+
url = ""
|
|
40
|
+
staff = factory.SubFactory("canvas_sdk.test_utils.factories.StaffFactory")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class StaffRoleFactory(factory.django.DjangoModelFactory[StaffRole]):
|
|
44
|
+
"""Factory for creating StaffRole."""
|
|
45
|
+
|
|
46
|
+
class Meta:
|
|
47
|
+
model = StaffRole
|
|
48
|
+
django_get_or_create = ("internal_code", "staff")
|
|
49
|
+
|
|
50
|
+
internal_code = "MD"
|
|
51
|
+
name = "Physician"
|
|
52
|
+
public_abbreviation = "MD"
|
|
53
|
+
domain = StaffRole.RoleDomain.CLINICAL
|
|
54
|
+
domain_privilege_level = 100000
|
|
55
|
+
permissions = factory.LazyFunction(lambda: {})
|
|
56
|
+
staff = factory.SubFactory("canvas_sdk.test_utils.factories.StaffFactory")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class StaffLicenseFactory(factory.django.DjangoModelFactory[StaffLicense]):
|
|
60
|
+
"""Factory for creating StaffLicense."""
|
|
61
|
+
|
|
62
|
+
class Meta:
|
|
63
|
+
model = StaffLicense
|
|
64
|
+
|
|
65
|
+
issuing_authority_long_name = "MEDICAL BOARD OF CALIFORNIA"
|
|
66
|
+
issuing_authority_url = "http://www.mbc.ca.gov/"
|
|
67
|
+
license_or_certification_identifier = "A60695"
|
|
68
|
+
issuance_date = factory.LazyFunction(datetime.date.today)
|
|
69
|
+
expiration_date = factory.LazyFunction(lambda: datetime.date.today() + relativedelta(years=2))
|
|
70
|
+
staff = factory.SubFactory("canvas_sdk.test_utils.factories.StaffFactory")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class StaffContactPointFactory(factory.django.DjangoModelFactory[StaffContactPoint]):
|
|
74
|
+
"""Factory for creating StaffContactPoint."""
|
|
75
|
+
|
|
76
|
+
class Meta:
|
|
77
|
+
model = StaffContactPoint
|
|
78
|
+
|
|
79
|
+
value = "8883331212"
|
|
80
|
+
system = ContactPointSystem.PHONE
|
|
81
|
+
use = ContactPointUse.HOME
|
|
82
|
+
staff = factory.SubFactory("canvas_sdk.test_utils.factories.StaffFactory")
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class StaffFactory(factory.django.DjangoModelFactory[Staff]):
|
|
86
|
+
"""Factory for creating Staff."""
|
|
87
|
+
|
|
88
|
+
class Meta:
|
|
89
|
+
model = Staff
|
|
90
|
+
django_get_or_create = ("user",)
|
|
91
|
+
|
|
92
|
+
first_name = factory.Faker("first_name")
|
|
93
|
+
middle_name = factory.Faker("first_name")
|
|
94
|
+
last_name = factory.Faker("last_name")
|
|
95
|
+
npi_number = "1111155556"
|
|
96
|
+
group_npi_number = "123456789"
|
|
97
|
+
tax_id = "98711111"
|
|
98
|
+
spi_number = 5630156655001
|
|
99
|
+
address = factory.RelatedFactory(StaffAddressFactory, "staff")
|
|
100
|
+
telecom = factory.RelatedFactory(StaffContactPointFactory, "staff")
|
|
101
|
+
primary_practice_location = factory.SubFactory(
|
|
102
|
+
"canvas_sdk.test_utils.factories.PracticeLocationFactory"
|
|
103
|
+
)
|
|
104
|
+
photos = factory.RelatedFactory(StaffPhotoFactory, "staff")
|
|
105
|
+
role = factory.RelatedFactory(StaffRoleFactory, "staff")
|
|
106
|
+
license = factory.RelatedFactory(StaffLicenseFactory, "staff")
|
|
107
|
+
birth_date = factory.Faker("date_object")
|
|
108
|
+
|
|
109
|
+
user = factory.SubFactory(
|
|
110
|
+
"canvas_sdk.test_utils.factories.user.CanvasUserFactory",
|
|
111
|
+
)
|