clinicedc 2.0.7__py3-none-any.whl → 2.0.8__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 (140) hide show
  1. {clinicedc-2.0.7.dist-info → clinicedc-2.0.8.dist-info}/METADATA +1 -1
  2. {clinicedc-2.0.7.dist-info → clinicedc-2.0.8.dist-info}/RECORD +134 -137
  3. {clinicedc-2.0.7.dist-info → clinicedc-2.0.8.dist-info}/WHEEL +1 -1
  4. edc_action_item/auths.py +37 -32
  5. edc_action_item/models/action_model_mixin.py +1 -2
  6. edc_action_item/models/signals.py +22 -23
  7. edc_action_item/site_action_items.py +5 -9
  8. edc_action_item/utils.py +3 -3
  9. edc_adverse_event/auths.py +55 -51
  10. edc_adverse_event/model_mixins/ae_tmg/ae_tmg_methods_model_mixin.py +2 -4
  11. edc_appointment/auths.py +14 -10
  12. edc_appointment/creators/appointment_creator.py +1 -1
  13. edc_appointment/creators/appointments_creator.py +1 -1
  14. edc_appointment/model_mixins/appointment_methods_model_mixin.py +2 -3
  15. edc_appointment/model_mixins/appointment_model_mixin.py +31 -28
  16. edc_appointment/models/appointment.py +1 -1
  17. edc_appointment/utils.py +19 -24
  18. edc_auth/auth_objects/__init__.py +2 -20
  19. edc_auth/auth_objects/default_groups.py +13 -11
  20. edc_auth/auth_objects/default_roles.py +26 -24
  21. edc_auth/auth_updater/auth_updater.py +13 -2
  22. edc_auth/auth_updater/group_updater.py +12 -10
  23. edc_auth/auth_updater/role_updater.py +2 -2
  24. edc_auth/constants.py +10 -0
  25. edc_auth/import_users.py +3 -3
  26. edc_auth/models/user_profile.py +14 -11
  27. edc_auth/site_auths.py +80 -67
  28. edc_consent/auths.py +18 -12
  29. edc_constants/constants.py +1 -0
  30. edc_crf/auths.py +5 -0
  31. edc_dashboard/auths.py +10 -6
  32. edc_dashboard/url_config.py +92 -83
  33. edc_dashboard/url_names.py +4 -4
  34. edc_dashboard/view_mixins/url_request_context_mixin.py +6 -5
  35. edc_data_manager/admin/data_query_admin.py +12 -11
  36. edc_data_manager/auths.py +37 -34
  37. edc_data_manager/rule/query_rule_wrapper.py +7 -7
  38. edc_export/archive_exporter.py +3 -2
  39. edc_export/auths.py +32 -28
  40. edc_export/model_exporter/model_exporter.py +4 -1
  41. edc_facility/auths.py +8 -3
  42. edc_facility/facility.py +8 -9
  43. edc_form_label/custom_label_condition.py +11 -8
  44. edc_form_label/form_label.py +1 -1
  45. edc_form_runners/auths.py +11 -6
  46. edc_form_validators/applicable_field_validator.py +7 -6
  47. edc_form_validators/base_form_validator.py +8 -9
  48. edc_form_validators/other_specify_field_validator.py +2 -8
  49. edc_form_validators/required_field_validator.py +19 -16
  50. edc_identifier/research_identifier.py +11 -10
  51. edc_identifier/simple_identifier.py +8 -2
  52. edc_lab/auths.py +26 -23
  53. edc_lab/lab/aliquot_creator.py +5 -8
  54. edc_lab/lab/primary_aliquot.py +14 -5
  55. edc_lab/model_mixins/requisition/requisition_model_mixin.py +6 -8
  56. edc_lab/models/aliquot.py +2 -2
  57. edc_lab/models/manifest/manifest.py +2 -2
  58. edc_lab/models/manifest/manifest_item.py +1 -1
  59. edc_lab_dashboard/auths.py +16 -11
  60. edc_lab_results/calculate_missing.py +8 -8
  61. edc_lab_results/form_validator_mixins/blood_results_form_validator_mixin.py +2 -2
  62. edc_lab_results/get_summary.py +26 -25
  63. edc_lab_results/model_mixins/blood_result_model_mixin.py +2 -0
  64. edc_label/auths.py +6 -1
  65. edc_label/label_template.py +8 -8
  66. edc_list_data/load_model_data.py +3 -3
  67. edc_list_data/post_migrate_signals.py +1 -1
  68. edc_list_data/preload_data.py +2 -2
  69. edc_list_data/row.py +1 -1
  70. edc_list_data/site_list_data.py +6 -5
  71. edc_locator/auths.py +18 -13
  72. edc_metadata/auths.py +11 -7
  73. edc_metadata/metadata/metadata.py +1 -1
  74. edc_metadata/metadata_rules/crf/crf_rule.py +1 -1
  75. edc_metadata/metadata_rules/metadata_rule_evaluator.py +5 -3
  76. edc_metadata/metadata_rules/rule.py +2 -3
  77. edc_metadata/metadata_rules/rule_evaluator.py +1 -1
  78. edc_metadata/model_mixins/updates/updates_crf_metadata_model_mixin.py +7 -4
  79. edc_metadata/model_mixins/updates/updates_requisition_metadata_model_mixin.py +5 -2
  80. edc_metadata/models/signals.py +10 -11
  81. edc_navbar/auths.py +18 -13
  82. edc_notification/auths.py +9 -4
  83. edc_notification/notification/graded_event_notification.py +2 -2
  84. edc_notification/notification/model_notification.py +3 -30
  85. edc_notification/notification/new_model_notification.py +1 -1
  86. edc_notification/notification/notification.py +1 -1
  87. edc_notification/notification/updated_model_notification.py +2 -2
  88. edc_offstudy/auths.py +12 -7
  89. edc_pdutils/df_exporters/csv_model_exporter.py +5 -2
  90. edc_pharmacy/auths.py +19 -15
  91. edc_pharmacy/models/medication/formulation.py +5 -7
  92. edc_pharmacy/prescribe/create_prescription.py +3 -3
  93. edc_pharmacy/utils/confirm_stock.py +1 -1
  94. edc_pharmacy/utils/confirm_stock_at_site.py +1 -1
  95. edc_pharmacy/views/confirmation_at_site_view.py +6 -9
  96. edc_prn/admin_site.py +5 -0
  97. edc_prn/prn.py +10 -11
  98. edc_prn/urls.py +11 -0
  99. edc_protocol_incident/action_items.py +4 -4
  100. edc_protocol_incident/auths.py +27 -20
  101. edc_pylabels/auths.py +6 -1
  102. edc_qareports/auths.py +11 -7
  103. edc_randomization/admin.py +30 -24
  104. edc_randomization/auths.py +12 -7
  105. edc_randomization/randomizer.py +22 -20
  106. edc_randomization/utils.py +17 -16
  107. edc_refusal/auths.py +7 -2
  108. edc_refusal/model_mixins.py +1 -1
  109. edc_registration/auths.py +28 -23
  110. edc_registration/model_mixins/updates_or_creates_registered_subject_model_mixin.py +13 -4
  111. edc_registration/models/registered_subject.py +1 -1
  112. edc_reportable/utils/get_reference_range_collection.py +2 -3
  113. edc_reportable/utils/load_data.py +1 -1
  114. edc_review_dashboard/auths.py +23 -18
  115. edc_screening/age_evaluator.py +3 -3
  116. edc_screening/auths.py +35 -30
  117. edc_screening/eligibility.py +1 -1
  118. edc_screening/gender_evaluator.py +1 -1
  119. edc_screening/model_mixins/eligibility_model_mixin.py +0 -2
  120. edc_screening/model_mixins/screening_methods_model_mixin.py +1 -1
  121. edc_screening/screening_eligibility.py +2 -4
  122. edc_screening/utils.py +9 -9
  123. edc_search/generate_slug.py +26 -0
  124. edc_search/model_mixins.py +10 -21
  125. edc_sites/auths.py +8 -3
  126. edc_subject_dashboard/auths.py +27 -22
  127. edc_timepoint/apps.py +0 -21
  128. edc_unblinding/auths.py +9 -4
  129. edc_utils/__init__.py +3 -1
  130. edc_utils/show_urls.py +29 -2
  131. edc_visit_schedule/auths.py +6 -1
  132. edc_visit_schedule/site_visit_schedules.py +2 -2
  133. edc_visit_tracking/models/signals.py +2 -2
  134. edc_form_label/models.py +0 -0
  135. edc_search/constants.py +0 -1
  136. edc_search/models.py +0 -0
  137. edc_search/search_slug.py +0 -51
  138. edc_search/updater.py +0 -30
  139. edc_search/wsgi.py +0 -7
  140. {clinicedc-2.0.7.dist-info → clinicedc-2.0.8.dist-info}/licenses/LICENSE +0 -0
