canvas 0.42.0__py3-none-any.whl → 0.44.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of canvas might be problematic. Click here for more details.

Files changed (47) hide show
  1. {canvas-0.42.0.dist-info → canvas-0.44.0.dist-info}/METADATA +1 -2
  2. {canvas-0.42.0.dist-info → canvas-0.44.0.dist-info}/RECORD +47 -33
  3. canvas_cli/apps/auth/storage.py +65 -0
  4. canvas_cli/apps/auth/utils.py +6 -42
  5. canvas_generated/messages/effects_pb2.py +2 -2
  6. canvas_generated/messages/effects_pb2.pyi +12 -0
  7. canvas_sdk/effects/note/appointment.py +135 -50
  8. canvas_sdk/effects/note/base.py +108 -10
  9. canvas_sdk/effects/note/note.py +81 -22
  10. canvas_sdk/effects/patient/__init__.py +10 -2
  11. canvas_sdk/effects/patient/base.py +20 -1
  12. canvas_sdk/effects/patient/create_patient_external_identifier.py +40 -0
  13. canvas_sdk/effects/protocol_card/__init__.py +4 -1
  14. canvas_sdk/effects/protocol_card/protocol_card.py +2 -0
  15. canvas_sdk/utils/http.py +46 -2
  16. canvas_sdk/v1/data/__init__.py +45 -0
  17. canvas_sdk/v1/data/allergy_intolerance.py +6 -2
  18. canvas_sdk/v1/data/assessment.py +7 -3
  19. canvas_sdk/v1/data/billing.py +1 -1
  20. canvas_sdk/v1/data/business_line.py +35 -0
  21. canvas_sdk/v1/data/claim.py +321 -0
  22. canvas_sdk/v1/data/claim_line_item.py +140 -0
  23. canvas_sdk/v1/data/command.py +12 -3
  24. canvas_sdk/v1/data/condition.py +7 -2
  25. canvas_sdk/v1/data/detected_issue.py +9 -3
  26. canvas_sdk/v1/data/device.py +9 -3
  27. canvas_sdk/v1/data/discount.py +21 -0
  28. canvas_sdk/v1/data/fields.py +37 -0
  29. canvas_sdk/v1/data/imaging.py +18 -6
  30. canvas_sdk/v1/data/invoice.py +62 -0
  31. canvas_sdk/v1/data/lab.py +36 -12
  32. canvas_sdk/v1/data/line_item_transaction.py +83 -0
  33. canvas_sdk/v1/data/medication.py +6 -2
  34. canvas_sdk/v1/data/observation.py +9 -3
  35. canvas_sdk/v1/data/organization.py +3 -1
  36. canvas_sdk/v1/data/patient.py +17 -1
  37. canvas_sdk/v1/data/patient_consent.py +92 -0
  38. canvas_sdk/v1/data/payment_collection.py +35 -0
  39. canvas_sdk/v1/data/payor_specific_charge.py +28 -0
  40. canvas_sdk/v1/data/posting.py +225 -0
  41. canvas_sdk/v1/data/protocol_override.py +6 -2
  42. canvas_sdk/v1/data/questionnaire.py +6 -2
  43. canvas_sdk/v1/data/user.py +2 -0
  44. canvas_sdk/v1/data/utils.py +10 -0
  45. protobufs/canvas_generated/messages/effects.proto +7 -0
  46. {canvas-0.42.0.dist-info → canvas-0.44.0.dist-info}/WHEEL +0 -0
  47. {canvas-0.42.0.dist-info → canvas-0.44.0.dist-info}/entry_points.txt +0 -0
@@ -1,3 +1,6 @@
1
1
  from canvas_sdk.effects.protocol_card.protocol_card import ProtocolCard, Recommendation
2
2
 
