diff --git a/atlas/forms.py b/atlas/forms.py index e516468e..830af729 100755 --- a/atlas/forms.py +++ b/atlas/forms.py @@ -617,6 +617,7 @@ class CaseForm(ModelForm): "presentation", "discussion", "report", + "procedures", "condition", "pathological_process", "open_access", @@ -649,6 +650,7 @@ class CaseForm(ModelForm): "presentation", "discussion", "condition", + "procedures", "pathological_process", "report", "open_access", @@ -677,6 +679,9 @@ class CaseForm(ModelForm): "subspecialty": CheckboxSelectMultiple(), "pathological_process": CheckboxSelectMultiple(), "previous_case": CaseSelect(), + "procedures": autocomplete.ModelSelect2Multiple( + url="atlas:procedure-autocomplete" + ), } def clean_cimar_uuid(self): diff --git a/atlas/migrations/0093_procedure_case_procedures.py b/atlas/migrations/0093_procedure_case_procedures.py new file mode 100644 index 00000000..ffd57946 --- /dev/null +++ b/atlas/migrations/0093_procedure_case_procedures.py @@ -0,0 +1,30 @@ +# Generated by Django 6.0.1 on 2026-02-16 14:01 + +import atlas.models +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('atlas', '0092_normalcase_author'), + ] + + operations = [ + migrations.CreateModel( + name='Procedure', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255, unique=True)), + ('canonical', models.ForeignKey(blank=True, help_text='If set, this Procedure is an alias and points to the canonical Procedure.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='aliases', to='atlas.procedure')), + ('subspecialty', models.ManyToManyField(blank=True, to='atlas.subspecialty')), + ], + bases=(atlas.models.SynMixin, models.Model), + ), + migrations.AddField( + model_name='case', + name='procedures', + field=models.ManyToManyField(blank=True, help_text='Procedure(s) or operations the patient has undergone.', to='atlas.procedure'), + ), + ] diff --git a/atlas/models.py b/atlas/models.py index e5e129ab..a7fda4ce 100644 --- a/atlas/models.py +++ b/atlas/models.py @@ -396,6 +396,35 @@ class PathologicalProcess(models.Model): return format_html("{}", self.get_absolute_url(), self.name) +class Procedure(SynMixin, models.Model): + """A procedure or operation performed on the patient (attachable to Cases). + + This mirrors the lightweight structure used by `Presentation` / `PathologicalProcess`. + """ + name = models.CharField(max_length=255, unique=True) + + # Optional canonical/alias pointer for future synonym handling + canonical = models.ForeignKey( + "self", + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name="aliases", + help_text="If set, this Procedure is an alias and points to the canonical Procedure.", + ) + + subspecialty = models.ManyToManyField("subspecialty", blank=True) + + def __str__(self) -> str: + return self.name + + def get_absolute_url(self): + return reverse("atlas:procedure_detail", kwargs={"pk": self.pk}) + + def get_link(self): + return format_html("{}", self.get_absolute_url(), self.name) + + class Differential(models.Model): condition = models.ForeignKey(Condition, on_delete=models.CASCADE) case = models.ForeignKey( @@ -484,6 +513,13 @@ class Case(models.Model, AuthorMixin, QuestionMixin): help_text="The presentation(s) the case is associated with.", ) + # Procedures performed on the patient (e.g. operations, interventions) + procedures = models.ManyToManyField( + "Procedure", + blank=True, + help_text="Procedure(s) or operations the patient has undergone.", + ) + pathological_process = models.ManyToManyField(PathologicalProcess, blank=True) differential = models.ManyToManyField( @@ -830,6 +866,7 @@ class NormalCase(models.Model, AuthorMixin): notes = models.TextField(null=True, blank=True) + class Meta: ordering = ["-added_date"] diff --git a/atlas/templates/atlas/case_display_block.html b/atlas/templates/atlas/case_display_block.html index c543d2a9..7e844ab4 100755 --- a/atlas/templates/atlas/case_display_block.html +++ b/atlas/templates/atlas/case_display_block.html @@ -302,6 +302,18 @@
Cases with this procedure:
+