meta-edc 0.3.38__py3-none-any.whl → 0.3.39__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.
Files changed (85) hide show
  1. meta_analytics/__init__.py +0 -2
  2. meta_analytics/dataframes/__init__.py +1 -0
  3. meta_analytics/dataframes/get_last_imp_visits_df.py +101 -0
  4. meta_auth/auth_objects.py +1 -0
  5. meta_consent/consents.py +6 -0
  6. meta_consent/locale/lg/LC_MESSAGES/django.po +69 -0
  7. meta_consent/locale/sw/LC_MESSAGES/django.po +12 -12
  8. meta_dashboard/locale/lg/LC_MESSAGES/django.po +30 -0
  9. meta_dashboard/locale/sw/LC_MESSAGES/django.po +11 -2
  10. meta_dashboard/navbars.py +2 -0
  11. meta_dashboard/tests/urls.py +0 -1
  12. meta_dashboard/view_utils/subject_screening_button.py +2 -2
  13. meta_edc/__init__.py +3 -10
  14. meta_edc/{celery/debug.py → celery.py} +2 -2
  15. meta_edc/navbars.py +2 -0
  16. meta_edc/settings/debug.py +4 -0
  17. meta_edc/settings/defaults.py +29 -16
  18. meta_edc/templates/meta_edc/bootstrap3/home.html +1 -1
  19. meta_edc/urls.py +1 -0
  20. {meta_edc-0.3.38.dist-info → meta_edc-0.3.39.dist-info}/METADATA +6 -6
  21. {meta_edc-0.3.38.dist-info → meta_edc-0.3.39.dist-info}/RECORD +70 -59
  22. {meta_edc-0.3.38.dist-info → meta_edc-0.3.39.dist-info}/WHEEL +1 -1
  23. meta_pharmacy/admin/__init__.py +0 -1
  24. meta_pharmacy/admin/actions.py +38 -0
  25. meta_pharmacy/admin_site.py +5 -1
  26. meta_pharmacy/apps.py +2 -0
  27. meta_pharmacy/forms/__init__.py +2 -0
  28. meta_pharmacy/forms/rx_form.py +16 -0
  29. meta_pharmacy/{forms.py → forms/substitutions_form.py} +1 -14
  30. meta_pharmacy/label_configs.py +30 -0
  31. meta_pharmacy/labels/__init__.py +3 -1
  32. meta_pharmacy/labels/draw_label_for_subject_with_barcode.py +58 -0
  33. meta_pharmacy/labels/draw_label_for_subject_with_code128.py +14 -0
  34. meta_pharmacy/labels/draw_label_with_test_data.py +26 -0
  35. meta_pharmacy/labels/label_data.py +14 -0
  36. meta_pharmacy/labels/print_sheets.py +22 -11
  37. meta_pharmacy/list_data.py +8 -0
  38. meta_pharmacy/management/commands/__init__.py +0 -0
  39. meta_pharmacy/management/commands/update_initial_pharmacy_data.py +10 -0
  40. meta_pharmacy/migrations/0002_initial.py +7 -5
  41. meta_pharmacy/migrations/0008_remove_lotnumber_medication_and_more.py +390 -0
  42. meta_pharmacy/migrations/0009_remove_historicalrx_slug.py +17 -0
  43. meta_pharmacy/models/__init__.py +1 -2
  44. meta_pharmacy/models/label_data.py +38 -0
  45. meta_pharmacy/models/{label.py → rx_label.py} +8 -19
  46. meta_pharmacy/utils/__init__.py +1 -0
  47. meta_pharmacy/utils/update_initial_pharmacy_data.py +146 -0
  48. meta_prn/admin/pregnancy_notification_admin.py +6 -2
  49. meta_reports/admin/__init__.py +1 -0
  50. meta_reports/admin/dbviews/glucose_summary_admin.py +1 -1
  51. meta_reports/admin/last_imp_refill_admin.py +181 -0
  52. meta_reports/migrations/0052_lastimpvisit.py +57 -0
  53. meta_reports/migrations/0053_rename_lastimpvisit_lastimprefill_and_more.py +31 -0
  54. meta_reports/models/__init__.py +1 -0
  55. meta_reports/models/last_imp_refill.py +34 -0
  56. meta_subject/admin/study_medication_admin.py +10 -0
  57. meta_subject/forms/study_medication_form.py +35 -0
  58. meta_subject/locale/lg/LC_MESSAGES/django.po +470 -0
  59. meta_subject/locale/sw/LC_MESSAGES/django.po +191 -89
  60. meta_subject/metadata_rules/predicates.py +34 -7
  61. meta_subject/migrations/0214_historicalstudymedication_stock_codes_and_more.py +44 -0
  62. meta_subject/migrations/0215_alter_historicalstudymedication_stock_codes_and_more.py +46 -0
  63. meta_subject/tests/tests/test_mnsi.py +180 -113
  64. meta_visit_schedule/visit_schedules/phase_three/crfs.py +18 -6
  65. tests/test_settings.py +4 -1
  66. meta_edc/celery/__init__.py +0 -2
  67. meta_edc/celery/live.py +0 -17
  68. meta_edc/celery/uat.py +0 -17
  69. meta_pharmacy/admin/lot_number_admin.py +0 -43
  70. meta_pharmacy/labels/get_label_data.py +0 -30
  71. meta_pharmacy/models/lot_number.py +0 -25
  72. meta_reports/models/unmanaged/README +0 -14
  73. meta_reports/models/unmanaged/patient_history_missing_baseline_cd4.py +0 -26
  74. meta_reports/models/unmanaged/patient_history_missing_baseline_cd4.sql +0 -10
  75. meta_reports/models/unmanaged/unattended_three_in_row.py +0 -24
  76. meta_reports/models/unmanaged/unattended_three_in_row.sql +0 -19
  77. meta_reports/models/unmanaged/unattended_three_in_row2.py +0 -24
  78. meta_reports/models/unmanaged/unattended_three_in_row2.sql +0 -39
  79. meta_reports/models/unmanaged/unattended_two_in_row.py +0 -22
  80. meta_reports/models/unmanaged/unattended_two_in_row.sql +0 -19
  81. {meta_reports/models/unmanaged → meta_edc/migrations}/__init__.py +0 -0
  82. {meta_edc-0.3.38.dist-info → meta_edc-0.3.39.dist-info}/AUTHORS +0 -0
  83. {meta_edc-0.3.38.dist-info → meta_edc-0.3.39.dist-info}/LICENSE +0 -0
  84. {meta_edc-0.3.38.dist-info → meta_edc-0.3.39.dist-info}/top_level.txt +0 -0
  85. /meta_pharmacy/{admin/label_admin.py → management/__init__.py} +0 -0