@@ -17,10 +17,10 @@ class ModelNotification(Notification):
17
17
 
18
18
  model: str | None = None # label_lower format
19
19
 
20
- model_operations = [CREATE, UPDATE, DELETE]
20
+ model_operations: tuple[str] = (CREATE, UPDATE, DELETE)
21
21
 
22
- create_fields = ["created"]
23
- update_fields = ["modified"]
22
+ create_fields: tuple[str] = ("created",)
23
+ update_fields: tuple[str] = ("modified",)
24
24
 
25
25
  email_body_template: str = (
26
26
  "\n\nDo not reply to this email\n\n"
@@ -177,30 +177,3 @@ class ModelNotification(Notification):
177
177
  )
178
178
 
179
179
  return opts
180
-
181
- # @property
182
- # def test_template_options(self) -> dict:
183
- # class Site:
184
- # domain = "gaborone.example.com"
185
- # name = "gaborone"
186
- # id = 99
187
- #
188
- # class Meta:
189
- # label_lower = self.model
190
- #
191
- # class DummyHistory:
192
- # def __init__(self, objects):
193
- # self._objects = objects
194
- #
195
- # def all(self):
196
- # return self._objects
197
- #
198
- # class DummyInstance:
199
- # id = 99
200
- # subject_identifier = "123456910"
201
- # site = Site()
202
- # _meta = Meta()
203
- #
204
- # instance = DummyInstance()
205
- # instance.history = DummyHistory(objects=[instance])
206
- # return dict(instance=instance)
@@ -3,4 +3,4 @@ from .model_notification import ModelNotification
3
3
 
