Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/genlab_bestilling/libs/genlabid.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,11 @@ def get_current_sequences(order_id: int | str) -> Any:
return sequences


def generate(order_id: int | str) -> None:
def generate(
order_id: int | str,
sorting_order: list[str] | None = None,
selected_samples: list[Any] | None = None,
) -> None:
"""
wrapper to handle errors and reset the sequence to the current sequence value
"""
Expand Down
31 changes: 30 additions & 1 deletion src/genlab_bestilling/models.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import uuid
from datetime import timedelta
from typing import Any
from typing import TYPE_CHECKING, Any

from django.conf import settings
from django.db import models, transaction
from django.db.models import QuerySet
from django.urls import reverse
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
Expand All @@ -12,6 +13,9 @@
from rest_framework.exceptions import ValidationError
from taggit.managers import TaggableManager

if TYPE_CHECKING:
from .models import Sample

from . import managers
from .libs.helpers import position_to_coordinates

Expand Down Expand Up @@ -301,6 +305,10 @@ def to_draft(self) -> None:
def get_type(self) -> str:
return "order"

@property
def filled_genlab_count(self) -> int:
return self.samples.filter(genlab_id__isnull=False).count()

@property
def next_status(self) -> OrderStatus | None:
current_index = self.STATUS_ORDER.index(self.status)
Expand Down Expand Up @@ -461,6 +469,27 @@ def order_manually_checked(self) -> None:
self.save()
app.configure_task(name="generate-genlab-ids").defer(order_id=self.id)

def order_selected_checked(
self,
sorting_order: list[str] | None = None,
selected_samples: QuerySet["Sample"] | None = None,
) -> None:
"""
Partially set the order as checked by the lab staff,
generate a genlab id for the samples selected
"""
self.internal_status = self.Status.CHECKED
self.status = self.OrderStatus.PROCESSING
self.save()

selected_sample_names = list(selected_samples.values_list("id", flat=True))

app.configure_task(name="generate-genlab-ids").defer(
order_id=self.id,
sorting_order=sorting_order,
selected_samples=selected_sample_names,
)


class AnalysisOrder(Order):
samples = models.ManyToManyField(
Expand Down
14 changes: 12 additions & 2 deletions src/genlab_bestilling/tasks.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# from .libs.isolation import isolate
from typing import Any

from django.db.utils import OperationalError
from procrastinate import RetryStrategy
from procrastinate.contrib.django import app
Expand All @@ -12,6 +14,14 @@
max_attempts=5, linear_wait=5, retry_exceptions={OperationalError}
),
)
def generate_ids(order_id: str | int) -> None:
generate_genlab_id(order_id=order_id)
def generate_ids(
order_id: int | str,
sorting_order: list[str] | None = None,
selected_samples: list[Any] | None = None,
) -> None:
generate_genlab_id(
order_id=order_id,
sorting_order=sorting_order,
selected_samples=selected_samples,
)
# isolate(order_id=order_id)
41 changes: 39 additions & 2 deletions src/staff/tables.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from typing import Any

import django_tables2 as tables
from django.db.models import IntegerField
from django.db.models.functions import Cast
from django.utils.safestring import mark_safe

from genlab_bestilling.models import (
Expand Down Expand Up @@ -139,6 +141,17 @@ class SampleBaseTable(tables.Table):
verbose_name="",
)

checked = tables.CheckBoxColumn(
attrs={
"th__input": {"type": "checkbox", "id": "select-all-checkbox"},
},
accessor="pk",
orderable=False,
empty_values=(),
)

name = tables.Column(order_by=("name_as_int",))

class Meta:
model = Sample
fields = [
Expand All @@ -154,17 +167,41 @@ class Meta:
"plate_positions",
]
attrs = {"class": "w-full table-auto tailwind-table table-sm"}
sequence = ("is_prioritised", "genlab_id", "guid", "name", "species", "type")
order_by = ("-is_prioritised", "species", "genlab_id", "name")
sequence = (
"checked",
"is_prioritised",
"genlab_id",
"guid",
"name",
"species",
"type",
)
order_by = (
"-is_prioritised",
"species",
"genlab_id",
"name_as_int",
)

