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.
- {canvas-0.42.0.dist-info → canvas-0.44.0.dist-info}/METADATA +1 -2
- {canvas-0.42.0.dist-info → canvas-0.44.0.dist-info}/RECORD +47 -33
- canvas_cli/apps/auth/storage.py +65 -0
- canvas_cli/apps/auth/utils.py +6 -42
- canvas_generated/messages/effects_pb2.py +2 -2
- canvas_generated/messages/effects_pb2.pyi +12 -0
- canvas_sdk/effects/note/appointment.py +135 -50
- canvas_sdk/effects/note/base.py +108 -10
- canvas_sdk/effects/note/note.py +81 -22
- canvas_sdk/effects/patient/__init__.py +10 -2
- canvas_sdk/effects/patient/base.py +20 -1
- canvas_sdk/effects/patient/create_patient_external_identifier.py +40 -0
- canvas_sdk/effects/protocol_card/__init__.py +4 -1
- canvas_sdk/effects/protocol_card/protocol_card.py +2 -0
- canvas_sdk/utils/http.py +46 -2
- canvas_sdk/v1/data/__init__.py +45 -0
- canvas_sdk/v1/data/allergy_intolerance.py +6 -2
- canvas_sdk/v1/data/assessment.py +7 -3
- canvas_sdk/v1/data/billing.py +1 -1
- canvas_sdk/v1/data/business_line.py +35 -0
- canvas_sdk/v1/data/claim.py +321 -0
- canvas_sdk/v1/data/claim_line_item.py +140 -0
- canvas_sdk/v1/data/command.py +12 -3
- canvas_sdk/v1/data/condition.py +7 -2
- canvas_sdk/v1/data/detected_issue.py +9 -3
- canvas_sdk/v1/data/device.py +9 -3
- canvas_sdk/v1/data/discount.py +21 -0
- canvas_sdk/v1/data/fields.py +37 -0
- canvas_sdk/v1/data/imaging.py +18 -6
- canvas_sdk/v1/data/invoice.py +62 -0
- canvas_sdk/v1/data/lab.py +36 -12
- canvas_sdk/v1/data/line_item_transaction.py +83 -0
- canvas_sdk/v1/data/medication.py +6 -2
- canvas_sdk/v1/data/observation.py +9 -3
- canvas_sdk/v1/data/organization.py +3 -1
- canvas_sdk/v1/data/patient.py +17 -1
- canvas_sdk/v1/data/patient_consent.py +92 -0
- canvas_sdk/v1/data/payment_collection.py +35 -0
- canvas_sdk/v1/data/payor_specific_charge.py +28 -0
- canvas_sdk/v1/data/posting.py +225 -0
- canvas_sdk/v1/data/protocol_override.py +6 -2
- canvas_sdk/v1/data/questionnaire.py +6 -2
- canvas_sdk/v1/data/user.py +2 -0
- canvas_sdk/v1/data/utils.py +10 -0
- protobufs/canvas_generated/messages/effects.proto +7 -0
- {canvas-0.42.0.dist-info → canvas-0.44.0.dist-info}/WHEEL +0 -0
- {canvas-0.42.0.dist-info → canvas-0.44.0.dist-info}/entry_points.txt +0 -0
|
@@ -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__(
|
|
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__(
|
|
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",
|
canvas_sdk/v1/data/__init__.py
CHANGED
|
@@ -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(
|
|
41
|
-
|
|
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,
|
canvas_sdk/v1/data/assessment.py
CHANGED
|
@@ -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(
|
|
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(
|
|
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,
|
canvas_sdk/v1/data/billing.py
CHANGED
|
@@ -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
|
+
)
|