Coverage for claims\models.py: 100%
40 statements
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-14 18:28 -0400
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-14 18:28 -0400
1from decimal import Decimal
3from django.contrib.auth.models import User
4from django.db import models
5from django.utils import timezone
8class Claim(models.Model):
9 """
10 Represents a single insurance claim.
11 """
13 class ClaimStatus(models.TextChoices):
14 """Defines the possible statuses for a claim."""
16 PAID = "PAID", "Paid"
17 DENIED = "DENIED", "Denied"
18 UNDER_REVIEW = "UNDER REVIEW", "Under Review"
20 id = models.IntegerField(primary_key=True, editable=False)
21 patient_name = models.CharField(
22 max_length=255, db_index=True, help_text="Full name of the patient."
23 )
24 billed_amount = models.DecimalField(
25 max_digits=10,
26 decimal_places=2,
27 help_text="The amount originally billed to the insurer.",
28 )
29 paid_amount = models.DecimalField(
30 max_digits=10, decimal_places=2, help_text="The amount paid by the insurer."
31 )
32 status = models.CharField(
33 max_length=20,
34 choices=ClaimStatus.choices,
35 db_index=True,
36 help_text="The current processing status of the claim.",
37 )
38 insurer_name = models.CharField(
39 max_length=255, db_index=True, help_text="The name of the insurance company."
40 )
41 discharge_date = models.DateField()
42 is_flagged = models.BooleanField(
43 default=False, help_text="Mark this claim for special review or follow-up."
44 )
46 # Auditing fields for tracking who flagged a claim and when.
47 flagged_by = models.ForeignKey(
48 User,
49 on_delete=models.SET_NULL,
50 null=True,
51 blank=True,
52 related_name="flagged_claims",
53 help_text="The user who flagged this claim.",
54 )
55 flagged_at = models.DateTimeField(
56 null=True, blank=True, help_text="The timestamp when the claim was flagged."
57 )
59 # Timestamps for record creation and updates.
60 created_at = models.DateTimeField(auto_now_add=True)
61 updated_at = models.DateTimeField(auto_now=True)
63 def __str__(self) -> str:
64 """String representation of the Claim model."""
65 return f"Claim {self.id} for {self.patient_name}"
67 @property
68 def underpayment(self) -> Decimal:
69 """
70 Calculates the difference between the billed and paid amounts and get the underpayment value.
71 """
72 return self.billed_amount - self.paid_amount
75class ClaimDetail(models.Model):
76 """
77 Provides specific, detailed information related to a single claim,
78 such as medical codes or denial reasons.
79 """
81 # A OneToOneField ensures that a claim can only have one detail record.
82 claim = models.OneToOneField(
83 Claim, on_delete=models.CASCADE, related_name="details"
84 )
85 cpt_codes = models.CharField(
86 max_length=255,
87 help_text="Comma-separated CPT (Current Procedural Terminology) codes.",
88 )
89 denial_reason = models.TextField(
90 blank=True,
91 null=True,
92 help_text="The reason provided by the insurer for denying the claim.",
93 )
95 def __str__(self) -> str:
96 """String representation of the ClaimDetail model."""
97 return f"Details for Claim {self.claim.id}"
100class Note(models.Model):
101 """
102 Stores user-generated annotations or notes for a specific claim.
103 """
105 claim = models.ForeignKey(Claim, on_delete=models.CASCADE, related_name="notes")
106 note = models.TextField(help_text="The content of the note.")
107 created_at = models.DateTimeField(default=timezone.now)
108 user = models.ForeignKey(
109 User,
110 on_delete=models.SET_NULL,
111 null=True,
112 help_text="The user who created this note.",
113 )
115 def __str__(self) -> str:
116 """
117 Provides a truncated preview of the note for display in the admin
118 or other contexts.
119 """
120 note_preview: str = (
121 (self.note[:75] + "...") if len(self.note) > 75 else self.note
122 )
123 return f"Note on {self.claim.id} at {self.created_at.strftime('%Y-%m-%d')}: {note_preview}"