@@ -0,0 +1,46 @@
1
+ # Generated by Django 5.1.2 on 2024-11-18 02:34
2
+
3
+ import django.core.validators
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ("meta_subject", "0214_historicalstudymedication_stock_codes_and_more"),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AlterField(
15
+ model_name="historicalstudymedication",
16
+ name="stock_codes",
17
+ field=models.CharField(
18
+ blank=True,
19
+ help_text="Enter the medication bottle barcode or barcodes seperated by comma, no spaces",
20
+ max_length=30,
21
+ null=True,
22
+ validators=[
23
+ django.core.validators.RegexValidator(
24
+ message="Enter one or more valid codes separated by comma",
25
+ regex="^([A-Z0-9]{6})(,[A-Z0-9]{6})*$",
26
+ )
27
+ ],
28
+ ),
29
+ ),
30
+ migrations.AlterField(
31
+ model_name="studymedication",
32
+ name="stock_codes",
33
+ field=models.CharField(
34
+ blank=True,
35
+ help_text="Enter the medication bottle barcode or barcodes seperated by comma, no spaces",
36
+ max_length=30,
37
+ null=True,
38
+ validators=[
39
+ django.core.validators.RegexValidator(
40
+ message="Enter one or more valid codes separated by comma",
41
+ regex="^([A-Z0-9]{6})(,[A-Z0-9]{6})*$",
42
+ )
43
+ ],
44
+ ),
45
+ ),
46
+ ]
@@ -3,15 +3,37 @@ from zoneinfo import ZoneInfo
3
3
 
4
4
  import time_machine
5
5
  from dateutil.relativedelta import relativedelta
6
- from django.test import TestCase
6
+ from django.core.exceptions import ObjectDoesNotExist
7
+ from django.test import TestCase, tag
7
8
  from edc_constants.constants import NO, YES
8
9
  from edc_utils import get_utcnow
9
10
  from model_bakery import baker
10
11
 
11
12
  from meta_screening.tests.meta_test_case_mixin import MetaTestCaseMixin
12
- from meta_visit_schedule.constants import MONTH1, MONTH3, MONTH6, MONTH9, MONTH12, WEEK2
13
-
14
-
13
+ from meta_subject.models import SubjectVisit
14
+ from meta_visit_schedule.constants import (
15
+ MONTH1,
16
+ MONTH3,
17
+ MONTH6,
18
+ MONTH9,
19
+ MONTH12,
20
+ MONTH15,
21
+ MONTH18,
22
+ MONTH21,
23
+ MONTH24,
24
+ MONTH27,
25
+ MONTH30,
26
+ MONTH33,
27
+ MONTH36,
28
+ MONTH39,
29
+ MONTH42,
30
+ MONTH45,
31
+ MONTH48,
32
+ WEEK2,
33
+ )
34
+
35
+
36
+ @tag("mnsi")
15
37
  @time_machine.travel(datetime(2022, 6, 11, 8, 00, tzinfo=ZoneInfo("UTC")))
16
38
  class TestMnsiRequired(MetaTestCaseMixin, TestCase):
17
39
  def setUp(self):
@@ -33,45 +55,34 @@ class TestMnsiRequired(MetaTestCaseMixin, TestCase):
33
55
  appt_datetime=six_months_ago,
34
56
  )
35
57
 