3
- __all__ = __exports__ = ("ProtocolCard", "Recommendation")
3
+ __all__ = __exports__ = (
4
+ "ProtocolCard",
5
+ "Recommendation",
6
+ )
@@ -55,6 +55,7 @@ class ProtocolCard(_BaseEffect):
55
55
  status: Status = Status.DUE
56
56
  feedback_enabled: bool = False
57
57
  due_in: int = -1
58
+ can_be_snoozed: bool = False
58
59
 
59
60
  @property
60
61
  def values(self) -> dict[str, Any]:
@@ -68,6 +69,7 @@ class ProtocolCard(_BaseEffect):
68
69
  "status": self.status.value,
69
70
  "feedback_enabled": self.feedback_enabled,
70
71
  "due_in": self.due_in,
72
+ "can_be_snoozed": self.can_be_snoozed,
71
73
  }
72
74
 
73
75
  @property
canvas_sdk/utils/http.py CHANGED
@@ -281,29 +281,73 @@ class OntologiesHttp(JsonOnlyHttp):
281
281
  """
282
282
 
283
283
  def __init__(self) -> None:
284
- super().__init__(base_url="https://ontologies.canvasmedical.com")
284
+ super().__init__(
285
+ base_url=os.getenv("ONTOLOGIES_ENDPOINT", "https://ontologies.canvasmedical.com")
286
+ )
285
287
 
286
288
  self._session.headers.update({"Authorization": os.getenv("PRE_SHARED_KEY", "")})
287
289
 
288
290
 
291
+ class PharmacyHttp:
292
+ """
293
+ An HTTP client for the pharmacy service.
294
+ """
295
+
296
+ def __init__(self) -> None:
297
+ self._http_client = JsonOnlyHttp(
298
+ base_url=os.getenv("PHARMACY_ENDPOINT", "https://pharmacy.canvasmedical.com")
299
+ )
300
+
301
+ self._http_client._session.headers.update(
302
+ {"Authorization": os.getenv("PRE_SHARED_KEY", "")}
303
+ )
304
+
305
+ def search_pharmacies(
306
+ self, search_term: str, latitude: str | None = None, longitude: str | None = None
307
+ ) -> list[dict]:
308
+ """Search for pharmacies by term and optional location."""
309
+ params = {"search": search_term}
310
+ if latitude and longitude:
311
+ params.update(
312
+ {
313
+ "latitude": latitude,
314
+ "longitude": longitude,
315
+ }
316
+ )
317
+
318
+ query_string = urllib.parse.urlencode(params)
319
+ response = self._http_client.get_json(f"/surescripts/pharmacy/?{query_string}")
320
+ response_json = response.json()
321
+ return response_json.get("results", []) if response_json else []
322
+
323
+ def get_pharmacy_by_ncpdp_id(self, ncpdp_id: str) -> dict[str, Any] | None:
324
+ """Lookup a pharmacy by its NCPDP ID."""
325
+ response = self._http_client.get_json(f"/surescripts/pharmacy/ncpdp_id/{ncpdp_id}/")
326
+ return response.json()
327
+
328
+
289
329
  class ScienceHttp(JsonOnlyHttp):
290
330
  """
291
331
  An HTTP client for the ontologies service.
