Skip to content

Commit

Permalink
Merge branch 'release/0.3.13' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
erikvw committed Nov 23, 2024
2 parents 6f84926 + e8a8651 commit 04f457c
Show file tree
Hide file tree
Showing 38 changed files with 2,044 additions and 291 deletions.
23 changes: 23 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,29 @@ Create new stock from an existing stock item. The container of the new stock ite
For example, create bottles of 128 tabs from a single bulk barrel of tablets.


User Testing
============

Watermarks
++++++++++

Print a watermark on labels during UAT deployments

.. code-block:: python
EDC_PHARMACY_LABEL_WATERMARK_WORD = "DO NOT USE"
See also `pylabels2 <https://github.com/erikvw/pylabels2>`__.

Print watermark on reports during UAT deployments

.. code-block:: python
EDC_PDF_REPORTS_WATERMARK_WORD = "SAMPLE"
EDC_PDF_REPORTS_WATERMARK_FONT = ("Helvetica", 100)
See also `edc-pdf-reports <https://github.com/clinicedc/edc-pdf-reports>`__.


.. |pypi| image:: https://img.shields.io/pypi/v/edc-pharmacy.svg
:target: https://pypi.python.org/pypi/edc-pharmacy
Expand Down
25 changes: 24 additions & 1 deletion edc_pharmacy/admin/medication/formulation_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,23 @@ class FormulationAdmin(ModelAdminMixin, admin.ModelAdmin):
"units",
"formulation_type",
"route",
"notes",
"description",
)
},
),
(
"Investigational medicinal product",
{
"fields": (
"imp",
"imp_description",
)
},
),
(
"Notes",
{"fields": ("notes",)},
),
audit_fieldset_tuple,
)

Expand All @@ -41,6 +54,16 @@ class FormulationAdmin(ModelAdminMixin, admin.ModelAdmin):
}

list_filter: Tuple[str, ...] = (
"imp",
"strength",
"units",
"formulation_type",
"route",
)

