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.
Files changed (185) hide show
  1. {canvas-0.63.0.dist-info → canvas-0.89.0.dist-info}/METADATA +4 -1
  2. {canvas-0.63.0.dist-info → canvas-0.89.0.dist-info}/RECORD +184 -98
  3. {canvas-0.63.0.dist-info → canvas-0.89.0.dist-info}/WHEEL +1 -1
  4. canvas_cli/apps/emit/event_fixtures/UNKNOWN.ndjson +1 -0
  5. canvas_cli/apps/logs/logs.py +386 -22
  6. canvas_cli/main.py +3 -1
  7. canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/tests/test_models.py +46 -4
  8. canvas_cli/utils/context/context.py +13 -13
  9. canvas_cli/utils/validators/manifest_schema.py +26 -1
  10. canvas_generated/messages/effects_pb2.py +5 -5
  11. canvas_generated/messages/effects_pb2.pyi +108 -2
  12. canvas_generated/messages/events_pb2.py +6 -6
  13. canvas_generated/messages/events_pb2.pyi +282 -2
  14. canvas_sdk/clients/__init__.py +1 -0
  15. canvas_sdk/clients/llms/__init__.py +17 -0
  16. canvas_sdk/clients/llms/libraries/__init__.py +11 -0
  17. canvas_sdk/clients/llms/libraries/llm_anthropic.py +87 -0
  18. canvas_sdk/clients/llms/libraries/llm_api.py +143 -0
  19. canvas_sdk/clients/llms/libraries/llm_google.py +92 -0
  20. canvas_sdk/clients/llms/libraries/llm_openai.py +98 -0
  21. canvas_sdk/clients/llms/structures/__init__.py +9 -0
  22. canvas_sdk/clients/llms/structures/llm_response.py +33 -0
  23. canvas_sdk/clients/llms/structures/llm_tokens.py +53 -0
  24. canvas_sdk/clients/llms/structures/llm_turn.py +47 -0
  25. canvas_sdk/clients/llms/structures/settings/__init__.py +13 -0
  26. canvas_sdk/clients/llms/structures/settings/llm_settings.py +27 -0
  27. canvas_sdk/clients/llms/structures/settings/llm_settings_anthropic.py +43 -0
  28. canvas_sdk/clients/llms/structures/settings/llm_settings_gemini.py +40 -0
  29. canvas_sdk/clients/llms/structures/settings/llm_settings_gpt4.py +40 -0
  30. canvas_sdk/clients/llms/structures/settings/llm_settings_gpt5.py +48 -0
  31. canvas_sdk/clients/third_party.py +3 -0
  32. canvas_sdk/commands/__init__.py +12 -0
  33. canvas_sdk/commands/base.py +33 -2
  34. canvas_sdk/commands/commands/adjust_prescription.py +4 -0
  35. canvas_sdk/commands/commands/custom_command.py +86 -0
  36. canvas_sdk/commands/commands/family_history.py +17 -1
  37. canvas_sdk/commands/commands/immunization_statement.py +42 -2
  38. canvas_sdk/commands/commands/medication_statement.py +16 -1
  39. canvas_sdk/commands/commands/past_surgical_history.py +16 -1
  40. canvas_sdk/commands/commands/perform.py +18 -1
  41. canvas_sdk/commands/commands/prescribe.py +8 -9
  42. canvas_sdk/commands/commands/refill.py +5 -5
  43. canvas_sdk/commands/commands/resolve_condition.py +5 -5
  44. canvas_sdk/commands/commands/review/__init__.py +3 -0
  45. canvas_sdk/commands/commands/review/base.py +72 -0
  46. canvas_sdk/commands/commands/review/imaging.py +13 -0
  47. canvas_sdk/commands/commands/review/lab.py +13 -0
  48. canvas_sdk/commands/commands/review/referral.py +13 -0
  49. canvas_sdk/commands/commands/review/uncategorized_document.py +13 -0
  50. canvas_sdk/commands/validation.py +43 -0
  51. canvas_sdk/effects/batch_originate.py +22 -0
  52. canvas_sdk/effects/calendar/__init__.py +13 -3
  53. canvas_sdk/effects/calendar/{create_calendar.py → calendar.py} +19 -5
  54. canvas_sdk/effects/calendar/event.py +172 -0
  55. canvas_sdk/effects/claim_label.py +93 -0
  56. canvas_sdk/effects/claim_line_item.py +47 -0
  57. canvas_sdk/effects/claim_queue.py +49 -0
  58. canvas_sdk/effects/fax/__init__.py +3 -0
  59. canvas_sdk/effects/fax/base.py +77 -0
  60. canvas_sdk/effects/fax/note.py +42 -0
  61. canvas_sdk/effects/metadata.py +15 -1
  62. canvas_sdk/effects/note/__init__.py +8 -1
  63. canvas_sdk/effects/note/appointment.py +135 -7
  64. canvas_sdk/effects/note/base.py +17 -0
  65. canvas_sdk/effects/note/message.py +22 -14
  66. canvas_sdk/effects/note/note.py +150 -1
  67. canvas_sdk/effects/observation/__init__.py +11 -0
  68. canvas_sdk/effects/observation/base.py +206 -0
  69. canvas_sdk/effects/patient/__init__.py +2 -0
  70. canvas_sdk/effects/patient/base.py +8 -0
  71. canvas_sdk/effects/payment/__init__.py +11 -0
  72. canvas_sdk/effects/payment/base.py +355 -0
  73. canvas_sdk/effects/payment/post_claim_payment.py +49 -0
  74. canvas_sdk/effects/send_contact_verification.py +42 -0
  75. canvas_sdk/effects/task/__init__.py +2 -1
  76. canvas_sdk/effects/task/task.py +30 -0
  77. canvas_sdk/effects/validation/__init__.py +3 -0
  78. canvas_sdk/effects/validation/base.py +92 -0
  79. canvas_sdk/events/base.py +15 -0
  80. canvas_sdk/handlers/application.py +7 -7
  81. canvas_sdk/handlers/simple_api/api.py +1 -4
  82. canvas_sdk/handlers/simple_api/websocket.py +1 -4
  83. canvas_sdk/handlers/utils.py +14 -0
  84. canvas_sdk/questionnaires/utils.py +1 -0
  85. canvas_sdk/templates/utils.py +17 -4
  86. canvas_sdk/test_utils/factories/FACTORY_GUIDE.md +362 -0
  87. canvas_sdk/test_utils/factories/__init__.py +115 -0
  88. canvas_sdk/test_utils/factories/calendar.py +24 -0
  89. canvas_sdk/test_utils/factories/claim.py +81 -0
  90. canvas_sdk/test_utils/factories/claim_diagnosis_code.py +16 -0
  91. canvas_sdk/test_utils/factories/coverage.py +17 -0
  92. canvas_sdk/test_utils/factories/imaging.py +74 -0
  93. canvas_sdk/test_utils/factories/lab.py +192 -0
  94. canvas_sdk/test_utils/factories/medication_history.py +75 -0
  95. canvas_sdk/test_utils/factories/note.py +52 -0
  96. canvas_sdk/test_utils/factories/organization.py +50 -0
  97. canvas_sdk/test_utils/factories/practicelocation.py +88 -0
  98. canvas_sdk/test_utils/factories/referral.py +81 -0
  99. canvas_sdk/test_utils/factories/staff.py +111 -0
  100. canvas_sdk/test_utils/factories/task.py +66 -0
  101. canvas_sdk/test_utils/factories/uncategorized_clinical_document.py +48 -0
  102. canvas_sdk/utils/metrics.py +4 -1
  103. canvas_sdk/v1/data/__init__.py +66 -7
  104. canvas_sdk/v1/data/allergy_intolerance.py +5 -11
  105. canvas_sdk/v1/data/appointment.py +18 -4
  106. canvas_sdk/v1/data/assessment.py +2 -12
  107. canvas_sdk/v1/data/banner_alert.py +2 -4
  108. canvas_sdk/v1/data/base.py +53 -14
  109. canvas_sdk/v1/data/billing.py +8 -11
  110. canvas_sdk/v1/data/calendar.py +64 -0
  111. canvas_sdk/v1/data/care_team.py +4 -10
  112. canvas_sdk/v1/data/claim.py +172 -66
  113. canvas_sdk/v1/data/claim_diagnosis_code.py +19 -0
  114. canvas_sdk/v1/data/claim_line_item.py +2 -5
  115. canvas_sdk/v1/data/coding.py +19 -0
  116. canvas_sdk/v1/data/command.py +2 -4
  117. canvas_sdk/v1/data/common.py +10 -0
  118. canvas_sdk/v1/data/compound_medication.py +3 -4
  119. canvas_sdk/v1/data/condition.py +4 -9
  120. canvas_sdk/v1/data/coverage.py +66 -26
  121. canvas_sdk/v1/data/detected_issue.py +20 -20
  122. canvas_sdk/v1/data/device.py +2 -14
  123. canvas_sdk/v1/data/discount.py +2 -5
  124. canvas_sdk/v1/data/encounter.py +44 -0
  125. canvas_sdk/v1/data/facility.py +1 -0
  126. canvas_sdk/v1/data/goal.py +2 -14
  127. canvas_sdk/v1/data/imaging.py +4 -30
  128. canvas_sdk/v1/data/immunization.py +7 -15
  129. canvas_sdk/v1/data/lab.py +12 -65
  130. canvas_sdk/v1/data/line_item_transaction.py +2 -5
  131. canvas_sdk/v1/data/medication.py +3 -8
  132. canvas_sdk/v1/data/medication_history.py +142 -0
  133. canvas_sdk/v1/data/medication_statement.py +41 -0
  134. canvas_sdk/v1/data/message.py +4 -8
  135. canvas_sdk/v1/data/note.py +37 -38
  136. canvas_sdk/v1/data/observation.py +9 -36
  137. canvas_sdk/v1/data/organization.py +70 -9
  138. canvas_sdk/v1/data/patient.py +8 -12
  139. canvas_sdk/v1/data/patient_consent.py +4 -14
  140. canvas_sdk/v1/data/payment_collection.py +2 -5
  141. canvas_sdk/v1/data/posting.py +3 -9
  142. canvas_sdk/v1/data/practicelocation.py +66 -7
  143. canvas_sdk/v1/data/protocol_override.py +3 -4
  144. canvas_sdk/v1/data/protocol_result.py +3 -3
  145. canvas_sdk/v1/data/questionnaire.py +10 -26
  146. canvas_sdk/v1/data/reason_for_visit.py +2 -6
  147. canvas_sdk/v1/data/referral.py +41 -17
  148. canvas_sdk/v1/data/staff.py +34 -26
  149. canvas_sdk/v1/data/stop_medication_event.py +27 -0
  150. canvas_sdk/v1/data/task.py +30 -11
  151. canvas_sdk/v1/data/team.py +2 -4
  152. canvas_sdk/v1/data/uncategorized_clinical_document.py +84 -0
  153. canvas_sdk/v1/data/user.py +14 -0
  154. canvas_sdk/v1/data/utils.py +5 -0
  155. canvas_sdk/value_set/v2026/__init__.py +1 -0
  156. canvas_sdk/value_set/v2026/adverse_event.py +157 -0
  157. canvas_sdk/value_set/v2026/allergy.py +116 -0
  158. canvas_sdk/value_set/v2026/assessment.py +466 -0
  159. canvas_sdk/value_set/v2026/communication.py +496 -0
  160. canvas_sdk/value_set/v2026/condition.py +52934 -0
  161. canvas_sdk/value_set/v2026/device.py +315 -0
  162. canvas_sdk/value_set/v2026/diagnostic_study.py +5243 -0
  163. canvas_sdk/value_set/v2026/encounter.py +2714 -0
  164. canvas_sdk/value_set/v2026/immunization.py +297 -0
  165. canvas_sdk/value_set/v2026/individual_characteristic.py +339 -0
  166. canvas_sdk/value_set/v2026/intervention.py +1703 -0
  167. canvas_sdk/value_set/v2026/laboratory_test.py +1831 -0
  168. canvas_sdk/value_set/v2026/medication.py +8218 -0
  169. canvas_sdk/value_set/v2026/no_qdm_category_assigned.py +26493 -0
  170. canvas_sdk/value_set/v2026/physical_exam.py +342 -0
  171. canvas_sdk/value_set/v2026/procedure.py +27869 -0
  172. canvas_sdk/value_set/v2026/symptom.py +625 -0
  173. logger/logger.py +30 -31
  174. logger/logstash.py +282 -0
  175. logger/pubsub.py +26 -0
  176. plugin_runner/allowed-module-imports.json +940 -9
  177. plugin_runner/generate_allowed_imports.py +1 -0
  178. plugin_runner/installation.py +2 -2
  179. plugin_runner/plugin_runner.py +21 -24
  180. plugin_runner/sandbox.py +34 -0
  181. protobufs/canvas_generated/messages/effects.proto +65 -0
  182. protobufs/canvas_generated/messages/events.proto +150 -51
  183. settings.py +27 -11
  184. canvas_sdk/effects/calendar/create_event.py +0 -43
  185. {canvas-0.63.0.dist-info → canvas-0.89.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,64 @@
1
+ from typing import Self, cast
2
+
3
+ from django.db import models
4
+ from django.db.models.manager import BaseManager
5
+ from timezone_utils.fields import TimeZoneField
6
+
7
+ from canvas_sdk.v1.data.base import BaseQuerySet, IdentifiableModel
8
+
9
+
10
+ class CalendarQuerySet(BaseQuerySet):
11
+ """A queryset for calendars."""
12
+
13
+ def for_calendar_name(self, provider_name: str, calendar_type: str, location: str) -> Self:
14
+ """Return a queryset that filters objects for a specific calendar name."""
15
+ calendar_name = f"{provider_name}: {calendar_type}{f': {location}' if location else ''}"
16
+
17
+ return self.filter(title=calendar_name)
18
+
19
+
20
+ CalendarManager = BaseManager.from_queryset(CalendarQuerySet)
21
+
22
+
23
+ class Calendar(IdentifiableModel):
24
+ """Model to represent the Calendar."""
25
+
26
+ class Meta:
27
+ db_table = "canvas_sdk_data_calendars_calendar_001"
28
+
29
+ objects = cast(CalendarQuerySet, CalendarManager())
30
+
31
+ title = models.CharField(max_length=128)
32
+ timezone = TimeZoneField(default="UTC")
33
+ description = models.TextField(blank=True, null=True)
34
+
35
+
36
+ class Event(IdentifiableModel):
37
+ """Model to represent the Calendar Event."""
38
+
39
+ class Meta:
40
+ db_table = "canvas_sdk_data_calendars_event_001"
41
+
42
+ title = models.CharField(max_length=512)
43
+ description = models.TextField(blank=True)
44
+ calendar = models.ForeignKey("v1.Calendar", on_delete=models.CASCADE, related_name="events")
45
+ starts_at = models.DateTimeField()
46
+ ends_at = models.DateTimeField()
47
+ recurrence = models.TextField(blank=True, null=True)
48
+ recurrence_ends_at = models.DateTimeField(blank=True, null=True)
49
+ recurring_parent_event = models.ForeignKey(
50
+ "self",
51
+ on_delete=models.CASCADE,
52
+ blank=True,
53
+ null=True,
54
+ related_name="exceptions",
55
+ )
56
+ original_starts_at = models.DateTimeField(blank=True, null=True)
57
+ is_all_day = models.BooleanField(default=False)
58
+ is_cancelled = models.BooleanField(default=False)
59
+ allowed_note_types = models.ManyToManyField(
60
+ "v1.NoteType", blank=True, db_table="canvas_sdk_data_calendars_event_allowed_note_types_001"
61
+ )
62
+
63
+
64
+ __exports__ = ("Calendar", "Event")
@@ -1,6 +1,7 @@
1
1
  from django.db import models
2
2
 
3
- from canvas_sdk.v1.data.base import IdentifiableModel, Model
3
+ from canvas_sdk.v1.data.base import IdentifiableModel, TimestampedModel
4
+ from canvas_sdk.v1.data.coding import Coding
4
5
 
5
6
 
6
7
  class CareTeamMembershipStatus(models.TextChoices):
@@ -13,31 +14,24 @@ class CareTeamMembershipStatus(models.TextChoices):
13
14
  ENTERED_IN_ERROR = "entered-in-error", "Entered in Error"
14
15
 
15
16
 
16
- class CareTeamRole(Model):
17
+ class CareTeamRole(Coding):
17
18
  """CareTeamRole."""
18
19
 
19
20
  class Meta:
20
21
  db_table = "canvas_sdk_data_api_careteamrole_001"
21
22
 
22
- system = models.CharField(max_length=255)
23
- version = models.CharField(max_length=255)
24
- code = models.CharField(max_length=255)
25
- display = models.CharField(max_length=1000)
26
- user_selected = models.BooleanField()
27
23
  active = models.BooleanField()
28
24
 
29
25
  def __str__(self) -> str:
30
26
  return self.display
31
27
 
32
28
 
33
- class CareTeamMembership(IdentifiableModel):
29
+ class CareTeamMembership(TimestampedModel, IdentifiableModel):
34
30
  """CareTeamMembership."""
35
31
 
36
32
  class Meta:
37
33
  db_table = "canvas_sdk_data_api_careteammembership_001"
38
34
 
39
- created = models.DateTimeField(auto_now_add=True)
40
- modified = models.DateTimeField(auto_now=True)
41
35
  patient = models.ForeignKey(
42
36
  "v1.Patient", on_delete=models.DO_NOTHING, related_name="care_team_memberships", null=True
43
37
  )
@@ -3,9 +3,13 @@ from typing import TYPE_CHECKING, Self
3
3
 
4
4
  from django.db import models
5
5
 
6
- from canvas_sdk.v1.data.base import IdentifiableModel, Model
6
+ from canvas_sdk.v1.data.base import AuditedModel, IdentifiableModel, TimestampedModel
7
7
  from canvas_sdk.v1.data.common import PersonSex
8
- from canvas_sdk.v1.data.coverage import CoverageRelationshipCode, CoverageType
8
+ from canvas_sdk.v1.data.coverage import (
9
+ CoverageRelationshipCode,
10
+ CoverageType,
11
+ TransactorCoverageType,
12
+ )
9
13
  from canvas_sdk.v1.data.fields import ChoiceArrayField
10
14
  from canvas_sdk.v1.data.utils import quantize
11
15
 
@@ -21,7 +25,7 @@ class InstallmentPlanStatus(models.TextChoices):
21
25
  CANCELLED = "cancelled", "Cancelled"
22
26
 
23
27
 
24
- class InstallmentPlan(Model):
28
+ class InstallmentPlan(TimestampedModel):
25
29
  """InstallmentPlan."""
26
30
 
27
31
  class Meta:
@@ -35,9 +39,6 @@ class InstallmentPlan(Model):
35
39
  status = models.CharField(choices=InstallmentPlanStatus.choices, max_length=10)
36
40
  expected_payoff_date = models.DateField()
37
41
 
38
- created = models.DateTimeField(auto_now_add=True)
39
- modified = models.DateTimeField(auto_now=True)
40
-
41
42
 
42
43
  class ClaimQueueColumns(models.TextChoices):
43
44
  """ClaimQueueColumns."""
@@ -73,7 +74,7 @@ class ClaimQueues(models.IntegerChoices):
73
74
  TRASH = 10, "Trash"
74
75
 
75
76
 
76
- class ClaimQueue(Model):
77
+ class ClaimQueue(TimestampedModel):
77
78
  """ClaimQueue."""
78
79
 
79
80
  class Meta:
@@ -83,14 +84,11 @@ class ClaimQueue(Model):
83
84
  name = models.CharField(max_length=100)
84
85
  display_name = models.CharField(max_length=100)
85
86
  description = models.CharField(max_length=500)
86
- show_in_revenue = models.BooleanField()
87
+ show_in_revenue = models.BooleanField(default=True)
87
88
  visible_columns = ChoiceArrayField(
88
89
  models.CharField(choices=ClaimQueueColumns.choices, max_length=64)
89
90
  )
90
91
 
91
- created = models.DateTimeField(auto_now_add=True)
92
- modified = models.DateTimeField(auto_now=True)
93
-
94
92
 
95
93
  class ClaimPayerOrder(models.TextChoices):
96
94
  """ClaimPayerOrder."""
@@ -116,6 +114,16 @@ class ClaimTypeCode(models.TextChoices):
116
114
  UNNECESSARY = "", "No Typecode necessary"
117
115
 
118
116
 
117
+ class ClaimComment(IdentifiableModel, AuditedModel):
118
+ """ClaimComment."""
119
+
120
+ class Meta:
121
+ db_table = "canvas_sdk_data_quality_and_revenue_claimcomment_001"
122
+
123
+ claim = models.ForeignKey("Claim", on_delete=models.CASCADE, related_name="comments")
124
+ comment = models.TextField()
125
+
126
+
119
127
  class ClaimCoverageQuerySet(models.QuerySet):
120
128
  """ClaimCoverageQuerySet."""
121
129
 
@@ -124,7 +132,7 @@ class ClaimCoverageQuerySet(models.QuerySet):
124
132
  return self.filter(active=True)
125
133
 
126
134
 
127
- class ClaimCoverage(Model):
135
+ class ClaimCoverage(TimestampedModel, IdentifiableModel):
128
136
  """A model that represents the link between a claim and a specific insurance coverage."""
129
137
 
130
138
  class Meta:
@@ -138,53 +146,118 @@ class ClaimCoverage(Model):
138
146
  "v1.Coverage", related_name="claim_coverages", on_delete=models.PROTECT
139
147
  )
