clinicedc 2.0.28__py3-none-any.whl → 2.0.30__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of clinicedc might be problematic. Click here for more details.

Files changed (98) hide show
  1. {clinicedc-2.0.28.dist-info → clinicedc-2.0.30.dist-info}/METADATA +2 -2
  2. {clinicedc-2.0.28.dist-info → clinicedc-2.0.30.dist-info}/RECORD +98 -98
  3. edc_auth/admin/fieldsets.py +11 -15
  4. edc_auth/admin/group_admin.py +2 -5
  5. edc_auth/admin/list_filters.py +8 -7
  6. edc_auth/admin/role_admin.py +7 -10
  7. edc_auth/admin/user_admin.py +2 -2
  8. edc_auth/admin/user_profile_admin.py +3 -7
  9. edc_auth/apps.py +2 -2
  10. edc_auth/auth_updater/group_updater.py +4 -4
  11. edc_auth/auth_updater/role_updater.py +1 -3
  12. edc_auth/backends.py +1 -1
  13. edc_auth/export_users.py +6 -5
  14. edc_auth/fix_export_permissions.py +8 -8
  15. edc_auth/forms.py +21 -24
  16. edc_auth/get_app_codenames.py +2 -2
  17. edc_auth/import_users.py +25 -24
  18. edc_auth/management/commands/export_users.py +1 -1
  19. edc_auth/management/commands/fix_export_permissions.py +1 -1
  20. edc_auth/management/commands/import_users.py +1 -1
  21. edc_auth/management/commands/reset_password.py +2 -2
  22. edc_auth/models/signals.py +1 -1
  23. edc_auth/models/user_profile.py +4 -5
  24. edc_auth/password_setter.py +4 -4
  25. edc_auth/post_migrate_signals.py +2 -2
  26. edc_auth/send_new_credentials_to_user.py +1 -1
  27. edc_auth/system_checks.py +7 -6
  28. edc_auth/utils.py +10 -12
  29. edc_consent/consent_definition.py +4 -1
  30. edc_dashboard/view_mixins/edc_view_mixin.py +1 -1
  31. edc_model_admin/mixins/model_admin_form_instructions_mixin.py +9 -3
  32. edc_model_admin/mixins/model_admin_next_url_redirect_mixin.py +3 -3
  33. edc_model_admin/mixins/model_admin_protect_pii_mixin.py +7 -7
  34. edc_model_admin/mixins/model_admin_redirect_on_delete_mixin.py +6 -8
  35. edc_pharmacy/admin_mixin.py +1 -1
  36. edc_pharmacy/approve_prescription.py +10 -8
  37. edc_pharmacy/auth_objects.py +1 -1
  38. edc_pharmacy/exceptions.py +7 -7
  39. edc_pharmacy/settings.py +1 -1
  40. edc_pharmacy/views/add_to_storage_bin_view.py +22 -24
  41. edc_pharmacy/views/allocate_to_subject_view.py +10 -18
  42. edc_pharmacy/views/celery_task_status_view.py +1 -2
  43. edc_pharmacy/views/confirm_stock_from_instance_view.py +1 -1
  44. edc_pharmacy/views/confirm_stock_from_queryset_view.py +5 -8
  45. edc_pharmacy/views/dispense_view.py +1 -1
  46. edc_pharmacy/views/move_to_storage_bin_view.py +7 -3
  47. edc_pharmacy/views/prepare_and_review_stock_request_view.py +62 -70
  48. edc_pharmacy/views/print_labels_view.py +1 -1
  49. edc_pharmacy/views/transfer_stock_view.py +1 -1
  50. edc_prn/modelform_mixins.py +8 -9
  51. edc_prn/models.py +3 -1
  52. edc_prn/site_prn_forms.py +2 -2
  53. edc_prn/templatetags/edc_prn_extras.py +1 -1
  54. edc_protocol/middleware.py +1 -1
  55. edc_protocol/research_protocol_config.py +7 -5
  56. edc_protocol_incident/admin/protocol_deviation_violation_admin.py +1 -1
  57. edc_protocol_incident/form_validators/mixins.py +9 -6
  58. edc_protocol_incident/modeladmin_mixins.py +1 -1
  59. edc_pylabels/admin/label_configuration_admin.py +1 -1
  60. edc_pylabels/admin/label_specification_admin.py +1 -1
  61. edc_pylabels/auth_objects.py +1 -1
  62. edc_pylabels/site_label_configs.py +2 -2
  63. edc_qareports/admin/qa_report_log_admin.py +5 -5
  64. edc_qareports/admin/qa_report_log_summary_admin.py +1 -1
  65. edc_qareports/forms/note_form.py +2 -3
  66. edc_qareports/modeladmin_mixins/list_filters.py +23 -19
  67. edc_qareports/modeladmin_mixins/note_modeladmin_mixin.py +7 -7
  68. edc_qareports/modeladmin_mixins/on_study_missing_values_modeladmin_mixin.py +8 -8
  69. edc_qareports/modeladmin_mixins/qa_report_modeladmin_mixin.py +3 -7
  70. edc_qareports/sql_generator/crf_case.py +1 -1
  71. edc_qareports/sql_generator/crf_subquery.py +1 -1
  72. edc_qareports/sql_generator/requisition_subquery.py +1 -1
  73. edc_qareports/sql_generator/sql_view_generator.py +1 -1
  74. edc_qareports/sql_generator/subquery_from_dict.py +39 -39
  75. edc_qareports/utils.py +12 -13
  76. edc_randomization/model_mixins.py +1 -1
  77. edc_randomization/system_checks.py +1 -1
  78. edc_refusal/admin.py +4 -2
  79. edc_registration/modeladmin_mixins.py +18 -20
  80. edc_registration/modelform_mixins.py +2 -2
  81. edc_registration/models/signals.py +1 -1
  82. edc_registration/utils.py +1 -1
  83. edc_reportable/age_evaluator.py +4 -4
  84. edc_reportable/data/grading_data/daids_july_2017.py +3 -3
  85. edc_reportable/evaluator.py +15 -15
  86. edc_reportable/exceptions.py +4 -4
  87. edc_reportable/forms/reportables_form_validator_mixin.py +6 -2
  88. edc_reportable/management/commands/export_reportables.py +1 -1
  89. edc_reportable/models/grading_exception.py +1 -6
  90. edc_reportable/models/normal_data.py +3 -3
  91. edc_reportable/models/reference_range_collection.py +1 -6
  92. edc_reportable/utils/get_grade_for_value.py +15 -15
  93. edc_reportable/utils/get_normal_data_or_raise.py +14 -14
  94. edc_reportable/utils/in_normal_bounds_or_raise.py +6 -6
  95. edc_reportable/utils/load_data.py +1 -1
  96. edc_reportable/utils/update_grading_exceptions.py +5 -5
  97. {clinicedc-2.0.28.dist-info → clinicedc-2.0.30.dist-info}/WHEEL +0 -0
  98. {clinicedc-2.0.28.dist-info → clinicedc-2.0.30.dist-info}/licenses/LICENSE +0 -0