4
4
 
5
5
  class NewModelNotification(ModelNotification):
6
- model_operations = [CREATE]
6
+ model_operations = (CREATE,)
@@ -214,7 +214,7 @@ class Notification:
214
214
 
215
215
  def send_email(
216
216
  self,
217
- email_to: list[str],
217
+ email_to: list[str] | None = None,
218
218
  fail_silently: bool | None = None,
219
219
  email_body_template: str | None = None,
220
220
  **kwargs,
@@ -3,9 +3,9 @@ from .model_notification import ModelNotification
3
3
 
4
4
 
5
5
  class UpdatedModelNotification(ModelNotification):
6
- model_operations = [UPDATE]
6
+ model_operations = (UPDATE,)
7
7
 
8
- update_fields = ["modified"]
8
+ update_fields = ("modified",)
9
9
 
10
10
  email_subject_template = (
11
11
  "*UPDATE* {test_subject_line}{protocol_name}: "
edc_offstudy/auths.py CHANGED
@@ -8,10 +8,15 @@ from edc_auth.site_auths import site_auths
8
8
 
9
9
  from .auth_objects import OFFSTUDY, OFFSTUDY_SUPER, OFFSTUDY_VIEW, codenames
10
10
 
11
- site_auths.add_group(*codenames, name=OFFSTUDY, no_delete=True)
12
- site_auths.add_group(*codenames, name=OFFSTUDY_SUPER)
13
- site_auths.add_group(*codenames, name=OFFSTUDY_VIEW, view_only=True)
14
- site_auths.update_role(OFFSTUDY, name=CLINICIAN_ROLE)
15
- site_auths.update_role(OFFSTUDY, name=NURSE_ROLE)
16
- site_auths.update_role(OFFSTUDY_SUPER, name=CLINICIAN_SUPER_ROLE)
17
- site_auths.update_role(OFFSTUDY_VIEW, name=AUDITOR_ROLE)
11
+
12
+ def update_site_auths():
13
+ site_auths.add_group(*codenames, name=OFFSTUDY, no_delete=True)
14
+ site_auths.add_group(*codenames, name=OFFSTUDY_SUPER)
15
+ site_auths.add_group(*codenames, name=OFFSTUDY_VIEW, view_only=True)
16
+ site_auths.update_role(OFFSTUDY, name=CLINICIAN_ROLE)
17
+ site_auths.update_role(OFFSTUDY, name=NURSE_ROLE)
18
+ site_auths.update_role(OFFSTUDY_SUPER, name=CLINICIAN_SUPER_ROLE)
19
+ site_auths.update_role(OFFSTUDY_VIEW, name=AUDITOR_ROLE)
20
+
21
+
22
+ update_site_auths()
@@ -30,6 +30,7 @@ class CsvModelExporter:
30
30
  **kwargs,
31
31
  ):
32
32
  self.model = model or queryset.model._meta.label_lower
33
+ self.export_folder = export_folder
33
34
  self.df_maker = self.df_maker_cls(
34
35
  model=model,
35
36
  queryset=queryset,
@@ -46,8 +47,10 @@ class CsvModelExporter:
46
47
 
47
48
  def to_csv(self):
48
49
  dataframe = self.df_maker.dataframe
49
- return self.csv_exporter.to_csv(dataframe=dataframe)
50
+ return self.csv_exporter.to_csv(dataframe=dataframe, export_folder=self.export_folder)
50
51
 
51
52
  def to_stata(self):
52
53
  dataframe = self.df_maker.dataframe
53
- return self.csv_exporter.to_stata(dataframe=dataframe)
54
+ return self.csv_exporter.to_stata(
55
+ dataframe=dataframe, export_folder=self.export_folder
56
+ )
edc_pharmacy/auths.py CHANGED
@@ -18,21 +18,25 @@ from .auth_objects import (
18
18
  prescriber_codenames,
19
19
  )
20
20
 
21
- site_auths.add_post_update_func(
22
- "edc_pharmacy", remove_default_model_permissions_from_edc_permissions
23
- )
24
- site_auths.add_custom_permissions_tuples(
25
- model="edc_pharmacy.edcpermissions", codename_tuples=navbar_tuples
26
- )
27
21
 
28
- site_auths.add_group(*pharmacy_codenames, name=PHARMACY_VIEW, view_only=True)
29
- site_auths.add_group(*prescriber_codenames, name=PHARMACY_PRESCRIBER, no_delete=True)
30
- site_auths.add_group(*pharmacy_site_codenames, name=PHARMACY_SITE, no_delete=False)
31
- site_auths.add_group(*pharmacy_codenames, name=PHARMACY, no_delete=False)
22
+ def update_site_auths() -> None:
23
+ site_auths.add_post_update_func(
24
+ "edc_pharmacy", remove_default_model_permissions_from_edc_permissions
25
+ )
26
+ site_auths.add_custom_permissions_tuples(
27
+ model="edc_pharmacy.edcpermissions", codename_tuples=navbar_tuples
28
+ )
29
+
30
+ site_auths.add_group(*pharmacy_codenames, name=PHARMACY_VIEW, view_only=True)
31
+ site_auths.add_group(*prescriber_codenames, name=PHARMACY_PRESCRIBER, no_delete=True)
32
+ site_auths.add_group(*pharmacy_site_codenames, name=PHARMACY_SITE, no_delete=False)
33
+ site_auths.add_group(*pharmacy_codenames, name=PHARMACY, no_delete=False)
34
+
35
+ site_auths.add_role(PHARMACY_VIEW, name=PHARMACY_AUDITOR_ROLE)
36
+ site_auths.add_role(PHARMACY_PRESCRIBER, name=PHARMACY_PRESCRIBER_ROLE)
37
+ site_auths.add_role(PHARMACY_SITE, PYLABELS, name=SITE_PHARMACIST_ROLE)
38
+ site_auths.add_role(PHARMACY, PYLABELS, name=PHARMACIST_ROLE)
39
+ site_auths.add_role(PHARMACY, name=PHARMACY_SUPER_ROLE)
32
40
 
33
41
 
34
- site_auths.add_role(PHARMACY_VIEW, name=PHARMACY_AUDITOR_ROLE)
35
- site_auths.add_role(PHARMACY_PRESCRIBER, name=PHARMACY_PRESCRIBER_ROLE)
36
- site_auths.add_role(PHARMACY_SITE, PYLABELS, name=SITE_PHARMACIST_ROLE)
37
- site_auths.add_role(PHARMACY, PYLABELS, name=PHARMACIST_ROLE)
38
- site_auths.add_role(PHARMACY, name=PHARMACY_SUPER_ROLE)
42
+ update_site_auths()
@@ -61,18 +61,17 @@ class Formulation(BaseUuidModel):
61
61
  def save(self, *args, **kwargs):
62
62
  self.description = self.get_description()
63
63
  if not self.imp:
64
- self.imp_description = None
64
+ self.imp_description = ""
65
65
  else:
66
66
  self.imp_description = (
67
67
  self.imp_description if self.imp_description else self.description
68
68
  )
69
69
  super().save(*args, **kwargs)
70
70
 
71
- def get_description(self):
71
+ def get_description(self) -> str:
72
72
  return (
73
73
  f"{self.medication} {round_half_away_from_zero(self.strength, 0)}"
74
74
  f"{self.get_units_display()} "
75
- # f"{self.get_formulation_type_display()} "
76
75
  f"{self.get_route_display()}"
77
76
  )
78
77
 
@@ -80,7 +79,6 @@ class Formulation(BaseUuidModel):
80
79
  return (
81
80
  f"{self.medication} {round_half_away_from_zero(self.strength, 0)}"
82
81
  f"{self.get_units_display()} "
83
- # f"{self.get_formulation_type_display()} "
84
82
  )
85
83
 
86
84
  def get_description_with_assignment(self, assignment: Assignment) -> str:
@@ -103,9 +101,9 @@ class Formulation(BaseUuidModel):
103
101
  class Meta(BaseUuidModel.Meta):
104
102
  verbose_name = "Formulation"
105
103
  verbose_name_plural = "Formulations"
106
- constraints = [
104
+ constraints = (
107
105
  UniqueConstraint(
108
106
  fields=["medication", "strength", "units", "formulation_type"],
109
107
  name="%(app_label)s_%(class)s_med_stren_uniq",
110
- )
111
- ]
108
+ ),
109
+ )
@@ -30,11 +30,11 @@ def create_prescription(
30
30
  for medication_name in medication_names:
31
31
  try:
32
32
  obj = medication_model_cls.objects.get(name__iexact=medication_name)
33
- except ObjectDoesNotExist:
33
+ except ObjectDoesNotExist as e:
34
34
  raise PrescriptionError(
35
35
  "Unable to create prescription. Medication does not exist. "
36
36
  f"Got {medication_name}"
37
- )
37
+ ) from e
38
38
  else:
39
39
  medications.append(obj)
40
40
  try:
@@ -51,7 +51,7 @@ def create_prescription(
51
51
  try:
52
52
  rx = rx_model_cls.objects.create(**opts)
53
53
  except ObjectDoesNotExist as e:
54
- raise CommandError(f"Site does not exists. site_id={site_id}. Got {e}")
54
+ raise CommandError(f"Site does not exists. site_id={site_id}. Got {e}") from e
55
55
  for obj in medications:
56
56
  rx.medications.add(obj)
57
57
  else:
@@ -15,7 +15,7 @@ def confirm_stock(
15
15
  stock_codes: list[str],
16
16
  fk_attr: str | None = None,
17
17
  confirmed_by: str | None = None,
18
- user_created: str = None,
18
+ user_created: str | None = None,
19
19
  ) -> tuple[list[str], list[str], list[str]]:
20
20
  """Confirm stock instances given a list of stock codes
21
21
  and a request/receive pk.
@@ -26,7 +26,7 @@ def confirm_stock_at_site(
26
26
  stock_transfer: StockTransfer,
27
27
  stock_codes: list[str],
28
28
  location: UUID,
29
- request: WSGIRequest = None,
29
+ request: WSGIRequest | None = None,
30
30
  ) -> tuple[list[str], list[str], list[str]]:
31
31
  """Confirm stock instances given a list of stock codes
32
32
  and a request/receive pk.
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import contextlib
3
4
  import uuid
4
5
  from uuid import uuid4
5
6
 
@@ -97,13 +98,12 @@ class ConfirmationAtSiteView(
97
98
  return min(unconfirmed_count, 12)
98
99
 
99
100
  def get_stock_codes(self, stock_transfer):
100
- stock_codes = [
101
+ return [
101
102
  code
102
103
  for code in stock_transfer.stocktransferitem_set.values_list(
103
104
  "stock__code", flat=True
104
105
  ).all()
105
106
  ]
106
- return stock_codes
107
107
 
108
108
  def get_unconfirmed_count(self, stock_transfer) -> int:
109
109
  return (
@@ -120,10 +120,8 @@ class ConfirmationAtSiteView(
120
120
  def site(self) -> Site | None:
121
121
  obj = None
122
122
  if self.kwargs.get("site_id"):
123
- try:
123
+ with contextlib.suppress(ObjectDoesNotExist):
124
124
  obj = Site.objects.get(id=self.kwargs.get("site_id"))
125
- except ObjectDoesNotExist:
126
- pass
127
125
  return obj
128
126
 
129
127
  @property
@@ -169,14 +167,13 @@ class ConfirmationAtSiteView(
169
167
  def confirmation_at_site_changelist_url(self) -> str:
170
168
  if self.confirmation_at_site:
171
169
  url = reverse("edc_pharmacy_admin:edc_pharmacy_confirmationatsite_changelist")
172
- url = f"{url}?q={self.confirmation_at_site.transfer_confirmation_identifier}"
173
- return url
170
+ return f"{url}?q={self.confirmation_at_site.transfer_confirmation_identifier}"
174
171
  return "/"
175
172
 
176
173
  def get_stock_transfer(
177
174
  self,
178
175
  stock_transfer_identifier: str,
179
- suppress_msg: bool = None,
176
+ suppress_msg: bool | None = None,
180
177
  ) -> StockTransfer | None:
181
178
  stock_transfer = None
182
179
  try:
@@ -198,7 +195,7 @@ class ConfirmationAtSiteView(
198
195
  )
199
196
  return stock_transfer
200
197
 
201
- def post(self, request, *args, **kwargs) -> HttpResponseRedirect:
198
+ def post(self, request, *args, **kwargs) -> HttpResponseRedirect: # noqa: ARG002
202
199
  # cancel
203
200
  if request.POST.get("cancel") and request.POST.get("cancel") == "cancel":
204
201
  url = reverse("edc_pharmacy:home_url")
edc_prn/admin_site.py ADDED
@@ -0,0 +1,5 @@
1
+ from edc_model_admin.admin_site import EdcAdminSite
2
+
3
+ from .apps import AppConfig
4
+
5
+ edc_prn_admin = EdcAdminSite(name="edc_prn_admin", app_label=AppConfig.name)
edc_prn/prn.py CHANGED
@@ -58,19 +58,18 @@ class Prn:
58
58
  try:
59
59
  return django_apps.get_model(self.model)
60
60
  except LookupError as e:
61
- raise PrnError(f"{e}. See {self!r}")
61
+ raise PrnError(f"{e}. See {self!r}") from e
62
62
 
63
- def get_show_on_dashboard(self, subject_identifier=None, **kwargs):
63
+ def get_show_on_dashboard(self, subject_identifier=None, **kwargs): # noqa: ARG002
64
64
  count = 0
65
- if self.show_on_dashboard:
66
- if subject_identifier:
67
- opts = dict(subject_identifier=subject_identifier)
68
- try:
69
- count = self.model_cls.objects.filter(**opts).count()
70
- except FieldError:
71
- opts = self.get_query_opts(subject_identifier)
72
- count = self.model_cls.objects.filter(**opts).count()
73
- return True if count and self.show_on_dashboard else False
65
+ if self.show_on_dashboard and subject_identifier:
66
+ opts = dict(subject_identifier=subject_identifier)
67
+ try:
68
+ count = self.model_cls.objects.filter(**opts).count()
69
+ except FieldError:
70
+ opts = self.get_query_opts(subject_identifier)
71
+ count = self.model_cls.objects.filter(**opts).count()
72
+ return count and self.show_on_dashboard
74
73
 
75
74
  def get_query_opts(self, subject_identifier):
76
75
  """Returns alternative query opts to search on
edc_prn/urls.py ADDED
@@ -0,0 +1,11 @@
1
+ from django.urls import path
2
+ from django.views.generic.base import RedirectView
3
+
4
+ from .admin_site import edc_prn_admin
5
+
6
+ app_name = "edc_prn"
7
+
8
+ urlpatterns = [
9
+ path("admin/", edc_prn_admin.urls),
10
+ path("", RedirectView.as_view(url="admin/"), name="home_url"),
11
+ ]
@@ -9,8 +9,8 @@ from .constants import (
9
9
 
10
10
 
11
11
  class ProtocolDeviationViolationAction(ActionWithNotification):
12
- reference_model = None # "my_app.protocolincident"
13
- admin_site_name = None # "my_app_admin"
12
+ reference_model = "edc_protocol_incident.protocoldeviationviolation"
13
+ admin_site_name = "edc_protocol_incident_admin"
14
14
 
15
15
  name = PROTOCOL_DEVIATION_VIOLATION_ACTION
16
16
  display_name = "Submit Protocol Deviation / Violation Report"
@@ -25,8 +25,8 @@ class ProtocolDeviationViolationAction(ActionWithNotification):
25
25
 
26
26
 
27
27
  class ProtocolIncidentAction(ActionWithNotification):
28
- reference_model = None # "my_app.protocolincident"
29
- admin_site_name = None # "my_app"
28
+ reference_model = "edc_protocol_incident.protocolincident"
29
+ admin_site_name = "edc_protocol_incident_admin"
30
30
 
31
31
  name = PROTOCOL_INCIDENT_ACTION
32
32
  display_name = "Submit Protocol Incident Report"
@@ -14,24 +14,31 @@ from .auth_objects import (
14
14
  )
15
15
  from .constants import PROTOCOL_DEVIATION_VIOLATION, PROTOCOL_INCIDENT
16
16
 
17
- incident_type = getattr(settings, "EDC_PROTOCOL_VIOLATION_TYPE", PROTOCOL_DEVIATION_VIOLATION)
18
-
19
- site_auths.add_group(*protocol_violation_codenames, name=PROTOCOL_VIOLATION)
20
- site_auths.add_group(*protocol_violation_view_codenames, name=PROTOCOL_VIOLATION_VIEW)
21
- site_auths.add_group(*protocol_incident_codenames, name=PROTOCOL_INCIDENT)
22
- site_auths.add_group(*protocol_incident_view_codenames, name=PROTOCOL_INCIDENT_VIEW)
23
-
24
- if incident_type == PROTOCOL_DEVIATION_VIOLATION:
25
- site_auths.update_role(PROTOCOL_VIOLATION, name=CLINICIAN_ROLE)
26
- site_auths.update_role(PROTOCOL_VIOLATION, name=CLINICIAN_SUPER_ROLE)
27
- site_auths.update_role(PROTOCOL_VIOLATION_VIEW, name=AUDITOR_ROLE)
28
- elif incident_type == PROTOCOL_INCIDENT:
29
- site_auths.update_role(PROTOCOL_INCIDENT, name=CLINICIAN_ROLE)
30
- site_auths.update_role(PROTOCOL_INCIDENT, name=CLINICIAN_SUPER_ROLE)
31
- site_auths.update_role(PROTOCOL_INCIDENT_VIEW, name=AUDITOR_ROLE)
32
- else:
33
- raise ValueError(
34
- "Invalid value for settings.EDC_PROTOCOL_VIOLATION_TYPE. "
35
- f"Expected `{PROTOCOL_INCIDENT}` or `{PROTOCOL_DEVIATION_VIOLATION}`. "
36
- f"Got {incident_type}."
17
+
18
+ def update_site_auths() -> None:
19
+ incident_type = getattr(
20
+ settings, "EDC_PROTOCOL_VIOLATION_TYPE", PROTOCOL_DEVIATION_VIOLATION
37
21
  )
22
+
23
+ site_auths.add_group(*protocol_violation_codenames, name=PROTOCOL_VIOLATION)
24
+ site_auths.add_group(*protocol_violation_view_codenames, name=PROTOCOL_VIOLATION_VIEW)
25
+ site_auths.add_group(*protocol_incident_codenames, name=PROTOCOL_INCIDENT)
26
+ site_auths.add_group(*protocol_incident_view_codenames, name=PROTOCOL_INCIDENT_VIEW)
27
+
28
+ if incident_type == PROTOCOL_DEVIATION_VIOLATION:
29
+ site_auths.update_role(PROTOCOL_VIOLATION, name=CLINICIAN_ROLE)
30
+ site_auths.update_role(PROTOCOL_VIOLATION, name=CLINICIAN_SUPER_ROLE)
31
+ site_auths.update_role(PROTOCOL_VIOLATION_VIEW, name=AUDITOR_ROLE)
32
+ elif incident_type == PROTOCOL_INCIDENT:
33
+ site_auths.update_role(PROTOCOL_INCIDENT, name=CLINICIAN_ROLE)
34
+ site_auths.update_role(PROTOCOL_INCIDENT, name=CLINICIAN_SUPER_ROLE)
35
+ site_auths.update_role(PROTOCOL_INCIDENT_VIEW, name=AUDITOR_ROLE)
36
+ else:
37
+ raise ValueError(
38
+ "Invalid value for settings.EDC_PROTOCOL_VIOLATION_TYPE. "
39
+ f"Expected `{PROTOCOL_INCIDENT}` or `{PROTOCOL_DEVIATION_VIOLATION}`. "
40
+ f"Got {incident_type}."
41
+ )
42
+
43
+
44
+ update_site_auths()
edc_pylabels/auths.py CHANGED
@@ -2,4 +2,9 @@ from edc_auth.site_auths import site_auths
2
2
 
3
3
  from .auth_objects import PYLABELS, codenames
4
4
 
5
- site_auths.add_group(*codenames, name=PYLABELS, no_delete=False)
5
+
6
+ def update_site_auths() -> None:
7
+ site_auths.add_group(*codenames, name=PYLABELS, no_delete=False)
8
+
9
+
10
+ update_site_auths()
edc_qareports/auths.py CHANGED
@@ -9,12 +9,16 @@ from .auth_objects import (
9
9
  qa_reports_codenames,
10
10
  )
11
11
 
12
- # groups
13
- site_auths.add_group(*qa_reports_codenames, name=QA_REPORTS)
14
- site_auths.add_group(*qa_reports_codenames, name=QA_REPORTS_AUDIT, view_only=True)
15
12
 
13
+ def update_site_auths() -> None:
14
+ # groups
15
+ site_auths.add_group(*qa_reports_codenames, name=QA_REPORTS)
16
+ site_auths.add_group(*qa_reports_codenames, name=QA_REPORTS_AUDIT, view_only=True)
16
17
 
17
- # roles
18
- site_auths.add_role(QA_REPORTS, name=QA_REPORTS_ROLE)
19
- site_auths.add_role(QA_REPORTS, name=QA_REPORTS_SUPER_ROLE)
20
- site_auths.add_role(QA_REPORTS_AUDIT, name=QA_REPORTS_AUDIT_ROLE)
18
+ # roles
19
+ site_auths.add_role(QA_REPORTS, name=QA_REPORTS_ROLE)
20
+ site_auths.add_role(QA_REPORTS, name=QA_REPORTS_SUPER_ROLE)
21
+ site_auths.add_role(QA_REPORTS_AUDIT, name=QA_REPORTS_AUDIT_ROLE)
22
+
23
+
24
+ update_site_auths()
@@ -1,3 +1,5 @@
1
+ import contextlib
2
+
1
3
  from django.conf import settings
2
4
  from django.contrib import admin
3
5
  from django.contrib.admin.sites import AlreadyRegistered
@@ -65,7 +67,8 @@ class RandomizationListModelAdmin(TemplatesModelAdminMixin, admin.ModelAdmin):
65
67
 
66
68
  def get_readonly_fields(self, request, obj=None):
67
69
  readonly_fields = super().get_readonly_fields(request, obj=obj)
68
- readonly_fields += (
70
+ readonly_fields = (
71
+ *readonly_fields,
69
72
  "subject_identifier",
70
73
  "sid",
71
74
  "site_name",
@@ -75,7 +78,8 @@ class RandomizationListModelAdmin(TemplatesModelAdminMixin, admin.ModelAdmin):
75
78
  "allocated_datetime",
76
79
  "allocated_site",
77
80
  "randomizer_name",
78
- ) + audit_fields
81
+ *audit_fields,
82
+ )
79
83
  return tuple(set(readonly_fields))
80
84
 
81
85
  def get_queryset(self, request):
@@ -90,7 +94,7 @@ class RandomizationListModelAdmin(TemplatesModelAdminMixin, admin.ModelAdmin):
90
94
  return qs
91
95
 
92
96
  def get_list_display(self, request) -> tuple[str, ...]:
93
- list_display = [
97
+ fields = (
94
98
  "sid",
95
99
  "assignment",
96
100
  "site_name",
@@ -98,22 +102,24 @@ class RandomizationListModelAdmin(TemplatesModelAdminMixin, admin.ModelAdmin):
98
102
  "allocated_datetime",
99
103
  "allocated_site",
100
104
  "randomizer_name",
101
- ]
105
+ )
106
+ if flds := site_randomizers.get_by_model(
107
+ self.model._meta.label_lower
108
+ ).get_extra_list_display():
109
+ fields = list(fields)
110
+ for pos, fname in flds:
111
+ fields.insert(pos, fname)
112
+ fields = tuple(fields)
102
113
  if user_is_blinded(request.user.username) or (
103
114
  not user_is_blinded(request.user.username)
104
115
  and RANDO_UNBLINDED not in [g.name for g in request.user.groups.all()]
105
116
  ):
106
- list_display.remove("assignment")
107
- if flds := site_randomizers.get_by_model(
108
- self.model._meta.label_lower
109
- ).get_extra_list_display():
110
- for pos, fldname in flds:
111
- list_display.insert(pos, fldname)
112
- return tuple(list_display)
117
+ fields = tuple([fname for fname in fields if fname != "assignment"])
118
+ return fields
113
119
 
114
120
  @staticmethod
115
121
  def get_fieldnames(request) -> tuple[str, ...]:
116
- fields = [
122
+ fields = (
117
123
  "subject_identifier",
118
124
  "sid",
119
125
  "assignment",
@@ -122,33 +128,35 @@ class RandomizationListModelAdmin(TemplatesModelAdminMixin, admin.ModelAdmin):
122
128
  "allocated_datetime",
123
129
  "allocated_site",
124
130
  "randomizer_name",
125
- ]
131
+ )
126
132
  if user_is_blinded(request.user.username) or (
127
133
  not user_is_blinded(request.user.username)
128
134
  and RANDO_UNBLINDED not in [g.name for g in request.user.groups.all()]
129
135
  ):
130
- fields.remove("assignment")
131
- return tuple(fields)
136
+ fields = tuple([fname for fname in fields if fname != "assignment"])
137
+ return fields
132
138
 
133
139
  def get_list_filter(self, request) -> tuple[str, ...]:
134
- list_filter = [
140
+ fields = (
135
141
  "assignment",
136
142
  "allocated_datetime",
137
143
  "allocated_site",
138
144
  "site_name",
139
145
  "randomizer_name",
140
- ]
146
+ )
141
147
  if flds := site_randomizers.get_by_model(
142
148
  self.model._meta.label_lower
143
149
  ).get_extra_list_filter():
144
- for pos, fldname in flds:
145
- list_filter.insert(pos, fldname)
150
+ fields = list(fields)
151
+ for pos, fname in flds:
152
+ fields.insert(pos, fname)
153
+ fields = tuple(fields)
146
154
  if user_is_blinded(request.user.username) or (
147
155
  not user_is_blinded(request.user.username)
148
156
  and RANDO_UNBLINDED not in [g.name for g in request.user.groups.all()]
149
157
  ):
150
- list_filter.remove("assignment")
151
- return tuple(list_filter)
158
+ fields = tuple([fname for fname in fields if fname != "assignment"])
159
+ return fields
152
160
 
153
161
 
154
162
  def register_admin():
@@ -156,10 +164,8 @@ def register_admin():
156
164
  for randomizer_cls in site_randomizers._registry.values():
157
165
  model = randomizer_cls.model_cls()
158
166
  admin_cls = type(f"{model.__name__}ModelAdmin", (RandomizationListModelAdmin,), {})
159
- try:
167
+ with contextlib.suppress(AlreadyRegistered):
160
168
  edc_randomization_admin.register(model, admin_cls)
161
- except AlreadyRegistered:
162
- pass
163
169
 
164
170
 
165
171
  register_admin()
@@ -9,11 +9,16 @@ from .auth_objects import (
9
9
  update_rando_group_permissions,
10
10
  )
11
11
 
12
- site_auths.add_post_update_func(
13
- "edc_randomization", remove_default_model_permissions_from_edc_permissions
14
- )
15
12
 
16
- site_auths.add_group(get_rando_permissions_codenames, name=RANDO_BLINDED, view_only=True)
17
- site_auths.add_group(get_rando_permissions_codenames, name=RANDO_UNBLINDED, view_only=True)
18
- site_auths.add_post_update_func("edc_randomization", update_rando_group_permissions)
19
- site_auths.add_post_update_func("edc_randomization", make_randomizationlist_view_only)
13
+ def update_site_auths() -> None:
14
+ site_auths.add_post_update_func(
15
+ "edc_randomization", remove_default_model_permissions_from_edc_permissions
16
+ )
17
+
18
+ site_auths.add_group(get_rando_permissions_codenames, name=RANDO_BLINDED, view_only=True)
19
+ site_auths.add_group(get_rando_permissions_codenames, name=RANDO_UNBLINDED, view_only=True)
20
+ site_auths.add_post_update_func("edc_randomization", update_rando_group_permissions)
21
+ site_auths.add_post_update_func("edc_randomization", make_randomizationlist_view_only)
22
+
23
+
24
+ update_site_auths()