36
- def get_week2_visit(self):
37
- return self.get_subject_visit(
38
- subject_screening=self.subject_screening,
39
- subject_consent=self.subject_consent,
40
- visit_code=WEEK2,
41
- appt_datetime=self.baseline_datetime + relativedelta(weeks=2),
42
- )
43
-
44
- def get_month1_visit(self):
45
- return self.get_subject_visit(
46
- subject_screening=self.subject_screening,
47
- subject_consent=self.subject_consent,
48
- visit_code=MONTH1,
49
- appt_datetime=self.baseline_datetime + relativedelta(months=1),
50
- )
51
-
52
- def get_month3_visit(self):
53
- return self.get_subject_visit(
54
- subject_screening=self.subject_screening,
55
- subject_consent=self.subject_consent,
56
- visit_code=MONTH3,
57
- appt_datetime=self.baseline_datetime + relativedelta(months=3),
58
- )
59
-
60
- def get_month6_visit(self):
61
- return self.get_subject_visit(
62
- subject_screening=self.subject_screening,
63
- subject_consent=self.subject_consent,
64
- visit_code=MONTH6,
65
- appt_datetime=self.baseline_datetime + relativedelta(months=6),
66
- )
67
-
68
- def get_month9_visit(self):
69
- return self.get_subject_visit(
70
- subject_screening=self.subject_screening,
71
- subject_consent=self.subject_consent,
72
- visit_code=MONTH9,
73
- appt_datetime=self.baseline_datetime + relativedelta(months=9),
74
- )
58
+ def get_visit(self, visit_code: str):
59
+ """Returns a scheduled visit with the specified visit code.
60
+
61
+ If the visit already exists, it will be returned. If not, it
62
+ will be created (along with any interim visits) and returned.
63
+ """
64
+ subject_identifier = self.subject_consent.subject_identifier
65
+ try:
66
+ subject_visit = SubjectVisit.objects.get(
67
+ subject_identifier=subject_identifier,
68
+ visit_code=visit_code,
69
+ visit_code_sequence=0,
70
+ )
71
+ except ObjectDoesNotExist:
72
+ subject_visit = (
73
+ SubjectVisit.objects.filter(
74
+ subject_identifier=subject_identifier,
75
+ visit_code_sequence=0,
76
+ )
77
+ .order_by("visit_code")
78
+ .last()
79
+ )
80
+ while subject_visit.visit_code != visit_code:
81
+ subject_visit = self.get_next_subject_visit(subject_visit)
82
+
83
+ self.assertEqual(subject_visit.visit_code, visit_code)
84
+ self.assertEqual(subject_visit.visit_code_sequence, 0)
85
+ return subject_visit
75
86
 
76
87
  @staticmethod
77
88
  def set_mnsi_status(subject_visit, mnsi_performed):
@@ -82,169 +93,225 @@ class TestMnsiRequired(MetaTestCaseMixin, TestCase):
82
93
  )
83
94
  visit_mnsi.save()
84
95
 
96
+ def test_mnsi_not_required_at_baseline(self):
97
+ crfs = self.get_crf_metadata(self.subject_visit)
98
+ self.assertNotIn("meta_subject.mnsi", [o.model for o in crfs.all()])
99
+
85
100
  def test_mnsi_not_required_at_2w(self):
86
- crfs = self.get_crf_metadata(self.get_week2_visit())
101
+ crfs = self.get_crf_metadata(self.get_visit(visit_code=WEEK2))
87
102
  self.assertNotIn("meta_subject.mnsi", [o.model for o in crfs.all()])
88
103
 
89
104
  def test_mnsi_required_at_1m(self):
90
- self.get_week2_visit()
91
-
92
- month1_visit = self.get_month1_visit()
93
- crfs = self.get_crf_metadata(month1_visit)
105
+ crfs = self.get_crf_metadata(self.get_visit(visit_code=MONTH1))
94
106
  self.assertIn("meta_subject.mnsi", [o.model for o in crfs.all()])
95
107
 
96
108
  def test_mnsi_not_required_at_3m_if_already_performed_at_1m(self):
97
- self.get_week2_visit()
98
-
99
109
  # MNSI shouldn't be required at any point after it has been performed
100
- month1_visit = self.get_month1_visit()
110
+ month1_visit = self.get_visit(visit_code=MONTH1)
101
111
  self.set_mnsi_status(subject_visit=month1_visit, mnsi_performed=YES)
102
112
 
103
- month3_visit = self.get_month3_visit()
113
+ month3_visit = self.get_visit(visit_code=MONTH3)
104
114
  crfs = self.get_crf_metadata(month3_visit)
105
115
  self.assertNotIn("meta_subject.mnsi", [o.model for o in crfs.all()])
106
116
 
107
117
  def test_mnsi_required_at_3m_if_not_performed_at_1m(self):
108
- self.get_week2_visit()
109
-
110
- month1_visit = self.get_month1_visit()
118
+ month1_visit = self.get_visit(visit_code=MONTH1)
111
119
  self.set_mnsi_status(subject_visit=month1_visit, mnsi_performed=NO)
112
120
 
113
- month3_visit = self.get_month3_visit()
121
+ month3_visit = self.get_visit(visit_code=MONTH3)
114
122
  crfs = self.get_crf_metadata(month3_visit)
115
123
  self.assertIn("meta_subject.mnsi", [o.model for o in crfs.all()])
116
124
 
117
125
  def test_mnsi_not_required_at_6m_if_already_performed_at_1m(self):
