clinicedc 2.0.39__py3-none-any.whl → 2.0.41__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 (156) hide show
  1. {clinicedc-2.0.39.dist-info → clinicedc-2.0.41.dist-info}/METADATA +3 -12
  2. {clinicedc-2.0.39.dist-info → clinicedc-2.0.41.dist-info}/RECORD +145 -151
  3. {clinicedc-2.0.39.dist-info → clinicedc-2.0.41.dist-info}/WHEEL +1 -1
  4. edc_adverse_event/dashboard_urls.py +2 -0
  5. edc_adverse_event/middleware.py +7 -6
  6. edc_adverse_event/navbars.py +4 -8
  7. edc_adverse_event/urls.py +14 -6
  8. edc_adverse_event/view_mixins/ae/ae_listboard_view_mixin.py +6 -8
  9. edc_adverse_event/view_mixins/ae/death_report_listboard_view_mixin.py +2 -4
  10. edc_adverse_event/view_mixins/tmg/tmg_ae_listboard_view_mixin.py +2 -3
  11. edc_adverse_event/views/home_view.py +1 -2
  12. edc_adverse_event/views/tmg/death_listboard_view.py +8 -6
  13. edc_adverse_event/views/tmg/home_view.py +4 -3
  14. edc_adverse_event/views/tmg/summary_listboard_view.py +4 -4
  15. edc_appointment/utils.py +3 -6
  16. edc_appointment/views/unscheduled_appointment_view.py +1 -1
  17. edc_consent/form_validators/consent_definition_form_validator_mixin.py +5 -2
  18. edc_consent/model_mixins/consent_version_model_mixin.py +1 -1
  19. edc_consent/navbars.py +2 -1
  20. edc_crf/model_mixins/crf_model_mixin.py +5 -1
  21. edc_crf/model_mixins/crf_no_manager_model_mixin.py +2 -2
  22. edc_crf/model_mixins/singleton_crf_model_mixin.py +1 -1
  23. edc_dashboard/middleware.py +10 -16
  24. edc_dashboard/middleware_mixins.py +10 -0
  25. edc_dashboard/navbars.py +1 -1
  26. edc_dashboard/url_config.py +50 -31
  27. edc_dashboard/url_names.py +23 -17
  28. edc_dashboard/utils.py +4 -4
  29. edc_dashboard/view_mixins/template_request_context_mixin.py +5 -8
  30. edc_dashboard/view_mixins/url_request_context_mixin.py +38 -26
  31. edc_dashboard/views/administration_view.py +2 -2
  32. edc_dashboard/views/dashboard_view.py +5 -10
  33. edc_data_manager/handlers/handlers.py +17 -5
  34. edc_data_manager/migrations/0043_alter_historicalqueryrule_comment_and_more.py +51 -0
  35. edc_data_manager/models/query_rule.py +7 -7
  36. edc_data_manager/navbar_item.py +1 -1
  37. edc_data_manager/rule/query_rule_wrapper.py +1 -1
  38. edc_data_manager/rule/rule_runner.py +6 -6
  39. edc_device/navbars.py +1 -1
  40. edc_export/navbars.py +2 -2
  41. edc_glucose/model_mixin_factories/fasting_model_mixin_factory.py +1 -1
  42. edc_identifier/identifier.py +6 -9
  43. edc_lab_dashboard/dashboard_urls.py +7 -5
  44. edc_lab_dashboard/middleware.py +10 -17
  45. edc_lab_dashboard/navbars.py +9 -9
  46. edc_lab_dashboard/templates/edc_lab_dashboard/listboard/tags/status_column.html +7 -0
  47. edc_lab_dashboard/urls.py +2 -5
  48. edc_lab_dashboard/view_mixins/form_action_view_mixin.py +1 -2
  49. edc_lab_dashboard/views/action_views/action_view.py +6 -6
  50. edc_lab_dashboard/views/action_views/aliquot_view.py +1 -1
  51. edc_lab_dashboard/views/action_views/manage_box_item_view.py +2 -3
  52. edc_lab_dashboard/views/action_views/manage_manifest_view.py +1 -1
  53. edc_lab_dashboard/views/action_views/manifest_view.py +2 -2
  54. edc_lab_dashboard/views/action_views/pack_view.py +2 -2
  55. edc_lab_dashboard/views/action_views/process_view.py +1 -1
  56. edc_lab_dashboard/views/action_views/receive_view.py +1 -1
  57. edc_lab_dashboard/views/action_views/requisition_view.py +1 -1
  58. edc_lab_dashboard/views/action_views/verify_box_item_view.py +1 -1
  59. edc_lab_dashboard/views/listboard_views/manage_box_listboard_view.py +4 -5
  60. edc_lab_dashboard/views/listboard_views/manifest_listboard_view.py +5 -6
  61. edc_lab_dashboard/views/listboard_views/process_listboard_view.py +4 -5
  62. edc_lab_dashboard/views/listboard_views/receive_listboard_view.py +5 -6
  63. edc_lab_dashboard/views/listboard_views/verify_box_listboard_view.py +5 -6
  64. edc_label/navbars.py +1 -1
  65. edc_list_data/admin.py +3 -3
  66. edc_list_data/load_model_data.py +1 -1
  67. edc_list_data/management/commands/load_list_data.py +2 -2
  68. edc_list_data/site_list_data.py +4 -4
  69. edc_listboard/middleware.py +9 -8
  70. edc_listboard/templates/edc_listboard/listboard.html +1 -1
  71. edc_listboard/view_mixins/listboard_filter_view_mixin.py +1 -1
  72. edc_listboard/view_mixins/search_form_view_mixin.py +1 -1
  73. edc_listboard/views/listboard_view.py +16 -25
  74. edc_listboard/views/screen/screening_listboard_view.py +2 -2
  75. edc_listboard/views/subject/subject_listboard_view.py +2 -2
  76. edc_locator/forms/subject_locator_form_validator.py +2 -2
  77. edc_ltfu/action_items.py +1 -2
  78. edc_ltfu/forms/ltfu_form_validator_mixin.py +3 -3
  79. edc_ltfu/modeladmin_mixin.py +1 -1
  80. edc_ltfu/modelform_mixins.py +2 -2
  81. edc_metadata/admin/modeladmin_mixins.py +11 -9
  82. edc_metadata/management/commands/update_metadata.py +1 -1
  83. edc_metadata/management/commands/update_metadata_schedule_names.py +7 -7
  84. edc_metadata/management/commands/validate_entry_status.py +1 -1
  85. edc_metadata/management/commands/validate_rule_groups.py +1 -1
  86. edc_metadata/metadata/metadata_getter.py +3 -5
  87. edc_metadata/metadata_handler.py +5 -5
  88. edc_metadata/metadata_mixins/source_model_metadata_mixin.py +1 -1
  89. edc_metadata/metadata_refresher.py +1 -1
  90. edc_metadata/metadata_rules/crf/crf_rule.py +1 -1
  91. edc_metadata/metadata_rules/logic.py +3 -3
  92. edc_metadata/metadata_rules/persistant_singleton_mixin.py +2 -4
  93. edc_metadata/metadata_rules/requisition/requisition_rule_group.py +1 -1
  94. edc_metadata/metadata_rules/rule.py +4 -3
  95. edc_metadata/metadata_rules/rule_group.py +2 -2
  96. edc_metadata/metadata_rules/rule_group_meta_options.py +2 -2
  97. edc_metadata/metadata_rules/rule_group_metaclass.py +21 -22
  98. edc_metadata/metadata_rules/site.py +1 -1
  99. edc_metadata/metadata_updater.py +4 -3
  100. edc_metadata/model_mixins/creates/creates_metadata_model_mixin.py +3 -5
  101. edc_metadata/model_mixins/updates/updates_metadata_model_mixin.py +1 -1
  102. edc_metadata/next_form_getter.py +15 -19
  103. edc_metadata/offline_models.py +1 -1
  104. edc_metadata/requisition/requisition_metadata_handler.py +5 -5
  105. edc_metadata/update_metadata_on_schedule_change.py +2 -4
  106. edc_metadata/utils.py +1 -1
  107. edc_model/models/signals.py +7 -2
  108. edc_model_admin/mixins/model_admin_redirect_on_delete_mixin.py +4 -3
  109. edc_navbar/apps.py +0 -2
  110. edc_navbar/navbar.py +1 -1
  111. edc_navbar/navbar_item.py +29 -16
  112. edc_navbar/navbars.py +6 -19
  113. edc_navbar/site_navbars.py +6 -7
  114. edc_navbar/system_checks.py +3 -10
  115. edc_navbar/utils.py +14 -0
  116. edc_navbar/view_mixin.py +6 -9
  117. edc_pharmacy/navbars.py +1 -1
  118. edc_pharmacy/views/confirm_stock_from_queryset_view.py +3 -3
  119. edc_protocol/middleware.py +9 -13
  120. edc_protocol/navbars.py +1 -1
  121. edc_refusal/forms.py +1 -3
  122. edc_reportable/utils/convert_units.py +1 -1
  123. edc_review_dashboard/middleware.py +6 -3
  124. edc_review_dashboard/navbars.py +1 -2
  125. edc_review_dashboard/urls.py +3 -2
  126. edc_review_dashboard/views/subject_review_listboard_view.py +4 -2
  127. edc_subject_dashboard/dashboard_templates.py +1 -3
  128. edc_subject_dashboard/dashboard_urls.py +8 -0
  129. edc_subject_dashboard/middleware.py +10 -7
  130. edc_subject_dashboard/templates/edc_subject_dashboard/buttons/refresh_appointments_button.html +1 -1
  131. edc_subject_dashboard/templates/edc_subject_dashboard/dashboard.html +1 -1
  132. edc_subject_dashboard/templatetags/edc_subject_dashboard_extras.py +3 -1
  133. edc_subject_dashboard/urls.py +13 -4
  134. edc_subject_dashboard/views/base_requisition_view.py +2 -1
  135. edc_subject_dashboard/views/subject_dashboard_view.py +1 -2
  136. edc_timepoint/__init__.py +0 -2
  137. edc_timepoint/model_mixins.py +1 -2
  138. edc_timepoint/utils.py +1 -1
  139. edc_timepoint/visit_timepoint_lookup.py +6 -0
  140. edc_visit_schedule/admin/subject_schedule_history_admin.py +1 -2
  141. edc_visit_schedule/navbars.py +3 -4
  142. edc_visit_schedule/visit/visit.py +15 -0
  143. edc_visit_tracking/model_mixins/visit_model_mixin/visit_model_mixin.py +5 -0
  144. edc_visit_tracking/models/subject_visit.py +5 -0
  145. edc_lab_dashboard/model_wrappers/__init__.py +0 -8
  146. edc_lab_dashboard/model_wrappers/aliquot_model_wrapper.py +0 -31
  147. edc_lab_dashboard/model_wrappers/base_box_item_model_wrapper.py +0 -21
  148. edc_lab_dashboard/model_wrappers/box_model_wrapper.py +0 -12
  149. edc_lab_dashboard/model_wrappers/manage_box_item_model_wrapper.py +0 -6
  150. edc_lab_dashboard/model_wrappers/manifest_item_model_wrapper.py +0 -21
  151. edc_lab_dashboard/model_wrappers/manifest_model_wrapper.py +0 -11
  152. edc_lab_dashboard/model_wrappers/requisition_model_wrapper.py +0 -25
  153. edc_lab_dashboard/model_wrappers/result_model_wrapper.py +0 -8
  154. edc_lab_dashboard/model_wrappers/verify_box_model_wrapper.py +0 -10
  155. edc_navbar/get_default_navbar.py +0 -9
  156. {clinicedc-2.0.39.dist-info → clinicedc-2.0.41.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,5 @@
1
1
  from django.contrib import admin
2
2
  from django.urls import path
3
-
4
3
  from edc_data_manager.views import HomeView
5
4
  from edc_protocol.research_protocol_config import ResearchProtocolConfig
6
5
 
@@ -10,7 +9,7 @@ app_name = "edc_review_dashboard"
10
9
 
11
10
  urlpatterns = SubjectReviewListboardView.urls(
12
11
  namespace=app_name,
13
- label="subject_review_listboard",
12
+ url_names_key="subject_review_listboard_url",
14
13
  identifier_pattern=ResearchProtocolConfig().subject_identifier_pattern,
15
14
  )
16
15
 
@@ -18,3 +17,5 @@ urlpatterns += [
18
17
  path("admin/", admin.site.urls),
19
18
  path("", HomeView.as_view(), name="home_url"),
20
19
  ]
20
+
21
+ # aliquot_listboard = ("edc_lab_dashboard:aliquot_listboard_url",)
@@ -3,7 +3,6 @@ from __future__ import annotations
3
3
  from typing import TYPE_CHECKING, Any
4
4
 
5
5
  from django.db.models.aggregates import Count
6
-
7
6
  from edc_appointment.view_mixins import AppointmentViewMixin
8
7
  from edc_dashboard.url_names import url_names
9
8
  from edc_dashboard.view_mixins import EdcViewMixin
@@ -44,6 +43,7 @@ class SubjectReviewListboardView(
44
43
 
45
44
  listboard_template = "subject_review_listboard_template"
46
45
  listboard_url = "subject_review_listboard_url"
46
+ listboard_back_url = "subject_review_listboard_url"
47
47
  listboard_panel_style = "default"
48
48
  listboard_panel_title = "Subject Review"
49
49
  listboard_view_permission_codename = "edc_review_dashboard.view_subject_review_listboard"
@@ -51,6 +51,7 @@ class SubjectReviewListboardView(
51
51
  navbar_selected_item = "subject_review"
52
52
  ordering = ("subject_identifier", "visit_code", "visit_code_sequence")
53
53
  paginate_by = 25
54
+ paginator_url = "subject_review_listboard_url"
54
55
  search_form_url = "subject_review_listboard_url"
55
56
  search_fields = (
56
57
  "subject_identifier",
@@ -59,7 +60,8 @@ class SubjectReviewListboardView(
59
60
  "user_modified",
60
61
  )
61
62
 
62
- # attr to call SubjectReviewListboardView.urls in urls.py
63
+ # Attribute to call SubjectReviewListboardView.urls in urls.py
64
+ # See UrlRequestContextMixin and UrlConfig
63
65
  urlconfig_getattr = "review_listboard_urls"
64
66
 
65
67
  def get_context_data(self, **kwargs) -> dict[str, Any]:
@@ -2,6 +2,4 @@
2
2
  use settings.DASHBOARD_BASE_TEMPLATES.
3
3
  """
4
4
 
5
- dashboard_templates = dict(
6
- edc_subject_dashboard_template="edc_subject_dashboard/dashboard.html"
7
- )
5
+ dashboard_templates = dict(subject_dashboard_template="edc_subject_dashboard/dashboard.html")
@@ -0,0 +1,8 @@
1
+ import contextlib
2
+
3
+ from django.conf import settings
4
+
5
+ dashboard_urls = dict()
6
+
7
+ with contextlib.suppress(AttributeError):
8
+ dashboard_urls.update(**settings.SUBJECT_DASHBOARD_URL_NAMES)
@@ -1,25 +1,28 @@
1
1
  from django.conf import settings
2
2
 
3
+ from edc_dashboard.middleware_mixins import EdcTemplateMiddlewareMixin
4
+ from edc_subject_dashboard.dashboard_urls import dashboard_urls
5
+
3
6
  from .dashboard_templates import dashboard_templates
4
7
 
5
8
 
6
- class DashboardMiddleware:
9
+ class DashboardMiddleware(EdcTemplateMiddlewareMixin):
7
10
  def __init__(self, get_response):
8
11
  self.get_response = get_response
9
12
 
10
13
  def __call__(self, request):
14
+ self.check_for_required_request_attrs(request)
11
15
  return self.get_response(request)
12
16
 
13
- def process_view(self, request, *args): # noqa: ARG002
17
+ def process_view(self, request, *args):
14
18
  """Adds/Updates references to templates."""
15
- try:
16
- template_data = settings.SUBJECT_DASHBOARD_BASE_TEMPLATES
17
- except AttributeError:
18
- template_data = dashboard_templates
19
+ request.url_name_data.update(**dashboard_urls)
20
+ template_data = getattr(settings, "SUBJECT_DASHBOARD_BASE_TEMPLATES", {})
21
+ template_data.update(**dashboard_templates)
19
22
  request.template_data.update(**template_data)
20
23
 
21
24
  def process_template_response(self, request, response):
22
- if response.context_data:
25
+ if getattr(response, "context_data", None):
23
26
  response.context_data.update(**request.url_name_data)
24
27
  response.context_data.update(**request.template_data)
25
28
  return response
@@ -1 +1 @@
1
- <a {% if url %}href="{{ url }}" {% else %} disabled {% endif %}data-toggle="tooltip" title="Refresh appointments" role="button" class="btn btn-sm btn-default"><i class="fas fa-arrows-rotate fa-1x fa-fw" aria-hidden="true"></i></a>
1
+ <a {% if url %}href="{{ url }}" {% else %} disabled {% endif %}data-toggle="tooltip" title="{{ title|default:"Refresh appointments" }}" role="button" class="btn btn-sm btn-default"><i class="fas fa-arrows-rotate fa-1x fa-fw" aria-hidden="true"></i></a>
@@ -1,4 +1,4 @@
1
- {% extends dashboard_base_template %}
1
+ {% extends dashboard_base_template|default:"edc_dashboard/base.html" %}
2
2
  {% load static i18n %}
3
3
  {% load edc_visit_schedule_extras edc_subject_dashboard_extras edc_dashboard_extras edc_adverse_event_extras %}
4
4
 
@@ -481,10 +481,12 @@ def render_refresh_appointments_button(
481
481
  visit_schedule_name: str | None = None,
482
482
  schedule_name: str | None = None,
483
483
  ) -> dict:
484
+ title = "Refresh appointments"
484
485
  if context["request"].user.userprofile.is_multisite_viewer or context[
485
486
  "request"
486
487
  ].user.userprofile.roles.filter(name=AUDITOR_ROLE):
487
488
  url = None
489
+ title = f"{title} (Disabled for Auditor)"
488
490
  else:
489
491
  url = reverse(
490
492
  "edc_subject_dashboard:refresh_appointments_url",
@@ -494,7 +496,7 @@ def render_refresh_appointments_button(
494
496
  schedule_name=schedule_name,
495
497
  ),
496
498
  )
497
- return dict(url=url)
499
+ return dict(url=url, title=title)
498
500
 
499
501
 
500
502
  @register.inclusion_tag(
@@ -1,5 +1,4 @@
1
1
  from django.urls.conf import path
2
-
3
2
  from edc_dashboard.url_names import url_names
4
3
  from edc_metadata.views import RefreshMetadataActionsView
5
4
 
@@ -37,6 +36,16 @@ urlpatterns = [
37
36
  ),
38
37
  ]
39
38
 
40
- url_names.register(url="requisition_print_actions_url", namespace=app_name)
41
- url_names.register(url="requisition_verify_actions_url", namespace=app_name)
42
- url_names.register(url="refresh_metadata_actions_url", namespace=app_name)
39
+ url_names.register(
40
+ key="requisition_print_actions_url",
41
+ url="requisition_print_actions_url",
42
+ namespace=app_name,
43
+ )
44
+ url_names.register(
45
+ key="requisition_verify_actions_url",
46
+ url="requisition_verify_actions_url",
47
+ namespace=app_name,
48
+ )
49
+ url_names.register(
50
+ key="refresh_metadata_actions_url", url="refresh_metadata_actions_url", namespace=app_name
51
+ )
@@ -9,12 +9,13 @@ from edc_label.printers_mixin import PrintersMixin
9
9
 
10
10
  class BaseRequisitionView(LoginRequiredMixin, PrintersMixin, View):
11
11
  success_url_name = "subject_dashboard_url"
12
+ lab_home_url_name = "requisition_listboard_url"
12
13
 
13
14
  def get_success_url(self):
14
15
  return url_names.get(self.success_url_name)
15
16
 
16
17
  def get(self, request, *args, **kwargs): # noqa: ARG002
17
- url = reverse("edc_lab_dashboard:home_url")
18
+ url = reverse(url_names.get(self.lab_home_url_name))
18
19
  return HttpResponseRedirect(url)
19
20
 
20
21
  def head(self, request, *args, **kwargs):
@@ -3,7 +3,6 @@ from __future__ import annotations
3
3
  from typing import Any
4
4
 
5
5
  from django.core.exceptions import ImproperlyConfigured
6
-
7
6
  from edc_action_item.view_mixins import ActionItemViewMixin
8
7
  from edc_appointment.view_mixins import AppointmentViewMixin
9
8
  from edc_consent.view_mixins import ConsentViewMixin
@@ -44,7 +43,7 @@ class SubjectDashboardView(
44
43
  navbar_selected_item = "consented_subject"
45
44
 
46
45
  dashboard_url_name = "subject_dashboard_url"
47
- dashboard_template = "subject_dashboard_template"
46
+ dashboard_template_name = "subject_dashboard_template"
48
47
 
49
48
  default_manager = "on_site"
50
49
 
edc_timepoint/__init__.py CHANGED
@@ -1,2 +0,0 @@
1
- from .timepoint import Timepoint
2
- from .timepoint_collection import TimepointCollection
@@ -32,8 +32,7 @@ class TimepointLookupModelMixin(models.Model):
32
32
  timepoint_lookup_cls = TimepointLookup
33
33
 
34
34
  def save(self, *args, **kwargs):
35
- timepoint_lookup_cls = getattr(self, "timepoint_lookup_cls", None)
36
- if timepoint_lookup_cls and get_enable_timepoint_checks():
35
+ if get_enable_timepoint_checks() and getattr(self, "timepoint_lookup_cls", None):
37
36
  timepoint_lookup = self.timepoint_lookup_cls()
38
37
  if timepoint_lookup.timepoint_model == self._meta.label_lower:
39
38
  raise ImproperlyConfigured(
edc_timepoint/utils.py CHANGED
@@ -2,4 +2,4 @@ from django.conf import settings
2
2
 
3
3
 
4
4
  def get_enable_timepoint_checks() -> bool:
5
- return getattr(settings, "ENABLE_TIMEPOINT_CHECKS", True)
5
+ return getattr(settings, "EDC_TIMEPOINT_ENABLE_CHECKS", True)
@@ -0,0 +1,6 @@
1
+ from .timepoint_lookup import TimepointLookup
2
+
3
+
4
+ class VisitTimepointLookup(TimepointLookup):
5
+ timepoint_model = "edc_appointment.appointment"
6
+ timepoint_related_model_lookup = "appointment"
@@ -3,7 +3,6 @@ from django.template.loader import render_to_string
3
3
  from django.urls import NoReverseMatch, reverse
4
4
  from django.utils.translation import gettext as _
5
5
  from django_audit_fields import audit_fields, audit_fieldset_tuple
6
-
7
6
  from edc_dashboard.url_names import url_names
8
7
  from edc_model_admin.dashboard import ModelAdminSubjectDashboardMixin
9
8
  from edc_sites.admin import SiteModelAdminMixin
@@ -100,7 +99,7 @@ class SubjectScheduleHistoryAdmin(
100
99
  def review(obj=None) -> str:
101
100
  try:
102
101
  url = (
103
- f"{reverse('edc_review_dashboard:subject_review_listboard_url')}?"
102
+ f"{reverse(url_names.get('subject_review_listboard_url'))}?"
104
103
  f"q={obj.subject_identifier}"
105
104
  )
106
105
  except NoReverseMatch:
@@ -8,7 +8,7 @@ navbar.register(
8
8
  title="Visit Schedule",
9
9
  label="Visit Schedule",
10
10
  fa_icon="fa-calendar",
11
- url_name="edc_visit_schedule:home_url",
11
+ url_with_namespace="edc_visit_schedule:home_url",
12
12
  codename="edc_navbar.nav_visit_schedule",
13
13
  )
14
14
  )
@@ -19,9 +19,8 @@ navbar.register(
19
19
  title="Subject History",
20
20
  label="Subject History",
21
21
  fa_icon="fa-history",
22
- url_name=(
23
- "edc_visit_schedule:edc_visit_schedule_admin:"
24
- "edc_visit_schedule_subjectschedulehistory_changelist"
22
+ url_with_namespace=(
23
+ "edc_visit_schedule_admin:edc_visit_schedule_subjectschedulehistory_changelist"
25
24
  ),
26
25
  codename="edc_navbar.nav_visit_schedule",
27
26
  )
@@ -217,6 +217,14 @@ class Visit:
217
217
 
218
218
  @property
219
219
  def all_crfs(self) -> CrfCollection:
220
+ """Return a new collection containing all crfs.
221
+
222
+ The new collection contains:
223
+ * crfs
224
+ * crfs_unscheduled
225
+ * crfs_prn
226
+ * crfs_missed
227
+ """
220
228
  crfs = list(self.crfs) + [
221
229
  crf
222
230
  for crf in self.crfs_unscheduled
@@ -232,6 +240,13 @@ class Visit:
232
240
 
233
241
  @property
234
242
  def all_requisitions(self) -> RequisitionCollection:
243
+ """Return a new collection containing all requisitions.
244
+
245
+ The new collection contains:
246
+ * requisitions
247
+ * requisitions_unscheduled
248
+ * requisitions_prn
249
+ """
235
250
  names = [r.name for r in self.requisitions]
236
251
  requisitions = list(self.requisitions) + [
237
252
  r for r in self.requisitions_unscheduled if r.name not in names
@@ -11,6 +11,8 @@ from edc_document_status.model_mixins import DocumentStatusModelMixin
11
11
  from edc_identifier.model_mixins import NonUniqueSubjectIdentifierFieldMixin
12
12
  from edc_metadata.model_mixins import MetadataHelperModelMixin
13
13
  from edc_offstudy.model_mixins import OffstudyNonCrfModelMixin
14
+ from edc_timepoint.model_mixins import TimepointLookupModelMixin
15
+ from edc_timepoint.visit_timepoint_lookup import VisitTimepointLookup
14
16
  from edc_visit_schedule.model_mixins import VisitScheduleModelMixin
15
17
 
16
18
  from ...constants import MISSED_VISIT, NO_FOLLOW_UP_REASONS
@@ -29,6 +31,7 @@ class VisitModelMixin(
29
31
  MetadataHelperModelMixin,
30
32
  OffstudyNonCrfModelMixin,
31
33
  RequiresConsentFieldsModelMixin,
34
+ TimepointLookupModelMixin,
32
35
  models.Model,
33
36
  ):
34
37
  """
@@ -41,6 +44,8 @@ class VisitModelMixin(
41
44
  app_label = 'my_app'
42
45
  """
43
46
 
47
+ timepoint_lookup_cls = VisitTimepointLookup
48
+
44
49
  metadata_helper_instance_attr = None
45
50
 
46
51
  appointment = models.OneToOneField("edc_appointment.appointment", on_delete=PROTECT)
@@ -8,6 +8,8 @@ from edc_metadata.model_mixins.creates import CreatesMetadataModelMixin
8
8
  from edc_model.models import BaseUuidModel, HistoricalRecords
9
9
  from edc_sites.managers import CurrentSiteManager
10
10
  from edc_sites.model_mixins import SiteModelMixin
11
+ from edc_timepoint.model_mixins import TimepointLookupModelMixin
12
+ from edc_timepoint.visit_timepoint_lookup import VisitTimepointLookup
11
13
  from edc_visit_tracking.choices import (
12
14
  VISIT_INFO_SOURCE,
13
15
  VISIT_REASON,
@@ -22,8 +24,11 @@ class SubjectVisit(
22
24
  CreatesMetadataModelMixin,
23
25
  SiteModelMixin,
24
26
  RequiresConsentFieldsModelMixin,
27
+ TimepointLookupModelMixin,
25
28
  BaseUuidModel,
26
29
  ):
30
+ timepoint_lookup_cls = VisitTimepointLookup
31
+
27
32
  appointment = models.OneToOneField(
28
33
  get_appointment_model_name(),
29
34
  on_delete=PROTECT,
@@ -1,8 +0,0 @@
1
- # from .aliquot_model_wrapper import AliquotModelWrapper
2
- # from .box_model_wrapper import BoxModelWrapper
3
- # from .manage_box_item_model_wrapper import ManageBoxItemModelWrapper
4
- # from .manifest_item_model_wrapper import ManifestItemModelWrapper
5
- # from .manifest_model_wrapper import ManifestModelWrapper
6
- # from .requisition_model_wrapper import RequisitionModelWrapper
7
- # from .result_model_wrapper import ResultModelWrapper
8
- # from .verify_box_model_wrapper import VerifyBoxItemModelWrapper
@@ -1,31 +0,0 @@
1
- from edc_model_wrapper import ModelWrapper
2
-
3
- from edc_lab.models import Aliquot, BoxItem, ManifestItem
4
-
5
-
6
- class AliquotModelWrapper(ModelWrapper):
7
- model_cls = Aliquot
8
- next_url_name = "aliquot_listboard_url"
9
-
10
- @property
11
- def human_readable_identifier(self):
12
- return self.object.human_readable_identifier
13
-
14
- @property
15
- def box_item(self):
16
- try:
17
- return BoxItem.objects.get(identifier=self.aliquot_identifier)
18
- except BoxItem.DoesNotExist:
19
- return None
20
-
21
- @property
22
- def manifest_item(self):
23
- manifest_item = None
24
- if self.box_item:
25
- try:
26
- manifest_item = ManifestItem.objects.get(
27
- identifier=self.box_item.box.box_identifier
28
- )
29
- except ManifestItem.DoesNotExist:
30
- pass
31
- return manifest_item
@@ -1,21 +0,0 @@
1
- from django.apps import apps as django_apps
2
- from edc_model_wrapper import ModelWrapper
3
-
4
- from edc_lab.models import BoxItem
5
-
6
- edc_lab_app_config = django_apps.get_app_config("edc_lab")
7
-
8
-
9
- class BaseBoxItemModelWrapper(ModelWrapper):
10
- model_cls = BoxItem
11
- action_name = None
12
- next_url_name = None
13
- next_url_attrs = ["box_identifier", "action_name"]
14
-
15
- @property
16
- def human_readable_identifier(self):
17
- return self.object.human_readable_identifier
18
-
19
- @property
20
- def box_identifier(self):
21
- return self.object.box.box_identifier
@@ -1,12 +0,0 @@
1
- from edc_model_wrapper import ModelWrapper
2
-
3
- from edc_lab.models import Box
4
-
5
-
6
- class BoxModelWrapper(ModelWrapper):
7
- model_cls = Box
8
- next_url_name = "pack_listboard_url"
9
-
10
- @property
11
- def human_readable_identifier(self):
12
- return self.object.human_readable_identifier
@@ -1,6 +0,0 @@
1
- from .base_box_item_model_wrapper import BaseBoxItemModelWrapper
2
-
3
-
4
- class ManageBoxItemModelWrapper(BaseBoxItemModelWrapper):
5
- action_name = "manage"
6
- next_url_name = "manage_box_listboard_url"
@@ -1,21 +0,0 @@
1
- from edc_model_wrapper import ModelWrapper
2
-
3
- from edc_lab.models import Box, ManifestItem
4
-
5
-
6
- class ManifestItemModelWrapper(ModelWrapper):
7
- model_cls = ManifestItem
8
- next_url_name = "manage_manifest_listboard_url"
9
- action_name = "manage"
10
-
11
- @property
12
- def manifest_identifier(self):
13
- return self.object.manifest.manifest_identifier
14
-
15
- @property
16
- def box_identifier(self):
17
- return self.object.identifier
18
-
19
- @property
20
- def box(self):
21
- return Box.objects.get(box_identifier=self.object.identifier)
@@ -1,11 +0,0 @@
1
- from django.apps import apps as django_apps
2
- from edc_model_wrapper import ModelWrapper
3
-
4
- from edc_lab.models import Manifest
5
-
6
- edc_lab_app_config = django_apps.get_app_config("edc_lab")
7
-
8
-
9
- class ManifestModelWrapper(ModelWrapper):
10
- model_cls = Manifest
11
- next_url_name = "manifest_listboard_url"
@@ -1,25 +0,0 @@
1
- from django.conf import settings
2
- from edc_model_wrapper import ModelWrapper
3
-
4
-
5
- class RequisitionModelWrapper(ModelWrapper):
6
- model = settings.SUBJECT_REQUISITION_MODEL
7
- next_url_name = "requisition_listboard_url"
8
- next_url_attrs = ["appointment", "subject_identifier"]
9
- querystring_attrs = ["subject_visit", "panel"]
10
-
11
- @property
12
- def subject_visit(self):
13
- return str(self.object.subject_visit.id)
14
-
15
- @property
16
- def appointment(self):
17
- return str(self.object.subject_visit.appointment.id)
18
-
19
- @property
20
- def subject_identifier(self):
21
- return self.object.subject_visit.subject_identifier
22
-
23
- @property
24
- def panel(self):
25
- return str(self.object.panel.id)
@@ -1,8 +0,0 @@
1
- from edc_model_wrapper import ModelWrapper
2
-
3
- from edc_lab.models import Result
4
-
5
-
6
- class ResultModelWrapper(ModelWrapper):
7
- model_cls = Result
8
- next_url_name = "result_listboard_url"
@@ -1,10 +0,0 @@
1
- from django.apps import apps as django_apps
2
-
3
- from .base_box_item_model_wrapper import BaseBoxItemModelWrapper
4
-
5
- app_config = django_apps.get_app_config("edc_lab_dashboard")
6
-
7
-
8
- class VerifyBoxItemModelWrapper(BaseBoxItemModelWrapper):
9
- next_url_name = "verify_box_listboard_url"
10
- action_name = "verify"
@@ -1,9 +0,0 @@
1
- from django.conf import settings
2
-
3
-
4
- def get_default_navbar():
5
- """Returns the default navbar name.
6
-
7
- For example: inte_dashboard for project INTE.
8
- """
9
- return getattr(settings, "EDC_NAVBAR_DEFAULT", f"{settings.APP_NAME}_dashboard".lower())