140
148
 
141
- active = models.BooleanField()
142
- payer_name = models.CharField(max_length=255)
143
- payer_id = models.CharField(max_length=255)
144
- payer_typecode = models.CharField(max_length=2)
145
- payer_order = models.CharField(choices=ClaimPayerOrder.choices, max_length=10)
146
- payer_addr1 = models.CharField(max_length=255)
147
- payer_addr2 = models.CharField(max_length=255)
148
- payer_city = models.CharField(max_length=255)
149
- payer_state = models.CharField(max_length=2)
150
- payer_zip = models.CharField(max_length=255)
151
- payer_plan_type = models.CharField(choices=ClaimTypeCode.choices, max_length=20)
152
- coverage_type = models.CharField(choices=CoverageType.choices, max_length=64)
153
-
154
- subscriber_employer = models.CharField(max_length=255)
155
- subscriber_group = models.CharField(max_length=255)
156
- subscriber_number = models.CharField(max_length=100)
157
- subscriber_plan = models.CharField(max_length=255)
158
- subscriber_dob = models.CharField(max_length=10)
159
- subscriber_first_name = models.CharField(max_length=255)
160
- subscriber_last_name = models.CharField(max_length=255)
161
- subscriber_middle_name = models.CharField(max_length=255)
162
- subscriber_phone = models.CharField(max_length=50)
163
- subscriber_sex = models.CharField(choices=PersonSex.choices, max_length=3)
164
- subscriber_addr1 = models.CharField(max_length=255)
165
- subscriber_addr2 = models.CharField(max_length=255)
166
- subscriber_city = models.CharField(max_length=255)
167
- subscriber_state = models.CharField(max_length=2)
168
- subscriber_zip = models.CharField(max_length=255)
169
- subscriber_country = models.CharField(max_length=50)
149
+ active = models.BooleanField(default=True)
150
+ payer_name = models.CharField(max_length=255, default="", blank=True, db_index=True)
151
+ payer_id = models.CharField(max_length=255, default="", blank=True)
152
+ payer_typecode = models.CharField(
153
+ max_length=2, choices=ClaimTypeCode.choices, default=ClaimTypeCode.UNNECESSARY
154
+ )
155
+ payer_order = models.CharField(
156
+ choices=ClaimPayerOrder.choices, max_length=10, default=ClaimPayerOrder.PRIMARY
157
+ )
158
+ payer_addr1 = models.CharField(max_length=255, default="", blank=True)
159
+ payer_addr2 = models.CharField(max_length=255, default="", blank=True)
160
+ payer_city = models.CharField(max_length=255, default="", blank=True)
161
+ payer_state = models.CharField(max_length=2, default="", blank=True)
162
+ payer_zip = models.CharField(max_length=255, default="", blank=True)
163
+ payer_plan_type = models.CharField(
164
+ choices=CoverageType.choices, max_length=20, default="", blank=True
165
+ )
166
+ coverage_type = models.CharField(
167
+ choices=TransactorCoverageType.choices, max_length=64, null=True, blank=True
168
+ )
169
+
170
+ subscriber_employer = models.CharField(max_length=255, default="", blank=True)
171
+ subscriber_group = models.CharField(max_length=255, default="", blank=True)
172
+ subscriber_number = models.CharField(max_length=100, default="", blank=True)
173
+ subscriber_plan = models.CharField(max_length=255, default="", blank=True)
174
+ subscriber_dob = models.CharField(max_length=10, default="0000-00-00")
175
+ subscriber_first_name = models.CharField(max_length=255, default="", blank=True)
176
+ subscriber_last_name = models.CharField(max_length=255, default="", blank=True)
177
+ subscriber_middle_name = models.CharField(max_length=255, default="", blank=True, null=True)
178
+ subscriber_phone = models.CharField(max_length=50, default="", blank=True)
179
+ subscriber_sex = models.CharField(
180
+ max_length=3, choices=PersonSex.choices, default=PersonSex.SEX_BLANK
181
+ )
182
+ subscriber_addr1 = models.CharField(max_length=255, default="", blank=True)
183
+ subscriber_addr2 = models.CharField(max_length=255, default="", blank=True, null=True)
184
+ subscriber_city = models.CharField(max_length=255, default="", blank=True)
185
+ subscriber_state = models.CharField(max_length=2, default="", blank=True)
186
+ subscriber_zip = models.CharField(max_length=255, default="", blank=True)
187
+ subscriber_country = models.CharField(max_length=50, default="", blank=True)
170
188
  patient_relationship_to_subscriber = models.CharField(
171
- choices=CoverageRelationshipCode.choices, max_length=2
189
+ max_length=2,
190
+ choices=CoverageRelationshipCode.choices,
191
+ default=CoverageRelationshipCode.SELF,
172
192
  )