118
- self.get_week2_visit()
119
-
120
126
  # MNSI shouldn't be required at any point after it has been performed
121
- month1_visit = self.get_month1_visit()
127
+ month1_visit = self.get_visit(visit_code=MONTH1)
122
128
  self.set_mnsi_status(subject_visit=month1_visit, mnsi_performed=YES)
123
129
 
124
- month3_visit = self.get_month3_visit()
130
+ month3_visit = self.get_visit(visit_code=MONTH3)
125
131
  crfs = self.get_crf_metadata(month3_visit)
126
132
  self.assertNotIn("meta_subject.mnsi", [o.model for o in crfs.all()])
127
133
 
128
- month6_visit = self.get_month6_visit()
134
+ month6_visit = self.get_visit(visit_code=MONTH6)
129
135
  crfs = self.get_crf_metadata(month6_visit)
130
136
  self.assertNotIn("meta_subject.mnsi", [o.model for o in crfs.all()])
131
137
 
132
138
  def test_mnsi_not_required_at_6m_if_already_performed_at_3m(self):
133
- self.get_week2_visit()
134
-
135
- month1_visit = self.get_month1_visit()
139
+ month1_visit = self.get_visit(visit_code=MONTH1)
136
140
  self.set_mnsi_status(subject_visit=month1_visit, mnsi_performed=NO)
137
141
 
138
142
  # MNSI shouldn't be required at any point after it has been performed
139
- month3_visit = self.get_month3_visit()
143
+ month3_visit = self.get_visit(visit_code=MONTH3)
140
144
  self.set_mnsi_status(subject_visit=month3_visit, mnsi_performed=YES)
141
145
 
142
- month6_visit = self.get_month6_visit()
146
+ month6_visit = self.get_visit(visit_code=MONTH6)
143
147
  crfs = self.get_crf_metadata(month6_visit)
144
148
  self.assertNotIn("meta_subject.mnsi", [o.model for o in crfs.all()])
145
149
 
146
150
  def test_mnsi_required_at_6m_if_not_performed_by_3m(self):
147
- self.get_week2_visit()
148
-
149
- month1_visit = self.get_month1_visit()
151
+ month1_visit = self.get_visit(visit_code=MONTH1)
150
152
  self.set_mnsi_status(subject_visit=month1_visit, mnsi_performed=NO)
151
153
 
152
- month3_visit = self.get_month3_visit()
154
+ month3_visit = self.get_visit(visit_code=MONTH3)
153
155
  self.set_mnsi_status(subject_visit=month3_visit, mnsi_performed=NO)
154
156
 
155
- month6_visit = self.get_month6_visit()
157
+ month6_visit = self.get_visit(visit_code=MONTH6)
156
158
  crfs = self.get_crf_metadata(month6_visit)
157
159
  self.assertIn("meta_subject.mnsi", [o.model for o in crfs.all()])
158
160
 
159
161
  def test_mnsi_not_required_at_9m_if_already_performed_at_1m(self):
160
- self.get_week2_visit()
161
-
162
162
  # MNSI shouldn't be required at any point after it has been performed
163
- month1_visit = self.get_month1_visit()
163
+ month1_visit = self.get_visit(visit_code=MONTH1)
164
164
  self.set_mnsi_status(subject_visit=month1_visit, mnsi_performed=YES)
165
165
 
166
- month3_visit = self.get_month3_visit()
166
+ month3_visit = self.get_visit(visit_code=MONTH3)
167
167
  crfs = self.get_crf_metadata(month3_visit)
168
168
  self.assertNotIn("meta_subject.mnsi", [o.model for o in crfs.all()])
169
169
 
170
- month6_visit = self.get_month6_visit()
170
+ month6_visit = self.get_visit(visit_code=MONTH6)
171
171
  crfs = self.get_crf_metadata(month6_visit)
172
172
  self.assertNotIn("meta_subject.mnsi", [o.model for o in crfs.all()])
173
173
 
174
- month9_visit = self.get_month9_visit()
174
+ month9_visit = self.get_visit(visit_code=MONTH9)
175
175
  crfs = self.get_crf_metadata(month9_visit)
176
176
  self.assertNotIn("meta_subject.mnsi", [o.model for o in crfs.all()])
177
177
 
178
178
  def test_mnsi_not_required_at_9m_if_already_performed_at_3m(self):
179
- self.get_week2_visit()
180
-
181
- month1_visit = self.get_month1_visit()
179
+ month1_visit = self.get_visit(visit_code=MONTH1)
182
180
  self.set_mnsi_status(subject_visit=month1_visit, mnsi_performed=NO)
183
181
 
184
182
  # MNSI shouldn't be required at any point after it has been performed
185
- month3_visit = self.get_month3_visit()
183
+ month3_visit = self.get_visit(visit_code=MONTH3)
186
184
  self.set_mnsi_status(subject_visit=month3_visit, mnsi_performed=YES)
187
185
 
188
- month6_visit = self.get_month6_visit()
186
+ month6_visit = self.get_visit(visit_code=MONTH6)
189
187
  crfs = self.get_crf_metadata(month6_visit)
190
188
  self.assertNotIn("meta_subject.mnsi", [o.model for o in crfs.all()])
