canvas 0.42.0__py3-none-any.whl → 0.43.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.43.0.dist-info}/METADATA +1 -1
- {canvas-0.42.0.dist-info → canvas-0.43.0.dist-info}/RECORD +37 -27
- canvas_generated/messages/effects_pb2.py +2 -2
- canvas_generated/messages/effects_pb2.pyi +2 -0
- 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 +29 -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/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/payment_collection.py +35 -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/utils.py +10 -0
- protobufs/canvas_generated/messages/effects.proto +1 -0
- {canvas-0.42.0.dist-info → canvas-0.43.0.dist-info}/WHEEL +0 -0
- {canvas-0.42.0.dist-info → canvas-0.43.0.dist-info}/entry_points.txt +0 -0
|
@@ -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
|
+
)
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
from decimal import Decimal
|
|
2
|
+
from typing import Any, Self
|
|
3
|
+
|
|
4
|
+
from django.db import models
|
|
5
|
+
from django.db.models import Q, Sum
|
|
6
|
+
from django.db.models.functions import Coalesce
|
|
7
|
+
|
|
8
|
+
from canvas_sdk.v1.data.note import PracticeLocationPOS
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ClaimLineItemStatus(models.TextChoices):
|
|
12
|
+
"""ClaimLineItemStatus."""
|
|
13
|
+
|
|
14
|
+
ACTIVE = "active", "Active"
|
|
15
|
+
REMOVED = "removed", "Removed"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class LineItemCodes(models.TextChoices):
|
|
19
|
+
"""LineItemCodes."""
|
|
20
|
+
|
|
21
|
+
COPAY = "COPAY"
|
|
22
|
+
UNLINKED = "UNLINKED"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class FamilyPlanningOptions(models.TextChoices):
|
|
26
|
+
"""FamilyPlanningOptions."""
|
|
27
|
+
|
|
28
|
+
YES = ("Y", "Yes")
|
|
29
|
+
NO = ("N", "No")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ClaimLineItemQuerySet(models.QuerySet):
|
|
33
|
+
"""ClaimLineItemQuerySet."""
|
|
34
|
+
|
|
35
|
+
def filter(self, *args: Any, **kwargs: Any) -> Self:
|
|
36
|
+
"""Apply standard filtering to the QuerySet."""
|
|
37
|
+
return super().filter(*args, **kwargs)
|
|
38
|
+
|
|
39
|
+
def exclude(self, *args: Any, **kwargs: Any) -> Self:
|
|
40
|
+
"""Apply standard exclusion to the QuerySet."""
|
|
41
|
+
return super().exclude(*args, **kwargs)
|
|
42
|
+
|
|
43
|
+
def apply_ordering(self) -> Self:
|
|
44
|
+
"""Apply ordering to the QuerySet."""
|
|
45
|
+
return self.order_by("from_date", "-proc_code")
|
|
46
|
+
|
|
47
|
+
def active(self) -> Self:
|
|
48
|
+
"""Return only active claim line items."""
|
|
49
|
+
return self.exclude(status=ClaimLineItemStatus.REMOVED).apply_ordering()
|
|
50
|
+
|
|
51
|
+
def exclude_removed_line_item_without_active_posting(self) -> Self:
|
|
52
|
+
"""Exclude out any line items that are deleted without any active postings."""
|
|
53
|
+
return (
|
|
54
|
+
self.filter(
|
|
55
|
+
Q(status=ClaimLineItemStatus.ACTIVE)
|
|
56
|
+
| Q(
|
|
57
|
+
newlineitempayments__isnull=False,
|
|
58
|
+
newlineitempayments__entered_in_error__isnull=True,
|
|
59
|
+
)
|
|
60
|
+
| Q(
|
|
61
|
+
newlineitemadjustments__isnull=False,
|
|
62
|
+
newlineitemadjustments__entered_in_error__isnull=True,
|
|
63
|
+
)
|
|
64
|
+
| Q(
|
|
65
|
+
lineitemtransfers__isnull=False,
|
|
66
|
+
lineitemtransfers__entered_in_error__isnull=True,
|
|
67
|
+
)
|
|
68
|
+
)
|
|
69
|
+
.exclude_removed_line_items_without_balances()
|
|
70
|
+
.apply_ordering()
|
|
71
|
+
.distinct()
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
def exclude_removed_line_items_without_balances(self) -> Self:
|
|
75
|
+
"""Exclude removed line items with zero balances."""
|
|
76
|
+
return (
|
|
77
|
+
self.annotate(
|
|
78
|
+
sum_of_all_payments=Coalesce(Sum("newlineitempayments__amount"), Decimal(0)),
|
|
79
|
+
sum_of_all_adjustments=Coalesce(Sum("newlineitemadjustments__amount"), Decimal(0)),
|
|
80
|
+
sum_of_all_transfers=Coalesce(Sum("lineitemtransfers__amount"), Decimal(0)),
|
|
81
|
+
)
|
|
82
|
+
.exclude(
|
|
83
|
+
Q(
|
|
84
|
+
status=ClaimLineItemStatus.REMOVED,
|
|
85
|
+
sum_of_all_payments=0,
|
|
86
|
+
sum_of_all_adjustments=0,
|
|
87
|
+
sum_of_all_transfers=0,
|
|
88
|
+
)
|
|
89
|
+
)
|
|
90
|
+
.distinct()
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
def exclude_copay_and_unlinked(self) -> Self:
|
|
94
|
+
"""Exclude both co-pay and unlinked line items."""
|
|
95
|
+
return self.exclude(
|
|
96
|
+
proc_code__in=[LineItemCodes.UNLINKED.value, LineItemCodes.COPAY.value]
|
|
97
|
+
).apply_ordering()
|
|
98
|
+
|
|
99
|
+
def exclude_copay(self) -> Self:
|
|
100
|
+
"""Exclude only co-pay line items."""
|
|
101
|
+
return self.exclude(proc_code=LineItemCodes.COPAY.value).apply_ordering()
|
|
102
|
+
|
|
103
|
+
def exclude_unlinked(self) -> Self:
|
|
104
|
+
"""Exclude only unlinked line items."""
|
|
105
|
+
return self.exclude(proc_code=LineItemCodes.UNLINKED.value).apply_ordering()
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class ClaimLineItem(models.Model):
|
|
109
|
+
"""ClaimLineItem."""
|
|
110
|
+
|
|
111
|
+
class Meta:
|
|
112
|
+
managed = False
|
|
113
|
+
db_table = "canvas_sdk_data_quality_and_revenue_claimlineitem_001"
|
|
114
|
+
|
|
115
|
+
objects = ClaimLineItemQuerySet.as_manager()
|
|
116
|
+
|
|
117
|
+
dbid = models.BigIntegerField(primary_key=True)
|
|
118
|
+
billing_line_item = models.ForeignKey("v1.BillingLineItem", on_delete=models.CASCADE, null=True)
|
|
119
|
+
claim = models.ForeignKey("v1.Claim", on_delete=models.CASCADE, related_name="line_items")
|
|
120
|
+
status = models.CharField(choices=ClaimLineItemStatus.choices)
|
|
121
|
+
charge = models.DecimalField(max_digits=8, decimal_places=2)
|
|
122
|
+
from_date = models.CharField()
|
|
123
|
+
thru_date = models.CharField()
|
|
124
|
+
narrative = models.CharField()
|
|
125
|
+
ndc_code = models.CharField()
|
|
126
|
+
ndc_dosage = models.CharField()
|
|
127
|
+
ndc_measure = models.CharField()
|
|
128
|
+
place_of_service = models.CharField(choices=PracticeLocationPOS.choices)
|
|
129
|
+
proc_code = models.CharField()
|
|
130
|
+
display = models.CharField()
|
|
131
|
+
remote_chg_id = models.CharField()
|
|
132
|
+
units = models.IntegerField()
|
|
133
|
+
epsdt = models.CharField()
|
|
134
|
+
family_planning = models.CharField(choices=FamilyPlanningOptions.choices)
|
|
135
|
+
|
|
136
|
+
created = models.DateTimeField()
|
|
137
|
+
modified = models.DateTimeField()
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
__exports__ = ("ClaimLineItem", "ClaimLineItemStatus", "LineItemCodes", "FamilyPlanningOptions")
|
canvas_sdk/v1/data/command.py
CHANGED
|
@@ -13,9 +13,18 @@ class Command(models.Model):
|
|
|
13
13
|
dbid = models.BigIntegerField(primary_key=True)
|
|
14
14
|
created = models.DateTimeField()
|
|
15
15
|
modified = models.DateTimeField()
|
|
16
|
-
originator = models.ForeignKey(
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
originator = models.ForeignKey(
|
|
17
|
+
"v1.CanvasUser", on_delete=models.DO_NOTHING, null=True, related_name="commands_originated"
|
|
18
|
+
)
|
|
19
|
+
committer = models.ForeignKey(
|
|
20
|
+
"v1.CanvasUser", on_delete=models.DO_NOTHING, null=True, related_name="commands_committed"
|
|
21
|
+
)
|
|
22
|
+
entered_in_error = models.ForeignKey(
|
|
23
|
+
"v1.CanvasUser",
|
|
24
|
+
on_delete=models.DO_NOTHING,
|
|
25
|
+
null=True,
|
|
26
|
+
related_name="commands_entered_in_error",
|
|
27
|
+
)
|
|
19
28
|
state = models.CharField()
|
|
20
29
|
patient = models.ForeignKey("v1.Patient", on_delete=models.DO_NOTHING, null=True)
|
|
21
30
|
note = models.ForeignKey("v1.Note", on_delete=models.DO_NOTHING, related_name="commands")
|
canvas_sdk/v1/data/condition.py
CHANGED
|
@@ -50,14 +50,19 @@ class Condition(models.Model):
|
|
|
50
50
|
id = models.UUIDField()
|
|
51
51
|
dbid = models.BigIntegerField(primary_key=True)
|
|
52
52
|
deleted = models.BooleanField()
|
|
53
|
-
entered_in_error = models.ForeignKey(
|
|
54
|
-
|
|
53
|
+
entered_in_error = models.ForeignKey(
|
|
54
|
+
"v1.CanvasUser", on_delete=models.DO_NOTHING, null=True, related_name="+"
|
|
55
|
+
)
|
|
56
|
+
committer = models.ForeignKey(
|
|
57
|
+
"v1.CanvasUser", on_delete=models.DO_NOTHING, null=True, related_name="+"
|
|
58
|
+
)
|
|
55
59
|
patient = models.ForeignKey(
|
|
56
60
|
"v1.Patient", on_delete=models.DO_NOTHING, related_name="conditions", null=True
|
|
57
61
|
)
|
|
58
62
|
onset_date = models.DateField()
|
|
59
63
|
resolution_date = models.DateField()
|
|
60
64
|
clinical_status = models.CharField(choices=ClinicalStatus.choices)
|
|
65
|
+
surgical = models.BooleanField()
|
|
61
66
|
|
|
62
67
|
|
|
63
68
|
class ConditionCoding(models.Model):
|
|
@@ -14,9 +14,15 @@ class DetectedIssue(models.Model):
|
|
|
14
14
|
modified = models.DateTimeField()
|
|
15
15
|
identified = models.DateTimeField()
|
|
16
16
|
deleted = models.BooleanField()
|
|
17
|
-
originator = models.ForeignKey(
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
originator = models.ForeignKey(
|
|
18
|
+
"v1.CanvasUser", on_delete=models.DO_NOTHING, null=True, related_name="+"
|
|
19
|
+
)
|
|
20
|
+
committer = models.ForeignKey(
|
|
21
|
+
"v1.CanvasUser", on_delete=models.DO_NOTHING, null=True, related_name="+"
|
|
22
|
+
)
|
|
23
|
+
entered_in_error = models.ForeignKey(
|
|
24
|
+
"v1.CanvasUser", on_delete=models.DO_NOTHING, null=True, related_name="+"
|
|
25
|
+
)
|
|
20
26
|
patient = models.ForeignKey(
|
|
21
27
|
"v1.Patient", on_delete=models.DO_NOTHING, related_name="detected_issues", null=True
|
|
22
28
|
)
|
canvas_sdk/v1/data/device.py
CHANGED
|
@@ -12,9 +12,15 @@ class Device(models.Model):
|
|
|
12
12
|
dbid = models.BigIntegerField(primary_key=True)
|
|
13
13
|
created = models.DateTimeField()
|
|
14
14
|
modified = models.DateTimeField()
|
|
15
|
-
originator = models.ForeignKey(
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
originator = models.ForeignKey(
|
|
16
|
+
"v1.CanvasUser", on_delete=models.DO_NOTHING, null=True, related_name="+"
|
|
17
|
+
)
|
|
18
|
+
committer = models.ForeignKey(
|
|
19
|
+
"v1.CanvasUser", on_delete=models.DO_NOTHING, null=True, related_name="+"
|
|
20
|
+
)
|
|
21
|
+
entered_in_error = models.ForeignKey(
|
|
22
|
+
"v1.CanvasUser", on_delete=models.DO_NOTHING, null=True, related_name="+"
|
|
23
|
+
)
|
|
18
24
|
patient = models.ForeignKey(
|
|
19
25
|
"v1.Patient", on_delete=models.DO_NOTHING, related_name="devices", null=True
|
|
20
26
|
)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from django.db import models
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Discount(models.Model):
|
|
5
|
+
"""Model to represent a discount applied to a claim or patient posting."""
|
|
6
|
+
|
|
7
|
+
class Meta:
|
|
8
|
+
managed = False
|
|
9
|
+
db_table = "canvas_sdk_data_quality_and_revenue_discount_001"
|
|
10
|
+
|
|
11
|
+
dbid = models.BigIntegerField(primary_key=True)
|
|
12
|
+
name = models.CharField()
|
|
13
|
+
adjustment_group = models.CharField()
|
|
14
|
+
adjustment_code = models.CharField()
|
|
15
|
+
discount = models.DecimalField(max_digits=8, decimal_places=2)
|
|
16
|
+
|
|
17
|
+
created = models.DateTimeField()
|
|
18
|
+
modified = models.DateTimeField()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
__exports__ = ("Discount",)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from typing import Any, cast
|
|
2
|
+
|
|
3
|
+
from django import forms
|
|
4
|
+
from django.contrib.postgres.fields import ArrayField
|
|
5
|
+
from django.forms import SelectMultiple
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ArraySelectMultiple(SelectMultiple):
|
|
9
|
+
"""ArraySelectMultiple."""
|
|
10
|
+
|
|
11
|
+
def value_omitted_from_data(self, data: Any, files: Any, name: str) -> bool:
|
|
12
|
+
"""Override to check if the value is omitted from data."""
|
|
13
|
+
return False
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ChoiceArrayField(ArrayField):
|
|
17
|
+
"""ChoiceArrayField."""
|
|
18
|
+
|
|
19
|
+
def formfield(
|
|
20
|
+
self,
|
|
21
|
+
form_class: type[forms.Field] | None = None,
|
|
22
|
+
choices_form_class: type[forms.ChoiceField] | None = None,
|
|
23
|
+
**kwargs: Any,
|
|
24
|
+
) -> forms.Field:
|
|
25
|
+
"""Override formfield to use a custom widget."""
|
|
26
|
+
defaults = {
|
|
27
|
+
"form_class": forms.TypedMultipleChoiceField,
|
|
28
|
+
"choices": self.base_field.choices,
|
|
29
|
+
"coerce": self.base_field.to_python,
|
|
30
|
+
"widget": ArraySelectMultiple,
|
|
31
|
+
}
|
|
32
|
+
defaults.update(kwargs)
|
|
33
|
+
|
|
34
|
+
return cast(forms.Field, super(ArrayField, self).formfield(**defaults)) # type: ignore[arg-type]
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
__exports__ = ()
|
canvas_sdk/v1/data/imaging.py
CHANGED
|
@@ -19,10 +19,16 @@ class ImagingOrder(models.Model):
|
|
|
19
19
|
dbid = models.BigIntegerField(primary_key=True)
|
|
20
20
|
created = models.DateTimeField()
|
|
21
21
|
modified = models.DateTimeField()
|
|
22
|
-
originator = models.ForeignKey(
|
|
22
|
+
originator = models.ForeignKey(
|
|
23
|
+
"v1.CanvasUser", on_delete=models.DO_NOTHING, null=True, related_name="+"
|
|
24
|
+
)
|
|
23
25
|
deleted = models.BooleanField()
|
|
24
|
-
committer = models.ForeignKey(
|
|
25
|
-
|
|
26
|
+
committer = models.ForeignKey(
|
|
27
|
+
"v1.CanvasUser", on_delete=models.DO_NOTHING, null=True, related_name="+"
|
|
28
|
+
)
|
|
29
|
+
entered_in_error = models.ForeignKey(
|
|
30
|
+
"v1.CanvasUser", on_delete=models.DO_NOTHING, related_name="+"
|
|
31
|
+
)
|
|
26
32
|
patient = models.ForeignKey(
|
|
27
33
|
"v1.Patient", on_delete=models.DO_NOTHING, related_name="imaging_orders", null=True
|
|
28
34
|
)
|
|
@@ -52,10 +58,16 @@ class ImagingReview(models.Model):
|
|
|
52
58
|
dbid = models.BigIntegerField(primary_key=True)
|
|
53
59
|
created = models.DateTimeField()
|
|
54
60
|
modified = models.DateTimeField()
|
|
55
|
-
originator = models.ForeignKey(
|
|
61
|
+
originator = models.ForeignKey(
|
|
62
|
+
"v1.CanvasUser", on_delete=models.DO_NOTHING, null=True, related_name="+"
|
|
63
|
+
)
|
|
56
64
|
deleted = models.BooleanField()
|
|
57
|
-
committer = models.ForeignKey(
|
|
58
|
-
|
|
65
|
+
committer = models.ForeignKey(
|
|
66
|
+
"v1.CanvasUser", on_delete=models.DO_NOTHING, null=True, related_name="+"
|
|
67
|
+
)
|
|
68
|
+
entered_in_error = models.ForeignKey(
|
|
69
|
+
"v1.CanvasUser", on_delete=models.DO_NOTHING, null=True, related_name="+"
|
|
70
|
+
)
|
|
59
71
|
patient_communication_method = models.CharField(choices=ReviewPatientCommunicationMethod)
|
|
60
72
|
# TODO - uncomment when Note model is complete
|
|
61
73
|
# note = models.ForeignKey('v1.Note', on_delete=models.DO_NOTHING, related_name="imaging_reviews", null=True)
|