edc_auth/utils.py CHANGED
@@ -1,5 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import contextlib
4
+ import sys
3
5
  from pprint import pprint
4
6
  from typing import TYPE_CHECKING, Any
5
7
 
@@ -24,25 +26,23 @@ def get_user(username: str) -> User | None:
24
26
  return user
25
27
 
26
28
 
27
- def compare_codenames_for_group(group_name: str = None, expected: list[str] = None) -> None:
29
+ def compare_codenames_for_group(group_name: str, expected: list[str]) -> None:
28
30
  group = django_apps.get_model("auth.group").objects.get(name=group_name)
29
31
  codenames = [p.codename for p in group.permissions.all()]
30
32
  new_expected = []
31
33
  for c in expected:
32
- try:
34
+ with contextlib.suppress(IndexError):
33
35
  c = c.split(".")[1]
34
- except IndexError:
35
- pass
36
36
  new_expected.append(c)
37
37
 
38
38
  compared = [c for c in new_expected if c not in codenames]
39
39
  if compared:
40
- print(group.name, "missing from codenames")
41
- pprint(compared)
40
+ sys.stdout.write(f"{group.name}, missing from codenames\n")
41
+ pprint(compared) # noqa: T203
42
42
  compared = [c for c in codenames if c not in new_expected]
43
43
  if compared:
44
- print(group.name, "extra codenames")
45
- pprint(compared)
44
+ sys.stdout.write(f"{group.name}, extra codenames\n")
45
+ pprint(compared) # noqa: T203
46
46
 
47
47
 
48
48
  def remove_default_model_permissions_from_edc_permissions(auth_updater: Any, app_label: str):