191
189
 
192
- month9_visit = self.get_month9_visit()
190
+ month9_visit = self.get_visit(visit_code=MONTH9)
193
191
  crfs = self.get_crf_metadata(month9_visit)
194
192
  self.assertNotIn("meta_subject.mnsi", [o.model for o in crfs.all()])
195
193
 
196
194
  def test_mnsi_not_required_at_9m_if_already_performed_at_6m(self):
197
- self.get_week2_visit()
198
-
199
- month1_visit = self.get_month1_visit()
195
+ month1_visit = self.get_visit(visit_code=MONTH1)
200
196
  self.set_mnsi_status(subject_visit=month1_visit, mnsi_performed=NO)
201
197
 
202
- month3_visit = self.get_month3_visit()
198
+ month3_visit = self.get_visit(visit_code=MONTH3)
203
199
  self.set_mnsi_status(subject_visit=month3_visit, mnsi_performed=NO)
204
200
 
205
201
  # MNSI shouldn't be required at any point after it has been performed
206
- month6_visit = self.get_month6_visit()
202
+ month6_visit = self.get_visit(visit_code=MONTH6)
207
203
  self.set_mnsi_status(subject_visit=month6_visit, mnsi_performed=YES)
208
204
 
209
- month9_visit = self.get_month9_visit()
205
+ month9_visit = self.get_visit(visit_code=MONTH9)
210
206
  crfs = self.get_crf_metadata(month9_visit)
211
207
  self.assertNotIn("meta_subject.mnsi", [o.model for o in crfs.all()])
212
208
 
213
- def test_mnsi_not_required_at_9m_even_if_not_performed_by_6m(self):
214
- self.get_week2_visit()
209
+ def test_mnsi_not_required_between_9m_and_33m_when_performed_in_first_6m(self):
210
+ month1_visit = self.get_visit(visit_code=MONTH1)
211
+ self.set_mnsi_status(subject_visit=month1_visit, mnsi_performed=NO)
212
+
213
+ month3_visit = self.get_visit(visit_code=MONTH3)
214
+ self.set_mnsi_status(subject_visit=month3_visit, mnsi_performed=YES)
215
215
 
216
- month1_visit = self.get_month1_visit()
216
+ for visit_code in [
217
+ MONTH9,
218
+ MONTH12,
219
+ MONTH15,
220
+ MONTH18,
221
+ MONTH21,
222
+ MONTH24,
223
+ MONTH27,
224
+ MONTH30,
225
+ MONTH33,
226
+ ]:
227
+ with self.subTest(visit_code=visit_code):
228
+ subject_visit = self.get_visit(visit_code=visit_code)
229
+ self.assertEqual(subject_visit.visit_code, visit_code)
230
+ self.assertEqual(subject_visit.visit_code_sequence, 0)
231
+ crfs = self.get_crf_metadata(subject_visit)
232
+ self.assertNotIn("meta_subject.mnsi", [o.model for o in crfs.all()])
233
+
234
+ def test_mnsi_not_required_between_9m_and_33m_even_if_not_performed_first_6m(self):
235
+ month1_visit = self.get_visit(visit_code=MONTH1)
217
236
  self.set_mnsi_status(subject_visit=month1_visit, mnsi_performed=NO)
218
237
 
219
- month3_visit = self.get_month3_visit()
238
+ month3_visit = self.get_visit(visit_code=MONTH3)
220
239
  self.set_mnsi_status(subject_visit=month3_visit, mnsi_performed=NO)
221
240
 
222
- month6_visit = self.get_month6_visit()
241
+ month6_visit = self.get_visit(visit_code=MONTH6)
223
242
  self.set_mnsi_status(subject_visit=month6_visit, mnsi_performed=NO)
224
243
 
225
- month9_visit = self.get_month9_visit()
226
- crfs = self.get_crf_metadata(month9_visit)
227
- self.assertNotIn("meta_subject.mnsi", [o.model for o in crfs.all()])
244
+ for visit_code in [
245
+ MONTH9,
246
+ MONTH12,
247
+ MONTH15,
248
+ MONTH18,
249
+ MONTH21,
250
+ MONTH24,
251
+ MONTH27,
252
+ MONTH30,
253
+ MONTH33,
254
+ ]:
255
+ with self.subTest(visit_code=visit_code):
256
+ subject_visit = self.get_visit(visit_code=visit_code)
257
+ self.assertEqual(subject_visit.visit_code, visit_code)
258
+ self.assertEqual(subject_visit.visit_code_sequence, 0)
259
+ crfs = self.get_crf_metadata(subject_visit)
260
+ self.assertNotIn("meta_subject.mnsi", [o.model for o in crfs.all()])
261
+
262
+ def test_mnsi_required_between_36m_and_45m(self):
263
+ month1_visit = self.get_visit(visit_code=MONTH1)
264
+ self.set_mnsi_status(subject_visit=month1_visit, mnsi_performed=YES)
228
265
 