173
193
 
174
- pay_to_addr1 = models.CharField(max_length=255)
175
- pay_to_addr2 = models.CharField(max_length=255)
176
- pay_to_city = models.CharField(max_length=255)
177
- pay_to_state = models.CharField(max_length=2)
178
- pay_to_zip = models.CharField(max_length=255)
194
+ pay_to_addr1 = models.CharField(max_length=255, default="", blank=True)
195
+ pay_to_addr2 = models.CharField(max_length=255, default="", blank=True)
196
+ pay_to_city = models.CharField(max_length=255, default="", blank=True)
197
+ pay_to_state = models.CharField(max_length=2, default="", blank=True)
198
+ pay_to_zip = models.CharField(max_length=255, default="", blank=True)
179
199
 
180
- resubmission_code = models.CharField(max_length=1)
181
- payer_icn = models.CharField(max_length=250)
200
+ resubmission_code = models.CharField(max_length=1, default="", blank=True)
201
+ payer_icn = models.CharField(max_length=250, default="", blank=True)
182
202
 
183
- created = models.DateTimeField(auto_now_add=True)
184
- modified = models.DateTimeField(auto_now=True)
185
203
 
204
+ class ClaimProvider(TimestampedModel, IdentifiableModel):
205
+ """ClaimProvider."""
186
206
 
