Skip to content

Commit

Permalink
staff and analysis setup
Browse files Browse the repository at this point in the history
  • Loading branch information
nicokant committed Dec 2, 2024
1 parent a939727 commit ac9f21b
Show file tree
Hide file tree
Showing 19 changed files with 726 additions and 5 deletions.
1 change: 1 addition & 0 deletions src/config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@
"apps.users",
"apps.core",
"genlab_bestilling",
"genlab_bestilling.staff",
"theme",
"frontend",
"nina",
Expand Down
1 change: 1 addition & 0 deletions src/config/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def get_redirect_url(self, *args: Any, **kwargs: Any) -> str | None:
path("api/", include("config.routers")),
path("accounts/", include("allauth.urls")),
path("", include("genlab_bestilling.urls")),
path("staff/", include("genlab_bestilling.staff.urls", namespace="staff")),
]


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# Generated by Django 5.1.1 on 2024-12-02 08:36

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
(
"genlab_bestilling",
"0006_genrequest_created_at_genrequest_last_modified_at_and_more",
),
]

operations = [
migrations.CreateModel(
name="Analysis",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField()),
("created_at", models.DateTimeField(auto_now_add=True)),
("last_modified_at", models.DateTimeField(auto_now=True)),
("analysis_date", models.DateTimeField(blank=True, null=True)),
("result_file", models.FileField(blank=True, null=True, upload_to="")),
("extra", models.JSONField(blank=True, null=True)),
],
),
migrations.CreateModel(
name="ExtractionPlate",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField()),
("created_at", models.DateTimeField(auto_now_add=True)),
("last_modified_at", models.DateTimeField(auto_now=True)),
],
),
migrations.CreateModel(
name="ExtractPlatePosition",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("position", models.IntegerField()),
],
),
migrations.AddField(
model_name="sample",
name="desired_extractions",
field=models.IntegerField(default=1),
),
migrations.AddField(
model_name="sample",
name="genlab_id",
field=models.CharField(blank=True, null=True),
),
migrations.AddField(
model_name="sample",
name="parent",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.PROTECT,
to="genlab_bestilling.sample",
),
),
migrations.AddField(
model_name="sample",
name="replica_number",
field=models.IntegerField(blank=True, null=True),
),
migrations.AddField(
model_name="sample",
name="running_number",
field=models.IntegerField(blank=True, null=True),
),
migrations.AddField(
model_name="species",
name="code",
field=models.CharField(blank=True, null=True),
),
migrations.AddConstraint(
model_name="species",
constraint=models.UniqueConstraint(
fields=("code",), name="unique species code"
),
),
migrations.AddField(
model_name="analysis",
name="marker",
field=models.ForeignKey(
on_delete=django.db.models.deletion.DO_NOTHING,
to="genlab_bestilling.marker",
),
),
migrations.AddField(
model_name="analysis",
name="samples",
field=models.ManyToManyField(blank=True, to="genlab_bestilling.sample"),
),
migrations.AddField(
model_name="sample",
name="extractions",
field=models.ManyToManyField(
blank=True, to="genlab_bestilling.extractionplate"
),
),
migrations.AddField(
model_name="extractplateposition",
name="plate",
field=models.ForeignKey(
on_delete=django.db.models.deletion.DO_NOTHING,
related_name="sample_positions",
to="genlab_bestilling.extractionplate",
),
),
migrations.AddField(
model_name="extractplateposition",
name="sample",
field=models.ForeignKey(
on_delete=django.db.models.deletion.PROTECT,
related_name="plate_positions",
to="genlab_bestilling.sample",
),
),
]
30 changes: 30 additions & 0 deletions src/genlab_bestilling/migrations/0008_alter_order_status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Generated by Django 5.1.1 on 2024-12-02 09:44

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
(
"genlab_bestilling",
"0007_analysis_extractionplate_extractplateposition_and_more",
),
]

operations = [
migrations.AlterField(
model_name="order",
name="status",
field=models.CharField(
choices=[
("draft", "Draft"),
("confirmed", "Confirmed"),
("processing", "Processing"),
("completed", "Completed"),
("checked", "Checked"),
("extracted", "Extracted"),
],
default="draft",
),
),
]
70 changes: 65 additions & 5 deletions src/genlab_bestilling/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,22 @@ def __str__(self) -> str:


class Species(models.Model):
# TODO: use IDs from Artsdatabanken?
name = models.CharField(max_length=255)
area = models.ForeignKey("Area", on_delete=models.CASCADE)
markers = models.ManyToManyField("Marker")
location_type = models.ForeignKey(
"LocationType", null=True, blank=True, on_delete=models.CASCADE
)
code = models.CharField(null=True, blank=True)

def __str__(self) -> str:
return self.name

class Meta:
verbose_name_plural = "Species"
constraints = [
models.UniqueConstraint(name="unique species code", fields=["code"])
]