229
- def test_mnsi_not_required_at_12m_even_if_not_performed_by_6m(self):
230
- self.get_week2_visit()
266
+ for visit_code in [MONTH36, MONTH39, MONTH42, MONTH45]:
267
+ with self.subTest(visit_code=visit_code):
268
+ subject_visit = self.get_visit(visit_code=visit_code)
269
+ crfs = self.get_crf_metadata(subject_visit)
270
+ self.assertIn("meta_subject.mnsi", [o.model for o in crfs.all()])
271
+ self.set_mnsi_status(subject_visit=subject_visit, mnsi_performed=NO)
231
272
 
232
- month1_visit = self.get_month1_visit()
233
- self.set_mnsi_status(subject_visit=month1_visit, mnsi_performed=NO)
273
+ def test_mnsi_only_required_once_between_36m_and_45m(self):
274
+ month1_visit = self.get_visit(visit_code=MONTH1)
275
+ self.set_mnsi_status(subject_visit=month1_visit, mnsi_performed=YES)
234
276
 
235
- month3_visit = self.get_month3_visit()
236
- self.set_mnsi_status(subject_visit=month3_visit, mnsi_performed=NO)
277
+ month36_visit = self.get_visit(visit_code=MONTH36)
278
+ crfs = self.get_crf_metadata(month36_visit)
279
+ self.assertIn("meta_subject.mnsi", [o.model for o in crfs.all()])
280
+ self.set_mnsi_status(subject_visit=month36_visit, mnsi_performed=NO)
237
281
 
238
- month6_visit = self.get_month6_visit()
239
- self.set_mnsi_status(subject_visit=month6_visit, mnsi_performed=NO)
282
+ month39_visit = self.get_next_subject_visit(month36_visit)
283
+ crfs = self.get_crf_metadata(month39_visit)
284
+ self.assertIn("meta_subject.mnsi", [o.model for o in crfs.all()])
285
+ self.set_mnsi_status(subject_visit=month39_visit, mnsi_performed=NO)
240
286
 
241
- self.get_month9_visit()
287
+ month42_visit = self.get_next_subject_visit(month39_visit)
288
+ crfs = self.get_crf_metadata(month42_visit)
289
+ self.assertIn("meta_subject.mnsi", [o.model for o in crfs.all()])
290
+ self.set_mnsi_status(subject_visit=month42_visit, mnsi_performed=YES)
242
291
 
243
- month12_visit = self.get_subject_visit(
244
- subject_screening=self.subject_screening,
245
- subject_consent=self.subject_consent,
246
- visit_code=MONTH12,
247
- appt_datetime=self.baseline_datetime + relativedelta(months=12),
248
- )
249
- crfs = self.get_crf_metadata(month12_visit)
292
+ month45_visit = self.get_next_subject_visit(month42_visit)
293
+ crfs = self.get_crf_metadata(month45_visit)
250
294
  self.assertNotIn("meta_subject.mnsi", [o.model for o in crfs.all()])