187
- class ClaimPatient(Model):
207
+ class Meta:
208
+ db_table = "canvas_sdk_data_quality_and_revenue_claimprovider_001"
209
+
210
+ claim = models.OneToOneField("v1.Claim", on_delete=models.CASCADE, related_name="provider")
211
+ clia_number = models.CharField(max_length=100, default="", blank=True)
212
+
213
+ billing_provider_name = models.CharField(max_length=255, default="", blank=True)
214
+ billing_provider_phone = models.CharField(max_length=15, default="", blank=True)
215
+ billing_provider_addr1 = models.CharField(max_length=255, default="", blank=True)
216
+ billing_provider_addr2 = models.CharField(max_length=255, default="", blank=True)
217
+ billing_provider_city = models.CharField(max_length=255, default="", blank=True)
218
+ billing_provider_state = models.CharField(max_length=2, default="", blank=True)
219
+ billing_provider_zip = models.CharField(max_length=255, default="", blank=True)
220
+ billing_provider_id = models.CharField(max_length=255, default="", blank=True)
221
+ billing_provider_npi = models.CharField(max_length=10, default="0")
222
+ billing_provider_tax_id = models.CharField(max_length=100, default="", blank=True)
223
+ billing_provider_tax_id_type = models.CharField(max_length=1, default="E")
224
+ billing_provider_taxonomy = models.CharField(max_length=100, default="", blank=True)
225
+
226
+ provider_id = models.CharField(max_length=255, default="", blank=True)
227
+ provider_first_name = models.CharField(max_length=255, default="", blank=True)
228
+ provider_last_name = models.CharField(max_length=255, default="", blank=True)
229
+ provider_middle_name = models.CharField(max_length=255, default="", blank=True)
230
+ provider_npi = models.CharField(max_length=10, default="0")
231
+ provider_tax_id = models.CharField(max_length=100, default="", blank=True)
232
+ provider_tax_id_type = models.CharField(max_length=1, default="E")
233
+ provider_taxonomy = models.CharField(max_length=100, default="", blank=True)
234
+ provider_ptan_identifier = models.CharField(max_length=50, default="", blank=True)
235
+
236
+ referring_provider_id = models.CharField(max_length=255, default="", blank=True)
237
+ referring_provider_first_name = models.CharField(max_length=255, default="", blank=True)
238
+ referring_provider_last_name = models.CharField(max_length=255, default="", blank=True)
239
+ referring_provider_middle_name = models.CharField(max_length=255, default="", blank=True)
240
+ referring_provider_npi = models.CharField(max_length=10, default="0")
241
+ referring_provider_ptan_identifier = models.CharField(max_length=50, default="", blank=True)
242
+
243
+ ordering_provider_first_name = models.CharField(max_length=255, default="", blank=True)
244
+ ordering_provider_last_name = models.CharField(max_length=255, default="", blank=True)
245
+ ordering_provider_middle_name = models.CharField(max_length=255, default="", blank=True)
246
+ ordering_provider_npi = models.CharField(max_length=10, default="0")
247
+
248
+ facility_id = models.CharField(max_length=255, default="", blank=True)
249
+ facility_name = models.CharField(max_length=255, default="", blank=True)
250
+ facility_npi = models.CharField(max_length=10, default="0")
251
+ facility_addr1 = models.CharField(max_length=255, default="", blank=True)
252
+ facility_addr2 = models.CharField(max_length=255, default="", blank=True)
253
+ facility_city = models.CharField(max_length=255, default="", blank=True)
254
+ facility_state = models.CharField(max_length=2, default="", blank=True)
255
+ facility_zip = models.CharField(max_length=255, default="", blank=True)
256
+ hosp_from_date = models.CharField(max_length=10, default="0000-00-00")
257
+ hosp_to_date = models.CharField(max_length=10, default="0000-00-00")
258
+
259
+
260
+ class ClaimPatient(TimestampedModel):
188
261
  """ClaimPatient."""