# TODO: better understand "other" case. should the user be able to insert new orws?
Expand Down Expand Up @@ -145,6 +148,9 @@ class OrderStatus(models.TextChoices):
PROCESSING = "processing", _("Processing")
COMPLETED = "completed", _("Completed")

CHECKED = "checked", _("Checked")
EXTRACTED = "extracted", _("Extracted")

name = models.CharField(null=True, blank=True)
genrequest = models.ForeignKey(
"Genrequest", on_delete=models.CASCADE, related_name="orders"
Expand Down Expand Up @@ -175,6 +181,18 @@ def clone(self):
self.species.add(*species)
self.sample_types.add(*sample_types)

def order_manually_checked(self):
self.status = Order.OrderStatus.CHECKED
self.save()

def to_draft(self):
self.status = Order.OrderStatus.DRAFT
self.confirmed_at = None
self.save()

def get_type(self):
return "order"

def __str__(self):
return f"#ORD_{self.id}"

Expand Down Expand Up @@ -216,6 +234,9 @@ def confirm_order(self):
raise Order.CannotConfirm(_("No equipments found"))
return super().confirm_order()

def get_type(self):
return "equipment"


class AnalysisOrder(Order):
needs_guid = models.BooleanField(default=False) # TODO: default?
Expand All @@ -232,6 +253,9 @@ def get_absolute_url(self):
kwargs={"pk": self.pk, "genrequest_id": self.genrequest_id},
)

def get_type(self):
return "analysis"

def clone(self):
markers = self.markers.all()
super().clone()
Expand Down Expand Up @@ -276,10 +300,17 @@ class Sample(models.Model):
)
volume = models.FloatField(null=True, blank=True)

extractions = models.ManyToManyField("ExtractionPlate", blank=True)
desired_extractions = models.IntegerField(default=1)
genlab_id = models.CharField(null=True, blank=True)
parent = models.ForeignKey("self", on_delete=models.PROTECT, null=True, blank=True)
running_number = models.IntegerField(blank=True, null=True)
replica_number = models.IntegerField(blank=True, null=True)

objects = managers.SampleQuerySet.as_manager()

def __str__(self) -> str:
return f"#SMP_{self.id}"
return self.genlab_id or f"#SMP_{self.id}"

@property
def has_error(self):
Expand Down Expand Up @@ -308,9 +339,6 @@ def has_error(self):
else:
return False

# plate
# coordinates on plate


# class Analysis(models.Model):
# type =
Expand All @@ -320,3 +348,35 @@ def has_error(self):
# result
# status
# assignee (one or plus?)


# Some extracts can be placed in multiple wells
class ExtractPlatePosition(models.Model):
plate = models.ForeignKey(
"ExtractionPlate", on_delete=models.DO_NOTHING, related_name="sample_positions"
)
sample = models.ForeignKey(
"Sample", on_delete=models.PROTECT, related_name="plate_positions"
)
position = models.IntegerField()

# TODO: unique position per plate


class ExtractionPlate(models.Model):
name = models.CharField()
created_at = models.DateTimeField(auto_now_add=True)
last_modified_at = models.DateTimeField(auto_now=True)
# freezer
# shelf


class Analysis(models.Model):
name = models.CharField()
created_at = models.DateTimeField(auto_now_add=True)
last_modified_at = models.DateTimeField(auto_now=True)
analysis_date = models.DateTimeField(null=True, blank=True)
marker = models.ForeignKey("Marker", on_delete=models.DO_NOTHING)
result_file = models.FileField(null=True, blank=True)
samples = models.ManyToManyField("Sample", blank=True)
extra = models.JSONField(null=True, blank=True)
Empty file.
15 changes: 15 additions & 0 deletions src/genlab_bestilling/staff/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from typing import Self

from django.apps import AppConfig as DjangoAppConfig
from django.utils.translation import gettext_lazy as _


class AppConfig(DjangoAppConfig):
name = "genlab_bestilling.staff"
verbose_name = _("GenLab staff")

def ready(self: Self) -> None:
try:
import genlab_bestilling.signals # noqa: F401
except ImportError:
pass
32 changes: 32 additions & 0 deletions src/genlab_bestilling/staff/filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import django_filters as filters

from ..models import AnalysisOrder, Sample


class AnalysisOrderFilter(filters.FilterSet):
class Meta:
model = AnalysisOrder
fields = [
"id",
"status",
"genrequest",
"genrequest__project",
]


class SampleFilter(filters.FilterSet):
class Meta:
model = Sample
fields = [
"order",
"guid",
"name",
"genlab_id",
"species",
"type",
"year",
"location",
"pop_id",
"type",
"desired_extractions",
]
Empty file.
Loading

0 comments on commit ac9f21b

Please sign in to comment.