Skip to content

Commit

Permalink
request and requestitem and original create request item action, etc WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
erikvw committed Nov 4, 2024
1 parent 25ff9e8 commit 9d993dd
Show file tree
Hide file tree
Showing 33 changed files with 2,091 additions and 2,015 deletions.
2 changes: 2 additions & 0 deletions edc_pharmacy/admin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,7 @@
ProductAdmin,
ReceiveAdmin,
ReceiveItemAdmin,
RequestAdmin,
RequestItemAdmin,
StockAdmin,
)
1 change: 1 addition & 0 deletions edc_pharmacy/admin/actions/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from .create_request_items import create_request_items_action
from .print_stock_labels import print_stock_labels
108 changes: 108 additions & 0 deletions edc_pharmacy/admin/actions/create_request_items.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
from typing import TYPE_CHECKING

import pandas as pd
from django.contrib import messages
from django.db.models import Q
from django.urls import reverse
from django.utils.html import format_html
from django.utils.translation import gettext as _
from django_pandas.io import read_frame
from edc_consent.utils import get_consent_model_cls
from edc_pdutils.dataframes import get_subject_visit
from edc_randomization.site_randomizers import site_randomizers
from edc_sites.site import sites as site_sites
from edc_utils import get_utcnow
from edc_visit_tracking.utils import get_related_visit_model
from sequences import get_next_value

from ...models import RequestItem, Rx
from ...utils import generate_code_with_checksum_from_id

if TYPE_CHECKING:
from ...models import Request


def create_request_items_action(modeladmin, request, queryset):
if queryset.count() > 1 or queryset.count() == 0:
messages.add_message(
request,
messages.ERROR,
_("Select one and only one existing label specification"),
)
else:
request_obj: Request = queryset.first()
now = get_utcnow()
df = get_subject_visit(model=get_related_visit_model())
df["last_visit_datetime"] = df["last_visit_datetime"].dt.normalize()
df = df[
(df.visit_code == df.last_visit_code)
& (df.visit_code_sequence == 0)
& (df.last_visit_datetime <= pd.to_datetime("today"))
& (df.site_id == request_obj.site_id)
]
df = df.reset_index(drop=True)
df_consent = read_frame(
get_consent_model_cls()
.objects.values("subject_identifier", "gender")
.filter(site=request_obj.site),
verbose=False,
)
df = df.merge(
df_consent[["subject_identifier", "gender"]], on="subject_identifier", how="left"
)
df = df.reset_index(drop=True)
df_rx = read_frame(
Rx.objects.values(
"id", "registered_subject__subject_identifier", "rx_expiration_date"
).filter(
Q(rx_expiration_date__gte=get_utcnow().date())
| Q(rx_expiration_date__isnull=True)
)
)

df_rx = df_rx.rename(
columns={
"registered_subject__subject_identifier": "subject_identifier",
"id": "rx_id",
}
)
df = df.merge(
df_rx[["subject_identifier", "rx_id"]], on="subject_identifier", how="left"
)
df = df[df.rx_id.notna()]
df = df.reset_index(drop=True)

df["site_name"] = df["site_id"].apply(lambda x: site_sites.get(x).name)