@@ -59,7 +59,7 @@ def remove_default_model_permissions_from_edc_permissions(auth_updater: Any, app
59
59
 
60
60
 
61
61
  def make_view_only_group_permissions(
62
- prefix: str = None, group: Group = None, model: str = None
62
+ prefix: str, group: Group, model: str|None = None
63
63
  ):
64
64
  """Remove all but view permissions for model.
65
65
 
@@ -119,9 +119,7 @@ def get_codenames_for_user(
119
119
  for role in roles.all():
120
120
  groups.extend([grp for grp in role.groups.all() if grp not in account_manager_groups])
121
121
  if include_groups:
122
- for group in user.groups.all():
123
- if group not in account_manager_groups:
124
- groups.append(group)
122
+ groups.extend([grp for grp in user.groups.all() if grp not in account_manager_groups])
125
123
  groups = list(set(groups))
126
124
  for group in groups:
127
125
  codenames.extend(
@@ -101,7 +101,10 @@ class ConsentDefinition:
101
101
 
102
102
  @property
103
103
  def model(self):
104
- from .managers import ConsentObjectsByCdefManager, CurrentSiteByCdefManager
104
+ from .managers import ( # noqa: PLC0415
105
+ ConsentObjectsByCdefManager,
106
+ CurrentSiteByCdefManager,
107
+ )
105
108
 
106
109
  model_cls = django_apps.get_model(self._model)
107
110
  if not model_cls._meta.proxy:
@@ -30,7 +30,7 @@ class EdcViewMixin(
30
30
  edc_device_app_config = django_apps.get_app_config(self.edc_device_app)
31
31
  except LookupError as e:
32
32
  edc_device_app_config = None
33
- warnings.warn(str(e))
33
+ warnings.warn(str(e), stacklevel=2)
34
34
  live_system = getattr(settings, "LIVE_SYSTEM", "TEST")
35
35
  kwargs.update(
36
36
  {
@@ -46,7 +46,9 @@ class ModelAdminFormInstructionsMixin:
46
46
  change_additional_instructions = ()
47
47
 
48
48
  def get_add_instructions(
49
- self, extra_context: dict | None, request: WSGIRequest | None = None
49
+ self,
50
+ extra_context: dict | None,
51
+ request: WSGIRequest | None = None, # noqa: ARG002
50
52
  ):
51
53
  extra_context = extra_context or {}
52
54
  extra_context["instructions"] = self.add_instructions or self.instructions
@@ -56,7 +58,9 @@ class ModelAdminFormInstructionsMixin:
56
58
  return extra_context
57
59
 
58
60
  def get_change_instructions(
59
- self, extra_context: dict | None, request: WSGIRequest | None = None
61
+ self,
62
+ extra_context: dict | None,
63
+ request: WSGIRequest | None = None, # noqa: ARG002
60
64
  ):
61
65
  extra_context = extra_context or {}
62
66
  extra_context["instructions"] = self.change_instructions or self.instructions
@@ -65,7 +69,9 @@ class ModelAdminFormInstructionsMixin:
65
69
  )
66
70
  return extra_context
67
71
 
68
- def add_view(self, request: WSGIRequest, form_url: str = "", extra_context: dict = None):
72
+ def add_view(
73
+ self, request: WSGIRequest, form_url: str = "", extra_context: dict | None = None
74
+ ):
69
75
  extra_context = self.get_add_instructions(extra_context, request=request)
70
76
  return super().add_view(request, form_url=form_url, extra_context=extra_context)
71
77
 
@@ -112,9 +112,9 @@ class ModelAdminNextUrlRedirectMixin(BaseModelAdminRedirectMixin):
112
112
  msg = f"{e}. Got url_name={url_name}, kwargs={options}."
113
113
  try:
114
114
  redirect_url = reverse(url_name) # retry without kwargs
115
- except NoReverseMatch:
115
+ except NoReverseMatch as e:
116
116
  # raise with first exception msg
117
- raise ModelAdminNextUrlRedirectError(msg)
117
+ raise ModelAdminNextUrlRedirectError(msg) from e
118
118
  else:
119
119
  if "q" in options and "changelist" in url_name:
120
120
  redirect_url = f"{redirect_url}?q={options['q']}"
@@ -163,7 +163,7 @@ class ModelAdminNextUrlRedirectMixin(BaseModelAdminRedirectMixin):
163
163
  )
164
164
  return None
165
165
 
166
- def get_next_options(self, request=None, **kwargs):
166
+ def get_next_options(self, request=None, **kwargs): # noqa: ARG002
167
167
  """Returns the key/value pairs from the "next" querystring
168
168
  as a dictionary.
169
169
  """
@@ -23,20 +23,20 @@ class ModelAdminProtectPiiMixin:
23
23
 
24
24
  extra_pii_attrs: tuple[str] | None = ()
25
25
 
26
- def get_extra_pii_attrs(self) -> list[str | tuple[str, str]]:
27
- return self.extra_pii_attrs or []
26
+ def get_extra_pii_attrs(self) -> tuple[str | tuple[str, str]]:
27
+ return self.extra_pii_attrs
28
28
 
29
29
  def get_encrypted_fields(self) -> tuple[str, ...]:
30
- encrypted_fields = [f.name for f in get_encrypted_fields(self.model)]
31
- encrypted_fields.extend(*self.get_extra_pii_attrs())
32
- return tuple(set(encrypted_fields))
30
+ encrypted_fields = tuple([f.name for f in get_encrypted_fields(self.model)])
31
+ return tuple({*encrypted_fields, *self.get_extra_pii_attrs()})
33
32
 
34
33
  def get_list_display(self, request) -> tuple[str]:
35
34
  list_display = super().get_list_display(request)
36
35
  if not request.user.groups.filter(name__in=[PII, PII_VIEW]).exists():
37
36
  # TODO: search replace from list_display if extra_pii_attr has tuple
38
- list_display = [f for f in list_display if f not in self.get_encrypted_fields()]
39
- list_display = tuple(list_display)
37
+ list_display = tuple(
38
+ *{f for f in list_display if f not in self.get_encrypted_fields()}
39
+ )
40
40
  return list_display
41
41
 
42
42
  def get_list_display_links(self, request, list_display) -> list[str] | None:
@@ -24,10 +24,10 @@ class ModelAdminRedirectOnDeleteMixin:
24
24
  self.post_url_on_delete = None
25
25
  super().__init__(*args)
26
26
 
27
- def get_post_url_on_delete_name(self, request) -> str:
27
+ def get_post_url_on_delete_name(self, request) -> str: # noqa: ARG002
28
28
  return url_names.get(self.post_url_on_delete_name)
29
29
 
30
- def get_post_full_url_on_delete(self, request) -> str | None:
30
+ def get_post_full_url_on_delete(self, request) -> str | None: # noqa: ARG002
31
31
  return self.post_full_url_on_delete
32
32
 
33
33
  def get_post_url_on_delete(self, request, obj) -> str | None:
@@ -50,14 +50,14 @@ class ModelAdminRedirectOnDeleteMixin:
50
50
  post_url_on_delete = f"{post_url_on_delete}?{querystring}"
51
51
  return post_url_on_delete
52
52
 
53
- def post_url_on_delete_kwargs(self, request, obj) -> dict:
53
+ def post_url_on_delete_kwargs(self, request, obj) -> dict: # noqa: ARG002
54
54
  """Returns kwargs needed to reverse the url.
55
55
 
56
56
  Override.
57
57
  """
58
58
  return {}
59
59
 
60
- def post_url_on_delete_querystring_kwargs(self, request, obj) -> dict:
60
+ def post_url_on_delete_querystring_kwargs(self, request, obj) -> dict: # noqa: ARG002
61
61
  """Returns kwargs for a querystring for the reversed url.
62
62
 
63
63
  Override.
@@ -75,10 +75,8 @@ class ModelAdminRedirectOnDeleteMixin:
75
75
  """Overridden to redirect to `post_url_on_delete`, if not None."""
76
76
  if self.post_url_on_delete:
77
77
  opts = self.model._meta
78
- msg = 'The %(name)s "%(obj)s" was deleted successfully.' % {
79
- "name": force_str(opts.verbose_name),
80
- "obj": force_str(obj_display),
81
- }
78
+ msg = (f'The {force_str(opts.verbose_name)} "{force_str(obj_display)}" '
79
+ 'was deleted successfully.')
82
80
  messages.add_message(request, messages.SUCCESS, msg)
83
81
  return HttpResponseRedirect(self.post_url_on_delete)
84
82
  return super().response_delete(request, obj_display, obj_id)
@@ -7,7 +7,7 @@ class PrintButtonAdminMixin:
7
7
  print_server_error = None
8
8
 
9
9
  def __init__(self, args, *kwargs):
10
- super(PrintButtonAdminMixin, self).__init__(*args, **kwargs)
10
+ super().__init__(*args, **kwargs)
11
11
  app_config = django_apps.get_app_config("edc_label")
12
12
  self._print_server = None
13
13
  self._printers = {}
@@ -8,12 +8,14 @@ class ApprovePrescription:
8
8
  def __init__(self, rx_model_obj=None):
9
9
  dispense_appointment = rx_model_obj.dispense_appointment
10
10
  previous_appointment = dispense_appointment.previous()
11
- if previous_appointment:
12
- if rx_model_obj.__class__.objects.filter(
11
+ if (
12
+ previous_appointment
13
+ and rx_model_obj.__class__.objects.filter(
13
14
  is_approved=False, dispense_appointment=previous_appointment
14
- ).exists():
15
- raise PrescriptionApprovalValidatorError(
16
- f"Future prescriptions cannot be approved. Approve "
17
- f"prescriptions for dispensing date "
18
- f"{previous_appointment.appt_datetime}"
19
- )
15
+ ).exists()
16
+ ):
17
+ raise PrescriptionApprovalValidatorError(
18
+ f"Future prescriptions cannot be approved. Approve "
19
+ f"prescriptions for dispensing date "
20
+ f"{previous_appointment.appt_datetime}"
21
+ )
@@ -20,7 +20,7 @@ PHARMACY_SUPER_ROLE = "PHARMACY_SUPER_ROLE"
20
20
  navbar_codenames = ["edc_pharmacy.nav_pharmacy_section"]
21
21
  navbar_tuples = []
22
22
  for codename in navbar_codenames:
23
- navbar_tuples.append((codename, f"Can access {codename.split('.')[1]}"))
23
+ navbar_tuples.append((codename, f"Can access {codename.split('.')[1]}")) # noqa: PERF401
24
24
 
25
25
 
26
26
  # central pharmacist
@@ -1,4 +1,4 @@
1
- class ActivePrescriptionRefillOverlap(Exception):
1
+ class ActivePrescriptionRefillOverlap(Exception): # noqa: N818
2
2
  pass
3
3
 
4
4
 
@@ -6,7 +6,7 @@ class RefillError(Exception):
6
6
  pass
7
7
 
8
8
 
9
- class ActiveRefillAlreadyExists(Exception):
9
+ class ActiveRefillAlreadyExists(Exception): # noqa: N818
10
10
  pass
11
11
 
12
12
 
@@ -34,7 +34,7 @@ class PackagingLotNumberMismatchError(Exception):
34
34
  pass
35
35
 
36
36
 
37
- class PrescriptionAlreadyExists(Exception):
37
+ class PrescriptionAlreadyExists(Exception): # noqa: N818
38
38
  pass
39
39
 
40
40
 
@@ -42,15 +42,15 @@ class PrescriptionError(Exception):
42
42
  pass
43
43
 
44
44
 
45
- class PrescriptionExpired(Exception):
45
+ class PrescriptionExpired(Exception): # noqa: N818
46
46
  pass
47
47
 
48
48
 
49
- class RefillAlreadyExists(Exception):
49
+ class RefillAlreadyExists(Exception): # noqa: N818
50
50
  pass
51
51
 
52
52
 
53
- class PrescriptionNotStarted(Exception):
53
+ class PrescriptionNotStarted(Exception): # noqa: N818
54
54
  pass
55
55
 
56
56
 
@@ -74,7 +74,7 @@ class InsufficientStockError(Exception):
74
74
  pass
75
75
 
76
76
 
77
- class InvalidContainer(Exception):
77
+ class InvalidContainer(Exception): # noqa: N818
78
78
  pass
79
79
 
80
80
 
edc_pharmacy/settings.py CHANGED
@@ -15,7 +15,7 @@ BASE_DIR = Path(__file__).resolve().parent.parent
15
15
  # See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/
16
16
 
17
17
  # SECURITY WARNING: keep the secret key used in production secret!
18
- SECRET_KEY = "django-insecure-+#-*m&byi1w8=#e5nr))^kollb=k1b#rvjffo#+teji^qpm14o" # nosec B105
18
+ SECRET_KEY = "django-insecure-+#-*m&byi1w8=#e5nr))^kollb=k1b#rvjffo#+teji^qpm14o" # nosec B105 # noqa: S105
19
19
 
20
20
  # SECURITY WARNING: don't run with debug turned on in production!
21
21
  DEBUG = True
@@ -95,8 +95,7 @@ class AddToStorageBinView(EdcViewMixin, NavbarViewMixin, EdcProtocolViewMixin, T
95
95
  def storage_bin_changelist_url(self) -> str:
96
96
  if self.storage_bin:
97
97
  url = reverse("edc_pharmacy_admin:edc_pharmacy_storagebin_changelist")
98
- url = f"{url}?q={self.storage_bin.bin_identifier}"
99
- return url
98
+ return f"{url}?q={self.storage_bin.bin_identifier}"
100
99
  return "/"
101
100
 
102
101
  def redirect_on_has_duplicates(
@@ -144,30 +143,29 @@ class AddToStorageBinView(EdcViewMixin, NavbarViewMixin, EdcProtocolViewMixin, T
144
143
  def redirect_on_invalid_subject_for_location(
145
144
  self, stock_codes: list[str], storage_bin: StorageBin
146
145
  ) -> HttpResponseRedirect | None:
147
- if stock_codes:
148
- if (
149
- Stock.objects.filter(code__in=stock_codes)
150
- .exclude(location=storage_bin.location)
151
- .exists()
152
- ):
153
- qs = Stock.objects.filter(code__in=stock_codes).exclude(
154
- location=storage_bin.location
155
- )
156
- messages.add_message(
157
- self.request,
158
- messages.ERROR,
159
- f"Stock not from this location. See {[obj.stock.code for obj in qs]}.",
160
- )
161
- url = reverse(
162
- "edc_pharmacy:add_to_storage_bin_url",
163
- kwargs={
164
- "storage_bin": storage_bin.id,
165
- },
166
- )
167
- return HttpResponseRedirect(url)
146
+ if stock_codes and (
147
+ Stock.objects.filter(code__in=stock_codes)
148
+ .exclude(location=storage_bin.location)
149
+ .exists()
150
+ ):
151
+ qs = Stock.objects.filter(code__in=stock_codes).exclude(
152
+ location=storage_bin.location
153
+ )
154
+ messages.add_message(
155
+ self.request,
156
+ messages.ERROR,
157
+ f"Stock not from this location. See {[obj.stock.code for obj in qs]}.",
158
+ )
159
+ url = reverse(
160
+ "edc_pharmacy:add_to_storage_bin_url",
161
+ kwargs={
162
+ "storage_bin": storage_bin.id,
163
+ },
164
+ )
165
+ return HttpResponseRedirect(url)
168
166
  return None
169
167
 
170
- def post(self, request, *args, **kwargs):
168
+ def post(self, request, *args, **kwargs): # noqa: ARG002
171
169
  stock_codes = request.POST.getlist("codes") if request.POST.get("codes") else None
172
170
  storage_bin = StorageBin.objects.get(id=kwargs.get("storage_bin"))
173
171
  items_to_scan = request.POST.get("items_to_scan") or kwargs.get("items_to_scan")
@@ -96,8 +96,7 @@ class AllocateToSubjectView(EdcViewMixin, NavbarViewMixin, EdcProtocolViewMixin,
96
96
  def stock_request_changelist_url(self) -> str:
97
97
  if self.stock_request:
98
98
  url = reverse("edc_pharmacy_admin:edc_pharmacy_stockrequest_changelist")
99
- url = f"{url}?q={self.stock_request.request_identifier}"
100
- return url
99
+ return f"{url}?q={self.stock_request.request_identifier}"
101
100
  return "/"
102
101
 
103
102
  @staticmethod
@@ -120,14 +119,13 @@ class AllocateToSubjectView(EdcViewMixin, NavbarViewMixin, EdcProtocolViewMixin,
120
119
  messages.ERROR,
121
120
  "Nothing saved. Duplicate codes detected in list. Please try again.",
122
121
  )
123
- url = reverse(
122
+ return reverse(
124
123
  "edc_pharmacy:allocate_url",
125
124
  kwargs={
126
125
  "stock_request": stock_request.id,
127
126
  "assignment": assignment.id,
128
127
  },
129
128
  )
130
- return url
131
129
  return None
132
130
 
133
131
  def redirect_on_uncomfirmed_stock_codes(
@@ -153,14 +151,13 @@ class AllocateToSubjectView(EdcViewMixin, NavbarViewMixin, EdcProtocolViewMixin,
153
151
  f"Got {uncomfirmed_codes}. "
154
152
  ),
155
153
  )
156
- url = reverse(
154
+ return reverse(
157
155
  "edc_pharmacy:allocate_url",
158
156
  kwargs={
159
157
  "stock_request": stock_request.id,
160
158
  "assignment": assignment.id,
161
159
  },
162
160
  )
163
- return url
164
161
  return None
165
162
 
166
163
  def redirect_on_invalid_stock_codes(
@@ -183,14 +180,13 @@ class AllocateToSubjectView(EdcViewMixin, NavbarViewMixin, EdcProtocolViewMixin,
183
180
  messages.ERROR,
184
181
  f"Nothing saved. Invalid codes detected. Got {invalid_codes}. ",
185
182
  )
186
- url = reverse(
183
+ return reverse(
187
184
  "edc_pharmacy:allocate_url",
188
185
  kwargs={
189
186
  "stock_request": stock_request.id,
190
187
  "assignment": assignment.id,
191
188
  },
192
189
  )
193
- return url
194
190
  return None
195
191
 
196
192
  def redirect_on_has_multiple_container_types(
@@ -211,14 +207,13 @@ class AllocateToSubjectView(EdcViewMixin, NavbarViewMixin, EdcProtocolViewMixin,
211
207
  f"only. See Stock request {stock_request.request_identifier} "
212
208
  ),
213
209
  )
214
- url = reverse(
210
+ return reverse(
215
211
  "edc_pharmacy:allocate_url",
216
212
  kwargs={
217
213
  "stock_request": stock_request.id,
218
214
  "assignment": assignment.id,
219
215
  },
220
216
  )
221
- return url
222
217
  return None
223
218
 
224
219
  def redirect_on_stock_already_allocated(
@@ -234,20 +229,19 @@ class AllocateToSubjectView(EdcViewMixin, NavbarViewMixin, EdcProtocolViewMixin,
234
229
  allocated_stock_codes = []
235
230
  for stock in Stock.objects.filter(code__in=stock_codes):
236
231
  if stock.allocation:
237
- allocated_stock_codes.append(stock.code)
232
+ allocated_stock_codes.append(stock.code) # noqa: PERF401
238
233
  messages.add_message(
239
234
  self.request,
240
235
  messages.ERROR,
241
236
  f"Stock already allocated. Got {','.join(allocated_stock_codes)}.",
242
237
  )
243
- url = reverse(
238
+ return reverse(
244
239
  "edc_pharmacy:allocate_url",
245
240
  kwargs={
246
241
  "stock_request": stock_request.id,
247
242
  "assignment": getattr(assignment, "id", None),
248
243
  },
249
244
  )
250
- return url
251
245
  return None
252
246
 
253
247
  def redirect_on_all_allocated_for_assignment(
@@ -265,14 +259,13 @@ class AllocateToSubjectView(EdcViewMixin, NavbarViewMixin, EdcProtocolViewMixin,
265
259
  )
266
260
  % {"assignment": assignment.display_name.upper()},
267
261
  )
268
- url = reverse(
262
+ return reverse(
269
263
  "edc_pharmacy:allocate_url",
270
264
  kwargs={
271
265
  "stock_request": stock_request.id,
272
266
  "assignment": getattr(assignment, "id", None),
273
267
  },
274
268
  )
275
- return url
276
269
  return None
277
270
 
278
271
  def redirect_on_incorrect_stock_for_assignment(
@@ -292,14 +285,13 @@ class AllocateToSubjectView(EdcViewMixin, NavbarViewMixin, EdcProtocolViewMixin,
292
285
  f"Expected `{assignment.display_name}` only. Check your work."
293
286
  ),
294
287
  )
295
- url = reverse(
288
+ return reverse(
296
289
  "edc_pharmacy:allocate_url",
297
290
  kwargs={
298
291
  "stock_request": stock_request.id,
299
292
  "assignment": getattr(assignment, "id", None),
300
293
  },
301
294
  )
302
- return url
303
295
  return None
304
296
 
305
297
  def get_counts(self, stock_request: StockRequest) -> tuple[int, int]:
@@ -315,7 +307,7 @@ class AllocateToSubjectView(EdcViewMixin, NavbarViewMixin, EdcProtocolViewMixin,
315
307
  return remaining_count or 0, total_count
316
308
  return 0, 0
317
309
 
318
- def post(self, request, *args, **kwargs):
310
+ def post(self, request, *args, **kwargs): # noqa: ARG002
319
311
  stock_codes = request.POST.getlist("codes") if request.POST.get("codes") else None
320
312
  subject_identifiers = request.POST.get("subject_identifiers")
321
313
  assignment_id = request.POST.get("assignment")
@@ -4,8 +4,7 @@ from django.views import View
4
4
 
5
5
 
6
6
  class CeleryTaskStatusView(View):
7
-
8
- def get(self, request, *args, **kwargs):
7
+ def get(self, request, *args, **kwargs): # noqa: ARG002
9
8
  task_id = request.GET.get("task_id")
10
9
  response_data = {"task_id": task_id, "status": None}
11
10
  try:
@@ -90,7 +90,7 @@ class ConfirmStockFromInstanceView(
90
90
  def model_cls(self):
91
91
  return django_apps.get_model(f"edc_pharmacy.{self.kwargs.get('model')}")
92
92
 
93
- def post(self, request, *args, **kwargs):
93
+ def post(self, request, *args, **kwargs): # noqa: ARG002
94
94
  dct = self.get_values_dict(**kwargs)
95
95
  codes = request.POST.getlist("codes")
96
96
  confirmed, already_confirmed, invalid = confirm_stock(
@@ -29,8 +29,8 @@ class ConfirmStockFromQuerySetView(
29
29
  navbar_selected_item = "pharmacy"
30
30
  codes_per_page = 12
31
31
 
32
- def get_context_data(self, **kwargs):
33
- context = dict(
32
+ def get_context_data(self, **kwargs): # noqa: ARG002
33
+ return dict(
34
34
  CONFIRMED=CONFIRMED,
35
35
  ALREADY_CONFIRMED=ALREADY_CONFIRMED,
36
36
  INVALID=INVALID,
@@ -40,7 +40,6 @@ class ConfirmStockFromQuerySetView(
40
40
  source_changelist_url=self.source_changelist_url,
41
41
  **self.session_data,
42
42
  )
43
- return context
44
43
 
45
44
  @property
46
45
  def session_data(self):
@@ -58,10 +57,8 @@ class ConfirmStockFromQuerySetView(
58
57
  [
59
58
  x,
60
59
  ALREADY_CONFIRMED,
61
- _(
62
- "already %(transaction_word)s"
63
- % {"transaction_word": transaction_word}
64
- ),
60
+ _("already %(transaction_word)s")
61
+ % {"transaction_word": transaction_word},
65
62
  ]
66
63
  for x in session_obj.get("already_confirmed_codes") or []
67
64
  ]
@@ -117,7 +114,7 @@ class ConfirmStockFromQuerySetView(
117
114
  label_lower = self.session_data.get("source_label_lower")
118
115
  return django_apps.get_model(label_lower)
119
116
 
120
- def post(self, request, *args, **kwargs):
117
+ def post(self, request, *args, **kwargs): # noqa: ARG002
121
118
  stock_codes = request.POST.getlist("stock_codes")
122
119
  if len(stock_codes) != len(list(set(stock_codes))):
123
120
  messages.add_message(
@@ -85,7 +85,7 @@ class DispenseView(EdcViewMixin, NavbarViewMixin, EdcProtocolViewMixin, Template
85
85
  )
86
86
  return confirmation_at_site
87
87
 
88
- def post(self, request, *args, **kwargs):
88
+ def post(self, request, *args, **kwargs): # noqa: ARG002
89
89
  location_id = request.POST.get("location_id")
90
90
  location = Location.objects.get(pk=location_id)
91
91
  formulation_id = request.POST.get("formulation_id")
@@ -11,6 +11,7 @@ from ..models import Stock, StorageBin, StorageBinItem
11
11
  from .add_to_storage_bin_view import AddToStorageBinView, StorageBinError
12
12
 
13
13
  p = inflect.engine()
14
+ MAX_STORAGE_BIN_CAPACITY = 50
14
15
 
15
16
 
16
17
  def move_to_bin(
@@ -25,8 +26,11 @@ def move_to_bin(
25
26
  new_capacity = StorageBinItem.objects.filter(storage_bin=storage_bin).count() + len(
26
27
  stock_codes
27
28
  )
28
- if new_capacity > 50:
29
- raise StorageBinError(f"Storage bin {storage_bin.name} capacity may not exceeded 50")
29
+ if new_capacity > MAX_STORAGE_BIN_CAPACITY:
30
+ raise StorageBinError(
31
+ f"Storage bin {storage_bin.name} capacity "
32
+ f"may not exceeded {MAX_STORAGE_BIN_CAPACITY}."
33
+ )
30
34
  if new_capacity > storage_bin.capacity:
31
35
  storage_bin.capacity = new_capacity
32
36
  storage_bin.save()
@@ -89,7 +93,7 @@ class MoveToStorageBinView(AddToStorageBinView):
89
93
  return HttpResponseRedirect(url)
90
94
  return None
91
95
 
92
- def post(self, request, *args, **kwargs):
96
+ def post(self, request, *args, **kwargs): # noqa: ARG002
93
97
  stock_codes = request.POST.getlist("codes") if request.POST.get("codes") else None
94
98
  storage_bin = StorageBin.objects.get(id=kwargs.get("storage_bin"))
95
99
  items_to_scan = request.POST.get("items_to_scan") or kwargs.get("items_to_scan")