295
+
296
+ def test_mnsi_required_at_48m(self):
297
+ month1_visit = self.get_visit(visit_code=MONTH1)
298
+ crfs = self.get_crf_metadata(month1_visit)
299
+ self.assertIn("meta_subject.mnsi", [o.model for o in crfs.all()])
300
+ self.set_mnsi_status(subject_visit=month1_visit, mnsi_performed=YES)
301
+
302
+ month3_visit = self.get_next_subject_visit(month1_visit)
303
+ crfs = self.get_crf_metadata(month3_visit)
304
+ self.assertNotIn("meta_subject.mnsi", [o.model for o in crfs.all()])
305
+
306
+ month36_visit = self.get_visit(visit_code=MONTH36)
307
+ crfs = self.get_crf_metadata(month36_visit)
308
+ self.assertIn("meta_subject.mnsi", [o.model for o in crfs.all()])
309
+ self.set_mnsi_status(subject_visit=month36_visit, mnsi_performed=YES)
310
+
311
+ month39_visit = self.get_next_subject_visit(month36_visit)
312
+ crfs = self.get_crf_metadata(month39_visit)
313
+ self.assertNotIn("meta_subject.mnsi", [o.model for o in crfs.all()])
314
+
315
+ month48_visit = self.get_visit(visit_code=MONTH48)
316
+ crfs = self.get_crf_metadata(month48_visit)
317
+ self.assertIn("meta_subject.mnsi", [o.model for o in crfs.all()])
@@ -9,6 +9,9 @@ crfs_prn = CrfCollection(
9
9
  Crf(show_order=255, model="meta_subject.bloodresultslft"),
10
10
  Crf(show_order=265, model="meta_subject.bloodresultslipids"),
11
11
  Crf(show_order=268, model="meta_subject.bloodresultsins"),
12
+ Crf(show_order=461, model="meta_subject.eq5d3l"),
13
+ Crf(show_order=466, model="meta_subject.sf12"),
14
+ Crf(show_order=471, model="meta_subject.mnsi"),
12
15
  Crf(show_order=275, model="meta_subject.hepatitistest"),
13
16
  Crf(show_order=285, model="meta_subject.malariatest"),
14
17
  Crf(show_order=295, model="meta_subject.urinedipsticktest"),
@@ -57,7 +60,7 @@ crfs_w2 = CrfCollection(
57
60
  Crf(show_order=310, model="meta_subject.medicationadherence"),
58
61
  Crf(show_order=460, model="meta_subject.eq5d3l"),
59
62
  Crf(show_order=465, model="meta_subject.sf12"),
60
- Crf(show_order=470, model="meta_subject.healtheconomicssimple"),
63
+ Crf(show_order=480, model="meta_subject.healtheconomicssimple"),
61
64
  name="week2",
62
65
  )
63
66
 
@@ -68,10 +71,10 @@ crfs_1m = CrfCollection(
68
71
  Crf(show_order=200, model="meta_subject.glucosefbg"),
69
72
  Crf(show_order=300, model="meta_subject.studymedication"),
70
73
  Crf(show_order=310, model="meta_subject.medicationadherence"),
71
- Crf(show_order=450, model="meta_subject.healtheconomicssimple", required=False),
72
74
  Crf(show_order=460, model="meta_subject.eq5d3l", required=False),
73
75
  Crf(show_order=465, model="meta_subject.sf12", required=False),
74
76
  Crf(show_order=470, model="meta_subject.mnsi"),
77
+ Crf(show_order=480, model="meta_subject.healtheconomicssimple", required=False),
75
78
  name="1m",
76
79
  )
77
80
 
@@ -191,6 +194,7 @@ crfs_24m = CrfCollection(
191
194
  Crf(show_order=310, model="meta_subject.medicationadherence"),
192
195
  Crf(show_order=460, model="meta_subject.eq5d3l", required=False),
193
196
  Crf(show_order=465, model="meta_subject.sf12", required=False),
197
+ Crf(show_order=470, model="meta_subject.mnsi"),
194
198
  Crf(show_order=500, model="meta_subject.healtheconomicsupdate", required=False),
195
199
  name="24m",
196
200
  )
@@ -203,6 +207,7 @@ crfs_27m = CrfCollection(
203
207
  Crf(show_order=310, model="meta_subject.medicationadherence"),
204
208
  Crf(show_order=460, model="meta_subject.eq5d3l", required=False),
205
209
  Crf(show_order=465, model="meta_subject.sf12", required=False),
210
+ Crf(show_order=470, model="meta_subject.mnsi", required=False),
206
211
  Crf(show_order=500, model="meta_subject.healtheconomicsupdate", required=False),
207
212
  name="27m",
208
213
  )
@@ -216,6 +221,7 @@ crfs_30m = CrfCollection(
216
221
  Crf(show_order=310, model="meta_subject.medicationadherence"),
217
222
  Crf(show_order=460, model="meta_subject.eq5d3l", required=False),
218
223
  Crf(show_order=465, model="meta_subject.sf12", required=False),
224
+ Crf(show_order=470, model="meta_subject.mnsi", required=False),
219
225
  Crf(show_order=500, model="meta_subject.healtheconomicsupdate", required=False),
220
226
  name="30m",
221
227
  )
@@ -228,6 +234,7 @@ crfs_33m = CrfCollection(
228
234
  Crf(show_order=310, model="meta_subject.medicationadherence"),
229
235
  Crf(show_order=460, model="meta_subject.eq5d3l", required=False),
230
236
  Crf(show_order=465, model="meta_subject.sf12", required=False),
237
+ Crf(show_order=470, model="meta_subject.mnsi", required=False),
231
238
  Crf(show_order=500, model="meta_subject.healtheconomicsupdate", required=False),
232
239
  name="33m",
233
240
  )
@@ -243,8 +250,9 @@ crfs_36m = CrfCollection(
243
250
  Crf(show_order=250, model="meta_subject.bloodresultslipids"),
244
251
  Crf(show_order=300, model="meta_subject.studymedication"),
245
252
  Crf(show_order=310, model="meta_subject.medicationadherence"),
246
- Crf(show_order=460, model="meta_subject.eq5d3l", required=False),
247
- Crf(show_order=465, model="meta_subject.sf12", required=False),
253
+ Crf(show_order=460, model="meta_subject.eq5d3l"),
254
+ Crf(show_order=465, model="meta_subject.sf12"),
255
+ Crf(show_order=470, model="meta_subject.mnsi"),
248
256
  Crf(show_order=500, model="meta_subject.healtheconomicsupdate", required=False),
249
257
  name="36m",
250
258
  )
@@ -257,6 +265,7 @@ crfs_39m = CrfCollection(
257
265
  Crf(show_order=310, model="meta_subject.medicationadherence"),
258
266
  Crf(show_order=460, model="meta_subject.eq5d3l", required=False),
259
267
  Crf(show_order=465, model="meta_subject.sf12", required=False),
268
+ Crf(show_order=470, model="meta_subject.mnsi", required=False),
260
269
  Crf(show_order=500, model="meta_subject.healtheconomicsupdate", required=False),
261
270
  name="39m",
262
271
  )
@@ -270,6 +279,7 @@ crfs_42m = CrfCollection(
270
279
  Crf(show_order=310, model="meta_subject.medicationadherence"),
271
280
  Crf(show_order=460, model="meta_subject.eq5d3l", required=False),
272
281
  Crf(show_order=465, model="meta_subject.sf12", required=False),
282
+ Crf(show_order=470, model="meta_subject.mnsi", required=False),
273
283
  Crf(show_order=500, model="meta_subject.healtheconomicsupdate", required=False),
274
284
  name="42m",
275
285
  )
@@ -282,6 +292,7 @@ crfs_45m = CrfCollection(
282
292
  Crf(show_order=310, model="meta_subject.medicationadherence"),
283
293
  Crf(show_order=460, model="meta_subject.eq5d3l", required=False),
284
294
  Crf(show_order=465, model="meta_subject.sf12", required=False),
295
+ Crf(show_order=470, model="meta_subject.mnsi", required=False),
285
296
  Crf(show_order=500, model="meta_subject.healtheconomicsupdate", required=False),
286
297
  name="45m",
287
298
  )
@@ -297,8 +308,9 @@ crfs_48m = CrfCollection(
297
308
  Crf(show_order=250, model="meta_subject.bloodresultslipids"),
298
309
  Crf(show_order=300, model="meta_subject.studymedication"),
299
310
  Crf(show_order=310, model="meta_subject.medicationadherence"),
300
- Crf(show_order=460, model="meta_subject.eq5d3l", required=False),
301
- Crf(show_order=465, model="meta_subject.sf12", required=False),
311
+ Crf(show_order=460, model="meta_subject.eq5d3l"),
312
+ Crf(show_order=465, model="meta_subject.sf12"),
313
+ Crf(show_order=470, model="meta_subject.mnsi"),
302
314
  Crf(show_order=500, model="meta_subject.healtheconomicsupdate", required=False),
303
315
  name="48m",
304
316
  )
tests/test_settings.py CHANGED
@@ -96,6 +96,7 @@ project_settings = DefaultTestSettings(
96
96
  "django.contrib.messages",
97
97
  "django.contrib.staticfiles",
98
98
  "django.contrib.sites",
99
+ "django_pylabels.apps.AppConfig",
99
100
  "django_crypto_fields.apps.AppConfig",
100
101
  "django_revision.apps.AppConfig",
101
102
  # "debug_toolbar",
@@ -104,6 +105,7 @@ project_settings = DefaultTestSettings(
104
105
  "logentry_admin",
105
106
  "simple_history",
106
107
  "storages",
108
+ "edc_pylabels.apps.AppConfig",
107
109
  "edc_sites.apps.AppConfig",
108
110
  "edc_action_item.apps.AppConfig",
109
111
  "edc_adherence.apps.AppConfig",
@@ -138,7 +140,6 @@ project_settings = DefaultTestSettings(
138
140
  "edc_visit_tracking.apps.AppConfig",
139
141
  "edc_visit_schedule.apps.AppConfig",
140
142
  "edc_pdutils.apps.AppConfig",
141
- "edc_pharmacy.apps.AppConfig",
142
143
  "edc_protocol.apps.AppConfig",
143
144
  "edc_protocol_incident.apps.AppConfig",
144
145
  "edc_prn.apps.AppConfig",
@@ -156,6 +157,7 @@ project_settings = DefaultTestSettings(
156
157
  "edc_qol.apps.AppConfig",
157
158
  "edc_dx_review.apps.AppConfig",
158
159
  "edc_dx.apps.AppConfig",
160
+ "edc_pharmacy.apps.AppConfig",
159
161
  "meta_auth.apps.AppConfig",
160
162
  "meta_consent.apps.AppConfig",
161
163
  "meta_lists.apps.AppConfig",
@@ -170,6 +172,7 @@ project_settings = DefaultTestSettings(
170
172
  "meta_sites.apps.AppConfig",
171
173
  "meta_screening.apps.AppConfig",
172
174
  "meta_reports.apps.AppConfig",
175
+ "meta_pharmacy.apps.AppConfig",
173
176
  "meta_edc.apps.AppConfig",
174
177
  "edc_appconfig.apps.AppConfig",
175
178
  ],
@@ -1,2 +0,0 @@
1
- # do not import modules
2
- # see conditional import at root __init__
meta_edc/celery/live.py DELETED
@@ -1,17 +0,0 @@
1
- import os
2
-
3
- from celery import Celery
4
-
5
- # load settings
6
- os.environ.setdefault("DJANGO_SETTINGS_MODULE", "meta_edc.settings.live")
7
-
8
- # config celery
9
- # remember to include additional apps with tasks
10
- app = Celery("meta_edc", include=["meta_reports"])
11
- app.config_from_object("django.conf:settings", namespace="CELERY")
12
- app.autodiscover_tasks()
13
-
14
-
15
- @app.task(bind=True)
16
- def debug_task(self):
17
- print("Request: {0!r}".format(self.request))
meta_edc/celery/uat.py DELETED
@@ -1,17 +0,0 @@
1
- import os
2
-
3
- from celery import Celery
4
-
5
- # load settings
6
- os.environ.setdefault("DJANGO_SETTINGS_MODULE", "meta_edc.settings.uat")
7
-
8
- # config celery
9
- # remember to include additional apps with tasks
10
- app = Celery("meta_edc", include=["meta_reports"])
11
- app.config_from_object("django.conf:settings", namespace="CELERY")
12
- app.autodiscover_tasks()
13
-
14
-
15
- @app.task(bind=True)
16
- def debug_task(self):
17
- print("Request: {0!r}".format(self.request))