292
332
  """
293
333
 
294
334
  def __init__(self) -> None:
295
- super().__init__(base_url="https://science.canvasmedical.com")
335
+ super().__init__(
336
+ base_url=os.getenv("SCIENCE_ENDPOINT", "https://science.canvasmedical.com")
337
+ )
296
338
 
297
339
  self._session.headers.update({"Authorization": os.getenv("PRE_SHARED_KEY", "")})
298
340
 
299
341
 
300
342
  ontologies_http = OntologiesHttp()
301
343
  science_http = ScienceHttp()
344
+ pharmacy_http = PharmacyHttp()
302
345
 
303
346
  __all__ = __exports__ = (
304
347
  "ThreadPoolExecutor",
305
348
  "Http",
306
349
  "ontologies_http",
350
+ "pharmacy_http",
307
351
  "science_http",
308
352
  "batch_get",
309
353
  "batch_post",
@@ -3,13 +3,18 @@ from .appointment import Appointment, AppointmentExternalIdentifier
3
3
  from .assessment import Assessment
4
4
  from .banner_alert import BannerAlert
5
5
  from .billing import BillingLineItem, BillingLineItemModifier
6
+ from .business_line import BusinessLine
6
7
  from .care_team import CareTeamMembership, CareTeamRole
8
+ from .claim import Claim, ClaimCoverage, ClaimPatient, ClaimQueue
9
+ from .claim_line_item import ClaimLineItem
7
10
  from .command import Command
8
11
  from .condition import Condition, ConditionCoding
9
12
  from .coverage import Coverage, Transactor, TransactorAddress, TransactorPhone
10
13
  from .detected_issue import DetectedIssue, DetectedIssueEvidence
11
14
  from .device import Device
15
+ from .discount import Discount
12
16
  from .imaging import ImagingOrder, ImagingReport, ImagingReview
17
+ from .invoice import Invoice
13
18
  from .lab import (
14
19
  LabOrder,
15
20
  LabOrderReason,
@@ -20,6 +25,11 @@ from .lab import (
20
25
  LabValue,
21
26
  LabValueCoding,
22
27
  )
28
+ from .line_item_transaction import (
29
+ LineItemTransfer,
30
+ NewLineItemAdjustment,
31
+ NewLineItemPayment,
32
+ )
23
33
  from .medication import Medication, MedicationCoding
24
34
  from .message import Message, MessageAttachment, MessageTransmission
25
35
  from .note import Note, NoteType
@@ -39,6 +49,20 @@ from .patient import (
39
49
  PatientMetadata,
40
50
  PatientSetting,
41
51
  )
52
+ from .patient_consent import (
53
+ PatientConsent,
54
+ PatientConsentCoding,
55
+ PatientConsentRejectionCoding,
56
+ )
57
+ from .payment_collection import PaymentCollection
58
+ from .payor_specific_charge import PayorSpecificCharge
59
+ from .posting import (
60
+ BasePosting,
61
+ BaseRemittanceAdvice,
62
+ BulkPatientPosting,
63
+ CoveragePosting,
64
+ PatientPosting,
65
+ )
42
66
  from .practicelocation import PracticeLocation, PracticeLocationSetting
43
67
  from .protocol_override import ProtocolOverride
44
68
  from .questionnaire import (
@@ -63,24 +87,36 @@ __all__ = __exports__ = (
63
87
  "AllergyIntoleranceCoding",
64
88
  "Assessment",
65
89
  "BannerAlert",
90
+ "BasePosting",
91
+ "BaseRemittanceAdvice",
66
92
  "BillingLineItem",
67
93
  "BillingLineItemModifier",
94
+ "BusinessLine",
95
+ "BulkPatientPosting",
68
96
  "CanvasUser",
69
97
  "CareTeamMembership",
70
98
  "CareTeamRole",
99
+ "Claim",
100
+ "ClaimCoverage",
101
+ "ClaimLineItem",
102
+ "ClaimPatient",
103
+ "ClaimQueue",
71
104
  "Command",
72
105
  "Condition",
73
106
  "ConditionCoding",
74
107
  "Coverage",
108
+ "CoveragePosting",
75
109
  "DetectedIssue",
76
110
  "DetectedIssueEvidence",
77
111
  "Device",
112
+ "Discount",
78
113
  "ImagingOrder",
79
114
  "ImagingReport",
80
115
  "ImagingReview",
81
116
  "Interview",
82
117
  "InterviewQuestionnaireMap",
83
118
  "InterviewQuestionResponse",
119
+ "Invoice",
84
120
  "LabOrder",
85
121
  "LabOrderReason",
86
122
  "LabOrderReasonCondition",
@@ -89,11 +125,14 @@ __all__ = __exports__ = (
89
125
  "LabTest",
90
126
  "LabValue",
91
127
  "LabValueCoding",
128
+ "LineItemTransfer",
92
129
  "Medication",
93
130
  "MedicationCoding",
94
131
  "Message",
95
132
  "MessageAttachment",
96
133
  "MessageTransmission",
134
+ "NewLineItemAdjustment",
135
+ "NewLineItemPayment",
97
136
  "Note",
98
137
  "NoteType",
99
138
  "Observation",
@@ -106,8 +145,14 @@ __all__ = __exports__ = (
106
145
  "PatientAddress",
107
146
  "PatientContactPoint",
108
147
  "PatientExternalIdentifier",
148
+ "PatientPosting",
109
149
  "PatientSetting",
110
150
  "PatientMetadata",
151
+ "PatientConsent",
152
+ "PatientConsentCoding",
153
+ "PatientConsentRejectionCoding",
154
+ "PayorSpecificCharge",
155
+ "PaymentCollection",
111
156
  "PracticeLocation",
112
157
  "PracticeLocationSetting",
113
158
  "ProtocolOverride",
@@ -37,8 +37,12 @@ class AllergyIntolerance(models.Model):
37
37
  created = models.DateTimeField()
38
38
  modified = models.DateTimeField()
39
39
  deleted = models.BooleanField()
40
- committer = models.ForeignKey("v1.CanvasUser", on_delete=models.DO_NOTHING, null=True)
41
- entered_in_error = models.ForeignKey("v1.CanvasUser", on_delete=models.DO_NOTHING, null=True)
40
+ committer = models.ForeignKey(
41
+ "v1.CanvasUser", on_delete=models.DO_NOTHING, null=True, related_name="+"
42
+ )
43
+ entered_in_error = models.ForeignKey(
44
+ "v1.CanvasUser", on_delete=models.DO_NOTHING, null=True, related_name="+"
45
+ )
42
46
  patient = models.ForeignKey(
43
47
  "v1.Patient",
44
48
  on_delete=models.DO_NOTHING,
@@ -20,10 +20,14 @@ class Assessment(models.Model):
20
20
  dbid = models.BigIntegerField(primary_key=True)
21
21
  created = models.DateTimeField()
22
22
  modified = models.DateTimeField()
23
- originator = models.ForeignKey("v1.CanvasUser", on_delete=models.DO_NOTHING)
24
- committer = models.ForeignKey("v1.CanvasUser", on_delete=models.DO_NOTHING, null=True)
23
+ originator = models.ForeignKey("v1.CanvasUser", on_delete=models.DO_NOTHING, related_name="+")
24
+ committer = models.ForeignKey(
25
+ "v1.CanvasUser", on_delete=models.DO_NOTHING, null=True, related_name="+"
26
+ )
25
27
  deleted = models.BooleanField()
26
- entered_in_error = models.ForeignKey("v1.CanvasUser", on_delete=models.DO_NOTHING, null=True)
28
+ entered_in_error = models.ForeignKey(
29
+ "v1.CanvasUser", on_delete=models.DO_NOTHING, null=True, related_name="+"
30
+ )
27
31
  patient = models.ForeignKey(
28
32
  "v1.Patient",
29
33
  on_delete=models.DO_NOTHING,
@@ -56,7 +56,7 @@ class BillingLineItem(models.Model):
56
56
  null=True,
57
57
  )
58
58
  cpt = models.CharField()
59
- charge = models.DecimalField()
59
+ charge = models.DecimalField(decimal_places=2, max_digits=8)
60
60
  description = models.CharField()
61
61
  units = models.IntegerField()
62
62
  command_type = models.CharField()
@@ -0,0 +1,35 @@
1
+ from django.db import models
2
+
3
+
4
+ class BusinessLineState(models.TextChoices):
5
+ """BusinessLineStatus."""
6
+
7
+ STATE_SUCCESS = "success", "Success"
8
+ STATE_PENDING = "pending", "Pending"
9
+ STATE_ERROR = "error", "Deleted"
10
+
11
+
12
+ class BusinessLine(models.Model):
13
+ """Business Line."""
14
+
15
+ class Meta:
16
+ managed = False
17
+ db_table = "canvas_sdk_data_api_businessline_001"
18
+
19
+ id = models.UUIDField()
20
+ dbid = models.BigIntegerField(primary_key=True)
21
+ name = models.CharField()
22
+ description = models.TextField()
23
+ area_code = models.CharField()
24
+ subdomain = models.CharField()
25
+ active = models.BooleanField()
26
+ state = models.CharField(max_length=20, choices=BusinessLineState)
27
+ organization = models.ForeignKey(
28
+ "v1.Organization", on_delete=models.DO_NOTHING, related_name="business_lines"
29
+ )
30
+
31
+
32
+ __exports__ = (
33
+ "BusinessLineState",
34
+ "BusinessLine",
35
+ )
@@ -0,0 +1,321 @@
1
+ from decimal import Decimal
2
+ from typing import TYPE_CHECKING, Self
3
+
4
+ from django.db import models
5
+
6
+ from canvas_sdk.v1.data.common import PersonSex
7
+ from canvas_sdk.v1.data.coverage import CoverageRelationshipCode, CoverageType
8
+ from canvas_sdk.v1.data.fields import ChoiceArrayField
9
+ from canvas_sdk.v1.data.utils import quantize
10
+
11
+ if TYPE_CHECKING:
12
+ from canvas_sdk.v1.data.claim_line_item import ClaimLineItemQuerySet
13
+
14
+
15
+ class InstallmentPlanStatus(models.TextChoices):
16
+ """InstallmentPlanStatus."""
17
+
18
+ ACTIVE = "active", "Active"
19
+ COMPLETED = "completed", "Completed"
20
+ CANCELLED = "cancelled", "Cancelled"
21
+
22
+
23
+ class InstallmentPlan(models.Model):
24
+ """InstallmentPlan."""
25
+
26
+ class Meta:
27
+ managed = False
28
+ db_table = "canvas_sdk_data_api_installmentplan_001"
29
+
30
+ creator = models.ForeignKey("v1.CanvasUser", on_delete=models.CASCADE)
31
+ patient = models.ForeignKey(
32
+ "v1.Patient", on_delete=models.CASCADE, related_name="installment_plans"
33
+ )
34
+ total_amount = models.DecimalField(max_digits=8, decimal_places=2)
35
+ status = models.CharField(choices=InstallmentPlanStatus.choices)
36
+ expected_payoff_date = models.DateField()
37
+ created_at = models.DateTimeField()
38
+ updated_at = models.DateTimeField()
39
+
40
+
41
+ class ClaimQueueColumns(models.TextChoices):
42
+ """ClaimQueueColumns."""
43
+
44
+ NOTE_TYPE = "NoteType", "Note type"
45
+ CLAIM_ID = "ClaimID", "Claim ID"
46
+ DOS = "DateOfService", "Date of service"
47
+ PATIENT = "Patient", "Patient"
48
+ ACTIVE_INSURANCE = "ActiveInsurance", "Active insurance"
49
+ INSURANCE_BALANCE = "InsuranceBalance", "Insurance balance"
50
+ PATIENT_BALANCE = "PatientBalance", "Patient balance"
51
+ DAYS_IN_QUEUE = "DaysInQueue", "Days in queue"
52
+ PROVIDER = "Provider", "Provider"
53
+ GUARANTOR = "Guarantor", "Guarantor"
54
+ LATEST_REMIT = "LatestRemit", "Latest remit"
55
+ LAST_INVOICED = "LastInvoiced", "Last invoiced"
56
+ SNOOZED_UNTIL = "SnoozedUntil", "Snoozed until"
57
+ LABELS = "Labels", "Labels"
58
+
59
+
60
+ class ClaimQueues(models.IntegerChoices):
61
+ """ClaimQueues."""
62
+
63
+ APPOINTMENT = 1, "Appointment"
64
+ NEEDS_CLINICIAN_REVIEW = 2, "NeedsClinicianReview"
65
+ NEEDS_CODING_REVIEW = 3, "NeedsCodingReview"
66
+ QUEUED_FOR_SUBMISSION = 4, "QueuedForSubmission"
67
+ FILED_AWAITING_RESPONSE = 5, "FiledAwaitingResponse"
68
+ REJECTED_NEEDS_REVIEW = 6, "RejectedNeedsReview"
69
+ ADJUDICATED_OPEN_BALANCE = 7, "AdjudicatedOpenBalance"
70
+ PATIENT_BALANCE = 8, "PatientBalance"
71
+ ZERO_BALANCE = 9, "ZeroBalance"
72
+ TRASH = 10, "Trash"
73
+
74
+
75
+ class ClaimQueue(models.Model):
76
+ """ClaimQueue."""
77
+
78
+ class Meta:
79
+ managed = False
80
+ db_table = "canvas_sdk_data_quality_and_revenue_queue_001"
81
+
82
+ dbid = models.BigIntegerField(primary_key=True)
83
+ queue_sort_ordering = models.IntegerField()
84
+ name = models.CharField()
85
+ display_name = models.CharField()
86
+ description = models.CharField()
87
+ show_in_revenue = models.BooleanField()
88
+ visible_columns = ChoiceArrayField(models.CharField(choices=ClaimQueueColumns.choices))
89
+
90
+ created = models.DateTimeField()
91
+ modified = models.DateTimeField()
92
+
93
+
94
+ class ClaimPayerOrder(models.TextChoices):
95
+ """ClaimPayerOrder."""
96
+
97
+ PRIMARY = "Primary", "Primary"
98
+ SECONDARY = "Secondary", "Secondary"
99
+ TERTIARY = "Tertiary", "Tertiary"
100
+ QUATERNARY = "Quaternary", "Quaternary"
101
+ QUINARY = "Quinary", "Quinary"
102
+
103
+
104
+ class ClaimTypeCode(models.TextChoices):
105
+ """ClaimTypeCode."""
106
+
107
+ WORKING_AGED = "12", "Working Aged (Age 65 or older)"
108
+ ESRD = "13", "End-Stage Renal Disease"
109
+ NO_FAULT = "14", "No-fault"
110
+ WORKERS_COMP = "15", "Workers Compensation"
111
+ BLACK_LUNG = "41", "Black Lung"
112
+ VA = "42", "Veterans Administration"
113
+ DISABLED = "43", "Disabled (Under Age 65)"
114
+ OTHER_LIABILITY = "47", "Other Liability Insurance is primary"
115
+ UNNECESSARY = "", "No Typecode necessary"
116
+
117
+
118
+ class ClaimCoverageQuerySet(models.QuerySet):
119
+ """ClaimCoverageQuerySet."""
120
+
121
+ def active(self) -> Self:
122
+ """Filter active claim coverages."""
123
+ return self.filter(active=True)
124
+
125
+
126
+ class ClaimCoverage(models.Model):
127
+ """A model that represents the link between a claim and a specific insurance coverage."""
128
+
129
+ class Meta:
130
+ managed = False
131
+ db_table = "canvas_sdk_data_quality_and_revenue_claimcoverage_001"
132
+
133
+ objects = ClaimCoverageQuerySet.as_manager()
134
+
135
+ dbid = models.BigIntegerField(primary_key=True)
136
+
137
+ claim = models.ForeignKey("Claim", on_delete=models.CASCADE, related_name="coverages")
138
+
139
+ coverage = models.ForeignKey(
140
+ "v1.Coverage", related_name="claim_coverages", on_delete=models.PROTECT
141
+ )
142
+
143
+ active = models.BooleanField()
144
+ payer_name = models.CharField()
145
+ payer_id = models.CharField()
146
+ payer_typecode = models.CharField()
147
+ payer_order = models.CharField(choices=ClaimPayerOrder.choices)
148
+ payer_addr1 = models.CharField()
149
+ payer_addr2 = models.CharField()
150
+ payer_city = models.CharField()
151
+ payer_state = models.CharField()
152
+ payer_zip = models.CharField()
153
+ payer_plan_type = models.CharField(choices=ClaimTypeCode.choices)
154
+ coverage_type = models.CharField(choices=CoverageType.choices)
155
+
156
+ subscriber_employer = models.CharField()
157
+ subscriber_group = models.CharField()
158
+ subscriber_number = models.CharField()
159
+ subscriber_plan = models.CharField()
160
+ subscriber_dob = models.CharField()
161
+ subscriber_first_name = models.CharField()
162
+ subscriber_last_name = models.CharField()
163
+ subscriber_middle_name = models.CharField()
164
+ subscriber_phone = models.CharField()
165
+ subscriber_sex = models.CharField(choices=PersonSex.choices)
166
+ subscriber_addr1 = models.CharField()
167
+ subscriber_addr2 = models.CharField()
168
+ subscriber_city = models.CharField()
169
+ subscriber_state = models.CharField()
170
+ subscriber_zip = models.CharField()
171
+ subscriber_country = models.CharField()
172
+ patient_relationship_to_subscriber = models.CharField(choices=CoverageRelationshipCode.choices)
173
+
174
+ pay_to_addr1 = models.CharField()
175
+ pay_to_addr2 = models.CharField()
176
+ pay_to_city = models.CharField()
177
+ pay_to_state = models.CharField()
178
+ pay_to_zip = models.CharField()
179
+
180
+ resubmission_code = models.CharField()
181
+ payer_icn = models.CharField()
182
+
183
+ created = models.DateTimeField()
184
+ modified = models.DateTimeField()
185
+
186
+
187
+ class ClaimPatient(models.Model):
188
+ """ClaimPatient."""
189
+
190
+ class Meta:
191
+ managed = False
192
+ db_table = "canvas_sdk_data_quality_and_revenue_claimpatient_001"
193
+
194
+ dbid = models.BigIntegerField(primary_key=True)
195
+ claim = models.OneToOneField("v1.Claim", on_delete=models.CASCADE, related_name="patient")
196
+ photo = models.CharField()
197
+ dob = models.CharField()
198
+ first_name = models.CharField()
199
+ last_name = models.CharField()
200
+ middle_name = models.CharField()
201
+ phone = models.CharField()
202
+ sex = models.CharField(choices=PersonSex.choices)
203
+ ssn = models.CharField()
204
+ addr1 = models.CharField()
205
+ addr2 = models.CharField()
206
+ city = models.CharField()
207
+ state = models.CharField()
208
+ zip = models.CharField()
209
+ country = models.CharField()
210
+
211
+ created = models.DateTimeField()
212
+ modified = models.DateTimeField()
213
+
214
+
215
+ class ClaimQueryset(models.QuerySet):
216
+ """ClaimQueryset."""
217
+
218
+ def active(self) -> Self:
219
+ """Active claims."""
220
+ return self.exclude(current_queue__queue_sort_ordering=ClaimQueues.TRASH)
221
+
222
+
223
+ class Claim(models.Model):
224
+ """Claim."""
225
+
226
+ class Meta:
227
+ managed = False
228
+ db_table = "canvas_sdk_data_quality_and_revenue_claim_001"
229
+
230
+ objects = ClaimQueryset.as_manager()
231
+
232
+ id = models.UUIDField()
233
+ dbid = models.BigIntegerField(primary_key=True)
234
+ note = models.ForeignKey("v1.Note", on_delete=models.PROTECT, related_name="claims", null=True)
235
+ installment_plan = models.ForeignKey(
236
+ InstallmentPlan, on_delete=models.SET_NULL, related_name="claims", null=True
237
+ )
238
+ current_queue = models.ForeignKey(ClaimQueue, on_delete=models.PROTECT, related_name="claims")
239
+ latest_invoice = models.ForeignKey("v1.Invoice", on_delete=models.SET_NULL, null=True)
240
+ current_coverage = models.ForeignKey(
241
+ ClaimCoverage, related_name="claims", on_delete=models.SET_NULL, null=True
242
+ )
243
+
244
+ accept_assign = models.BooleanField()
245
+ auto_accident = models.BooleanField()
246
+ auto_accident_state = models.CharField()
247
+ employment_related = models.BooleanField()
248
+ other_accident = models.BooleanField()
249
+ accident_code = models.CharField()
250
+ illness_date = models.DateField()
251
+ remote_batch_id = models.CharField()
252
+ remote_file_id = models.CharField()
253
+ prior_auth = models.CharField()
254
+
255
+ narrative = models.CharField()
256
+ account_number = models.CharField()
257
+ snoozed_until = models.DateField()
258
+
259
+ patient_balance = models.DecimalField(max_digits=8, decimal_places=2)
260
+ aggregate_coverage_balance = models.DecimalField(max_digits=8, decimal_places=2)
261
+ created = models.DateTimeField()
262
+ modified = models.DateTimeField()
263
+
264
+ @property
265
+ def total_charges(self) -> Decimal:
266
+ """Total charges for the claim."""
267
+ line_items = self.get_active_claim_line_items()
268
+ if line_items:
269
+ return quantize(sum(line_item.charge for line_item in line_items))
270
+ return Decimal("0.00")
271
+
272
+ @property
273
+ def total_paid(self) -> Decimal | int:
274
+ """Total paid amount for the claim."""
275
+ return sum(posting.paid_amount for posting in self.postings.active()) or Decimal("0.00")
276
+
277
+ @property
278
+ def total_adjusted(self) -> Decimal | int:
279
+ """Total adjusted amount for the claim."""
280
+ return sum(
281
+ posting.adjusted_and_transferred_amount for posting in self.postings.active()
282
+ ) or Decimal("0.00")
283
+
284
+ @property
285
+ def balance(self) -> Decimal:
286
+ """Balance for the claim."""
287
+ return self.aggregate_coverage_balance + self.patient_balance
288
+
289
+ @property
290
+ def total_patient_paid(self) -> Decimal | int:
291
+ """Total amount paid by the patient."""
292
+ return sum(posting.paid_amount for posting in self.patient.postings.active()) or Decimal(
293
+ "0.00"
294
+ )
295
+
296
+ @property
297
+ def total_payer_paid(self) -> Decimal | int:
298
+ """Total amount paid by the coverages."""
299
+ return sum(
300
+ posting.paid_amount
301
+ for coverage in self.coverages.active()
302
+ for posting in coverage.postings.active()
303
+ ) or Decimal("0.00")
304
+
305
+ def get_active_claim_line_items(self) -> "ClaimLineItemQuerySet":
306
+ """Return the active claim line items."""
307
+ return self.line_items.active().exclude_copay_and_unlinked()
308
+
309
+
310
+ __exports__ = (
311
+ "Claim",
312
+ "ClaimQueue",
313
+ "ClaimCoverage",
314
+ "ClaimPatient",
315
+ "ClaimPayerOrder",
316
+ "ClaimQueues",
317
+ "ClaimQueueColumns",
318
+ "ClaimTypeCode",
319
+ "InstallmentPlan",
320
+ "InstallmentPlanStatus",
321
+ )