data = []
for i, row in df.iterrows():
rx = Rx.objects.get(id=row["rx_id"])
randomizer = site_randomizers.get(rx.randomizer_name)
rando_obj = randomizer.model_cls().objects.get(
subject_identifier=row["subject_identifier"]
)
next_id = get_next_value(RequestItem._meta.label_lower)
obj = RequestItem(
request=request_obj,
request_item_identifier=f"{next_id:06d}",
code=generate_code_with_checksum_from_id(next_id),
subject_identifier=row["subject_identifier"],
gender=row["gender"],
site_id=row["site_id"],
rx_id=row["rx_id"],
sid=rando_obj.sid,
created=now,
)
data.append(obj)
created = len(RequestItem.objects.bulk_create(data))
url = reverse("edc_pharmacy_admin:edc_pharmacy_request_changelist")
url = f"{url}?q={request_obj.request_identifier}"
msg = format_html(
_("Created request %(request_identifier)s with %(created)s records")
% {
"created": created,
"request_identifier": request_obj.request_identifier,
"url": url,
}
)
messages.add_message(request, messages.SUCCESS, message=msg)
3 changes: 3 additions & 0 deletions edc_pharmacy/admin/stock/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@
from .product_admin import ProductAdmin
from .receive_admin import ReceiveAdmin
from .receive_item_admin import ReceiveItemAdmin
from .request_admin import RequestAdmin
from .request_item_admin import RequestItemAdmin
from .site_proxy_admin import SiteProxyAdmin
from .stock_admin import StockAdmin
116 changes: 116 additions & 0 deletions edc_pharmacy/admin/stock/request_admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
from django.contrib import admin
from django.template.loader import render_to_string
from django.urls import reverse
from django_audit_fields import audit_fieldset_tuple
from edc_utils.date import to_local

from ...admin_site import edc_pharmacy_admin
from ...forms import RequestForm
from ...models import Request, RequestItem
from ..actions import create_request_items_action
from ..model_admin_mixin import ModelAdminMixin


@admin.register(Request, site=edc_pharmacy_admin)
class RequestAdmin(ModelAdminMixin, admin.ModelAdmin):
change_list_title = "Pharmacy: Request for stock"
show_object_tools = True
show_cancel = True
autocomplete_fields = ["container", "formulation", "site_proxy"]
form = RequestForm

actions = [create_request_items_action]

fieldsets = (
(
"Section A",
{
"fields": (
"request_identifier",
"request_datetime",
"site_proxy",
)
},
),
(
"Section B",
{"fields": ("formulation", "container", "containers_per_subject")},
),
(
"Section C",
{"fields": ("item_count", "status")},
),
(
"Section D",
{"fields": ("labels",)},
),
audit_fieldset_tuple,
)

list_display = (
"request_id",
"request_date",
"site_proxy",
"formulation",
"container",
"per_subject",
"request_item_count",
"add_request_item",
"items",
"status",
)

list_filter = (
"request_datetime",
"status",
"formulation",
"container",
)

radio_fields = {
"status": admin.VERTICAL,
}

search_fields = ["id", "request_identifier"]

@admin.display(description="Request #", ordering="request_identifier")
def request_id(self, obj):
return obj.request_identifier

@admin.display(description="Per", ordering="containers_per_subject")
def per_subject(self, obj):
return obj.containers_per_subject

@admin.display(description="items", ordering="item_count")
def request_item_count(self, obj):
return obj.item_count

@admin.display(description="Request")
def items(self, obj):
url = reverse("edc_pharmacy_admin:edc_pharmacy_requestitem_changelist")
url = f"{url}?q={obj.request_identifier}"
context = dict(url=url, label="Request items", title="Go to request items")
return render_to_string("edc_pharmacy/stock/items_as_link.html", context=context)

@admin.display(description="Add")
def add_request_item(self, obj):
if obj.item_count > RequestItem.objects.filter(request=obj).count():
url = reverse("edc_pharmacy_admin:edc_pharmacy_requestitem_add")
next_url = "edc_pharmacy_admin:edc_pharmacy_request_changelist"
url = (
f"{url}?next={next_url}&request={str(obj.id)}&q={str(obj.request_identifier)}"
)
context = dict(url=url, label="Add item")
return render_to_string("edc_pharmacy/stock/items_as_button.html", context=context)
return None

@admin.display(description="Request date")
def request_date(self, obj):
return to_local(obj.request_datetime).date()

def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "request" and request.GET.get("request"):
kwargs["queryset"] = db_field.related_model.objects.filter(
pk=request.GET.get("rx", 0)
)
return super().formfield_for_foreignkey(db_field, request, **kwargs)
99 changes: 99 additions & 0 deletions edc_pharmacy/admin/stock/request_item_admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
from django.contrib import admin
from django.template.loader import render_to_string
from django.urls import reverse
from django_audit_fields import audit_fieldset_tuple
from edc_utils.date import to_local