empty_text = "No Samples"

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

if hasattr(self.data, "data"):
self.data.data = self.data.data.annotate(
name_as_int=Cast("name", output_field=IntegerField())
)

def render_plate_positions(self, value: Any) -> str:
if value:
return ", ".join([str(v) for v in value.all()])

return ""

def render_checked(self, record: Any) -> str:
return mark_safe(f'<input type="checkbox" name="checked" value="{record.id}">') # noqa: S308


def create_sample_table(base_fields: list[str] | None = None) -> type[tables.Table]:
class CustomSampleTable(tables.Table):
Expand Down
14 changes: 14 additions & 0 deletions src/staff/templates/staff/analysisorder_filter.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
{% extends "staff/base_filter.html" %}
{% load crispy_forms_tags static %}
{% load render_table from django_tables2 %}

{% block page-title %}
Analysis Orders
{% endblock page-title %}

{% block page-inner %}
<form method="get" class="py-3 px-4 border mb-3 ">
<div class="flex flex-wrap gap-4">
{{ filter.form | crispy }}
</div>
<button class="btn bg-primary" type="submit">Search</button>
</form>

{% render_table table %}

{% endblock page-inner %}
22 changes: 13 additions & 9 deletions src/staff/templates/staff/base_filter.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,23 @@
{% block content %}
<h3 class="text-4xl mb-5">{% block page-title %}{% endblock page-title %}</h3>
{% block page-inner %}{% endblock page-inner %}

<form method="get" class="py-3 px-4 border mb-3 ">
<div class="flex flex-wrap gap-4">
{{ filter.form | crispy }}
</div>
<button class="btn bg-primary" type="submit">Search</button>
</form>

{% render_table table %}
{% endblock %}

{% block body_javascript %}
{{ block.super }}
<script type="text/javascript" src="{% static 'admin/js/vendor/jquery/jquery.js' %}"></script>
{{ filter.form.media }}
<script>
document.addEventListener('DOMContentLoaded', function () {
const selectAll = document.getElementById('select-all-checkbox');
if (selectAll) {
selectAll.addEventListener('change', function () {
const checkboxes = document.querySelectorAll('input[name="checked"]');
checkboxes.forEach(cb => {
cb.checked = selectAll.checked;
});
});
}
});
</script>
{% endblock body_javascript %}
14 changes: 14 additions & 0 deletions src/staff/templates/staff/equipmentorder_filter.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
{% extends "staff/base_filter.html" %}
{% load crispy_forms_tags static %}
{% load render_table from django_tables2 %}

{% block page-title %}
Equipment Orders
{% endblock page-title %}

{% block page-inner %}
<form method="get" class="py-3 px-4 border mb-3 ">
<div class="flex flex-wrap gap-4">
{{ filter.form | crispy }}
</div>
<button class="btn bg-primary" type="submit">Search</button>
</form>

{% render_table table %}

{% endblock page-inner %}
14 changes: 14 additions & 0 deletions src/staff/templates/staff/extractionorder_filter.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
{% extends "staff/base_filter.html" %}
{% load crispy_forms_tags static %}
{% load render_table from django_tables2 %}

{% block page-title %}
Extraction Orders
{% endblock page-title %}

{% block page-inner %}
<form method="get" class="py-3 px-4 border mb-3 ">
<div class="flex flex-wrap gap-4">
{{ filter.form | crispy }}
</div>
<button class="btn bg-primary" type="submit">Search</button>
</form>

{% render_table table %}

{% endblock page-inner %}
11 changes: 11 additions & 0 deletions src/staff/templates/staff/extractionplate_filter.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{% extends "staff/base_filter.html" %}
{% load crispy_forms_tags static %}
{% load render_table from django_tables2 %}

{% block page-title %}
Extraction plates
Expand All @@ -8,4 +10,13 @@
<div class="flex justify-end my-3">
<a class="btn bg-primary" href="{% url 'staff:plates-create' %}">Create</a>
</div>

