forked from botswana-harvard/edc-pharmacy
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
request and requestitem and original create request item action, etc WIP
- Loading branch information
Showing
33 changed files
with
2,091 additions
and
2,015 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,5 +21,7 @@ | |
ProductAdmin, | ||
ReceiveAdmin, | ||
ReceiveItemAdmin, | ||
RequestAdmin, | ||
RequestItemAdmin, | ||
StockAdmin, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,5 +14,7 @@ | |
ProductForm, | ||
ReceiveForm, | ||
ReceiveItemForm, | ||
RequestForm, | ||
RequestItemForm, | ||
StockForm, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"}), | ||
} |
Oops, something went wrong.