meta-edc 1.2.6__py3-none-any.whl → 1.2.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 meta-edc might be problematic. Click here for more details.
- meta_analytics/dataframes/constants.py +3 -1
- meta_analytics/dataframes/get_glucose_df.py +13 -3
- meta_analytics/dataframes/glucose_endpoints/endpoint_by_date.py +27 -5
- meta_analytics/dataframes/glucose_endpoints/glucose_endpoints_by_date.py +61 -8
- meta_analytics/dataframes/screening/get_screening_df.py +1 -5
- meta_consent/migrations/0035_alter_historicalsubjectconsent_consent_definition_name_and_more.py +43 -0
- meta_dashboard/navbars.py +2 -6
- meta_dashboard/urls.py +5 -5
- meta_dashboard/views/screening/listboard_view.py +2 -3
- meta_dashboard/views/subject/dashboard/dashboard_view.py +4 -5
- meta_dashboard/views/subject/listboard/listboard_view.py +2 -3
- meta_edc/settings/debug.py +2 -2
- {meta_edc-1.2.6.dist-info → meta_edc-1.2.8.dist-info}/METADATA +5 -5
- {meta_edc-1.2.6.dist-info → meta_edc-1.2.8.dist-info}/RECORD +40 -28
- {meta_edc-1.2.6.dist-info → meta_edc-1.2.8.dist-info}/WHEEL +1 -1
- meta_prn/forms/offschedule_form.py +25 -0
- meta_screening/admin/subject_screening_admin.py +4 -3
- meta_subject/admin/__init__.py +2 -0
- meta_subject/admin/glucose_fbg_admin.py +12 -1
- meta_subject/admin/hiv_exit_review_admin.py +55 -0
- meta_subject/form_validators/__init__.py +4 -0
- meta_subject/form_validators/glucose_fbg_form_validator.py +77 -0
- meta_subject/form_validators/glucose_form_validator.py +10 -82
- meta_subject/form_validators/hiv_exit_review_form_validator.py +18 -0
- meta_subject/form_validators/mixins.py +95 -0
- meta_subject/forms/__init__.py +2 -0
- meta_subject/forms/glucose_fbg_form.py +1 -46
- meta_subject/forms/hiv_exit_review_form.py +13 -0
- meta_subject/migrations/0235_glucosefbg_endpoint_today_and_more.py +606 -0
- meta_subject/migrations/0236_alter_historicalhivexitreview_other_current_arv_regimen_and_more.py +58 -0
- meta_subject/migrations/0237_historicalhivexitreview_singleton_field_and_more.py +68 -0
- meta_subject/migrations/0238_historicalhivexitreview_available_and_more.py +88 -0
- meta_subject/model_mixins/__init__.py +2 -0
- meta_subject/model_mixins/arv_history_model_mixin.py +3 -44
- meta_subject/model_mixins/arv_review_model_mixin.py +53 -0
- meta_subject/models/__init__.py +2 -0
- meta_subject/models/glucose_fbg.py +15 -1
- meta_subject/models/hiv_exit_review.py +44 -0
- meta_visit_schedule/visit_schedules/phase_three/crfs.py +14 -0
- {meta_edc-1.2.6.dist-info → meta_edc-1.2.8.dist-info}/licenses/LICENSE +0 -0
|
@@ -2,10 +2,11 @@ CASE_EOS = 7
|
|
|
2
2
|
CASE_FBGS_WITH_FIRST_OGTT = 2
|
|
3
3
|
CASE_FBGS_WITH_SECOND_OGTT = 3
|
|
4
4
|
CASE_FBG_ONLY = 4
|
|
5
|
+
CASE_FBG_VERY_HIGH = 5
|
|
5
6
|
CASE_OGTT = 1
|
|
6
7
|
EOS_DM_MET = "EOS - Patient developed diabetes"
|
|
7
8
|
OGTT_THRESHOLD_MET = "OGTT >= 11.1"
|
|
8
|
-
|
|
9
|
+
FBG_BEYOND_THRESHOLD = 20.0
|
|
9
10
|
endpoint_columns = [
|
|
10
11
|
"subject_identifier",
|
|
11
12
|
"site_id",
|
|
@@ -29,5 +30,6 @@ endpoint_cases = {
|
|
|
29
30
|
CASE_FBGS_WITH_FIRST_OGTT: "FBG >= 7 x 2, first OGTT<=11.1",
|
|
30
31
|
CASE_FBGS_WITH_SECOND_OGTT: "FBG >= 7 x 2, second OGTT<=11.1",
|
|
31
32
|
CASE_FBG_ONLY: "FBG >= 7 x 2, OGTT not considered",
|
|
33
|
+
# CASE_FBG_VERY_HIGH: f"FBG>={FBG_BEYOND_THRESHOLD}",
|
|
32
34
|
CASE_EOS: EOS_DM_MET,
|
|
33
35
|
}
|
|
@@ -7,13 +7,23 @@ from edc_pdutils.dataframes import get_eos, get_subject_consent, get_subject_vis
|
|
|
7
7
|
from meta_subject.models import Glucose, GlucoseFbg
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
def get_glucose_df() -> pd.DataFrame:
|
|
10
|
+
def get_glucose_df(subject_identifiers: list[str] | None = None) -> pd.DataFrame:
|
|
11
11
|
subject_visit_df = (
|
|
12
|
-
get_subject_visit("meta_subject.subjectvisit")
|
|
12
|
+
get_subject_visit("meta_subject.subjectvisit", subject_identifiers)
|
|
13
13
|
.rename(columns={"id": "subject_visit_id"})
|
|
14
14
|
.query("appt_timing!=@MISSED_APPT")
|
|
15
15
|
)
|
|
16
|
-
|
|
16
|
+
if subject_identifiers:
|
|
17
|
+
df_glucose_fbg = read_frame(
|
|
18
|
+
GlucoseFbg.objects.filter(
|
|
19
|
+
subject_visit__subject_identifier__in=subject_identifiers
|
|
20
|
+
),
|
|
21
|
+
verbose=False,
|
|
22
|
+
)
|
|
23
|
+
else:
|
|
24
|
+
df_glucose_fbg = read_frame(GlucoseFbg.objects.all(), verbose=False)
|
|
25
|
+
|
|
26
|
+
df_glucose_fbg = df_glucose_fbg.rename(
|
|
17
27
|
columns={"fasting": "fasted", "subject_visit": "subject_visit_id"},
|
|
18
28
|
)
|
|
19
29
|
df_glucose_fbg["fasting_hrs"] = np.nan
|
|
@@ -67,9 +67,11 @@ class CaseData:
|
|
|
67
67
|
self.previous_fasted = self.df.loc[self.index - 1, "fasted"]
|
|
68
68
|
|
|
69
69
|
def case_two(self) -> bool:
|
|
70
|
-
"""
|
|
70
|
+
"""FBG >= 7 x 2, first OGTT<=11.1"""
|
|
71
71
|
return bool(
|
|
72
|
-
|
|
72
|
+
pd.notna(self.next_fbg_datetime)
|
|
73
|
+
and pd.notna(self.fbg_datetime)
|
|
74
|
+
and self.fbg_value >= self.fbg_threshold
|
|
73
75
|
and self.next_fbg_value >= self.fbg_threshold
|
|
74
76
|
and 0.0 < self.ogtt_value < self.ogtt_threshold
|
|
75
77
|
and self.fasted == YES
|
|
@@ -78,9 +80,11 @@ class CaseData:
|
|
|
78
80
|
)
|
|
79
81
|
|
|
80
82
|
def case_three(self) -> bool:
|
|
81
|
-
"""
|
|
83
|
+
"""FBG >= 7 x 2, second OGTT<=11.1"""
|
|
82
84
|
return bool(
|
|
83
|
-
|
|
85
|
+
pd.notna(self.next_fbg_datetime)
|
|
86
|
+
and pd.notna(self.fbg_datetime)
|
|
87
|
+
and self.fbg_value >= self.fbg_threshold
|
|
84
88
|
and self.next_fbg_value >= self.fbg_threshold
|
|
85
89
|
and 0.0 < self.next_ogtt_value < self.ogtt_threshold
|
|
86
90
|
and self.fasted == YES
|
|
@@ -91,7 +95,9 @@ class CaseData:
|
|
|
91
95
|
def case_two_reversed(self) -> bool:
|
|
92
96
|
"""Same as case 2, but with the previous FBG reading."""
|
|
93
97
|
return bool(
|
|
94
|
-
|
|
98
|
+
pd.notna(self.next_fbg_datetime)
|
|
99
|
+
and pd.notna(self.fbg_datetime)
|
|
100
|
+
and self.fbg_value >= self.fbg_threshold
|
|
95
101
|
and self.previous_fbg_value >= self.fbg_threshold
|
|
96
102
|
and 0.0 < self.previous_ogtt_value < self.ogtt_threshold
|
|
97
103
|
and self.fasted == YES
|
|
@@ -99,6 +105,19 @@ class CaseData:
|
|
|
99
105
|
and (self.fbg_datetime.date() - self.previous_fbg_datetime.date()).days > 6
|
|
100
106
|
)
|
|
101
107
|
|
|
108
|
+
# def case_four(self) -> bool:
|
|
109
|
+
# """FBG >= 20.0"""
|
|
110
|
+
# return bool(
|
|
111
|
+
# pd.notna(self.next_fbg_datetime)
|
|
112
|
+
# and pd.notna(self.fbg_datetime)
|
|
113
|
+
# and self.fbg_value >= self.fbg_threshold
|
|
114
|
+
# and self.next_fbg_value >= self.fbg_threshold
|
|
115
|
+
# and 0.0 < self.next_ogtt_value < self.ogtt_threshold
|
|
116
|
+
# and self.fasted == YES
|
|
117
|
+
# and self.next_fasted == YES
|
|
118
|
+
# and (self.next_fbg_datetime.date() - self.fbg_datetime.date()).days > 6
|
|
119
|
+
# )
|
|
120
|
+
|
|
102
121
|
|
|
103
122
|
class EndpointByDate:
|
|
104
123
|
"""Given all timepoints for a subject, flag the first timepoint
|
|
@@ -113,6 +132,9 @@ class EndpointByDate:
|
|
|
113
132
|
* case 2. FBG >= 7 x 2, first OGTT<11.1
|
|
114
133
|
* case 3. FBG >= 7 x 2, second OGTT<11.1
|
|
115
134
|
|
|
135
|
+
If the endpoint is reached by FBG+OGTT, the date of endpoint is
|
|
136
|
+
always the date of the second measurement.
|
|
137
|
+
|
|
116
138
|
Additional criteria considered:
|
|
117
139
|
1. any threshhold FBG must be taken while fasted (fasted=YES)
|
|
118
140
|
2. threshhold FBG readings must be consecutive (no
|
|
@@ -6,9 +6,11 @@ from edc_constants.constants import NULL_STRING, YES
|
|
|
6
6
|
|
|
7
7
|
from ..constants import (
|
|
8
8
|
CASE_EOS,
|
|
9
|
+
CASE_FBG_ONLY,
|
|
9
10
|
CASE_FBGS_WITH_FIRST_OGTT,
|
|
10
11
|
CASE_FBGS_WITH_SECOND_OGTT,
|
|
11
12
|
CASE_OGTT,
|
|
13
|
+
FBG_BEYOND_THRESHOLD,
|
|
12
14
|
endpoint_cases,
|
|
13
15
|
endpoint_columns,
|
|
14
16
|
)
|
|
@@ -40,6 +42,7 @@ class GlucoseEndpointsByDate:
|
|
|
40
42
|
"""
|
|
41
43
|
|
|
42
44
|
fbg_threshhold = 7.0
|
|
45
|
+
fbg_beyond_threshold = FBG_BEYOND_THRESHOLD
|
|
43
46
|
ogtt_threshhold = 11.1
|
|
44
47
|
endpoint_cls = EndpointByDate
|
|
45
48
|
keep_cols = [ # noqa: RUF012
|
|
@@ -77,13 +80,15 @@ class GlucoseEndpointsByDate:
|
|
|
77
80
|
]
|
|
78
81
|
self.endpoint_cases = {k: v for k, v in endpoint_cases.items() if k in self.case_list}
|
|
79
82
|
|
|
80
|
-
self.df = get_glucose_df().copy()
|
|
83
|
+
self.df = get_glucose_df(subject_identifiers=self.subject_identifiers).copy()
|
|
81
84
|
|
|
82
85
|
# label rows by type of glu tests (ones with value)
|
|
83
86
|
self.df["test"] = self.df.apply(get_test_string, axis=1)
|
|
84
87
|
|
|
85
|
-
self.df =
|
|
86
|
-
|
|
88
|
+
self.df = (
|
|
89
|
+
self.df.query("not (fbg_value.isna() and ogtt_value.isna())")
|
|
90
|
+
.sort_values(by=["subject_identifier", "fbg_datetime"])
|
|
91
|
+
.reset_index(drop=True)
|
|
87
92
|
)
|
|
88
93
|
self.working_df = self.df.copy()
|
|
89
94
|
self.working_df["endpoint"] = 0
|
|
@@ -91,11 +96,11 @@ class GlucoseEndpointsByDate:
|
|
|
91
96
|
|
|
92
97
|
def run(self):
|
|
93
98
|
self.process_by_ogtt_only()
|
|
99
|
+
# self.process_by_fbg_only()
|
|
94
100
|
subject_identifiers_df = get_unique_subject_identifiers(self.df)
|
|
95
101
|
for _, row in subject_identifiers_df.iterrows():
|
|
96
|
-
subject_df = self.get_subject_df(row["subject_identifier"])
|
|
97
102
|
subject_df = self.endpoint_cls(
|
|
98
|
-
subject_df=
|
|
103
|
+
subject_df=self.get_subject_df(row["subject_identifier"]),
|
|
99
104
|
fbg_threshhold=self.fbg_threshhold,
|
|
100
105
|
ogtt_threshhold=self.ogtt_threshhold,
|
|
101
106
|
).subject_df
|
|
@@ -105,6 +110,53 @@ class GlucoseEndpointsByDate:
|
|
|
105
110
|
self.post_check_endpoint()
|
|
106
111
|
self.merge_with_final_endpoints()
|
|
107
112
|
|
|
113
|
+
def process_by_fbg_only(self):
|
|
114
|
+
"""Flag subjects that met endpoint by hitting the absurd FBG
|
|
115
|
+
|
|
116
|
+
Not used yet. Waiting for confirmation from Anu.
|
|
117
|
+
"""
|
|
118
|
+
subject_endpoint_df = self.working_df.loc[
|
|
119
|
+
(self.working_df["fbg_value"] >= self.fbg_beyond_threshold)
|
|
120
|
+
# & (self.working_df["fasted"] == YES)
|
|
121
|
+
].copy()
|
|
122
|
+
|
|
123
|
+
subject_endpoint_df = (
|
|
124
|
+
subject_endpoint_df.sort_values(by=["subject_identifier", "fbg_datetime"])
|
|
125
|
+
.reset_index(drop=True)
|
|
126
|
+
.drop_duplicates(subset=["subject_identifier"], keep="first")
|
|
127
|
+
.reset_index(drop=True)
|
|
128
|
+
)
|
|
129
|
+
if not subject_endpoint_df.empty:
|
|
130
|
+
# flag the selected endpoint rows as endpoints
|
|
131
|
+
subject_endpoint_df["endpoint"] = 1
|
|
132
|
+
subject_endpoint_df["endpoint_label"] = self.endpoint_cases[CASE_OGTT]
|
|
133
|
+
subject_endpoint_df["endpoint_type"] = CASE_FBG_ONLY
|
|
134
|
+
subject_endpoint_df["interval_in_days"] = np.nan
|
|
135
|
+
|
|
136
|
+
# add back the others rows for these subjects
|
|
137
|
+
subjects_df = self.working_df.loc[
|
|
138
|
+
(
|
|
139
|
+
self.working_df["subject_identifier"].isin(
|
|
140
|
+
subject_endpoint_df["subject_identifier"]
|
|
141
|
+
)
|
|
142
|
+
& ~(
|
|
143
|
+
self.working_df["fbg_datetime"].isin(
|
|
144
|
+
subject_endpoint_df["fbg_datetime"]
|
|
145
|
+
)
|
|
146
|
+
)
|
|
147
|
+
)
|
|
148
|
+
].copy()
|
|
149
|
+
subjects_df = subjects_df.reset_index(drop=True)
|
|
150
|
+
subjects_df["endpoint"] = np.nan
|
|
151
|
+
subjects_df["endpoint_label"] = None
|
|
152
|
+
subjects_df["endpoint_type"] = None
|
|
153
|
+
subjects_df["interval_in_days"] = np.nan
|
|
154
|
+
subjects_df = pd.concat([subjects_df, subject_endpoint_df])
|
|
155
|
+
subjects_df = subjects_df.reset_index(drop=True)
|
|
156
|
+
|
|
157
|
+
self.append_subject_to_endpoint_df(subjects_df[endpoint_columns])
|
|
158
|
+
self.remove_subjects_from_working_df(subjects_df)
|
|
159
|
+
|
|
108
160
|
def process_by_ogtt_only(self):
|
|
109
161
|
"""Flag subjects that met endpoint by hitting the OGTT
|
|
110
162
|
threshold.
|
|
@@ -126,7 +178,7 @@ class GlucoseEndpointsByDate:
|
|
|
126
178
|
"""
|
|
127
179
|
subject_endpoint_df = self.working_df.loc[
|
|
128
180
|
(self.working_df["ogtt_value"] >= self.ogtt_threshhold)
|
|
129
|
-
& (self.working_df["ogtt_value"]
|
|
181
|
+
& (self.working_df["ogtt_value"] <= 9999.99)
|
|
130
182
|
& (self.working_df["fasted"] == YES)
|
|
131
183
|
& (self.working_df["fbg_value"].notna())
|
|
132
184
|
].copy()
|
|
@@ -292,8 +344,9 @@ class GlucoseEndpointsByDate:
|
|
|
292
344
|
how="left",
|
|
293
345
|
suffixes=("", "_y"),
|
|
294
346
|
)
|
|
295
|
-
self.df = self.df.sort_values(by=["subject_identifier", "fbg_datetime"])
|
|
296
|
-
|
|
347
|
+
self.df = self.df.sort_values(by=["subject_identifier", "fbg_datetime"]).reset_index(
|
|
348
|
+
drop=True
|
|
349
|
+
)
|
|
297
350
|
|
|
298
351
|
def to_model(self):
|
|
299
352
|
"""Write endpoint_only_df to the Endpoints model"""
|
|
@@ -124,16 +124,12 @@ def get_screening_df(df: pd.DataFrame | None = None) -> pd.DataFrame:
|
|
|
124
124
|
df_physical_exam = read_frame(qs_physical_exam)
|
|
125
125
|
# merge w/ subject visit to get subject_identifier
|
|
126
126
|
df_physical_exam = df_physical_exam.merge(
|
|
127
|
-
df_physical_exam,
|
|
128
127
|
df_subject_visit[
|
|
129
128
|
["subject_visit", "subject_identifier", "visit_code", "visit_code_sequence"]
|
|
130
129
|
],
|
|
131
130
|
on="subject_visit",
|
|
132
131
|
how="left",
|
|
133
|
-
)
|
|
134
|
-
df_physical_exam = df_physical_exam[
|
|
135
|
-
["subject_identifier", "visit_code", "visit_code_sequence", "waist_circumference"]
|
|
136
|
-
]
|
|
132
|
+
)[["subject_identifier", "visit_code", "visit_code_sequence", "waist_circumference"]]
|
|
137
133
|
df_physical_exam[["waist_circumference"]] = df_physical_exam[
|
|
138
134
|
["waist_circumference"]
|
|
139
135
|
].apply(pd.to_numeric)
|
meta_consent/migrations/0035_alter_historicalsubjectconsent_consent_definition_name_and_more.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Generated by Django 5.2.7 on 2025-10-24 04:17
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
("meta_consent", "0034_remove_subjectconsentspfq_site_and_more"),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AlterField(
|
|
14
|
+
model_name="historicalsubjectconsent",
|
|
15
|
+
name="consent_definition_name",
|
|
16
|
+
field=models.CharField(
|
|
17
|
+
default="",
|
|
18
|
+
editable=False,
|
|
19
|
+
max_length=50,
|
|
20
|
+
verbose_name="Consent definition",
|
|
21
|
+
),
|
|
22
|
+
),
|
|
23
|
+
migrations.AlterField(
|
|
24
|
+
model_name="historicalsubjectconsentv1",
|
|
25
|
+
name="consent_definition_name",
|
|
26
|
+
field=models.CharField(
|
|
27
|
+
default="",
|
|
28
|
+
editable=False,
|
|
29
|
+
max_length=50,
|
|
30
|
+
verbose_name="Consent definition",
|
|
31
|
+
),
|
|
32
|
+
),
|
|
33
|
+
migrations.AlterField(
|
|
34
|
+
model_name="subjectconsent",
|
|
35
|
+
name="consent_definition_name",
|
|
36
|
+
field=models.CharField(
|
|
37
|
+
default="",
|
|
38
|
+
editable=False,
|
|
39
|
+
max_length=50,
|
|
40
|
+
verbose_name="Consent definition",
|
|
41
|
+
),
|
|
42
|
+
),
|
|
43
|
+
]
|
meta_dashboard/navbars.py
CHANGED
|
@@ -4,8 +4,6 @@ from edc_navbar import Navbar, NavbarItem, site_navbars
|
|
|
4
4
|
from edc_pharmacy.navbars import pharmacy_navbar_item
|
|
5
5
|
from edc_review_dashboard.navbars import navbar_item as review_navbar_item
|
|
6
6
|
|
|
7
|
-
no_url_namespace = False # True if settings.APP_NAME == "meta_dashboard" else False
|
|
8
|
-
|
|
9
7
|
navbar = Navbar(name="meta_dashboard")
|
|
10
8
|
|
|
11
9
|
|
|
@@ -16,8 +14,7 @@ navbar.register(
|
|
|
16
14
|
label="Screening",
|
|
17
15
|
fa_icon="fa-user-plus",
|
|
18
16
|
codename="edc_screening.view_screening_listboard",
|
|
19
|
-
|
|
20
|
-
no_url_namespace=no_url_namespace,
|
|
17
|
+
url_names_key="screening_listboard_url",
|
|
21
18
|
)
|
|
22
19
|
)
|
|
23
20
|
|
|
@@ -28,8 +25,7 @@ navbar.register(
|
|
|
28
25
|
label="Subjects",
|
|
29
26
|
fa_icon="fa-user-circle",
|
|
30
27
|
codename="edc_subject_dashboard.view_subject_listboard",
|
|
31
|
-
|
|
32
|
-
no_url_namespace=no_url_namespace,
|
|
28
|
+
url_names_key="subject_listboard_url",
|
|
33
29
|
)
|
|
34
30
|
)
|
|
35
31
|
|
meta_dashboard/urls.py
CHANGED
|
@@ -13,28 +13,28 @@ app_name = "meta_dashboard"
|
|
|
13
13
|
|
|
14
14
|
urlpatterns = SubjectListboardView.urls(
|
|
15
15
|
namespace=app_name,
|
|
16
|
-
|
|
16
|
+
url_names_key="subject_listboard_url",
|
|
17
17
|
identifier_pattern=ResearchProtocolConfig().subject_identifier_pattern,
|
|
18
18
|
)
|
|
19
19
|
urlpatterns += ScreeningListboardView.urls(
|
|
20
20
|
namespace=app_name,
|
|
21
|
-
|
|
21
|
+
url_names_key="screening_listboard_url",
|
|
22
22
|
identifier_label="screening_identifier",
|
|
23
23
|
identifier_pattern=screening_identifier,
|
|
24
24
|
)
|
|
25
25
|
urlpatterns += SubjectDashboardView.urls(
|
|
26
26
|
namespace=app_name,
|
|
27
|
-
|
|
27
|
+
url_names_key="subject_dashboard_url",
|
|
28
28
|
identifier_pattern=ResearchProtocolConfig().subject_identifier_pattern,
|
|
29
29
|
)
|
|
30
30
|
|
|
31
31
|
urlpatterns += AeListboardView.urls(
|
|
32
32
|
namespace=app_name,
|
|
33
|
-
|
|
33
|
+
url_names_key="ae_listboard_url",
|
|
34
34
|
identifier_pattern=ResearchProtocolConfig().subject_identifier_pattern,
|
|
35
35
|
)
|
|
36
36
|
urlpatterns += DeathReportListboardView.urls(
|
|
37
37
|
namespace=app_name,
|
|
38
|
-
|
|
38
|
+
url_names_key="death_report_listboard_url",
|
|
39
39
|
identifier_pattern=ResearchProtocolConfig().subject_identifier_pattern,
|
|
40
40
|
)
|
|
@@ -11,7 +11,6 @@ class ListboardView(ScreeningListboardView):
|
|
|
11
11
|
kwargs.update(meta_version=get_meta_version())
|
|
12
12
|
return super().get_context_data(**kwargs)
|
|
13
13
|
|
|
14
|
-
def get_search_fields(self) ->
|
|
14
|
+
def get_search_fields(self) -> tuple[str, ...]:
|
|
15
15
|
fields = super().get_search_fields()
|
|
16
|
-
fields
|
|
17
|
-
return fields
|
|
16
|
+
return *fields, "hospital_identifier__exact"
|
|
@@ -20,23 +20,22 @@ class DashboardView(SubjectDashboardView):
|
|
|
20
20
|
|
|
21
21
|
def get_context_data(self, **kwargs) -> dict[str, Any]:
|
|
22
22
|
"""Add message if subject reaches DM Endpoint."""
|
|
23
|
-
|
|
24
|
-
context.update(subject_consent_v1_ext=self.subject_consent_v1_ext)
|
|
23
|
+
kwargs.update(subject_consent_v1_ext=self.subject_consent_v1_ext)
|
|
25
24
|
try:
|
|
26
25
|
Endpoints.objects.get(subject_identifier=self.subject_identifier)
|
|
27
26
|
except ObjectDoesNotExist:
|
|
28
27
|
pass
|
|
29
28
|
else:
|
|
30
29
|
url = reverse("meta_reports_admin:meta_reports_glucosesummary_changelist")
|
|
31
|
-
url = f"{url}?q={self.subject_identifier}"
|
|
30
|
+
url = mark_safe(f"{url}?q={self.subject_identifier}") # noqa: S308
|
|
32
31
|
message = format_html(
|
|
33
32
|
'{text} <A href="{url}">{verbose_name}</A>',
|
|
34
33
|
text=_("Subject has reached the protocol endpoint. See "),
|
|
35
|
-
url=
|
|
34
|
+
url=url,
|
|
36
35
|
verbose_name=GlucoseSummary._meta.verbose_name,
|
|
37
36
|
)
|
|
38
37
|
self.message_user(message, level=messages.WARNING)
|
|
39
|
-
return
|
|
38
|
+
return super().get_context_data(**kwargs)
|
|
40
39
|
|
|
41
40
|
@property
|
|
42
41
|
def subject_consent_v1_ext(self):
|
|
@@ -11,7 +11,6 @@ class SubjectListboardView(BaseSubjectListboardView):
|
|
|
11
11
|
kwargs.update(meta_version=get_meta_version())
|
|
12
12
|
return super().get_context_data(**kwargs)
|
|
13
13
|
|
|
14
|
-
def get_search_fields(self) ->
|
|
14
|
+
def get_search_fields(self) -> tuple[str, ...]:
|
|
15
15
|
fields = super().get_search_fields()
|
|
16
|
-
fields
|
|
17
|
-
return fields
|
|
16
|
+
return *fields, "identity__exact"
|
meta_edc/settings/debug.py
CHANGED
|
@@ -11,12 +11,12 @@ sys.stdout.write(f"Settings file {__file__}\n")
|
|
|
11
11
|
# from django.core.cache import cache
|
|
12
12
|
# cache.clear()
|
|
13
13
|
# TZ Sites:
|
|
14
|
-
SITE_ID = SiteID(default=20) # Amana
|
|
14
|
+
# SITE_ID = SiteID(default=20) # Amana
|
|
15
15
|
# SITE_ID = SiteID(default=10) # Hindu Mandal
|
|
16
16
|
# SITE_ID = SiteID(default=40) # Mwananyamala
|
|
17
17
|
# SITE_ID = SiteID(default=50) # Mbagala
|
|
18
18
|
# SITE_ID = SiteID(default=60) # Mnazi-Moja
|
|
19
|
-
|
|
19
|
+
SITE_ID = SiteID(default=30) # Temeke
|
|
20
20
|
|
|
21
21
|
INDEX_PAGE = "http://localhost:8000"
|
|
22
22
|
EDC_SITES_UAT_DOMAIN = False
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meta-edc
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.8
|
|
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
|
|
@@ -15,7 +15,7 @@ Classifier: Intended Audience :: Science/Research
|
|
|
15
15
|
Classifier: Operating System :: OS Independent
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
-
Requires-Dist: clinicedc>=2.0.
|
|
18
|
+
Requires-Dist: clinicedc>=2.0.41
|
|
19
19
|
Requires-Dist: edc-he>=1.2.0
|
|
20
20
|
Requires-Dist: edc-microscopy>=1.2.0
|
|
21
21
|
Requires-Dist: edc-mnsi>=1.2.0
|
|
@@ -89,8 +89,8 @@ Assuming you are logged into the account ``myaccount``:
|
|
|
89
89
|
mkdir ~/edc && \
|
|
90
90
|
cd ~/edc && \
|
|
91
91
|
uv venv && \
|
|
92
|
-
uv pip install -U meta-edc==1.2.
|
|
93
|
-
wget https://raw.githubusercontent.com/meta-trial/meta-edc/1.2.
|
|
92
|
+
uv pip install -U meta-edc==1.2.7 && \
|
|
93
|
+
wget https://raw.githubusercontent.com/meta-trial/meta-edc/1.2.7/manage.py && \
|
|
94
94
|
uv pip freeze | grep meta-edc
|
|
95
95
|
|
|
96
96
|
Copy your ``.env`` file to ``~/.etc``.
|
|
@@ -140,7 +140,7 @@ From the above example:
|
|
|
140
140
|
|
|
141
141
|
cd ~/edc && \
|
|
142
142
|
uv venv --clear && \
|
|
143
|
-
uv pip install -U meta-edc==1.2.
|
|
143
|
+
uv pip install -U meta-edc==1.2.7 && \
|
|
144
144
|
wget -O manage.py https://raw.githubusercontent.com/meta-trial/meta-edc/1.1.10/manage.py && \
|
|
145
145
|
uv pip freeze | grep meta-edc && \
|
|
146
146
|
python manage.py check
|