""" Clinical Data — Observations, labs, PROMs, imaging, OAP measures. """ import uuid from django.db import models from access_core.constants import TRACK_CHOICES class ClinicalObservation(models.Model): OBSERVATION_TYPE_CHOICES = [ ("lab", "Lab"), ("vital_sign", "Vital Sign"), ("symptom", "Symptom"), ("imaging_finding", "Imaging Finding"), ("prom_score", "PROM Score"), ("other", "Other"), ] DATA_SOURCE_CHOICES = [ ("labcorp", "Labcorp"), ("quest", "Quest"), ("patient_upload", "Patient Upload"), ("device", "Device"), ("physician_entered", "Physician Entered"), ("curation", "Curation"), ] STATUS_CHOICES = [ ("imported", "Imported"), ("cleaning_pending", "Cleaning Pending"), ("curated_draft", "Curated Draft"), ("needs_clarification", "Needs Clarification"), ("qc_passed", "QC Passed"), ("clinician_review_required", "Clinician Review Required"), ("physician_review_required", "Physician Review Required"), ("approved", "Approved"), ("locked_for_reporting", "Locked for Reporting"), ("submitted_to_cms", "Submitted to CMS"), ("rejected", "Rejected"), ("superseded", "Superseded"), ] id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) beneficiary = models.ForeignKey( "identity.Beneficiary", on_delete=models.PROTECT, related_name="clinical_observations", ) care_period = models.ForeignKey( "monitoring.CarePeriod", on_delete=models.SET_NULL, null=True, blank=True, related_name="clinical_observations", ) observation_type = models.TextField(choices=OBSERVATION_TYPE_CHOICES) measure_name = models.TextField() loinc_code = models.ForeignKey( "LoincCode", on_delete=models.SET_NULL, null=True, blank=True ) value_text = models.TextField(null=True, blank=True) value_numeric = models.FloatField(null=True, blank=True) unit = models.TextField(null=True, blank=True) ucum_unit = models.TextField(null=True, blank=True) collection_date = models.DateField() data_source = models.TextField(choices=DATA_SOURCE_CHOICES) source_record = models.ForeignKey( "intake.RawIngestionRecord", on_delete=models.SET_NULL, null=True, blank=True ) source_document = models.ForeignKey( "curation.ClinicalDocument", on_delete=models.SET_NULL, null=True, blank=True ) collection_method = models.TextField(null=True, blank=True) entry_user = models.ForeignKey( "identity.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="entered_observations", ) review_user = models.ForeignKey( "identity.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="reviewed_observations", ) is_synthetic = models.BooleanField(default=True) status = models.TextField(choices=STATUS_CHOICES, default="imported") created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): return f"{self.beneficiary} - {self.measure_name} ({self.observation_type})" class Meta: app_label = "clinical" ordering = ["-collection_date"] class ClinicalObservationSource(models.Model): SOURCE_TYPE_CHOICES = [ ("lab_result", "Lab Result"), ("prom_score", "PROM Score"), ("imaging_finding", "Imaging Finding"), ("execution_log", "Execution Log"), ("status_log", "Status Log"), ("daily_checkin", "Daily Checkin"), ] id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) observation = models.ForeignKey( ClinicalObservation, on_delete=models.CASCADE, related_name="sources" ) source_type = models.TextField(choices=SOURCE_TYPE_CHOICES) source_record_id = models.UUIDField() created_at = models.DateTimeField(auto_now_add=True) class Meta: app_label = "clinical" class LabResult(models.Model): SOURCE_TYPE_CHOICES = [ ("pdf_upload", "PDF Upload"), ("structured_feed", "Structured Feed"), ("patient_upload", "Patient Upload"), ] id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) beneficiary = models.ForeignKey( "identity.Beneficiary", on_delete=models.PROTECT, related_name="lab_results" ) care_period = models.ForeignKey( "monitoring.CarePeriod", on_delete=models.SET_NULL, null=True, blank=True, related_name="lab_results", ) lab_order_date = models.DateField(null=True, blank=True) specimen_collection_date = models.DateField(null=True, blank=True) result_date = models.DateField(null=True, blank=True) ordering_physician = models.TextField(null=True, blank=True) lab_facility = models.TextField(null=True, blank=True) source_document = models.ForeignKey( "curation.ClinicalDocument", on_delete=models.SET_NULL, null=True, blank=True ) source_type = models.TextField(choices=SOURCE_TYPE_CHOICES) is_synthetic = models.BooleanField(default=True) created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return f"Lab for {self.beneficiary} ({self.lab_facility})" class Meta: app_label = "clinical" class LabResultItem(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) lab_result = models.ForeignKey( LabResult, on_delete=models.CASCADE, related_name="items" ) loinc_code = models.ForeignKey( "LoincCode", on_delete=models.SET_NULL, null=True, blank=True ) test_name = models.TextField() value = models.FloatField(null=True, blank=True) unit = models.TextField(null=True, blank=True) ucum_unit = models.TextField(null=True, blank=True) reference_range_low = models.FloatField(null=True, blank=True) reference_range_high = models.FloatField(null=True, blank=True) flags = models.TextField(null=True, blank=True) status = models.TextField(default="imported") entry_user = models.ForeignKey( "identity.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="entered_lab_items", ) review_user = models.ForeignKey( "identity.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="reviewed_lab_items", ) def __str__(self): return f"{self.test_name} = {self.value} {self.unit}" class Meta: app_label = "clinical" class PromInstrument(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) instrument_name = models.TextField() version = models.TextField() scoring_logic = models.JSONField() response_options = models.JSONField(null=True, blank=True) applicable_track = models.TextField(choices=TRACK_CHOICES) is_active = models.BooleanField(default=True) def __str__(self): return f"{self.instrument_name} v{self.version} ({self.applicable_track})" class Meta: app_label = "clinical" class PromResponse(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) beneficiary = models.ForeignKey( "identity.Beneficiary", on_delete=models.PROTECT, related_name="prom_responses" ) care_period = models.ForeignKey( "monitoring.CarePeriod", on_delete=models.SET_NULL, null=True, blank=True ) instrument = models.ForeignKey(PromInstrument, on_delete=models.PROTECT) body_site = models.TextField(null=True, blank=True) raw_item_responses = models.JSONField() completion_date = models.DateTimeField() device_metadata = models.JSONField(null=True, blank=True) is_synthetic = models.BooleanField(default=True) created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return f"PROM: {self.beneficiary} - {self.instrument} ({self.completion_date})" class Meta: app_label = "clinical" class PromScore(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) prom_response = models.ForeignKey( PromResponse, on_delete=models.CASCADE, related_name="scores" ) instrument = models.ForeignKey(PromInstrument, on_delete=models.PROTECT) score = models.FloatField() score_interpretation = models.TextField(null=True, blank=True) reporting_status = models.TextField(default="not_applicable") status = models.TextField(default="computed") review_user = models.ForeignKey( "identity.User", on_delete=models.SET_NULL, null=True, blank=True ) def __str__(self): return f"Score: {self.instrument} = {self.score}" class Meta: app_label = "clinical" class ImagingStudy(models.Model): IMAGING_TYPE_CHOICES = [ ("carotid_ultrasound", "Carotid Ultrasound"), ("fatty_liver_ultrasound", "Fatty Liver Ultrasound"), ("kidney_ultrasound", "Kidney Ultrasound"), ("thyroid_ultrasound", "Thyroid Ultrasound"), ("other", "Other"), ] STATUS_CHOICES = [ ("imported", "Imported"), ("curated_draft", "Curated Draft"), ("approved", "Approved"), ("rejected", "Rejected"), ] id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) beneficiary = models.ForeignKey( "identity.Beneficiary", on_delete=models.PROTECT, related_name="imaging_studies" ) care_period = models.ForeignKey( "monitoring.CarePeriod", on_delete=models.SET_NULL, null=True, blank=True, related_name="imaging_studies", ) imaging_type = models.TextField(choices=IMAGING_TYPE_CHOICES) facility = models.TextField(null=True, blank=True) study_date = models.DateField(null=True, blank=True) report_date = models.DateField(null=True, blank=True) radiologist = models.TextField(null=True, blank=True) source_document = models.ForeignKey( "curation.ClinicalDocument", on_delete=models.SET_NULL, null=True, blank=True ) physician_interpretation = models.TextField(null=True, blank=True) is_synthetic = models.BooleanField(default=True) status = models.TextField(choices=STATUS_CHOICES, default="imported") created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return f"Imaging: {self.beneficiary} - {self.imaging_type} ({self.study_date})" class Meta: app_label = "clinical" class CarotidUltrasoundFinding(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) imaging_study = models.ForeignKey( ImagingStudy, on_delete=models.CASCADE, related_name="carotid_findings" ) laterality = models.TextField( choices=[("left", "Left"), ("right", "Right"), ("bilateral", "Bilateral")] ) anatomic_segment = models.TextField(null=True, blank=True) plaque_location = models.TextField(null=True, blank=True) plaque_length_mm = models.FloatField(null=True, blank=True) plaque_thickness_mm = models.FloatField(null=True, blank=True) residual_lumen_diameter_mm = models.FloatField(null=True, blank=True) psv_cm_s = models.FloatField(null=True, blank=True) edv_cm_s = models.FloatField(null=True, blank=True) stenosis_classification = models.TextField(null=True, blank=True) plaque_morphology = models.TextField(null=True, blank=True) flow_direction = models.TextField(null=True, blank=True) measurement_method = models.TextField(null=True, blank=True) status = models.TextField(default="drafted") created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return f"Carotid US: {self.imaging_study} ({self.laterality})" class Meta: app_label = "clinical" class LiverUltrasoundFinding(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) imaging_study = models.ForeignKey( ImagingStudy, on_delete=models.CASCADE, related_name="liver_findings" ) steatosis_grade = models.TextField(null=True, blank=True) liver_echogenicity = models.TextField(null=True, blank=True) liver_size_cm = models.FloatField(null=True, blank=True) other_findings = models.TextField(null=True, blank=True) status = models.TextField(default="drafted") created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return f"Liver US: {self.imaging_study} ({self.steatosis_grade})" class Meta: app_label = "clinical" class ImagingStudyComparison(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) current_study = models.ForeignKey( ImagingStudy, on_delete=models.CASCADE, related_name="current_comparisons" ) baseline_study = models.ForeignKey( ImagingStudy, on_delete=models.SET_NULL, null=True, blank=True, related_name="baseline_comparisons", ) prior_study = models.ForeignKey( ImagingStudy, on_delete=models.SET_NULL, null=True, blank=True, related_name="prior_comparisons", ) finding_type = models.TextField() calculated_change = models.TextField(null=True, blank=True) trajectory = models.TextField(null=True, blank=True) physician_interpretation = models.TextField(null=True, blank=True) created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return f"Comparison: {self.current_study} - {self.finding_type}" class Meta: app_label = "clinical" class StructuralEvidence(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) beneficiary = models.ForeignKey( "identity.Beneficiary", on_delete=models.PROTECT, related_name="structural_evidence", ) care_period = models.ForeignKey("monitoring.CarePeriod", on_delete=models.PROTECT) evidence_type = models.TextField() evidence_summary = models.TextField() trajectory = models.TextField(null=True, blank=True) is_synthetic = models.BooleanField(default=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): return f"Structural evidence: {self.beneficiary} ({self.evidence_type})" class Meta: app_label = "clinical" class StructuralEvidenceSource(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) evidence = models.ForeignKey( StructuralEvidence, on_delete=models.CASCADE, related_name="sources" ) source_type = models.TextField() source_record_id = models.UUIDField() created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return f"Source: {self.source_type} for {self.evidence}" class Meta: app_label = "clinical" class OAPMeasureDefinition(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) measure_name = models.TextField() clinical_track = models.TextField(choices=TRACK_CHOICES) unit = models.TextField(null=True, blank=True) reporting_types = models.TextField(null=True, blank=True) loinc_code = models.ForeignKey( "LoincCode", on_delete=models.SET_NULL, null=True, blank=True ) ucum_unit = models.TextField(null=True, blank=True) fhir_code_mapping = models.TextField(null=True, blank=True) description = models.TextField(null=True, blank=True) is_active = models.BooleanField(default=True) def __str__(self): return f"{self.measure_name} ({self.clinical_track})" class Meta: app_label = "clinical" class OAPMeasureObservation(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) measure_definition = models.ForeignKey( OAPMeasureDefinition, on_delete=models.PROTECT ) beneficiary = models.ForeignKey("identity.Beneficiary", on_delete=models.PROTECT) care_period = models.ForeignKey("monitoring.CarePeriod", on_delete=models.PROTECT) canonical_observation = models.ForeignKey( ClinicalObservation, on_delete=models.PROTECT ) reporting_type = models.TextField() collection_date = models.DateField() submission_date = models.DateField(null=True, blank=True) validity_window_status = models.TextField() data_source = models.TextField() collection_method = models.TextField(null=True, blank=True) source_document = models.ForeignKey( "curation.ClinicalDocument", on_delete=models.SET_NULL, null=True, blank=True ) entry_user = models.ForeignKey( "identity.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="entered_oap_observations", ) review_user = models.ForeignKey( "identity.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="reviewed_oap_observations", ) physician_review_status = models.TextField() cms_submission_payload = models.JSONField(null=True, blank=True) cms_submission_response = models.JSONField(null=True, blank=True) status = models.TextField(default="draft") created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): return f"OAP: {self.measure_definition} for {self.beneficiary}" class Meta: app_label = "clinical" class OAPReportingWindow(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) care_period = models.ForeignKey( "monitoring.CarePeriod", on_delete=models.CASCADE, related_name="reporting_windows", ) reporting_type = models.TextField() window_start = models.DateField() window_end = models.DateField() is_active = models.BooleanField(default=True) created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return ( f"Window: {self.reporting_type} ({self.window_start} to {self.window_end})" ) class Meta: app_label = "clinical" class LoincCode(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) loinc_number = models.TextField(unique=True) component = models.TextField() property = models.TextField(null=True, blank=True) time_aspect = models.TextField(null=True, blank=True) system = models.TextField(null=True, blank=True) method = models.TextField(null=True, blank=True) class_name = models.TextField(null=True, blank=True) common_name = models.TextField(null=True, blank=True) is_active = models.BooleanField(default=True) created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return f"{self.loinc_number} - {self.component}" class Meta: app_label = "clinical" class UCUMUnit(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) ucum_code = models.TextField(unique=True) description = models.TextField() is_active = models.BooleanField(default=True) created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return self.ucum_code class Meta: app_label = "clinical" class FHIRConceptMapping(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) source_system = models.TextField() source_code = models.TextField() fhir_system = models.TextField() fhir_code = models.TextField() display = models.TextField(null=True, blank=True) mapping_status = models.TextField(default="pending_review") created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): return f"{self.source_system}:{self.source_code} -> {self.fhir_code}" class Meta: app_label = "clinical"