189
262
 
190
263
  class Meta:
@@ -206,9 +279,6 @@ class ClaimPatient(Model):
206
279
  zip = models.CharField(max_length=255)
207
280
  country = models.CharField(max_length=50)
208
281
 
209
- created = models.DateTimeField(auto_now_add=True)
210
- modified = models.DateTimeField(auto_now=True)
211
-
212
282
 
213
283
  class ClaimQueryset(models.QuerySet):
214
284
  """ClaimQueryset."""
@@ -218,7 +288,7 @@ class ClaimQueryset(models.QuerySet):
218
288
  return self.exclude(current_queue__queue_sort_ordering=ClaimQueues.TRASH)
219
289
 
220
290
 
221
- class Claim(IdentifiableModel):
291
+ class Claim(TimestampedModel, IdentifiableModel):
222
292
  """Claim."""
223
293
 
224
294
  class Meta:
@@ -236,25 +306,23 @@ class Claim(IdentifiableModel):
236
306
  ClaimCoverage, related_name="claims", on_delete=models.SET_NULL, null=True
237
307
  )
238
308
 
239
- accept_assign = models.BooleanField()
240
- auto_accident = models.BooleanField()
309
+ accept_assign = models.BooleanField(default=True)
310
+ auto_accident = models.BooleanField(default=False)
241
311
  auto_accident_state = models.CharField(max_length=2)