list_display = (
"description",
"medication",
"strength",
"units",
"formulation_type",
Expand Down
1 change: 1 addition & 0 deletions edc_pharmacy/admin/stock/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@
from .stock_request_item_admin import StockRequestItemAdmin
from .stock_transfer_admin import StockTransferAdmin
from .stock_transfer_confirmation_admin import StockTransferConfirmationAdmin
from .stock_transfer_confirmation_item_admin import StockTransferConfirmationItemAdmin
from .stock_transfer_item_admin import StockTransferItemAdmin
from .supplier_admin import SupplierAdmin
75 changes: 52 additions & 23 deletions edc_pharmacy/admin/stock/stock_transfer_confirmation_admin.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from django.contrib import admin
from django.template.loader import render_to_string
from django.urls import reverse
from django.utils.translation import gettext as _
from django_audit_fields import audit_fieldset_tuple
from edc_utils.date import to_local

from ...admin_site import edc_pharmacy_admin
from ...models import StockTransferConfirmation
Expand All @@ -10,23 +12,24 @@

@admin.register(StockTransferConfirmation, site=edc_pharmacy_admin)
class StockTransferConfirmationAdmin(ModelAdminMixin, admin.ModelAdmin):
change_list_title = "Pharmacy: Stock transfer confirmations"
change_form_title = "Pharmacy: Stock transfer confirmation"
change_list_title = "Pharmacy: Site stock transfer confirmations"
change_form_title = "Pharmacy: Site stock transfer confirmation"
show_object_tools = True
show_cancel = True
list_per_page = 20

ordering = ("confirmed_datetime",)
ordering = ("-transfer_confirmation_identifier",)

fieldsets = (
(
None,
{
"fields": (
"transfer_confirmation_identifier",
"stock",
"confirmed_datetime",
"confirmed_by",
"transfer_confirmation_datetime",
"stock_transfer",
"location",
"comments",
)
},
),
Expand All @@ -35,33 +38,59 @@ class StockTransferConfirmationAdmin(ModelAdminMixin, admin.ModelAdmin):

list_display = (
"identifier",
"subject",
"stock_changelist",
"confirmed_datetime",
"confirmed_by",
"transfer_confirmation_date",
"location",
"stock_transfer_confirmation_item_changelist",
"stock_transfer_changelist",
)

list_filter = (
"transfer_confirmation_datetime",
"location",
)

readonly_fields = (
"transfer_confirmation_identifier",
"stock",
"confirmed_datetime",
"confirmed_by",
"transfer_confirmation_datetime",
"stock_transfer",
"location",
)

search_fields = ("pk", "stock_transfer__pk")

@admin.display(description="CONFIRMATION #", ordering="-transfer_confirmation_identifier")
def identifier(self, obj):
return obj.transfer_confirmation_identifier.split("-")[0]

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

@admin.display(description="Confirmed items")
def stock_transfer_confirmation_item_changelist(self, obj):
item_count = obj.stocktransferconfirmationitem_set.all().count()
url = reverse(
"edc_pharmacy_admin:edc_pharmacy_stocktransferconfirmationitem_changelist"
)
url = f"{url}?q={obj.id}"
context = dict(
url=url,
label=_("Confirmed items (%(item_count)s)") % {"item_count": item_count},
title="Go to stock transfer confirmation items",
)
return render_to_string("edc_pharmacy/stock/items_as_link.html", context=context)

@admin.display(
description="SUBJECT #",
ordering="stock__allocation__registered_subject__subject_identifier",
description="Stock Transfer", ordering="stock_transfer__transfer_identifier"
)
def subject(self, obj):
return obj.stock.allocation.registered_subject.subject_identifier

@admin.display(description="Stock", ordering="stock__code")
def stock_changelist(self, obj):
url = reverse("edc_pharmacy_admin:edc_pharmacy_stock_changelist")
url = f"{url}?q={obj.stock.code}"
context = dict(url=url, label=obj.stock.code, title="Go to stock")
def stock_transfer_changelist(self, obj):
url = reverse("edc_pharmacy_admin:edc_pharmacy_stocktransfer_changelist")
url = f"{url}?q={obj.stock_transfer.id}"
context = dict(
url=url,
label=(
f"{obj.stock_transfer.transfer_identifier} ({obj.stock_transfer.item_count})"
),
title="Go to stock transfer",
)
return render_to_string("edc_pharmacy/stock/items_as_link.html", context=context)
111 changes: 111 additions & 0 deletions edc_pharmacy/admin/stock/stock_transfer_confirmation_item_admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
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 ...models import StockTransferConfirmationItem
from ..model_admin_mixin import ModelAdminMixin


@admin.register(StockTransferConfirmationItem, site=edc_pharmacy_admin)
class StockTransferConfirmationItemAdmin(ModelAdminMixin, admin.ModelAdmin):
change_list_title = "Pharmacy: Site stock transfer confirmation items"
change_form_title = "Pharmacy: Site stock transfer confirmation item"
show_object_tools = True
show_cancel = True
list_per_page = 20

ordering = ("-transfer_confirmation_item_identifier",)

fieldsets = (
(
None,
{
"fields": (
"transfer_confirmation_item_identifier",
"transfer_confirmation_item_datetime",
"stock_transfer_confirmation",
"stock",
"confirmed_datetime",
"confirmed_by",
)
},
),
audit_fieldset_tuple,
)

list_display = (
"identifier",
"transfer_confirmation_item_date",
"subject",
"site",
"stock_changelist",
"stock_transfer_confirmation_changelist",
"confirmed_datetime",
"confirmed_by",
)

list_filter = ("transfer_confirmation_item_datetime",)

readonly_fields = (
"transfer_confirmation_item_identifier",
"transfer_confirmation_item_datetime",
"stock_transfer_confirmation",
"stock",
"confirmed_datetime",
"confirmed_by",
)

search_fields = (
"pk",
"stock_transfer_confirmation__pk",
"stock__code",
"stock__pk",
"stock__allocation__registered_subject__subject_identifier",
)

@admin.display(
description="CONFIRMATION #", ordering="-transfer_confirmation_item_identifier"
)
def identifier(self, obj):
return obj.transfer_confirmation_item_identifier

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

@admin.display(
description="Site", ordering="stock_transfer_confirmation__location__site__id"
)
def site(self, obj):
return obj.stock_transfer_confirmation.location.site.id

@admin.display(
description="SUBJECT #",
ordering="stock__allocation__registered_subject__subject_identifier",
)
def subject(self, obj):
return obj.stock.allocation.registered_subject.subject_identifier

@admin.display(
description="Transfer confirmation",
ordering="stock_transfer_confirmation__transfer_confirmation_identifier",
)
def stock_transfer_confirmation_changelist(self, obj):
url = reverse("edc_pharmacy_admin:edc_pharmacy_stocktransferconfirmation_changelist")
url = f"{url}?q={obj.stock_transfer_confirmation.id}"
context = dict(
url=url,
label=obj.stock_transfer_confirmation.transfer_confirmation_identifier,
title="Go to stock transfer confirmation",
)
return render_to_string("edc_pharmacy/stock/items_as_link.html", context=context)

@admin.display(description="Stock", ordering="stock__code")
def stock_changelist(self, obj):
url = reverse("edc_pharmacy_admin:edc_pharmacy_stock_changelist")
url = f"{url}?q={obj.stock.code}"
context = dict(url=url, label=obj.stock.code, title="Go to stock")
return render_to_string("edc_pharmacy/stock/items_as_link.html", context=context)
20 changes: 11 additions & 9 deletions edc_pharmacy/admin/stock/stock_transfer_item_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class StockTransferItemAdmin(ModelAdminMixin, admin.ModelAdmin):
"stock_transfer_changelist",
"stock_changelist",
"stock__location",
"stock_transfer_confirmation_changelist",
"stock_transfer_confirmation_item_changelist",
)

list_filter = ("transfer_item_datetime",)
Expand Down Expand Up @@ -83,21 +83,23 @@ def stock_transfer_changelist(self, obj):
return render_to_string("edc_pharmacy/stock/items_as_link.html", context=context)

@admin.display(
description="Confirmation #",
ordering="stocktransferconfirmation__transfer_confirmation_identifier",
description="Site Confirmation #",
ordering="stock__stocktransferconfirmationitem__transfer_confirmation_item_identifier",
)
def stock_transfer_confirmation_changelist(self, obj):
url = reverse("edc_pharmacy_admin:edc_pharmacy_stocktransferconfirmation_changelist")
url = f"{url}?q={obj.id}"
def stock_transfer_confirmation_item_changelist(self, obj):
try:
transfer_confirmation = obj.stock.stocktransferconfirmation
transfer_confirmation_item = obj.stock.stocktransferconfirmationitem
except ObjectDoesNotExist:
pass
else:
url = reverse(
"edc_pharmacy_admin:edc_pharmacy_stocktransferconfirmationitem_changelist"
)
url = f"{url}?q={transfer_confirmation_item.pk}"
context = dict(
url=url,
label=transfer_confirmation.transfer_confirmation_identifier,
title="Go to stock transfer confirmation",
label=transfer_confirmation_item.transfer_confirmation_item_identifier,
title="Go to stock transfer confirmation item",
)
return render_to_string("edc_pharmacy/stock/items_as_link.html", context=context)
return None
2 changes: 2 additions & 0 deletions edc_pharmacy/constants.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
ALLOCATED = "allocated"
ALREADY_CONFIRMED = "already_confirmed"
AVAILABLE = "available"
CANCELLED = "cancelled"
CONTROL_ARM = "control_arm"
DAYS = "days"
DISPENSED = "dispensed"
FILLED = "filled"
INVALID = "invalid"
IN_PROGRESS_APPT = "in_progress"
PARTIAL = "partial"
PER_DAY = "day"
Expand Down
4 changes: 4 additions & 0 deletions edc_pharmacy/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,7 @@ class StockTransferError(Exception):

class AssignmentError(Exception):
pass


class StockTransferConfirmationError(Exception):
pass
2 changes: 1 addition & 1 deletion edc_pharmacy/labels/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from .draw_bulk_stock_label_code39 import draw_bulk_stock_label_code39
from .draw_bulk_stock_label_code128 import draw_bulk_stock_label_code128
from .draw_label_watermark import draw_label_watermark
from .draw_patient_stock_label_code128 import draw_patient_stock_label_code128
from .draw_vertical_barcode_only_code128 import draw_vertical_barcode_only_code128
from .label_data import LabelData
from .print_sheets import print_sheets
4 changes: 4 additions & 0 deletions edc_pharmacy/labels/draw_bulk_stock_label_code128.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from reportlab.graphics.shapes import Drawing, String

from ..utils import format_qty
from .draw_label_watermark import draw_label_watermark

if TYPE_CHECKING:
from ..models import Stock
Expand All @@ -21,6 +22,9 @@ def draw_bulk_stock_label_code128(
"""Callable to draw a single study medication label given a model
instance `obj`
"""

draw_label_watermark(label, width, height, fontSize=18)

text = str(ResearchProtocolConfig().protocol_name)
qty = format_qty(obj.container.qty, obj.container)
br = BarcodeCode128(humanReadable=True, barHeight=30, barWidth=0.7, gap=1.7)
Expand Down
Loading

0 comments on commit 04f457c

Please sign in to comment.