meta-edc 1.6.5__py3-none-any.whl → 1.6.7__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.
- {meta_edc-1.6.5.dist-info → meta_edc-1.6.7.dist-info}/METADATA +5 -5
- {meta_edc-1.6.5.dist-info → meta_edc-1.6.7.dist-info}/RECORD +16 -13
- meta_lists/constants.py +2 -0
- meta_lists/list_data.py +5 -2
- meta_subject/admin/glucose_admin.py +26 -3
- meta_subject/admin/glucose_fbg_admin.py +16 -2
- meta_subject/form_validators/glucose_fbg_form_validator.py +10 -2
- meta_subject/form_validators/glucose_form_validator.py +9 -3
- meta_subject/form_validators/mixins.py +27 -26
- meta_subject/migrations/0241_remove_glucose_diagnostic_device_and_more.py +35 -0
- meta_subject/migrations/0242_glucose_ogtt_diagnostic_device_and_more.py +86 -0
- meta_subject/models/glucose.py +13 -2
- meta_subject/models/glucose_fbg.py +3 -2
- meta_visit_schedule/visit_schedules/phase_three/schedule.py +2 -0
- {meta_edc-1.6.5.dist-info → meta_edc-1.6.7.dist-info}/WHEEL +0 -0
- {meta_edc-1.6.5.dist-info → meta_edc-1.6.7.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meta-edc
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.7
|
|
4
4
|
Summary: META Trial EDC (https://www.isrctn.com/ISRCTN76157257)
|
|
5
5
|
Keywords: django,clinicedc,META EDC,EDC,clinical trials,META Trial,ISRCTN76157257
|
|
6
6
|
Author: Erik van Widenfelt, Jonathan Willitts
|
|
@@ -18,7 +18,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.13
|
|
19
19
|
Requires-Dist: django==5.2.10
|
|
20
20
|
Requires-Dist: celery>=5.6.2
|
|
21
|
-
Requires-Dist: clinicedc==2.3.
|
|
21
|
+
Requires-Dist: clinicedc==2.3.7
|
|
22
22
|
Requires-Dist: edc-he>=1.5.2
|
|
23
23
|
Requires-Dist: edc-microscopy>=1.4.2
|
|
24
24
|
Requires-Dist: edc-mnsi>=1.4.0
|
|
@@ -92,8 +92,8 @@ Assuming you are logged into the account ``myaccount``:
|
|
|
92
92
|
mkdir ~/edc && \
|
|
93
93
|
cd ~/edc && \
|
|
94
94
|
uv venv && \
|
|
95
|
-
uv pip install -U meta-edc==1.6.
|
|
96
|
-
wget https://raw.githubusercontent.com/meta-trial/meta-edc/1.6.
|
|
95
|
+
uv pip install -U meta-edc==1.6.6 && \
|
|
96
|
+
wget https://raw.githubusercontent.com/meta-trial/meta-edc/1.6.6/manage.py && \
|
|
97
97
|
uv pip freeze | grep meta-edc
|
|
98
98
|
|
|
99
99
|
Copy your ``.env`` file to ``~/.etc``.
|
|
@@ -143,7 +143,7 @@ From the above example:
|
|
|
143
143
|
|
|
144
144
|
cd ~/edc && \
|
|
145
145
|
uv venv --clear && \
|
|
146
|
-
uv pip install -U meta-edc==1.6.
|
|
146
|
+
uv pip install -U meta-edc==1.6.6 && \
|
|
147
147
|
wget -O manage.py https://raw.githubusercontent.com/meta-trial/meta-edc/1.1.10/manage.py && \
|
|
148
148
|
uv pip freeze | grep meta-edc && \
|
|
149
149
|
python manage.py check
|
|
@@ -262,7 +262,8 @@ meta_lists/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
262
262
|
meta_lists/admin.py,sha256=_Ww9dkT8BiXwbBFAAUuFYjsWmrF22FEVyR_8E5FsH_g,2318
|
|
263
263
|
meta_lists/admin_site.py,sha256=M4uorELumZDIKD8SHs-AEX1doQFqXhRy-eCcRWYEu9k,165
|
|
264
264
|
meta_lists/apps.py,sha256=aegHpyrHw188UxhNVFd-v35HP9wO7J7G9BYmliOOE0c,278
|
|
265
|
-
meta_lists/
|
|
265
|
+
meta_lists/constants.py,sha256=t5IS9rwOKG1nd3Wda2FdUkkJI05Nc9CzXZeSnR4wvEw,42
|
|
266
|
+
meta_lists/list_data.py,sha256=VHZuzUJqvFTbc2jW_N2TKnpbhIY8Lx6cTYCkMcvChhg,10125
|
|
266
267
|
meta_lists/migrations/0001_initial.py,sha256=87crhJGEUzUxe9TaNTzzKM6AjE3Pjw032PkhYrnRz9k,13881
|
|
267
268
|
meta_lists/migrations/0002_auto_20191026_2231.py,sha256=lV7keU3h-MC7O_RJLYxSY_Gr2T7ROtCf0qm_WkS2s3g,4608
|
|
268
269
|
meta_lists/migrations/0003_auto_20191102_0033.py,sha256=LkLUHM5zTj6vg3l1997g57uhncZPLHW-jrJgiUSe6rM,2555
|
|
@@ -748,8 +749,8 @@ meta_subject/admin/fields.py,sha256=wlKr_x8-PWL4urv6N0L4ti5yG3D7FnLy2U_hH6Baqzc,
|
|
|
748
749
|
meta_subject/admin/fieldsets.py,sha256=NjFKDAMvzePa9TijR_-zTLsDbawfBQDuws2BzWDzeZQ,1516
|
|
749
750
|
meta_subject/admin/followup_examination_admin.py,sha256=nNFQvW_zipgJCd1RDa2A2UOQkcPIq8cirwM2f3Ih0ZY,5278
|
|
750
751
|
meta_subject/admin/followup_vitals_admin.py,sha256=a2bwBwFsQ1sMmnBgmeCOEv6wNCXuKeIqIwEZB-Lqt_E,2297
|
|
751
|
-
meta_subject/admin/glucose_admin.py,sha256=
|
|
752
|
-
meta_subject/admin/glucose_fbg_admin.py,sha256=
|
|
752
|
+
meta_subject/admin/glucose_admin.py,sha256=4nxsbjgzffhdjTtG4x-RIDEQFJGOLwpBZazAwt14iI8,4222
|
|
753
|
+
meta_subject/admin/glucose_fbg_admin.py,sha256=dtgdlcLBDgXME-b9GFFG3vZt2YSMShay7eLf6CPh_Is,3487
|
|
753
754
|
meta_subject/admin/health_economics/__init__.py,sha256=t0vFauE3auk7FESIvk5tFjc3-Jtshl9eiAJswQBG1gw,212
|
|
754
755
|
meta_subject/admin/health_economics/health_economics_simple_admin.py,sha256=nL0CvjWQsFsR19ine14iItt9e8Px53Ln_tSppMN8UQ4,1053
|
|
755
756
|
meta_subject/admin/health_economics/health_economics_update_admin.py,sha256=mtsd1fJ8yvTK1eol5f03fZ8jk1afeYKSxEydPGmma7w,3905
|
|
@@ -784,11 +785,11 @@ meta_subject/form_validators/dm_endpoint_form_validator.py,sha256=KKt2G1UVzeCgpK
|
|
|
784
785
|
meta_subject/form_validators/dm_followup_form_validator.py,sha256=78vfIr6BuW5AASdUvjIPpocIgyRhMuxmh73jBVmP8Xk,7977
|
|
785
786
|
meta_subject/form_validators/egfr_drop_notification_form_validator.py,sha256=RiSwH6ZTt_bWgeTWTtSR9YT58lp7ATKx0AI7CRHSeC0,526
|
|
786
787
|
meta_subject/form_validators/followup_examination_form_validator.py,sha256=AQItUjh65R-tPGWIzcHuPbCvfkr6Rzhy2dOVyPD_gVA,4237
|
|
787
|
-
meta_subject/form_validators/glucose_fbg_form_validator.py,sha256=
|
|
788
|
-
meta_subject/form_validators/glucose_form_validator.py,sha256=
|
|
788
|
+
meta_subject/form_validators/glucose_fbg_form_validator.py,sha256=GERc2U10EQx7R7tMljcM5L5wnCZLfUACn07Z5o4a6dg,3403
|
|
789
|
+
meta_subject/form_validators/glucose_form_validator.py,sha256=3giJ7TRPKmtr1oXYRUJq3qP_ZU4VejBHOjGXQVRAsaw,1316
|
|
789
790
|
meta_subject/form_validators/health_economics_form_validator.py,sha256=kp-LQU4ydBXlnYFt-0xKuVSb8Y4irlhz9d_X8ppvWgE,250
|
|
790
791
|
meta_subject/form_validators/hiv_exit_review_form_validator.py,sha256=9w3CHoBUkC4kWzpzGfbmsfULH-70NOegzh3IDJPEqDk,630
|
|
791
|
-
meta_subject/form_validators/mixins.py,sha256=
|
|
792
|
+
meta_subject/form_validators/mixins.py,sha256=5mhsCynXu11tKHf2SZ2Cw_IgNe1nSx8JRAfk6CPPPxw,3745
|
|
792
793
|
meta_subject/forms/__init__.py,sha256=KOuMcL66-FN192az3dDSmzBb7X4r1RE2HM2zpv4PNbQ,2853
|
|
793
794
|
meta_subject/forms/birth_outcomes_form.py,sha256=qqhZNQKiYk8C8CFebZTQB0hOm4ONrgkTG7hfuK7kW-o,374
|
|
794
795
|
meta_subject/forms/blood_results/__init__.py,sha256=DYs2J30cgTPxvY9qDuKfr_kF_muoZ1iVmpu_I3wLpdM,528
|
|
@@ -1084,6 +1085,8 @@ meta_subject/migrations/0237_historicalhivexitreview_singleton_field_and_more.py
|
|
|
1084
1085
|
meta_subject/migrations/0238_historicalhivexitreview_available_and_more.py,sha256=r2kSbcMSbKzQswJSfMP1CqRAZSdDayHjjQzsv6p-D3I,2900
|
|
1085
1086
|
meta_subject/migrations/0239_glucosefbg_diagnostic_device_and_more.py,sha256=SIU3VMAIOwwvYtKOx6MmHlyAX6QnWi5VC9wtib-OVcI,1220
|
|
1086
1087
|
meta_subject/migrations/0240_glucose_diagnostic_device_and_more.py,sha256=GzJJSbGU4cHvkRRZQyB94Gfiu8nKJyBJjZQkp2XTcig,2111
|
|
1088
|
+
meta_subject/migrations/0241_remove_glucose_diagnostic_device_and_more.py,sha256=ITanoKLlhkjn9jNuRM951ob5L9vb9av-3K6UpFHH9v0,1024
|
|
1089
|
+
meta_subject/migrations/0242_glucose_ogtt_diagnostic_device_and_more.py,sha256=cL7IfDqNkXdgPz7DIegsTKQtWowHX4U82Y4s1cpS3vE,3176
|
|
1087
1090
|
meta_subject/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
1088
1091
|
meta_subject/model_mixins/__init__.py,sha256=2Dae7t4r2f3YubLevk_HH_GVTDrZREOpCDDMYthLV5U,522
|
|
1089
1092
|
meta_subject/model_mixins/arv_history_model_mixin.py,sha256=Ync4oLFng1OQW3pVxNxbEhKplWVNpUY5BiXy47lv6pk,1573
|
|
@@ -1115,8 +1118,8 @@ meta_subject/models/egfr_drop_notification.py,sha256=LSA0s4klzQ69CwPDI_q89eQ49Xb
|
|
|
1115
1118
|
meta_subject/models/eq5d3l.py,sha256=itRrbfzL7Jsg9u7ml0SXwsw4nMoMcNyG0-YCD2VeXB0,291
|
|
1116
1119
|
meta_subject/models/followup_examination.py,sha256=ZNapm_-fofIQiWZtWbtVnmSY4NJ3OdktmY_16rVxvrs,8072
|
|
1117
1120
|
meta_subject/models/followup_vitals.py,sha256=pBZt4xrw7eVUfHBRtotUh9orJdNjOGxSuNa6JeWQRqA,903
|
|
1118
|
-
meta_subject/models/glucose.py,sha256=
|
|
1119
|
-
meta_subject/models/glucose_fbg.py,sha256=
|
|
1121
|
+
meta_subject/models/glucose.py,sha256=gnjmJd8_E_pYq4rlYiXLvN_59mvz4Fd6JvRLJElXGhI,2925
|
|
1122
|
+
meta_subject/models/glucose_fbg.py,sha256=PPu9Nf7APN8LICkTFVs_8V_TR7asSdgylrOCxf33_jo,2448
|
|
1120
1123
|
meta_subject/models/glucose_review.py,sha256=bCnSBe_C3LeBy1XrZpV9rv-hOk8onZ_Tl37t7dqm-sw,450
|
|
1121
1124
|
meta_subject/models/health_economics/__init__.py,sha256=J557vTjzK1EvUAM4mx9zDVQ7Zr0W25stnWXz_zE2a-c,245
|
|
1122
1125
|
meta_subject/models/health_economics/health_economics.py,sha256=lZE6sMmYQTPjz9QbXZ2rznlbgW61G0JYYIQ07IueJvw,9705
|
|
@@ -1158,11 +1161,11 @@ meta_visit_schedule/visit_schedules/phase_three/__init__.py,sha256=lnBC3j17W54TQ
|
|
|
1158
1161
|
meta_visit_schedule/visit_schedules/phase_three/crfs.py,sha256=M1BTT-eB9B5xpElafhhcgd7N0uX8aisT1igMK0VTP2E,18690
|
|
1159
1162
|
meta_visit_schedule/visit_schedules/phase_three/crfs_pregnancy.py,sha256=_I6IVLMC3-KlpI86eii790mlx-p2vxWxvNRKD927rXo,169
|
|
1160
1163
|
meta_visit_schedule/visit_schedules/phase_three/requisitions.py,sha256=Noeki8zX2MCwQVmCCWfuOyh_aN4YC-cyhUmrAZP8d5g,4579
|
|
1161
|
-
meta_visit_schedule/visit_schedules/phase_three/schedule.py,sha256=
|
|
1164
|
+
meta_visit_schedule/visit_schedules/phase_three/schedule.py,sha256=pn57uzGRmY8kWZ2LaTm5Upj4UJQ13oEzp8lA4LTvuM4,8363
|
|
1162
1165
|
meta_visit_schedule/visit_schedules/phase_three/schedule_dm_referral.py,sha256=q12p5wXc2D7lSiJVBnoSQw8Q3vL6uDx1t3PuDJO-Z-U,1735
|
|
1163
1166
|
meta_visit_schedule/visit_schedules/phase_three/schedule_pregnancy.py,sha256=bEpbpCX3vfZmnsqudr0z8PU5kiaX4ws1sO5Im98Mo28,1106
|
|
1164
1167
|
meta_visit_schedule/visit_schedules/phase_three/visit_schedule.py,sha256=ak4qazeKlpIlvpqrK9hDDO0fwWuWyvb4Ec-JU31IJxc,654
|
|
1165
|
-
meta_edc-1.6.
|
|
1166
|
-
meta_edc-1.6.
|
|
1167
|
-
meta_edc-1.6.
|
|
1168
|
-
meta_edc-1.6.
|
|
1168
|
+
meta_edc-1.6.7.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
1169
|
+
meta_edc-1.6.7.dist-info/WHEEL,sha256=XV0cjMrO7zXhVAIyyc8aFf1VjZ33Fen4IiJk5zFlC3g,80
|
|
1170
|
+
meta_edc-1.6.7.dist-info/METADATA,sha256=EYvFxLQ2eppikad0tgdw5OWJckSh4kk-kARqtJoEw1Y,5260
|
|
1171
|
+
meta_edc-1.6.7.dist-info/RECORD,,
|
meta_lists/constants.py
ADDED
meta_lists/list_data.py
CHANGED
|
@@ -5,6 +5,7 @@ from clinicedc_constants import (
|
|
|
5
5
|
DIABETES,
|
|
6
6
|
LTFU,
|
|
7
7
|
NONE,
|
|
8
|
+
NOT_APPLICABLE,
|
|
8
9
|
OTHER,
|
|
9
10
|
PREGNANCY,
|
|
10
11
|
TOXICITY,
|
|
@@ -13,6 +14,7 @@ from clinicedc_constants import (
|
|
|
13
14
|
from edc_offstudy.constants import COMPLETED_FOLLOWUP, WITHDRAWAL
|
|
14
15
|
from edc_transfer.constants import TRANSFERRED
|
|
15
16
|
|
|
17
|
+
from meta_lists.constants import ACCUCHEK, HEMACUE
|
|
16
18
|
from meta_prn.constants import (
|
|
17
19
|
CLINICAL_WITHDRAWAL,
|
|
18
20
|
COMPLETED_FOLLOWUP_48,
|
|
@@ -241,8 +243,9 @@ list_data = {
|
|
|
241
243
|
(CLINIC, "META Study Clinic"),
|
|
242
244
|
],
|
|
243
245
|
"meta_lists.diagnosticdevices": [
|
|
244
|
-
(
|
|
245
|
-
(
|
|
246
|
+
(HEMACUE, "Hemocue"),
|
|
247
|
+
(ACCUCHEK, "Accu-chek"),
|
|
246
248
|
(OTHER, "Other not listed"),
|
|
249
|
+
(NOT_APPLICABLE, "Not applicable"),
|
|
247
250
|
],
|
|
248
251
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from clinicedc_constants import NOT_APPLICABLE
|
|
3
4
|
from django.contrib import admin
|
|
4
5
|
from django.contrib.admin import SimpleListFilter
|
|
5
6
|
from django.template.loader import render_to_string
|
|
@@ -7,6 +8,9 @@ from django_audit_fields.admin import audit_fieldset_tuple
|
|
|
7
8
|
from edc_crf.fieldset import crf_status_fieldset
|
|
8
9
|
from edc_model_admin.history import SimpleHistoryAdmin
|
|
9
10
|
|
|
11
|
+
from meta_lists.constants import HEMACUE
|
|
12
|
+
from meta_lists.models import DiagnosticDevices
|
|
13
|
+
|
|
10
14
|
from ..admin_site import meta_subject_admin
|
|
11
15
|
from ..forms import GlucoseForm
|
|
12
16
|
from ..models import Glucose
|
|
@@ -36,9 +40,9 @@ class GlucoseAdmin(CrfModelAdminMixin, SimpleHistoryAdmin):
|
|
|
36
40
|
"fbg_performed",
|
|
37
41
|
"fbg_not_performed_reason",
|
|
38
42
|
"fbg_datetime",
|
|
43
|
+
"fbg_diagnostic_device",
|
|
39
44
|
"fbg_value",
|
|
40
45
|
"fbg_units",
|
|
41
|
-
"diagnostic_device",
|
|
42
46
|
)
|
|
43
47
|
},
|
|
44
48
|
),
|
|
@@ -50,6 +54,7 @@ class GlucoseAdmin(CrfModelAdminMixin, SimpleHistoryAdmin):
|
|
|
50
54
|
"ogtt_not_performed_reason",
|
|
51
55
|
"ogtt_base_datetime",
|
|
52
56
|
"ogtt_datetime",
|
|
57
|
+
"ogtt_diagnostic_device",
|
|
53
58
|
"ogtt_value",
|
|
54
59
|
"ogtt_units",
|
|
55
60
|
)
|
|
@@ -78,7 +83,8 @@ class GlucoseAdmin(CrfModelAdminMixin, SimpleHistoryAdmin):
|
|
|
78
83
|
"ogtt_performed": admin.VERTICAL,
|
|
79
84
|
"ogtt_units": admin.VERTICAL,
|
|
80
85
|
"endpoint_today": admin.VERTICAL,
|
|
81
|
-
"
|
|
86
|
+
"fbg_diagnostic_device": admin.VERTICAL,
|
|
87
|
+
"ogtt_diagnostic_device": admin.VERTICAL,
|
|
82
88
|
}
|
|
83
89
|
|
|
84
90
|
def get_list_display(self, request) -> tuple[str, ...]:
|
|
@@ -92,7 +98,8 @@ class GlucoseAdmin(CrfModelAdminMixin, SimpleHistoryAdmin):
|
|
|
92
98
|
def get_list_filter(self, request) -> tuple[str | type[SimpleListFilter], ...]:
|
|
93
99
|
list_filter = super().get_list_filter(request)
|
|
94
100
|
list_filter = list(list_filter)
|
|
95
|
-
list_filter.insert(2, "
|
|
101
|
+
list_filter.insert(2, "fbg_diagnostic_device")
|
|
102
|
+
list_filter.insert(2, "ogtt_diagnostic_device")
|
|
96
103
|
list_filter.insert(2, OgttListFilter)
|
|
97
104
|
list_filter.insert(2, FbgListFilter)
|
|
98
105
|
return tuple(list_filter)
|
|
@@ -104,3 +111,19 @@ class GlucoseAdmin(CrfModelAdminMixin, SimpleHistoryAdmin):
|
|
|
104
111
|
@admin.display(description="OGTT", ordering="ogtt_value")
|
|
105
112
|
def ogtt(self, obj):
|
|
106
113
|
return obj.ogtt_value
|
|
114
|
+
|
|
115
|
+
def get_changeform_initial_data(self, request) -> dict:
|
|
116
|
+
initial_data = super().get_changeform_initial_data(request)
|
|
117
|
+
try:
|
|
118
|
+
obj = DiagnosticDevices.objects.get(name=HEMACUE)
|
|
119
|
+
except DiagnosticDevices.DoesNotExist:
|
|
120
|
+
pass
|
|
121
|
+
else:
|
|
122
|
+
initial_data["fbg_diagnostic_device"] = obj.id
|
|
123
|
+
try:
|
|
124
|
+
obj = DiagnosticDevices.objects.get(name=NOT_APPLICABLE)
|
|
125
|
+
except DiagnosticDevices.DoesNotExist:
|
|
126
|
+
pass
|
|
127
|
+
else:
|
|
128
|
+
initial_data["ogtt_diagnostic_device"] = obj.id
|
|
129
|
+
return initial_data
|
|
@@ -7,6 +7,9 @@ from django_audit_fields import audit_fieldset_tuple
|
|
|
7
7
|
from edc_crf.fieldset import crf_status_fieldset
|
|
8
8
|
from edc_model_admin.history import SimpleHistoryAdmin
|
|
9
9
|
|
|
10
|
+
from meta_lists.constants import HEMACUE
|
|
11
|
+
from meta_lists.models import DiagnosticDevices
|
|
12
|
+
|
|
10
13
|
from ..admin_site import meta_subject_admin
|
|
11
14
|
from ..forms import GlucoseFbgForm
|
|
12
15
|
from ..models import GlucoseFbg
|
|
@@ -36,9 +39,9 @@ class GlucoseFbgAdmin(CrfModelAdminMixin, SimpleHistoryAdmin):
|
|
|
36
39
|
"fbg_performed",
|
|
37
40
|
"fbg_not_performed_reason",
|
|
38
41
|
"fbg_datetime",
|
|
42
|
+
"fbg_diagnostic_device",
|
|
39
43
|
"fbg_value",
|
|
40
44
|
"fbg_units",
|
|
41
|
-
"diagnostic_device",
|
|
42
45
|
)
|
|
43
46
|
},
|
|
44
47
|
),
|
|
@@ -71,7 +74,7 @@ class GlucoseFbgAdmin(CrfModelAdminMixin, SimpleHistoryAdmin):
|
|
|
71
74
|
"fbg_units": admin.VERTICAL,
|
|
72
75
|
"fbg_performed": admin.VERTICAL,
|
|
73
76
|
"endpoint_today": admin.VERTICAL,
|
|
74
|
-
"
|
|
77
|
+
"fbg_diagnostic_device": admin.VERTICAL,
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
@admin.display(description="FBG", ordering="fbg_value")
|
|
@@ -81,6 +84,7 @@ class GlucoseFbgAdmin(CrfModelAdminMixin, SimpleHistoryAdmin):
|
|
|
81
84
|
def get_list_display(self, request) -> tuple[str, ...]:
|
|
82
85
|
list_display = super().get_list_display(request)
|
|
83
86
|
list_display = list(list_display)
|
|
87
|
+
list_display.insert(3, "fbg_diagnostic_device")
|
|
84
88
|
list_display.insert(3, "fbg")
|
|
85
89
|
list_display = [f for f in list_display if f != "__str__"]
|
|
86
90
|
return tuple(list_display)
|
|
@@ -90,3 +94,13 @@ class GlucoseFbgAdmin(CrfModelAdminMixin, SimpleHistoryAdmin):
|
|
|
90
94
|
list_filter = list(list_filter)
|
|
91
95
|
list_filter.insert(2, GlucoseListFilter)
|
|
92
96
|
return tuple(list_filter)
|
|
97
|
+
|
|
98
|
+
def get_changeform_initial_data(self, request) -> dict:
|
|
99
|
+
initial_data = super().get_changeform_initial_data(request)
|
|
100
|
+
try:
|
|
101
|
+
obj = DiagnosticDevices.objects.get(name=HEMACUE)
|
|
102
|
+
except DiagnosticDevices.DoesNotExist:
|
|
103
|
+
pass
|
|
104
|
+
else:
|
|
105
|
+
initial_data["fbg_diagnostic_device"] = obj.id
|
|
106
|
+
return initial_data
|
|
@@ -25,13 +25,21 @@ class GlucoseFbgFormValidator(
|
|
|
25
25
|
{"fbg_datetime": "Invalid. Must be on or after report date above"},
|
|
26
26
|
INVALID_ERROR,
|
|
27
27
|
)
|
|
28
|
+
self.applicable_if(
|
|
29
|
+
YES, field="fbg_performed", field_applicable="fbg_diagnostic_device"
|
|
30
|
+
)
|
|
28
31
|
self.required_if(YES, field="fbg_performed", field_required="fbg_value")
|
|
29
32
|
|
|
30
33
|
self.applicable_if(YES, field="fbg_performed", field_applicable="fbg_units")
|
|
31
34
|
|
|
32
35
|
# endpoint
|
|
33
|
-
self.applicable_if(
|
|
34
|
-
|
|
36
|
+
self.applicable_if(
|
|
37
|
+
YES,
|
|
38
|
+
field="fbg_performed",
|
|
39
|
+
field_applicable="endpoint_today",
|
|
40
|
+
not_applicable_msg="This field is not applicable. Not performed",
|
|
41
|
+
)
|
|
42
|
+
self.validate_endpoint_fields(performed=self.cleaned_data.get("fbg_value") is not None)
|
|
35
43
|
|
|
36
44
|
# repeat_fbg_date
|
|
37
45
|
self.required_if(PENDING, field="endpoint_today", field_required="repeat_fbg_date")
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from clinicedc_constants import PENDING
|
|
1
|
+
from clinicedc_constants import PENDING, YES
|
|
2
2
|
from edc_crf.crf_form_validator import CrfFormValidator
|
|
3
3
|
from edc_glucose.form_validators import FbgOgttFormValidatorMixin
|
|
4
4
|
|
|
@@ -13,7 +13,8 @@ class GlucoseFormValidator(
|
|
|
13
13
|
CrfFormValidator,
|
|
14
14
|
):
|
|
15
15
|
def clean(self):
|
|
16
|
-
self.
|
|
16
|
+
self.required_if(YES, field="fasting", field_required="fasting_duration_str")
|
|
17
|
+
self.validate_glucose_testing_matrix(include_fbg=True)
|
|
17
18
|
has_results = (
|
|
18
19
|
self.cleaned_data.get("fbg_value") is not None
|
|
19
20
|
and self.cleaned_data.get("ogtt_value") is not None
|
|
@@ -21,6 +22,11 @@ class GlucoseFormValidator(
|
|
|
21
22
|
)
|
|
22
23
|
self.applicable_if_true(has_results, field_applicable="endpoint_today")
|
|
23
24
|
if has_results:
|
|
24
|
-
self.validate_endpoint_fields(
|
|
25
|
+
self.validate_endpoint_fields(
|
|
26
|
+
performed=bool(
|
|
27
|
+
self.cleaned_data.get("fbg_value") is not None
|
|
28
|
+
or self.cleaned_data.get("ogtt_value") is not None
|
|
29
|
+
)
|
|
30
|
+
)
|
|
25
31
|
self.required_if(PENDING, field="endpoint_today", field_required="repeat_fbg_date")
|
|
26
32
|
self.validate_repeat_fbg_date()
|
|
@@ -7,33 +7,34 @@ from meta_reports.models import GlucoseSummary
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class EndpointValidatorMixin:
|
|
10
|
-
def validate_endpoint_fields(self):
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
self.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
self.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
10
|
+
def validate_endpoint_fields(self, performed: bool):
|
|
11
|
+
if performed:
|
|
12
|
+
is_endpoint = self.is_endpoint()
|
|
13
|
+
if is_endpoint == YES and self.cleaned_data.get("endpoint_today") != YES:
|
|
14
|
+
self.raise_validation_error(
|
|
15
|
+
{
|
|
16
|
+
"endpoint_today": (
|
|
17
|
+
"Participant has reached a study endpoint today. Expected YES"
|
|
18
|
+
)
|
|
19
|
+
},
|
|
20
|
+
INVALID_ERROR,
|
|
21
|
+
)
|
|
22
|
+
elif is_endpoint == PENDING and self.cleaned_data.get("endpoint_today") != PENDING:
|
|
23
|
+
self.raise_validation_error(
|
|
24
|
+
{
|
|
25
|
+
"endpoint_today": (
|
|
26
|
+
"Participant has not reached a study endpoint today. "
|
|
27
|
+
"Expected to repeat FBG"
|
|
28
|
+
)
|
|
29
|
+
},
|
|
30
|
+
INVALID_ERROR,
|
|
31
|
+
)
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
elif is_endpoint == NO and self.cleaned_data.get("endpoint_today") != NO:
|
|
34
|
+
self.raise_validation_error(
|
|
35
|
+
{"endpoint_today": "Participant has not reached a study endpoint today"},
|
|
36
|
+
INVALID_ERROR,
|
|
37
|
+
)
|
|
37
38
|
|
|
38
39
|
def is_endpoint(self):
|
|
39
40
|
value = NO
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Generated by Django 5.2.10 on 2026-01-23 13:40
|
|
2
|
+
|
|
3
|
+
import django.db.models.deletion
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+
dependencies = [
|
|
10
|
+
("meta_lists", "0021_diagnosticdevices"),
|
|
11
|
+
("meta_subject", "0240_glucose_diagnostic_device_and_more"),
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
operations = [
|
|
15
|
+
migrations.RenameField(
|
|
16
|
+
model_name="glucose",
|
|
17
|
+
old_name="diagnostic_device",
|
|
18
|
+
new_name="fbg_diagnostic_device",
|
|
19
|
+
),
|
|
20
|
+
migrations.RenameField(
|
|
21
|
+
model_name="glucosefbg",
|
|
22
|
+
old_name="diagnostic_device",
|
|
23
|
+
new_name="fbg_diagnostic_device",
|
|
24
|
+
),
|
|
25
|
+
migrations.RenameField(
|
|
26
|
+
model_name="historicalglucose",
|
|
27
|
+
old_name="diagnostic_device",
|
|
28
|
+
new_name="fbg_diagnostic_device",
|
|
29
|
+
),
|
|
30
|
+
migrations.RenameField(
|
|
31
|
+
model_name="historicalglucosefbg",
|
|
32
|
+
old_name="diagnostic_device",
|
|
33
|
+
new_name="fbg_diagnostic_device",
|
|
34
|
+
),
|
|
35
|
+
]
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Generated by Django 5.2.10 on 2026-01-23 14:00
|
|
2
|
+
|
|
3
|
+
import django.db.models.deletion
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+
dependencies = [
|
|
10
|
+
("meta_lists", "0021_diagnosticdevices"),
|
|
11
|
+
("meta_subject", "0241_remove_glucose_diagnostic_device_and_more"),
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
operations = [
|
|
15
|
+
migrations.AddField(
|
|
16
|
+
model_name="glucose",
|
|
17
|
+
name="ogtt_diagnostic_device",
|
|
18
|
+
field=models.ForeignKey(
|
|
19
|
+
limit_choices_to={"name__in": ["accuchek", "hemocue", "OTHER", "N/A"]},
|
|
20
|
+
null=True,
|
|
21
|
+
on_delete=django.db.models.deletion.PROTECT,
|
|
22
|
+
related_name="ogtt_diagnostic_device",
|
|
23
|
+
to="meta_lists.diagnosticdevices",
|
|
24
|
+
),
|
|
25
|
+
),
|
|
26
|
+
migrations.AddField(
|
|
27
|
+
model_name="historicalglucose",
|
|
28
|
+
name="ogtt_diagnostic_device",
|
|
29
|
+
field=models.ForeignKey(
|
|
30
|
+
blank=True,
|
|
31
|
+
db_constraint=False,
|
|
32
|
+
limit_choices_to={"name__in": ["accuchek", "hemocue", "OTHER", "N/A"]},
|
|
33
|
+
null=True,
|
|
34
|
+
on_delete=django.db.models.deletion.DO_NOTHING,
|
|
35
|
+
related_name="+",
|
|
36
|
+
to="meta_lists.diagnosticdevices",
|
|
37
|
+
),
|
|
38
|
+
),
|
|
39
|
+
migrations.AlterField(
|
|
40
|
+
model_name="glucose",
|
|
41
|
+
name="fbg_diagnostic_device",
|
|
42
|
+
field=models.ForeignKey(
|
|
43
|
+
limit_choices_to={"name__in": ["accuchek", "hemocue", "OTHER", "N/A"]},
|
|
44
|
+
null=True,
|
|
45
|
+
on_delete=django.db.models.deletion.PROTECT,
|
|
46
|
+
related_name="fbg_diagnostic_device",
|
|
47
|
+
to="meta_lists.diagnosticdevices",
|
|
48
|
+
),
|
|
49
|
+
),
|
|
50
|
+
migrations.AlterField(
|
|
51
|
+
model_name="glucosefbg",
|
|
52
|
+
name="fbg_diagnostic_device",
|
|
53
|
+
field=models.ForeignKey(
|
|
54
|
+
limit_choices_to={"name__in": ["accuchek", "hemocue", "OTHER", "N/A"]},
|
|
55
|
+
null=True,
|
|
56
|
+
on_delete=django.db.models.deletion.PROTECT,
|
|
57
|
+
to="meta_lists.diagnosticdevices",
|
|
58
|
+
),
|
|
59
|
+
),
|
|
60
|
+
migrations.AlterField(
|
|
61
|
+
model_name="historicalglucose",
|
|
62
|
+
name="fbg_diagnostic_device",
|
|
63
|
+
field=models.ForeignKey(
|
|
64
|
+
blank=True,
|
|
65
|
+
db_constraint=False,
|
|
66
|
+
limit_choices_to={"name__in": ["accuchek", "hemocue", "OTHER", "N/A"]},
|
|
67
|
+
null=True,
|
|
68
|
+
on_delete=django.db.models.deletion.DO_NOTHING,
|
|
69
|
+
related_name="+",
|
|
70
|
+
to="meta_lists.diagnosticdevices",
|
|
71
|
+
),
|
|
72
|
+
),
|
|
73
|
+
migrations.AlterField(
|
|
74
|
+
model_name="historicalglucosefbg",
|
|
75
|
+
name="fbg_diagnostic_device",
|
|
76
|
+
field=models.ForeignKey(
|
|
77
|
+
blank=True,
|
|
78
|
+
db_constraint=False,
|
|
79
|
+
limit_choices_to={"name__in": ["accuchek", "hemocue", "OTHER", "N/A"]},
|
|
80
|
+
null=True,
|
|
81
|
+
on_delete=django.db.models.deletion.DO_NOTHING,
|
|
82
|
+
related_name="+",
|
|
83
|
+
to="meta_lists.diagnosticdevices",
|
|
84
|
+
),
|
|
85
|
+
),
|
|
86
|
+
]
|
meta_subject/models/glucose.py
CHANGED
|
@@ -9,6 +9,7 @@ from edc_glucose.model_mixin_factories import (
|
|
|
9
9
|
from edc_model.models import BaseUuidModel
|
|
10
10
|
from edc_utils import formatted_date
|
|
11
11
|
|
|
12
|
+
from meta_lists.constants import ACCUCHEK, HEMACUE
|
|
12
13
|
from meta_lists.models import DiagnosticDevices
|
|
13
14
|
|
|
14
15
|
from ..choices import ENDPOINT_CHOICES
|
|
@@ -48,12 +49,13 @@ class Glucose(
|
|
|
48
49
|
verbose_name="If NO, provide reason", max_length=150, default="", blank=True
|
|
49
50
|
)
|
|
50
51
|
|
|
51
|
-
|
|
52
|
+
fbg_diagnostic_device = models.ForeignKey(
|
|
52
53
|
DiagnosticDevices,
|
|
53
54
|
on_delete=models.PROTECT,
|
|
54
55
|
null=True,
|
|
55
56
|
blank=False,
|
|
56
|
-
limit_choices_to={"name__in": [
|
|
57
|
+
limit_choices_to={"name__in": [ACCUCHEK, HEMACUE, OTHER, NOT_APPLICABLE]},
|
|
58
|
+
related_name="fbg_diagnostic_device",
|
|
57
59
|
)
|
|
58
60
|
|
|
59
61
|
ogtt_performed = models.CharField(
|
|
@@ -66,6 +68,15 @@ class Glucose(
|
|
|
66
68
|
verbose_name="If NO, provide reason", max_length=150, default="", blank=True
|
|
67
69
|
)
|
|
68
70
|
|
|
71
|
+
ogtt_diagnostic_device = models.ForeignKey(
|
|
72
|
+
DiagnosticDevices,
|
|
73
|
+
on_delete=models.PROTECT,
|
|
74
|
+
null=True,
|
|
75
|
+
blank=False,
|
|
76
|
+
limit_choices_to={"name__in": [ACCUCHEK, HEMACUE, OTHER, NOT_APPLICABLE]},
|
|
77
|
+
related_name="ogtt_diagnostic_device",
|
|
78
|
+
)
|
|
79
|
+
|
|
69
80
|
endpoint_today = models.CharField(
|
|
70
81
|
verbose_name="Has the participant reached a study endpoint today?",
|
|
71
82
|
max_length=25,
|
|
@@ -8,6 +8,7 @@ from edc_glucose.model_mixin_factories import (
|
|
|
8
8
|
from edc_model.models import BaseUuidModel
|
|
9
9
|
from edc_utils import formatted_date
|
|
10
10
|
|
|
11
|
+
from meta_lists.constants import ACCUCHEK, HEMACUE
|
|
11
12
|
from meta_lists.models import DiagnosticDevices
|
|
12
13
|
|
|
13
14
|
from ..choices import ENDPOINT_CHOICES
|
|
@@ -71,12 +72,12 @@ class GlucoseFbg(
|
|
|
71
72
|
help_text="Date should be within 1 week of report date",
|
|
72
73
|
)
|
|
73
74
|
|
|
74
|
-
|
|
75
|
+
fbg_diagnostic_device = models.ForeignKey(
|
|
75
76
|
DiagnosticDevices,
|
|
76
77
|
on_delete=models.PROTECT,
|
|
77
78
|
null=True,
|
|
78
79
|
blank=False,
|
|
79
|
-
limit_choices_to={"name__in": [
|
|
80
|
+
limit_choices_to={"name__in": [ACCUCHEK, HEMACUE, OTHER, NOT_APPLICABLE]},
|
|
80
81
|
)
|
|
81
82
|
|
|
82
83
|
class Meta(CrfModelMixin.Meta, BaseUuidModel.Meta):
|
|
@@ -291,6 +291,7 @@ visit36 = Visit(
|
|
|
291
291
|
requisitions=requisitions_36m,
|
|
292
292
|
crfs=crfs_36m,
|
|
293
293
|
facility_name=FIVE_DAY_CLINIC,
|
|
294
|
+
allow_unscheduled_extended=True,
|
|
294
295
|
)
|
|
295
296
|
|
|
296
297
|
visit39 = Visit(
|
|
@@ -340,6 +341,7 @@ visit48 = Visit(
|
|
|
340
341
|
requisitions=requisitions_48m,
|
|
341
342
|
crfs=crfs_48m,
|
|
342
343
|
facility_name=FIVE_DAY_CLINIC,
|
|
344
|
+
allow_unscheduled_extended=True,
|
|
343
345
|
)
|
|
344
346
|
|
|
345
347
|
visits = [
|
|
File without changes
|
|
File without changes
|