242
- employment_related = models.BooleanField()
243
- other_accident = models.BooleanField()
312
+ employment_related = models.BooleanField(default=False)
313
+ other_accident = models.BooleanField(default=False)
244
314
  accident_code = models.CharField(max_length=10)
245
- illness_date = models.DateField()
315
+ illness_date = models.DateField(blank=True, null=True)
246
316
  remote_batch_id = models.CharField(max_length=100)
247
317
  remote_file_id = models.CharField(max_length=100)
248
318
  prior_auth = models.CharField(max_length=100)
249
319
 
250
320
  narrative = models.CharField(max_length=2500)
251
321
  account_number = models.CharField(max_length=255)
252
- snoozed_until = models.DateField()
322
+ snoozed_until = models.DateField(null=True)
253
323
 
254
- patient_balance = models.DecimalField(max_digits=8, decimal_places=2)
255
- aggregate_coverage_balance = models.DecimalField(max_digits=8, decimal_places=2)
256
- created = models.DateTimeField(auto_now_add=True)
257
- modified = models.DateTimeField(auto_now=True)
324
+ patient_balance = models.DecimalField(max_digits=8, decimal_places=2, default=0.00)
325
+ aggregate_coverage_balance = models.DecimalField(max_digits=8, decimal_places=2, default=0.00)
258
326
 