from ...admin_site import edc_pharmacy_admin
from ...forms import RequestItemForm
from ...models import RequestItem
from ..model_admin_mixin import ModelAdminMixin


@admin.register(RequestItem, site=edc_pharmacy_admin)
class RequestItemAdmin(ModelAdminMixin, admin.ModelAdmin):
change_list_title = "Pharmacy: Request item for stock request"
show_object_tools = False
show_cancel = True
form = RequestItemForm
autocomplete_fields = ["rx"]

fieldsets = (
(
"Section A",
{
"fields": (
"request",
"request_item_datetime",
"rx",
)
},
),
(
"Section B",
{
"classes": ("collapse",),
"fields": ("code", "gender", "sid", "site"),
},
),
(
"Section C",
{
"classes": ("collapse",),
"fields": ("printed_datetime", "printed", "scanned_datetime", "scanned"),
},
),
audit_fieldset_tuple,
)

list_display = (
"request_item_id",
"item_date",
"request_changelist",
"site_number",
"subject",
"code",
"gender",
"sid",
"printed",
"scanned",
"received",
"dispensed",
)
readonly_fields = (
"printed_datetime",
"printed",
"scanned_datetime",
"scanned",
"site",
"gender",
"sid",
"code",
)

search_fields = ("code", "id", "rx__subject_identifier", "request__request_identifier")

@admin.display(description="Date", ordering="request_item_datetime")
def item_date(self, obj):
return to_local(obj.request_item_datetime).date()

@admin.display(description="Subject", ordering="subject_identifier")
def subject(self, obj):
return obj.subject_identifier

@admin.display(description="Site", ordering="site_id")
def site_number(self, obj):
return obj.site_id

@admin.display(description="ITEM#", ordering="request_item_identifier")
def request_item_id(self, obj):
return obj.request_item_identifier

@admin.display(description="Request#")
def request_changelist(self, obj):
url = reverse("edc_pharmacy_admin:edc_pharmacy_request_changelist")
url = f"{url}?q={obj.request.request_identifier}"
context = dict(
url=url, label=f"{obj.request.request_identifier}", title="Back to request"
)
return render_to_string("edc_pharmacy/stock/items_as_link.html", context=context)
9 changes: 9 additions & 0 deletions edc_pharmacy/admin/stock/site_proxy_admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from django.contrib import admin

from ...admin_site import edc_pharmacy_admin
from ...models import SiteProxy


@admin.register(SiteProxy, site=edc_pharmacy_admin)
class SiteProxyAdmin(admin.ModelAdmin):
search_fields = ["id", "name"]
2 changes: 1 addition & 1 deletion edc_pharmacy/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@

class AppConfig(DjangoAppConfig):
name = "edc_pharmacy"
verbose_name = "Pharmacy"
verbose_name = "Edc Pharmacy"
has_exportable_data = True
include_in_administration_section = True
2 changes: 2 additions & 0 deletions edc_pharmacy/forms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,7 @@
ProductForm,
ReceiveForm,
ReceiveItemForm,
RequestForm,
RequestItemForm,
StockForm,
)
2 changes: 2 additions & 0 deletions edc_pharmacy/forms/stock/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@
from .product_form import ProductForm
from .receive_form import ReceiveForm
from .receive_item_form import ReceiveItemForm
from .request_form import RequestForm
from .request_item_form import RequestItemForm
from .stock_form import StockForm
13 changes: 13 additions & 0 deletions edc_pharmacy/forms/stock/request_form.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from django import forms

from ...models import Request


class RequestForm(forms.ModelForm):
class Meta:
model = Request
fields = "__all__"
help_text = {"request_identifier": "(read-only)"}
widgets = {
"request_identifier": forms.TextInput(attrs={"readonly": "readonly"}),
}
Loading

0 comments on commit 9d993dd

Please sign in to comment.