<form method="get" class="py-3 px-4 border mb-3 ">
<div class="flex flex-wrap gap-4">
{{ filter.form | crispy }}
</div>
<button class="btn bg-primary" type="submit">Search</button>
</form>

{% render_table table %}
{% endblock page-inner %}
14 changes: 14 additions & 0 deletions src/staff/templates/staff/project_filter.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
{% extends "staff/base_filter.html" %}
{% load crispy_forms_tags static %}
{% load render_table from django_tables2 %}

{% block page-title %}
Projects
{% endblock page-title %}

{% block page-inner %}
<form method="get" class="py-3 px-4 border mb-3 ">
<div class="flex flex-wrap gap-4">
{{ filter.form | crispy }}
</div>
<button class="btn bg-primary" type="submit">Search</button>
</form>

{% render_table table %}

{% endblock page-inner %}
29 changes: 28 additions & 1 deletion src/staff/templates/staff/sample_filter.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
{% extends "staff/base_filter.html" %}
{% load crispy_forms_tags static %}
{% load render_table from django_tables2 %}

{% block page-title %}
{% if order %}{{ order }} - Samples{% else %}Samples{% endif %}
<div class="flex justify-between items-center w-full">
<div>
{% if order %}
{{ order }} - Samples
{% else %}
Samples
{% endif %}
</div>
{% if order %}
<div>
{{ order.filled_genlab_count }} / {{ order.samples.count }} Genlabs generated
</div>
{% endif %}
</div>
{% endblock page-title %}

{% block page-inner %}
Expand All @@ -11,5 +26,17 @@
<a class="btn bg-yellow-500" href="{% url 'samples-csv' %}?order={{ order.pk }}"><i class="fas fa-download"></i> Download CSV</a>
<a class="btn bg-primary" href="{% url 'staff:order-extraction-samples-lab' order.pk %}"><i class="fas fa-flask"></i> Lab</a>
</div>

<form method="post" action="{% url 'staff:generate-genlab-ids' pk=order.pk %}">
{% csrf_token %}
<input type="hidden" name="sort" value="{{ request.GET.sort|default:'' }}">
<button class="btn bg-blue-500 text-white mt-4" type="submit" name="generate_genlab_ids">
<i class="fa-solid fa-id-badge"></i> Generate genlab IDs
</button>

<div class="text-right text-sm text-red-500"> This page is under development. The genlab IDs will generate for all, and without sorting as per now. </div>

{% render_table table %}
</form>
{% endif %}
{% endblock page-inner %}
12 changes: 12 additions & 0 deletions src/staff/templates/staff/samplemarkeranalysis_filter.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{% extends "staff/base_filter.html" %}
{% load crispy_forms_tags static %}
{% load render_table from django_tables2 %}

{% block page-title %}
{% if order %}{{ order }} - Samples{% else %}Samples{% endif %}
Expand All @@ -10,4 +12,14 @@
<a class="btn bg-primary" href="../"><i class="fas fa-arrow-left"></i> back</a>
</div>
{% endif %}

<form method="get" class="py-3 px-4 border mb-3 ">
<div class="flex flex-wrap gap-4">
{{ filter.form | crispy }}
</div>
<button class="btn bg-primary" type="submit">Search</button>
</form>

{% render_table table %}

{% endblock page-inner %}
6 changes: 6 additions & 0 deletions src/staff/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
ExtractionPlateCreateView,
ExtractionPlateDetailView,
ExtractionPlateListView,
GenerateGenlabIDsView,
ManaullyCheckedOrderActionView,
OrderAnalysisSamplesListView,
OrderExtractionSamplesListView,
Expand Down Expand Up @@ -85,6 +86,11 @@
SampleLabView.as_view(),
name="order-extraction-samples-lab",
),
path(
"orders/extraction/<int:pk>/samples/generate-genlab-ids/",
GenerateGenlabIDsView.as_view(),
name="generate-genlab-ids",
),
path(
"orders/analysis/<int:pk>/samples/",
OrderAnalysisSamplesListView.as_view(),
Expand Down
Loading