259
327
  @property
260
328
  def total_charges(self) -> Decimal:
@@ -301,15 +369,53 @@ class Claim(IdentifiableModel):
301
369
  """Return the active claim line items."""
302
370
  return self.line_items.active().exclude_copay_and_unlinked()
303
371
 
372
+ def get_coverage_by_payer_id(
373
+ self, payer_id: str, subscriber_number: str | None = None
374
+ ) -> ClaimCoverage | None:
375
+ """Finds the active coverage associated with a payer_id. Optionally checks if the subscriber_number matches,
376
+ which will choose the correct coverage in the case where a patient has two coverages with the same payer_id.
377
+ """
378
+ base_qs = self.coverages.active().filter(payer_id=payer_id)
379
+ qs = base_qs.filter(subscriber_number=subscriber_number) if subscriber_number else base_qs
380
+ return qs.first() or base_qs.first()
381
+
382
+
383
+ class ClaimLabel(IdentifiableModel):
384
+ """ClaimLabel."""
385
+
386
+ class Meta:
387
+ db_table = "canvas_sdk_data_quality_and_revenue_claimlabel_001"
388
+
389
+ claim = models.ForeignKey("v1.Claim", on_delete=models.PROTECT, related_name="claim_labels")
390
+ label = models.ForeignKey("v1.TaskLabel", on_delete=models.PROTECT, related_name="claim_labels")
391
+
392
+
393
+ class ClaimSubmission(IdentifiableModel):
394
+ """ClaimSubmission."""
395
+
396
+ class Meta:
397
+ db_table = "canvas_sdk_data_quality_and_revenue_claimsubmission_001"
398
+
399
+ claim = models.ForeignKey("v1.Claim", on_delete=models.PROTECT, related_name="submissions")
400
+ coverage = models.ForeignKey(
401
+ "v1.ClaimCoverage", on_delete=models.PROTECT, related_name="submissions", null=True
402
+ )
403
+ clearinghouse_claim_id = models.CharField(max_length=255, default="", blank=True, null=True)
404
+ claim_index = models.PositiveIntegerField(default=0)
405
+
304
406
 
305
407
  __exports__ = (
306
408
  "Claim",
409
+ "ClaimLabel",
307
410
  "ClaimQueue",
411
+ "ClaimComment",
308
412
  "ClaimCoverage",
309
413
  "ClaimPatient",
310
414
  "ClaimPayerOrder",
415
+ "ClaimProvider",
311
416
  "ClaimQueues",
312
417
  "ClaimQueueColumns",
418
+ "ClaimSubmission",
313
419
  "ClaimTypeCode",
314
420
  "InstallmentPlan",
315
421
  "InstallmentPlanStatus",
@@ -0,0 +1,19 @@
1
+ from django.db import models
2
+
3
+ from canvas_sdk.v1.data.base import IdentifiableModel, TimestampedModel
4
+
5
+
6
+ class ClaimDiagnosisCode(TimestampedModel, IdentifiableModel):
7
+ """ClaimDiagnosisCode model for claim diagnosis codes."""
8
+
9
+ class Meta:
10
+ db_table = "canvas_sdk_data_quality_and_revenue_claimdiagnosiscode_001"
11
+ ordering = ["rank"]
12
+
13
+ claim = models.ForeignKey("v1.Claim", on_delete=models.CASCADE, related_name="diagnosis_codes")
14
+ rank = models.IntegerField()
15
+ code = models.CharField(max_length=20, blank=True)
16
+ display = models.CharField(max_length=1000, blank=True)
17
+
18
+
19
+ __exports__ = ("ClaimDiagnosisCode",)
@@ -5,7 +5,7 @@ from django.db import models
5
5
  from django.db.models import Q, Sum
6
6
  from django.db.models.functions import Coalesce
7
7
 
8
- from canvas_sdk.v1.data.base import Model
8
+ from canvas_sdk.v1.data.base import IdentifiableModel, TimestampedModel
9
9
  from canvas_sdk.v1.data.note import PracticeLocationPOS
10
10
 
11
11
 
@@ -106,7 +106,7 @@ class ClaimLineItemQuerySet(models.QuerySet):
106
106
  return self.exclude(proc_code=LineItemCodes.UNLINKED.value).apply_ordering()
107
107
 
108
108
 
109
- class ClaimLineItem(Model):
109
+ class ClaimLineItem(TimestampedModel, IdentifiableModel):
110
110
  """ClaimLineItem."""
111
111
 
112
112
  class Meta:
@@ -132,8 +132,5 @@ class ClaimLineItem(Model):
132
132
  epsdt = models.CharField(max_length=2)
133
133
  family_planning = models.CharField(choices=FamilyPlanningOptions.choices, max_length=1)
134
134
 
135
- created = models.DateTimeField(auto_now_add=True)
136
- modified = models.DateTimeField(auto_now=True)
137
-
138
135
 
139
136
  __exports__ = ("ClaimLineItem", "ClaimLineItemStatus", "LineItemCodes", "FamilyPlanningOptions")
@@ -0,0 +1,19 @@
1
+ from django.db import models
2
+
3
+ from canvas_sdk.v1.data.base import Model
4
+
5
+
6
+ class Coding(Model):
7
+ """A representation of a coding from a terminology system."""
8
+
9
+ class Meta:
10
+ abstract = True
11
+
12
+ code = models.CharField(max_length=255, blank=True, default="")
13
+ display = models.CharField(max_length=1000)
14
+ system = models.CharField(max_length=255)
15
+ version = models.CharField(max_length=255, blank=True, default="")
16
+ user_selected = models.BooleanField(default=False)
17
+
18
+
19
+ __exports__ = ()
@@ -1,17 +1,15 @@
1
1
  from django.apps import apps
2
2
  from django.db import models
3
3
 
4
- from canvas_sdk.v1.data.base import IdentifiableModel
4
+ from canvas_sdk.v1.data.base import IdentifiableModel, TimestampedModel
5
5
 
6
6
 
7
- class Command(IdentifiableModel):
7
+ class Command(TimestampedModel, IdentifiableModel):
8
8
  """Command."""
9
9
 
10
10
  class Meta:
11
11
  db_table = "canvas_sdk_data_commands_command_001"
12
12
 
13
- created = models.DateTimeField(auto_now_add=True)
14
- modified = models.DateTimeField(auto_now=True)
15
13
  originator = models.ForeignKey(
16
14
  "v1.CanvasUser", on_delete=models.DO_NOTHING, null=True, related_name="commands_originated"
17
15
  )
@@ -141,6 +141,16 @@ class AddressUse(models.TextChoices):
141
141
  OLD = "old", "Old"
142
142
 
143
143
 
144
+ class AddressUseWithBilling(models.TextChoices):
145
+ """AddressUse, which also includes Billing."""
146
+
147
+ HOME = "home", "Home"
148
+ WORK = "work", "Work"
149
+ TEMP = "temp", "Temp"
150
+ OLD = "old", "Old"
151
+ BILLING = "billing", "Billing"
152
+
153
+
144
154
  class AddressType(models.TextChoices):
145
155
  """AddressType."""
146
156
 
@@ -1,12 +1,13 @@
1
1
  from django.db import models
2
2
  from django.db.models import TextChoices
3
3
 
4
+ from canvas_sdk.v1.data.base import IdentifiableModel
4
5
 
5
- class CompoundMedication(models.Model):
6
+
7
+ class CompoundMedication(IdentifiableModel):
6
8
  """CompoundMedication."""
7
9
 
8
10
  class Meta:
9
- managed = False
10
11
  db_table = "canvas_sdk_data_api_compoundmedication_001"
11
12
 
12
13
  class PotencyUnits(TextChoices):
@@ -50,8 +51,6 @@ class CompoundMedication(models.Model):
50
51
  SCHEDULE_IV = "IV", "Schedule IV"
51
52
  SCHEDULE_V = "V", "Schedule V"
52
53
 
53
- id = models.UUIDField()
54
- dbid = models.BigIntegerField(primary_key=True)
55
54
  active = models.BooleanField(default=True)
56
55
  formulation = models.CharField(max_length=105)
57
56
  potency_unit_code = models.CharField(max_length=20, choices=PotencyUnits.choices)
@@ -9,9 +9,9 @@ from canvas_sdk.v1.data.base import (
9
9
  CommittableQuerySetMixin,
10
10
  ForPatientQuerySetMixin,
11
11
  IdentifiableModel,
12
- Model,
13
12
  ValueSetLookupQuerySetMixin,
14
13
  )
14
+ from canvas_sdk.v1.data.coding import Coding
15
15
 
16
16
 
17
17
  class ClinicalStatus(TextChoices):
@@ -25,10 +25,10 @@ class ClinicalStatus(TextChoices):
25
25
 
26
26
 
27
27
  class ConditionQuerySet(
28
- BaseQuerySet,
29
- ValueSetLookupQuerySetMixin,
30
28
  CommittableQuerySetMixin,
31
29
  ForPatientQuerySetMixin,
30
+ ValueSetLookupQuerySetMixin,
31
+ BaseQuerySet,
32
32
  ):
33
33
  """ConditionQuerySet."""
34
34
 
@@ -64,17 +64,12 @@ class Condition(IdentifiableModel):
64
64
  surgical = models.BooleanField()
65
65
 
66
66
 
67
- class ConditionCoding(Model):
67
+ class ConditionCoding(Coding):
68
68
  """ConditionCoding."""
69
69
 
70
70
  class Meta:
71
71
  db_table = "canvas_sdk_data_api_conditioncoding_001"
72
72
 
73
- system = models.CharField(max_length=255)
74
- version = models.CharField(max_length=255)
75
- code = models.CharField(max_length=255)
76
- display = models.CharField(max_length=1000)
77
- user_selected = models.BooleanField()
78
73
  condition = models.ForeignKey(
79
74
  Condition, on_delete=models.DO_NOTHING, related_name="codings", null=True
80
75
  )