meta-edc 1.1.19__py3-none-any.whl → 1.2.0__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.

@@ -1,5 +1,4 @@
1
1
  from .subject_consent_admin import SubjectConsentAdmin
2
- from .subject_consent_spfq_admin import SubjectConsentSpfqAdmin
3
2
  from .subject_consent_v1_admin import SubjectConsentV1Admin
4
3
  from .subject_consent_v1_ext_admin import SubjectConsentV1ExtAdmin
5
4
 
@@ -1,12 +1,10 @@
1
1
  from .subject_consent_form import SubjectConsentForm
2
- from .subject_consent_spfq_form import SubjectConsentSpfqForm
3
2
  from .subject_consent_v1_ext_form import SubjectConsentV1ExtForm
4
3
  from .subject_consent_v1_form import SubjectConsentV1Form
5
4
  from .subject_reconsent_form import SubjectReconsentForm
6
5
 
7
6
  __all__ = [
8
7
  "SubjectConsentForm",
9
- "SubjectConsentSpfqForm",
10
8
  "SubjectConsentV1ExtForm",
11
9
  "SubjectConsentV1Form",
12
10
  "SubjectReconsentForm",
@@ -0,0 +1,23 @@
1
+ # Generated by Django 5.2.6 on 2025-09-30 22:50
2
+
3
+ from django.db import migrations
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("meta_consent", "0033_historicalsubjectconsentspfq_subjectconsentspfq"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.RemoveField(
14
+ model_name="subjectconsentspfq",
15
+ name="site",
16
+ ),
17
+ migrations.DeleteModel(
18
+ name="HistoricalSubjectConsentSpfq",
19
+ ),
20
+ migrations.DeleteModel(
21
+ name="SubjectConsentSpfq",
22
+ ),
23
+ ]
@@ -1,13 +1,11 @@
1
1
  from .signals import subject_consent_on_post_delete, subject_consent_on_post_save
2
2
  from .subject_consent import SubjectConsent
3
- from .subject_consent_spfq import SubjectConsentSpfq
4
3
  from .subject_consent_v1 import SubjectConsentV1
5
4
  from .subject_consent_v1_ext import SubjectConsentV1Ext
6
5
  from .subject_reconsent import SubjectReconsent
7
6
 
8
7
  __all__ = [
9
8
  "SubjectConsent",
10
- "SubjectConsentSpfq",
11
9
  "SubjectConsentV1",
12
10
  "SubjectConsentV1Ext",
13
11
  "SubjectReconsent",
@@ -4,7 +4,6 @@ from django.core.exceptions import ValidationError
4
4
  from django.db.models.signals import post_delete, post_save
5
5
  from django.dispatch import receiver
6
6
  from edc_action_item.delete_action_item import ActionItemDeleteError, delete_action_item
7
- from edc_appointment.utils import refresh_appointments
8
7
  from edc_constants.constants import YES
9
8
  from edc_pharmacy.exceptions import PrescriptionAlreadyExists
10
9
  from edc_pharmacy.prescribe import create_prescription
@@ -14,12 +13,10 @@ from edc_visit_schedule.site_visit_schedules import site_visit_schedules
14
13
  from meta_edc.meta_version import get_meta_version
15
14
  from meta_screening.models import SubjectScreening
16
15
  from meta_subject.models import SubjectVisit
17
- from meta_visit_schedule.constants import SCHEDULE, VISIT_SCHEDULE
18
16
 
19
17
  from ..action_items import ReconsentAction
20
18
  from .subject_consent import SubjectConsent
21
19
  from .subject_consent_v1 import SubjectConsentV1
22
- from .subject_consent_v1_ext import SubjectConsentV1Ext
23
20
 
24
21
 
25
22
  @receiver(
@@ -85,19 +82,19 @@ def subject_consent_on_post_save(sender, instance, raw, created, **kwargs): # n
85
82
  )
86
83
 
87
84
 
88
- @receiver(
89
- post_save,
90
- weak=False,
91
- sender=SubjectConsentV1Ext,
92
- dispatch_uid="subject_consent_v1_ext_on_post_save",
93
- )
94
- def subject_consent_v1_ext_on_post_save(sender, instance, raw, created, **kwargs): # noqa: ARG001
95
- if not raw:
96
- refresh_appointments(
97
- subject_identifier=instance.subject_identifier,
98
- visit_schedule_name=VISIT_SCHEDULE,
99
- schedule_name=SCHEDULE,
100
- )
85
+ # @receiver(
86
+ # post_save,
87
+ # weak=False,
88
+ # sender=SubjectConsentV1Ext,
89
+ # dispatch_uid="subject_consent_v1_ext_on_post_save",
90
+ # )
91
+ # def subject_consent_v1_ext_on_post_save(sender, instance, raw, created, **kwargs):
92
+ # if not raw:
93
+ # refresh_appointments(
94
+ # subject_identifier=instance.subject_identifier,
95
+ # visit_schedule_name=VISIT_SCHEDULE,
96
+ # schedule_name=SCHEDULE,
97
+ # )
101
98
 
102
99
 
103
100
  @receiver(
@@ -38,7 +38,7 @@ if os.getenv("DJANGO_BASE_DIR"):
38
38
  BASE_DIR = Path(os.getenv("DJANGO_BASE_DIR"))
39
39
  else:
40
40
  # when running from a repo
41
- BASE_DIR = Path(__file__).resolve().parent.parent.parent
41
+ BASE_DIR = Path(__file__).resolve().parent.parent.parent.parent
42
42
 
43
43
  if os.getenv("DJANGO_ENV_DIR"):
44
44
  ENV_DIR = Path(os.getenv("DJANGO_ENV_DIR"))
@@ -54,6 +54,15 @@ else:
54
54
  raise FileExistsError(f"Environment file does not exist. Got `{(ENV_DIR / '.env')}`")
55
55
  env.read_env(ENV_DIR / ".env")
56
56
 
57
+ # django_revision
58
+ GIT_DIR = Path(env.str("EDC_REVISION_GIT_DIR", default=BASE_DIR))
59
+
60
+ # django_crypto_fields
61
+ KEY_PATH = env.str("DJANGO_KEY_FOLDER")
62
+ AUTO_CREATE_KEYS = env("DJANGO_AUTO_CREATE_KEYS")
63
+
64
+ EXPORT_FOLDER = env.str("DJANGO_EXPORT_FOLDER") or Path("~/").expanduser()
65
+
57
66
 
58
67
  LOGGING_ENABLED = env("DJANGO_LOGGING_ENABLED")
59
68
  if LOGGING_ENABLED:
@@ -188,6 +197,7 @@ INSTALLED_APPS = [
188
197
  "meta_pharmacy.apps.AppConfig",
189
198
  "meta_screening.apps.AppConfig",
190
199
  "meta_sites.apps.AppConfig",
200
+ "meta_spfq.apps.AppConfig",
191
201
  "meta_edc.apps.AppConfig",
192
202
  "edc_appconfig.apps.AppConfig",
193
203
  ]
@@ -485,15 +495,6 @@ if TWILIO_ENABLED:
485
495
  TWILIO_AUTH_TOKEN = env.str("TWILIO_AUTH_TOKEN")
486
496
  TWILIO_SENDER = env.str("TWILIO_SENDER")
487
497
 
488
- # django_revision
489
- GIT_DIR = BASE_DIR.parent
490
-
491
- # django_crypto_fields
492
- KEY_PATH = env.str("DJANGO_KEY_FOLDER")
493
- AUTO_CREATE_KEYS = env("DJANGO_AUTO_CREATE_KEYS")
494
-
495
- EXPORT_FOLDER = env.str("DJANGO_EXPORT_FOLDER") or Path("~/").expanduser()
496
-
497
498
  # django_simple_history
498
499
  SIMPLE_HISTORY_ENFORCE_HISTORY_MODEL_PERMISSIONS = True
499
500
 
@@ -592,3 +593,6 @@ if "test" in sys.argv:
592
593
  MIGRATION_MODULES = DisableMigrations()
593
594
  PASSWORD_HASHERS = ("django.contrib.auth.hashers.MD5PasswordHasher",)
594
595
  DEFAULT_FILE_STORAGE = "inmemorystorage.InMemoryStorage"
596
+
597
+
598
+ META_SPFQ_LIST_FILENAME = env.str("META_SPFQ_LIST_FILENAME")
meta_edc/urls.py CHANGED
@@ -69,6 +69,7 @@ urlpatterns = [
69
69
  *paths_for_urlpatterns("meta_screening"),
70
70
  *paths_for_urlpatterns("meta_subject"),
71
71
  *paths_for_urlpatterns("meta_reports"),
72
+ *paths_for_urlpatterns("meta_spfq"),
72
73
  ]
73
74
 
74
75
  if settings.DEFENDER_ENABLED:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meta-edc
3
- Version: 1.1.19
3
+ Version: 1.2.0
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,12 +15,13 @@ 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.27
18
+ Requires-Dist: clinicedc>=2.0.30
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
22
22
  Requires-Dist: edc-phq9>=1.1.0
23
23
  Requires-Dist: edc-qol>=1.2.0
24
+ Requires-Dist: notebook>=7.4.7
24
25
  Requires-Python: >=3.12, <3.14
25
26
  Description-Content-Type: text/x-rst
26
27
 
@@ -88,8 +89,8 @@ Assuming you are logged into the account ``myaccount``:
88
89
  mkdir ~/edc && \
89
90
  cd ~/edc && \
90
91
  uv venv && \
91
- uv pip install -U meta-edc==1.1.18 && \
92
- wget https://raw.githubusercontent.com/meta-trial/meta-edc/1.1.18/manage.py && \
92
+ uv pip install -U meta-edc==1.1.19 && \
93
+ wget https://raw.githubusercontent.com/meta-trial/meta-edc/1.1.19/manage.py && \
93
94
  uv pip freeze | grep meta-edc
94
95
 
95
96
  Copy your ``.env`` file to ``~/.etc``.
@@ -139,7 +140,7 @@ From the above example:
139
140
 
140
141
  cd ~/edc && \
141
142
  uv venv --clear && \
142
- uv pip install -U meta-edc==1.1.18 && \
143
+ uv pip install -U meta-edc==1.1.19 && \
143
144
  wget -O manage.py https://raw.githubusercontent.com/meta-trial/meta-edc/1.1.10/manage.py && \
144
145
  uv pip freeze | grep meta-edc && \
145
146
  python manage.py check
@@ -109,13 +109,12 @@ meta_auth/auths.py,sha256=EBdK6b5b2yduDvqYmnmJFRvuJ0fLDQ_q226iuwHA_QU,3008
109
109
  meta_auth/urls.py,sha256=_sVCnQeiAFRYKhxga3_DjoKj_4bgs1s2gjcynDiapvA,111
110
110
  meta_consent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
111
111
  meta_consent/action_items.py,sha256=tSt9PsKWommXY59d65gvT8YxJc55mwp5RDlRH6RqHZY,1425
112
- meta_consent/admin/__init__.py,sha256=xSwd9MBy1MyumjzbZc3-HL_9Oko6FepGbvEkK0PM5hA,349
112
+ meta_consent/admin/__init__.py,sha256=d_6yWMi1yGgKxq4kFQIr7NNj96GqLDppXE0P83A14WQ,285
113
113
  meta_consent/admin/actions/__init__.py,sha256=dxQmm21wkVYcznzBeQU6cBEfPRnkEsBQLwptJr2xoYI,113
114
114
  meta_consent/admin/actions/create_missing_prescriptions.py,sha256=mksb9aAL8FK0KN3Z2a5N-QRrUSiilObUMCqoWCTlfv8,1500
115
115
  meta_consent/admin/list_filters.py,sha256=gVKcHW1YHT3X0fYDDgCI_PDY9F7A3Z3z8CRq2ZRC9MA,775
116
116
  meta_consent/admin/modeladmin_mixins.py,sha256=AWGHMjjZleGtE4UhfL_1hykiT1qpBkndgKbgeEo3ilo,5387
117
117
  meta_consent/admin/subject_consent_admin.py,sha256=IfGANb9TFvVs9yga8WOTxHxy2yRHP--KgsVUWEg30MQ,647
118
- meta_consent/admin/subject_consent_spfq_admin.py,sha256=Om1rkJSCfxLfHuTZ4K-q5pCSS5ZXnRfpeuJOrrM73lQ,1720
119
118
  meta_consent/admin/subject_consent_v1_admin.py,sha256=nmssuWL7eomQfXi3mVrszs3Ghufhz46JAwr9wFU3gkI,657
120
119
  meta_consent/admin/subject_consent_v1_ext_admin.py,sha256=o0XiCiyFr7ARV6f3Y-TLVknljomsoKrVFDxQfCRgEaY,2849
121
120
  meta_consent/admin_site.py,sha256=r5FtGwonVpqhyGekVNplmHr2mwbEGilJBiyvsIz2_lY,169
@@ -125,9 +124,8 @@ meta_consent/consents.py,sha256=JkO2dlt7Fn7ckWRGgdicAaXWgtIANo1amwxK5ykL5uk,1185
125
124
  meta_consent/constants.py,sha256=w5n3B4jwUDDZEc4gMpkKeffsHqi724GnoABFtjmvbQk,78
126
125
  meta_consent/form_validators/__init__.py,sha256=3xf1nNmydleMyROWyHvwI8-HC5y7gMYQW_bTeStiI7Q,115
127
126
  meta_consent/form_validators/subject_consent_form_validator.py,sha256=2f4FY1VZ1qU4u35LSoRtBIhmRhrflOhs0Zal8z1Ogo8,1258
128
- meta_consent/forms/__init__.py,sha256=5Q_KvDuxEJ_CR21RaGhMT2ZYva58JRAimMauTc16MGM,453
127
+ meta_consent/forms/__init__.py,sha256=owYPqBIxjy6U58sdWHrCgxqBY0ObE_tlIOXOcnTy7LM,361
129
128
  meta_consent/forms/subject_consent_form.py,sha256=Dwnwn7y-8AABvzgTa1zfs2b2Mli0OKnNMsx0VOxO9n0,1293
130
- meta_consent/forms/subject_consent_spfq_form.py,sha256=NGC7HhL2uCqrDGnO7boe0Cq_2ZbVJYB9qeecu5aMZyY,2016
131
129
  meta_consent/forms/subject_consent_v1_ext_form.py,sha256=jkm3bDrmepChP2OsmiAalhCW-IwhsR7BhR_qcycrTlc,1735
132
130
  meta_consent/forms/subject_consent_v1_form.py,sha256=XHrklzP-wh6ny3VJ2Bf9v7BTaUlfTToYVrpIAm3JZFc,766
133
131
  meta_consent/forms/subject_reconsent_form.py,sha256=hR2c1SgBXDXbL2gv33ArACr6UoGsM22C03uyCtuwT8o,1350
@@ -169,12 +167,12 @@ meta_consent/migrations/0030_auto_20250120_2114.py,sha256=Unk3dddqbNTog5VZOmq-68
169
167
  meta_consent/migrations/0031_alter_historicalsubjectconsent_guardian_name_and_more.py,sha256=a3-_1ls36Z8UXe3v2U44SqPVeNiCgUjJX6jOWsk1EoQ,5645
170
168
  meta_consent/migrations/0032_alter_historicalsubjectconsent_device_created_and_more.py,sha256=Ty4I6TSHw_rHRKyrYQUMDuZmCSe9_rC4PMD8PM6EdB0,24682
171
169
  meta_consent/migrations/0033_historicalsubjectconsentspfq_subjectconsentspfq.py,sha256=6GKEKT1BbPqqq2U2rHMQWl1VITtB3Inzl3aJGiy26ro,25192
170
+ meta_consent/migrations/0034_remove_subjectconsentspfq_site_and_more.py,sha256=RbTC6Oo2pOLYaOMkhPtdM612nyZwnOXdWVZ769WGF4o,546
172
171
  meta_consent/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
173
- meta_consent/models/__init__.py,sha256=DURcTNQg9A7ok4_SVKm59yQAACZbj0_moy_7EPb0nSQ,544
172
+ meta_consent/models/__init__.py,sha256=qDfnpsbAP3hr5oKa80hkr5u9P2PN6KV8P5EMujfgt_8,465
174
173
  meta_consent/models/model_mixins.py,sha256=mEN2gDycLKoZiExM2_H3Dxz8AMAwRSrCq4vu3afr5hA,275
175
- meta_consent/models/signals.py,sha256=grdBFzC46jX_IpoMLhDkYY1MjeK4Xzc8kv-yXdF4mnY,5198
174
+ meta_consent/models/signals.py,sha256=qjzBtnLR5qcOrn39sFrleUm6a9DG2yZnHGLnKQ-tLkc,5030
176
175
  meta_consent/models/subject_consent.py,sha256=Ssr94mZijpseoer-APH0jhh54cLeoUI0TPUah3od91c,3804
177
- meta_consent/models/subject_consent_spfq.py,sha256=vXMRfEU9AeOqKDGUzTNnZl6D_hM-H4_uEfcx3QjJlzc,3038
178
176
  meta_consent/models/subject_consent_v1.py,sha256=ELkFhv_6eRiuuoJOohdLwq3b2e2YXngK5omkGwMoRQE,457
179
177
  meta_consent/models/subject_consent_v1_ext.py,sha256=MpK5TlUqf2JuYRpmRLzYBClOFstC_6pIGwDRUckIztU,1033
180
178
  meta_consent/models/subject_reconsent.py,sha256=CqkrnThqjfnJnIj-k5QEEijue3gqp-0YvzcqKHjC8Gs,3605
@@ -233,14 +231,14 @@ meta_edc/models.py,sha256=DLA-hDdFszAVNCe1sZqVoLmIXifFW0HeZsipP9D1Ic4,46
233
231
  meta_edc/navbars.py,sha256=Rl2a62elRVTbkGVV9toYwwT388TE1BI7-1j1w2v1m-I,1208
234
232
  meta_edc/settings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
235
233
  meta_edc/settings/debug.py,sha256=XfYEL34kzpyiXQkTil34-r-NVKhmxs_kVQP2u5XtfVE,1313
236
- meta_edc/settings/defaults.py,sha256=uHcahlXL1lmgIzekQrfR6_wb07jcrBCz6BuJHQ_l7zc,20239
234
+ meta_edc/settings/defaults.py,sha256=lXN6DoEbUudUQSqJ1BJ8dVcAo4q-ZoEMxbnN8xkMSro,20381
237
235
  meta_edc/settings/live.py,sha256=A4gDWiUIgcRDUWaT4oEOHkGmaeLRPNsr7MPrl0r8AuI,289
238
236
  meta_edc/settings/logging.py,sha256=7RQ2guyuMhK3MtoojmnD0CVqiFZZ6ZT6zc7Rwn0nYGk,2115
239
237
  meta_edc/settings/minimal.py,sha256=ZZM7hZ-3AH33nGpLJLbYgs50oa5meKv_aGShidnm9G0,511
240
238
  meta_edc/settings/uat.py,sha256=kA6Aw2qDeh6gXNJgtiR93D0rWmBNHswcrufPk40RYhc,295
241
239
  meta_edc/templates/meta_edc/base.html,sha256=SRsitjNhwDyPueJXm8gAyz9MsqDKFfhs50zl4dGBGsU,154
242
240
  meta_edc/templates/meta_edc/home.html,sha256=EMdNWUw3NURSrC8xlKCkxuV0SxVLcmB8kyy2N6LgFLQ,4579
243
- meta_edc/urls.py,sha256=NAiynaCQyd-9FqKD1QQriqJ9HbK6YX-kIjXMPfPrcqI,3640
241
+ meta_edc/urls.py,sha256=XEqI0_flKCQO7_E8WQ_La_YhMnsx2c7N5mluAohEm1w,3681
244
242
  meta_edc/utils.py,sha256=BX6KQNiygI17TftUx-08-b1K30Kooxg0Kg1E5Auys5s,367
245
243
  meta_edc/views/__init__.py,sha256=8kC2jsMR87Hhtw86MHJD8hS_8k6ZqPSr9E4-dcRQmUM,56
246
244
  meta_edc/views/home_view.py,sha256=BXydy77TcdcM0-R3S_uHI4DtfnLMIzPJMyqjFJZFSsA,916
@@ -346,7 +344,7 @@ meta_prn/admin/protocol_incident_admin.py,sha256=42XTm6Z9EyKtSXWnIep3DmYwibCtMHx
346
344
  meta_prn/admin/subject_transfer_admin.py,sha256=ixYbel84vXwFuBaczTJBscpau3iMjHEzhpHvGRRXLD0,741
347
345
  meta_prn/admin_site.py,sha256=E4dJ6ofu9Kp-1SIWIuY3PraVPbEJSWBBqhorJPGUNqU,161
348
346
  meta_prn/apps.py,sha256=NEqrwzEW277BAPGeL1H1KdK9e74FqXfYHK6o46BtaJA,280
349
- meta_prn/baker_recipes.py,sha256=DAOuwnJCfRTou4WV4-oLdX_JHuov7KRZy4tcXF3TCBw,667
347
+ meta_prn/baker_recipes.py,sha256=MgTdr_2wawEMSQifsgXpP7LS_8va9HjlXXE2etpq8sM,715
350
348
  meta_prn/choices.py,sha256=QmWGz2zpWIt5Uqa3QP_YC-Ky8eKYDPdA5R8vPsOP22Q,3318
351
349
  meta_prn/constants.py,sha256=Z0atxRnTIj-_bWbfYY0vZIwfmbwaFRpSZqb1-K1B4Jo,1018
352
350
  meta_prn/form_validators/__init__.py,sha256=bHMDsNInx7AEghhcU2_2Bmc5pgP_Y7p4fbklXiugjYQ,194
@@ -432,6 +430,7 @@ meta_prn/migrations/0065_alter_historicaloffstudymedication_subject_identifier_a
432
430
  meta_prn/migrations/0066_alter_historicallosstofollowup_subject_identifier_and_more.py,sha256=hUTNf3oiIxJODNXXwjTeVZS-xEMBsCn3XyR2aPcfO7o,662
433
431
  meta_prn/migrations/0067_alter_offschedule_managers_and_more.py,sha256=FgwTeEgMbvyH3G6C7p3O9jUcUf7aX0dOmTuULlpWHKU,95266
434
432
  meta_prn/migrations/0068_alter_dmreferral_referral_note_and_more.py,sha256=CKbtUdAVA4r74WTHMh_lAh7Fm7YC23A0aPD0mWs59sU,8347
433
+ meta_prn/migrations/0069_alter_historicaloffstudymedication_singleton_field_and_more.py,sha256=oM6nxwAZOkJ0wjuNzVH-KrNEYUjLR97c1BTXY1lxab4,1085
435
434
  meta_prn/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
436
435
  meta_prn/models/__init__.py,sha256=RTi_GFeNhZEnB7_WR5bahlanI7BGR9rTC47TveoRrR4,1224
437
436
  meta_prn/models/dm_referral.py,sha256=_5sVeT9A2mnmbkv2LvbTkS4G-QYPWqR5zMRGDAWCENA,1153
@@ -457,10 +456,10 @@ meta_rando/migrations/0004_alter_randomizationlist_options_and_more.py,sha256=_U
457
456
  meta_rando/migrations/0005_alter_randomizationlist_options_and_more.py,sha256=GBaNqwy4SlmQ88lYX2uEqAI0FIUQem-C8qJLI6d6SfI,3248
458
457
  meta_rando/migrations/0006_alter_historicalrandomizationlist_allocated_user_and_more.py,sha256=XS6srUOHPAJWqsTLLPCHmcIKlOkEky95JrH1739gL2w,4584
459
458
  meta_rando/migrations/0007_spfqlist.py,sha256=UbzXuvNy3EuapG0ZQktiEVOM3BVjLgeAmTqViAh9cKg,7276
459
+ meta_rando/migrations/0008_delete_spfqlist.py,sha256=hF6G6B5kMirD_W8xOCRe_IA2IIq2xkKEYcF5KTSgnSY,290
460
460
  meta_rando/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
461
- meta_rando/models/__init__.py,sha256=iKW5AvXiLK58AMspZmWYUzOmA7mrJQp3_FcMqtWa5xc,82
461
+ meta_rando/models/__init__.py,sha256=Y723EYwgR2rCsy6GKK8uEh0V1-a3L1mr-n-vk6ZkQVs,50
462
462
  meta_rando/models/randomization_list.py,sha256=IBj1kSui1tHNgZdVbHvgmunw9BwBZ4ZZnft98x1B-Gg,510
463
- meta_rando/models/spfq_list.py,sha256=Ba0nasvtMAPnJVukOCFZ1EvVuyEeXxiPjDX0N1t4C9w,839
464
463
  meta_rando/randomizers.py,sha256=GpsV3kkqd-HupfnQw6Y7R172ZpOEpIbmVkXOwsOf-HA,1592
465
464
  meta_reports/__init__.py,sha256=huYR-GaImMWZqv6puEYfY7y_8m1OA_hRVXRYNBvNLkQ,80
466
465
  meta_reports/admin/__init__.py,sha256=V-rlMJJZCgnDaMOwk5PgZNIclOp_FW2y9yc-iCLQFHA,910
@@ -722,7 +721,7 @@ meta_sites/models.py,sha256=DLA-hDdFszAVNCe1sZqVoLmIXifFW0HeZsipP9D1Ic4,46
722
721
  meta_sites/sites.py,sha256=H26Erar3_fLVl5wf2ILDM5C6wGEoi0dQbiSPmzb9OGw,1625
723
722
  meta_subject/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
724
723
  meta_subject/action_items.py,sha256=l7Bw4m0Hu72bemH70UToI__VCERz8YKEKcsWCL6BJxk,6804
725
- meta_subject/admin/__init__.py,sha256=75Z-caHseLIT6Z5w5eYc8WUjmMlyNiGU8M5Ghiq95Tc,2830
724
+ meta_subject/admin/__init__.py,sha256=04MeBKUNsTc1DKJDE7r9w-KfZWxBEB-QLBIiazhzzFs,2779
726
725
  meta_subject/admin/autocomplete_admin.py,sha256=bVxma7KTHhKHWqLPxbP2GwiGcHeBUyMutTDXZ2RomEY,1158
727
726
  meta_subject/admin/birth_outcome_admin.py,sha256=76hwS4wIbuFpxAvIoQwjVqyr4znVGhWOnuKBuk1FIZ8,3242
728
727
  meta_subject/admin/blood_results/__init__.py,sha256=24WaqyGYCj3F-8amy7HFEwet1Z1ZHgsVvdSrWmmGvVs,546
@@ -762,7 +761,6 @@ meta_subject/admin/patient_history_admin.py,sha256=xeHhoeZS-F7nXAopZI8HxAjZUFLDY
762
761
  meta_subject/admin/physical_exam_admin.py,sha256=NnYsclV3dAQZO9f9IUIj44d8ttbCFFmAPi-KXF8uVQg,1874
763
762
  meta_subject/admin/pregnancy_update_admin.py,sha256=g-pXELecNtxePvDGlx7Iwx7w0GNUtPMEw0q5eVdMAg0,929
764
763
  meta_subject/admin/sf12_admin.py,sha256=1PDNewdE_JDcjfyh0tb0MEWnBgpE3-7W0tkNfWkSX5U,742
765
- meta_subject/admin/spfg_admin.py,sha256=xAKximXRHtUgpuqDK4dmXbpN7OodLRQcEBbRy4Nb-iE,3522
766
764
  meta_subject/admin/study_medication_admin.py,sha256=E1xZDDEMDoCSfgYhJ7E815ClSrh-A4HTY7iOy52auF4,6146
767
765
  meta_subject/admin/subject_requisition_admin.py,sha256=CJxO4Qvphxm8RfjS0IFef9smMFVmVzI2KbSmdhpocXU,1864
768
766
  meta_subject/admin/subject_visit_admin.py,sha256=FMJ6-aB_3JLrYnCAKM8vvYyWqN9P58RwR25JB1Po6bc,1405
@@ -772,8 +770,8 @@ meta_subject/admin/urine_pregnancy_admin.py,sha256=o90kDiRm28SqgSR8pwj4MVSICkzt_
772
770
  meta_subject/admin_site.py,sha256=fxUn5QKgo6wYUG18HW11kVrPqWvmWV2_PzKbgZQM4pU,169
773
771
  meta_subject/apps.py,sha256=iAQ8lizUpKa4gJnCGkTsuRQPtGWmSjnshZn8rZUguO8,289
774
772
  meta_subject/baker_recipes.py,sha256=KEJQTjNH47KcGCR_2OxDwmSKhAWhmjiD3YsnqeqkzFU,2816
775
- meta_subject/choices.py,sha256=m-7bftnK_GoFEkeCDbBzxJGf6nf_6Ll0OShUGBo62oo,7721
776
- meta_subject/constants.py,sha256=LUbaJbgY88FgRiVStpWuyJn6LPhW_nUAfydPQkAL_84,1124
773
+ meta_subject/choices.py,sha256=lFseBsxliIRshCmqsIwdPnYXs1p_WT5D_Dfn2PcWONs,6754
774
+ meta_subject/constants.py,sha256=6rpHsHj3CPV7ntdWxYScRhPVoj4YIxX2lUZdZ9lrFN0,704
777
775
  meta_subject/form_validators/__init__.py,sha256=2g1unLOkE4Wj1ZrWkXSdnZzYnV0kggn_SCpMrhnc_Rg,840
778
776
  meta_subject/form_validators/birth_outcomes_form_validator.py,sha256=vujgXKIW4z8bJ536_9uBhETlbChhUvA3Rj5H8zR3UfI,349
779
777
  meta_subject/form_validators/delivery_form_validator.py,sha256=mmi6mnr-DLa93uGMoqud_J1LuM1nPyu-VcNyIwEOXk8,3205
@@ -783,7 +781,7 @@ meta_subject/form_validators/egfr_drop_notification_form_validator.py,sha256=y5M
783
781
  meta_subject/form_validators/followup_examination_form_validator.py,sha256=NS3Sa-bwC_HEe-CmezkFrbbjPanLe9p1v5ZOFspqgxg,4241
784
782
  meta_subject/form_validators/glucose_form_validator.py,sha256=azIttaercmdE2-KM8hrlAzBmH3LHknrIxQ-o_s1kYcE,3979
785
783
  meta_subject/form_validators/health_economics_form_validator.py,sha256=kp-LQU4ydBXlnYFt-0xKuVSb8Y4irlhz9d_X8ppvWgE,250
786
- meta_subject/forms/__init__.py,sha256=Zu39xg6SPfQUuh231UWe6BbPqWrXA-CPVJJF_VPnY7s,2824
784
+ meta_subject/forms/__init__.py,sha256=LaxPRgHKMfmEWYnxHFbPkVFGSSNVrelG8dL2x49M5oU,2776
787
785
  meta_subject/forms/birth_outcomes_form.py,sha256=qqhZNQKiYk8C8CFebZTQB0hOm4ONrgkTG7hfuK7kW-o,374
788
786
  meta_subject/forms/blood_results/__init__.py,sha256=DYs2J30cgTPxvY9qDuKfr_kF_muoZ1iVmpu_I3wLpdM,528
789
787
  meta_subject/forms/blood_results/blood_results_fbc_form.py,sha256=g6m0HE9I3DIxDPgk6TZUPVU-vliOb3Fiqe3kDyN7h38,714
@@ -820,7 +818,6 @@ meta_subject/forms/physical_exam_form.py,sha256=QgH1zAmYgp8Hi1tU-e68HaRRkZxf-6xG
820
818
  meta_subject/forms/pregnancy_update_form.py,sha256=BTiWPoQ-HYbZhW0Go2DSqYU_e51pmJ_UIxEdSNlzTwE,559
821
819
  meta_subject/forms/sf12_form.py,sha256=VDV4hyU9UckPX70isylfHWggcWZwiQfCWrpk9kGvxis,397
822
820
  meta_subject/forms/slider_widget.py,sha256=aHUszQ1Xxjyf9Ph0echFMX1VuWl4mmabvWN2ixpRy-I,837
823
- meta_subject/forms/spfq_form.py,sha256=WNMawCxrKCKq3gV1GOoZpxAeF5oAh4QBt6TMu1xGRv0,2123
824
821
  meta_subject/forms/study_medication_form.py,sha256=zLPxVmxE3czWIRrSTnnD5-BRvIj5YDfOxhCNQELA9q4,3218
825
822
  meta_subject/forms/subject_requisition_form.py,sha256=wf_IVqrwrgaZrPxwyS7Ku-NfWR9eWGW4N9VexANcnHA,950
826
823
  meta_subject/forms/subject_visit_form.py,sha256=Zxyjb5-7wUmcLHD-M76ofuM8Vr92yzjvXqQ7GsB3U6o,1374
@@ -1071,6 +1068,7 @@ meta_subject/migrations/0230_alter_historicaldelivery_action_identifier_and_more
1071
1068
  meta_subject/migrations/0231_alter_historicalmedicationadherence_consent_model_and_more.py,sha256=LMY0vJ4utO36Zpk0uugU_KlXkv9bCG9-nf8oFsUuWII,78654
1072
1069
  meta_subject/migrations/0232_alter_patienthistory_concomitant_conditions_and_more.py,sha256=vX0wJmbLQSg7JYnvzAt3zA20bfPz1AnxNpodKAxdYhM,43686
1073
1070
  meta_subject/migrations/0233_historicalspfq_spfq.py,sha256=U8imocD_gtCGTC0zUNt6UZlqZYBUtUNB7cEdFxBbnjA,46072
1071
+ meta_subject/migrations/0234_remove_spfq_site_remove_spfq_subject_visit_and_more.py,sha256=s_1aOSihYNqca-oVYWxiC19joGtOgvB4nz0qtEqmdwQ,584
1074
1072
  meta_subject/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1075
1073
  meta_subject/model_mixins/__init__.py,sha256=fWZpFJ_Ex-TOJFjgSGjcrquKSCenCh_K9Hiy8QUg36o,439
1076
1074
  meta_subject/model_mixins/arv_history_model_mixin.py,sha256=6ILacF2koyYmwZIFHmmQO1uIT1eWzrahXxhAlxpQiX0,2898
@@ -1078,7 +1076,7 @@ meta_subject/model_mixins/crf_model_mixin.py,sha256=UK1ycbYwaZ8LSNTJm74QJ5c-01HD
1078
1076
  meta_subject/model_mixins/crf_with_action_model_mixin.py,sha256=q1Q16YyPjQlpDtCPOXRkO5C7Vr7JO_QL8xWC48Uz33M,298
1079
1077
  meta_subject/model_mixins/search_slug_model_mixin.py,sha256=mEN2gDycLKoZiExM2_H3Dxz8AMAwRSrCq4vu3afr5hA,275
1080
1078
  meta_subject/model_mixins/vitals_fields_model_mixin.py,sha256=Uimo-sQS-l4I3KyHej8t0_49mT2UakMKCbO8giYUMQw,2205
1081
- meta_subject/models/__init__.py,sha256=d2ruW2PO_9tCPts8tprk7kj2ScpUokwwGCm1PXlnvjY,3009
1079
+ meta_subject/models/__init__.py,sha256=NXw6Ba2QlYL7ZjZoWeoS1A5g6R3ONnOKtFEH8ltDTvg,2974
1082
1080
  meta_subject/models/birth_outcomes.py,sha256=DQp-8Cv5ZWBuaGdiYlL1V3uJaL6H2tf9gYPfYcMTCs8,3142
1083
1081
  meta_subject/models/blood_results/__init__.py,sha256=F2jncEUtvrb4G9v5V6p3gSi4dI721CFVCImdJ9qFHmQ,530
1084
1082
  meta_subject/models/blood_results/blood_results_fbc.py,sha256=kkOqCsqeIvCf2rw7vHGWMCEgo1_yiMDtTOi44aKtBro,1324
@@ -1105,7 +1103,7 @@ meta_subject/models/glucose_fbg.py,sha256=MzTPX1sVlp_ypqLmhsurVUV-Ks8XTIMHJy5MBj
1105
1103
  meta_subject/models/glucose_review.py,sha256=bCnSBe_C3LeBy1XrZpV9rv-hOk8onZ_Tl37t7dqm-sw,450
1106
1104
  meta_subject/models/health_economics/__init__.py,sha256=J557vTjzK1EvUAM4mx9zDVQ7Zr0W25stnWXz_zE2a-c,245
1107
1105
  meta_subject/models/health_economics/health_economics.py,sha256=pjEbz3d6s-Cy2DEPZnGcd8KjFc27pVed9D6vr3eYLVg,9709
1108
- meta_subject/models/health_economics/health_economics_simple.py,sha256=pHMDPUi9ojPBI6koTtciVGUYV8oFr7VXTmf8JP_eU40,741
1106
+ meta_subject/models/health_economics/health_economics_simple.py,sha256=w46TrjNvfk736IjtZ8lrN0H3is_ddGRUq8v6MgSqoBY,711
1109
1107
  meta_subject/models/health_economics/health_economics_update.py,sha256=gzbu2lpVr9txwYUVfYKADgE0Om1YkNfrVPcwLczbNYc,3334
1110
1108
  meta_subject/models/hepatitis_test.py,sha256=_jfDlR_spt7h4KGsMDxmobgAaToKiAZdLGIXCqfH60o,1852
1111
1109
  meta_subject/models/malaria_test.py,sha256=4gQNBnvLDv70rjRcFBOpLPmYL8eeuqs0lRsJ7LrFqHM,343
@@ -1120,7 +1118,6 @@ meta_subject/models/physical_exam.py,sha256=0QH10ZutmowM6_uLyHaMsO0UiH3RrVWhfZD_
1120
1118
  meta_subject/models/pregnancy_update.py,sha256=yeoMeDkMQxUBjKYjFvqkQCwByTH50jU0QiNXchqJMZo,950
1121
1119
  meta_subject/models/sf12.py,sha256=1f6cAMtBUXy7jMaacAU8RJFFv73r9c3rJjBbNl-bSM4,283
1122
1120
  meta_subject/models/signals.py,sha256=Z5qoVkSmls9bVm2HwdbaBAPuI6X9Y8v-7PP5F-GQbiU,4568
1123
- meta_subject/models/spfq.py,sha256=kJjwPsG9YNU8P1XHOmmFvuKX1C36Agm4Np2reWliYcc,6239
1124
1121
  meta_subject/models/study_medication.py,sha256=1kA_w4pYT1gcunfiQ46KdM01pd1jrQqLt4JEPLvfTTo,461
1125
1122
  meta_subject/models/subject_requisition.py,sha256=bSDwD-hpXeioH3xA7E6eGMu4hxWLDDSxhznfjrpXTjw,341
1126
1123
  meta_subject/models/subject_visit.py,sha256=UQQ31lsJS0znw-8d2ft7VOPamn1o-cixHQ9L8rV1vWA,2153
@@ -1147,7 +1144,7 @@ meta_visit_schedule/visit_schedules/phase_three/schedule.py,sha256=LU1HRaV6o1UeK
1147
1144
  meta_visit_schedule/visit_schedules/phase_three/schedule_dm_referral.py,sha256=q12p5wXc2D7lSiJVBnoSQw8Q3vL6uDx1t3PuDJO-Z-U,1735
1148
1145
  meta_visit_schedule/visit_schedules/phase_three/schedule_pregnancy.py,sha256=bEpbpCX3vfZmnsqudr0z8PU5kiaX4ws1sO5Im98Mo28,1106
1149
1146
  meta_visit_schedule/visit_schedules/phase_three/visit_schedule.py,sha256=ak4qazeKlpIlvpqrK9hDDO0fwWuWyvb4Ec-JU31IJxc,654
1150
- meta_edc-1.1.19.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
1151
- meta_edc-1.1.19.dist-info/WHEEL,sha256=-neZj6nU9KAMg2CnCY6T3w8J53nx1kFGw_9HfoSzM60,79
1152
- meta_edc-1.1.19.dist-info/METADATA,sha256=pms4LnnVTVZfwtk5LloEcHLiyPqQ6sgziU_MbCzrp4o,5136
1153
- meta_edc-1.1.19.dist-info/RECORD,,
1147
+ meta_edc-1.2.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
1148
+ meta_edc-1.2.0.dist-info/WHEEL,sha256=-neZj6nU9KAMg2CnCY6T3w8J53nx1kFGw_9HfoSzM60,79
1149
+ meta_edc-1.2.0.dist-info/METADATA,sha256=DiyZTaq7ut9pqEqAuJEpkcWT5wPdZDm5Ug_uyZokP9E,5166
1150
+ meta_edc-1.2.0.dist-info/RECORD,,
meta_prn/baker_recipes.py CHANGED
@@ -1,6 +1,6 @@
1
1
  from dateutil.relativedelta import relativedelta
2
2
  from django.utils import timezone
3
- from edc_constants.constants import YES
3
+ from edc_constants.constants import NULL_STRING, YES
4
4
  from faker import Faker
5
5
  from model_bakery.recipe import Recipe
6
6
 
@@ -12,17 +12,17 @@ fake = Faker()
12
12
  pregnancynotification = Recipe(
13
13
  PregnancyNotification,
14
14
  # site=None,
15
- action_identifier=None,
16
- subject_identifier=None,
15
+ action_identifier=NULL_STRING,
16
+ subject_identifier=NULL_STRING,
17
17
  report_datetime=timezone.now(),
18
18
  bhcg_confirmed=YES,
19
- unconfirmed_details=None,
19
+ unconfirmed_details=NULL_STRING,
20
20
  edd=timezone.now() + relativedelta(months=6),
21
21
  )
22
22
 
23
23
  dmreferral = Recipe(
24
24
  DmReferral,
25
- action_identifier=None,
26
- subject_identifier=None,
25
+ action_identifier=NULL_STRING,
26
+ subject_identifier=NULL_STRING,
27
27
  report_datetime=timezone.now(),
28
28
  )
@@ -0,0 +1,37 @@
1
+ # Generated by Django 5.2.7 on 2025-10-01 14:33
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("meta_prn", "0068_alter_dmreferral_referral_note_and_more"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AlterField(
14
+ model_name="historicaloffstudymedication",
15
+ name="singleton_field",
16
+ field=models.CharField(
17
+ db_index=True,
18
+ default="",
19
+ editable=False,
20
+ help_text="auto updated for unique constraint",
21
+ max_length=50,
22
+ verbose_name="subject identifier",
23
+ ),
24
+ ),
25
+ migrations.AlterField(
26
+ model_name="offstudymedication",
27
+ name="singleton_field",
28
+ field=models.CharField(
29
+ default="",
30
+ editable=False,
31
+ help_text="auto updated for unique constraint",
32
+ max_length=50,
33
+ unique=True,
34
+ verbose_name="subject identifier",
35
+ ),
36
+ ),
37
+ ]
@@ -0,0 +1,16 @@
1
+ # Generated by Django 5.2.6 on 2025-09-30 22:50
2
+
3
+ from django.db import migrations
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("meta_rando", "0007_spfqlist"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.DeleteModel(
14
+ name="SpfqList",
15
+ ),
16
+ ]
@@ -1,2 +1 @@
1
1
  from .randomization_list import RandomizationList
2
- from .spfq_list import SpfqList
@@ -28,7 +28,6 @@ from .patient_history_admin import PatientHistoryAdmin
28
28
  from .physical_exam_admin import PhysicalExamAdmin
29
29
  from .pregnancy_update_admin import PregnancyUpdateAdmin
30
30
  from .sf12_admin import Sf12Admin
31
- from .spfg_admin import SpfqAdmin
32
31
  from .study_medication_admin import StudyMedicationAdmin
33
32
  from .subject_requisition_admin import SubjectRequisitionAdmin
34
33
  from .subject_visit_admin import SubjectVisitAdmin
@@ -67,7 +66,6 @@ __all__ = [
67
66
  "PhysicalExamAdmin",
68
67
  "PregnancyUpdateAdmin",
69
68
  "Sf12Admin",
70
- "SpfqAdmin",
71
69
  "StudyMedicationAdmin",
72
70
  "SubjectRequisitionAdmin",
73
71
  "SubjectVisitAdmin",
meta_subject/choices.py CHANGED
@@ -26,28 +26,14 @@ from .constants import (
26
26
  ALL_OF_THE_TIME,
27
27
  APPT,
28
28
  APPT_OTHER,
29
- EXTREME,
30
29
  GOOD_BIT_OF_THE_TIME,
31
- HIGHLY,
32
30
  LITTLE_OF_THE_TIME,
33
31
  LIVE_AT_TERM,
34
32
  LIVE_PRETERM,
35
- MODERATE,
36
- MODERATELY,
37
33
  MOST_OF_THE_TIME,
38
- MUCH_LESS_EXPECTED,
39
- MUCH_MORE_EXPECTED,
40
34
  NO_COMPLICATIONS,
41
35
  NONE_OF_THE_TIME,
42
- NOT_AT_ALL,
43
- SAME_AS_EXPECTED,
44
- SEVERE,
45
- SLIGHT,
46
- SLIGHTLY,
47
36
  SOME_OF_THE_TIME,
48
- SOMEWHAT_LESS_EXPECTED,
49
- SOMEWHAT_MORE_EXPECTED,
50
- VERY_HIGHLY,
51
37
  )
52
38
 
53
39
  ACTIVITY_CHOICES = (
@@ -256,26 +242,3 @@ YES_NO_NO_EXAM = (
256
242
  (NO, _(NO)),
257
243
  (NO_EXAM, _("Exam not performed")),
258
244
  )
259
-
260
- NOT_AT_ALL_TO_SEVERE_CHOICE = (
261
- (NOT_AT_ALL, _("Not at all")),
262
- (SLIGHT, _("Slight")),
263
- (MODERATE, _("Moderate")),
264
- (EXTREME, _("Extreme")),
265
- (SEVERE, _("Severe")),
266
- )
267
-
268
- NOT_AT_ALL_TO_HIGHLY_CHOICE = (
269
- (NOT_AT_ALL, _("Not at all")),
270
- (SLIGHTLY, _("Slightly")),
271
- (MODERATELY, _("Moderately")),
272
- (HIGHLY, _("Highly")),
273
- (VERY_HIGHLY, _("Very highly")),
274
- )
275
- LESS_EXPECTED_TO_MORE_EXPECTED_CHOICE = (
276
- (MUCH_LESS_EXPECTED, _("Much less than expected")),
277
- (SOMEWHAT_LESS_EXPECTED, _("Somewhat less than expected")),
278
- (SAME_AS_EXPECTED, _("Same as expected")),
279
- (SOMEWHAT_MORE_EXPECTED, _("Somewhat more than expected")),
280
- (MUCH_MORE_EXPECTED, _("Much more than expected")),
281
- )
meta_subject/constants.py CHANGED
@@ -6,29 +6,15 @@ APPT = "appt"
6
6
  APPT_OTHER = "other_routine_appt"
7
7
  DELIVERY_ACTION = "delivery_action"
8
8
  DM_FOLLOWUP_ACTION = "dm_followup_action"
9
- EXTREME = "extreme"
10
9
  FOLLOWUP_EXAMINATION_ACTION = "followup-examination-ae"
11
10
  GOOD_BIT_OF_THE_TIME = "good_bit_of_the_time"
12
- HIGHLY = "highly"
13
11
  LITTLE_OF_THE_TIME = "little_of_the_time"
14
12
  LIVE_AT_TERM = "live_at_term"
15
13
  LIVE_PRETERM = "live_preterm"
16
14
  LOW_EGFR_ACTION = "low-egfr"
17
15
  MISSED_VISIT_ACTION = "missed_visit_action"
18
- MODERATE = "moderate"
19
- MODERATELY = "moderately"
20
16
  MOST_OF_THE_TIME = "most_of_the_time"
21
- MUCH_LESS_EXPECTED = "much_less_expected"
22
- MUCH_MORE_EXPECTED = "much_more_expected"
23
17
  NONE_OF_THE_TIME = "none_of_the_time"
24
- NOT_AT_ALL = "not_at_all"
25
18
  NO_COMPLICATIONS = "no_complications"
26
- SAME_AS_EXPECTED = "same_as_expected"
27
- SEVERE = "severe"
28
- SLIGHT = "slight"
29
- SLIGHTLY = "slightly"
30
- SOMEWHAT_LESS_EXPECTED = "somewhat_less_expected"
31
- SOMEWHAT_MORE_EXPECTED = "somewhat_more_expected"
32
19
  SOME_OF_THE_TIME = "some_of_the_time"
33
20
  URINE_PREGNANCY_ACTION = "urine_pregnancy_action"
34
- VERY_HIGHLY = "very_highly"
@@ -29,7 +29,6 @@ from .patient_history_form import PatientHistoryForm
29
29
  from .physical_exam_form import PhysicalExamForm
30
30
  from .pregnancy_update_form import PregnancyUpdateForm
31
31
  from .sf12_form import Sf12Form
32
- from .spfq_form import SpfqForm
33
32
  from .study_medication_form import StudyMedicationForm
34
33
  from .subject_requisition_form import SubjectRequisitionForm
35
34
  from .subject_visit_form import SubjectVisitForm
@@ -70,7 +69,6 @@ __all__ = [
70
69
  "PhysicalExamForm",
71
70
  "PregnancyUpdateForm",
72
71
  "Sf12Form",
73
- "SpfqForm",
74
72
  "StudyMedicationForm",
75
73
  "SubjectRequisitionForm",
76
74
  "SubjectVisitForm",
@@ -0,0 +1,27 @@
1
+ # Generated by Django 5.2.6 on 2025-09-30 22:50
2
+
3
+ from django.db import migrations
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("meta_subject", "0233_historicalspfq_spfq"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.RemoveField(
14
+ model_name="spfq",
15
+ name="site",
16
+ ),
17
+ migrations.RemoveField(
18
+ model_name="spfq",
19
+ name="subject_visit",
20
+ ),
21
+ migrations.DeleteModel(
22
+ name="HistoricalSpfq",
23
+ ),
24
+ migrations.DeleteModel(
25
+ name="Spfq",
26
+ ),
27
+ ]
@@ -42,7 +42,6 @@ from .signals import (
42
42
  update_pregnancy_notification_on_delivery_post_save,
43
43
  update_schedule_on_delivery_post_save,
44
44
  )
45
- from .spfq import Spfq
46
45
  from .study_medication import StudyMedication
47
46
  from .subject_requisition import SubjectRequisition
48
47
  from .subject_visit import SubjectVisit
@@ -86,7 +85,6 @@ __all__ = [
86
85
  "PhysicalExam",
87
86
  "PregnancyUpdate",
88
87
  "Sf12",
89
- "Spfq",
90
88
  "StudyMedication",
91
89
  "SubjectRequisition",
92
90
  "SubjectVisit",
@@ -1,12 +1,12 @@
1
1
  from django.db import models
2
2
  from edc_constants.choices import MARITAL_STATUS
3
- from edc_he.model_mixins import HealthEconomicsEducationModelMixin
3
+ from edc_he.model_mixins import EducationModelMixin
4
4
  from edc_model.models import BaseUuidModel
5
5
 
6
6
  from ...model_mixins import CrfModelMixin
7
7
 
8
8
 
9
- class HealthEconomicsSimple(HealthEconomicsEducationModelMixin, CrfModelMixin, BaseUuidModel):
9
+ class HealthEconomicsSimple(EducationModelMixin, CrfModelMixin, BaseUuidModel):
10
10
  occupation = models.CharField(
11
11
  verbose_name="What is your occupation/profession?", max_length=50
12
12
  )
@@ -1,58 +0,0 @@
1
- from django.contrib import admin
2
- from django.utils.translation import gettext as _
3
- from django_audit_fields import audit_fieldset_tuple
4
- from edc_model_admin.dashboard import ModelAdminSubjectDashboardMixin
5
- from edc_model_admin.history import SimpleHistoryAdmin
6
-
7
- from ..admin_site import meta_consent_admin
8
- from ..forms import SubjectConsentSpfqForm
9
- from ..models import SubjectConsentSpfq
10
-
11
-
12
- @admin.register(SubjectConsentSpfq, site=meta_consent_admin)
13
- class SubjectConsentSpfqAdmin(
14
- ModelAdminSubjectDashboardMixin,
15
- SimpleHistoryAdmin,
16
- ):
17
- form = SubjectConsentSpfqForm
18
-
19
- fieldsets = (
20
- (
21
- None,
22
- {
23
- "fields": (
24
- "subject_identifier",
25
- "initials",
26
- "gender",
27
- "language",
28
- "consent_datetime",
29
- )
30
- },
31
- ),
32
- (
33
- "Review Questions",
34
- {
35
- "fields": (
36
- "consent_reviewed",
37
- "study_questions",
38
- "assessment_score",
39
- "consent_signature",
40
- "consent_copy",
41
- ),
42
- "description": _("The following questions are directed to the interviewer."),
43
- },
44
- ),
45
- audit_fieldset_tuple,
46
- )
47
-
48
- search_fields = ("subject_identifier",)
49
-
50
- radio_fields = { # noqa: RUF012
51
- "gender": admin.VERTICAL,
52
- "assessment_score": admin.VERTICAL,
53
- "consent_copy": admin.VERTICAL,
54
- "consent_reviewed": admin.VERTICAL,
55
- "consent_signature": admin.VERTICAL,
56
- "language": admin.VERTICAL,
57
- "study_questions": admin.VERTICAL,
58
- }
@@ -1,55 +0,0 @@
1
- from django import forms
2
- from django.core.exceptions import ObjectDoesNotExist
3
- from edc_action_item.forms import ActionItemFormMixin
4
- from edc_form_validators import FormValidatorMixin
5
- from edc_registration.models import RegisteredSubject
6
- from edc_sites.modelform_mixins import SiteModelFormMixin
7
-
8
- from meta_consent.models import SubjectConsentSpfq
9
- from meta_rando.models import SpfqList
10
-
11
-
12
- class SubjectConsentSpfqForm(
13
- SiteModelFormMixin, ActionItemFormMixin, FormValidatorMixin, forms.ModelForm
14
- ):
15
- def clean(self):
16
- cleaned_data = super().clean()
17
-
18
- try:
19
- RegisteredSubject.objects.get(
20
- subject_identifier=cleaned_data.get("subject_identifier"),
21
- initials=cleaned_data.get("initials"),
22
- gender=cleaned_data.get("gender"),
23
- )
24
- except ObjectDoesNotExist as e:
25
- raise forms.ValidationError(
26
- {
27
- "__all__": (
28
- "Subject not known to the META trial. "
29
- "Check that the identifier, initials and gender match the patient "
30
- "register from the main META trial."
31
- )
32
- }
33
- ) from e
34
- try:
35
- SpfqList.objects.get(
36
- subject_identifier=cleaned_data.get("subject_identifier"),
37
- )
38
- except ObjectDoesNotExist as e:
39
- raise forms.ValidationError(
40
- {
41
- "__all__": (
42
- "Subject not found .A subject with this identifier "
43
- "has not been selected for the sub-study."
44
- )
45
- }
46
- ) from e
47
- return cleaned_data
48
-
49
- class Meta:
50
- model = SubjectConsentSpfq
51
- fields = "__all__"
52
- widgets = { # noqa: RUF012
53
- "action_identifier": forms.TextInput(attrs={"readonly": "readonly"}),
54
- "subject_identifier": forms.TextInput(attrs={"readonly": "readonly"}),
55
- }
@@ -1,103 +0,0 @@
1
- from django.conf import settings
2
- from django.contrib.sites.managers import CurrentSiteManager
3
- from django.core.validators import RegexValidator
4
- from django.db import models
5
- from django.utils import timezone
6
- from django.utils.translation import gettext_lazy as _
7
- from django_crypto_fields.fields import EncryptedCharField
8
- from edc_consent.field_mixins import (
9
- ReviewFieldsMixin,
10
- )
11
- from edc_consent.managers import ConsentObjectsManager
12
- from edc_constants.choices import GENDER
13
- from edc_constants.constants import NULL_STRING
14
- from edc_model.models import BaseUuidModel, HistoricalRecords
15
- from edc_sites.model_mixins import SiteModelMixin
16
-
17
- from .model_mixins import SearchSlugModelMixin
18
-
19
-
20
- class SubjectConsentSpfq(
21
- SiteModelMixin,
22
- ReviewFieldsMixin,
23
- SearchSlugModelMixin,
24
- BaseUuidModel,
25
- ):
26
- """A model completed by the user that captures the ICF for SPFQ."""
27
-
28
- subject_identifier = models.CharField(
29
- verbose_name=_("Subject identifier"), max_length=50, unique=True
30
- )
31
-
32
- initials = EncryptedCharField(
33
- validators=[
34
- RegexValidator(
35
- regex=r"^[A-Z]{2,3}$",
36
- message="Ensure initials consist of letters only in upper case, no spaces.",
37
- )
38
- ],
39
- default=NULL_STRING,
40
- )
41
-
42
- gender = models.CharField(
43
- verbose_name="Gender",
44
- choices=GENDER,
45
- max_length=1,
46
- )
47
-
48
- consent_datetime = models.DateTimeField(
49
- verbose_name=_("Consent datetime"), default=timezone.now
50
- )
51
-
52
- report_datetime = models.DateTimeField(null=True, editable=False)
53
-
54
- language = models.CharField(
55
- verbose_name=_("Language of consent"),
56
- max_length=25,
57
- choices=settings.LANGUAGES,
58
- help_text=_(
59
- "The language used for the consent process will "
60
- "also be used during data collection."
61
- ),
62
- )
63
-
64
- model_name = models.CharField(
65
- verbose_name="model",
66
- max_length=50,
67
- help_text=(
68
- "label_lower of this model class. Will be different if "
69
- "instance has been added/edited via a proxy model"
70
- ),
71
- default=NULL_STRING,
72
- editable=False,
73
- )
74
-
75
- version = models.CharField(
76
- verbose_name="Consent version",
77
- max_length=10,
78
- default="1.0",
79
- help_text="See 'consent definition' for consent versions by period.",
80
- editable=False,
81
- )
82
-
83
- on_site = CurrentSiteManager()
84
-
85
- objects = ConsentObjectsManager()
86
-
87
- history = HistoricalRecords()
88
-
89
- def __str__(self):
90
- return f"{self.subject_identifier} V{self.version}"
91
-
92
- def save(self, *args, **kwargs):
93
- if not self.id:
94
- self.model_name = self._meta.label_lower
95
- self.report_datetime = self.consent_datetime
96
- super().save(*args, **kwargs)
97
-
98
- def natural_key(self):
99
- return self.subject_identifier, self.version
100
-
101
- class Meta(BaseUuidModel.Meta):
102
- verbose_name = "Subject Consent for SPFQ"
103
- verbose_name_plural = "Subject Consents for SPFQ"
@@ -1,26 +0,0 @@
1
- from django.db import models
2
- from edc_constants.choices import GENDER
3
- from edc_identifier.model_mixins import UniqueSubjectIdentifierFieldMixin
4
- from edc_model.models import BaseUuidModel
5
- from edc_sites.model_mixins import SiteModelMixin
6
-
7
-
8
- class SpfqList(SiteModelMixin, UniqueSubjectIdentifierFieldMixin, BaseUuidModel):
9
- sid = models.IntegerField(unique=True)
10
-
11
- last_visit_code = models.CharField(max_length=25)
12
-
13
- last_appt_datetime = models.DateTimeField()
14
-
15
- gender = models.CharField(max_length=10, choices=GENDER)
16
-
17
- weight_bin = models.CharField(
18
- max_length=25,
19
- choices=(("lt_35", "<35"), ("gte_35__lte_49", "35-49"), ("gte_50", ">=50")),
20
- )
21
-
22
- date_generated = models.DateTimeField()
23
-
24
- class Meta(BaseUuidModel.Meta):
25
- verbose_name = "SPFQ List"
26
- verbose_name_plural = "SPFQ List"
@@ -1,103 +0,0 @@
1
- from django.contrib import admin
2
- from django.utils.safestring import mark_safe
3
- from django_audit_fields import audit_fieldset_tuple
4
- from edc_crf.fieldset import crf_status_fieldset
5
- from edc_model_admin.history import SimpleHistoryAdmin
6
-
7
- from ..admin_site import meta_subject_admin
8
- from ..forms import SpfqForm
9
- from ..models import Spfq
10
- from .modeladmin import CrfModelAdminMixin
11
-
12
-
13
- @admin.register(Spfq, site=meta_subject_admin)
14
- class SpfqAdmin(CrfModelAdminMixin, SimpleHistoryAdmin):
15
- additional_instructions = mark_safe(
16
- "The Study Participant Feedback Questionnaire Toolkit (SPFQ) is a set of three "
17
- "brief validated patient questionnaires designed to capture patients’ experiences "
18
- "at the beginning, during, and end of each clinical study, independent of disease "
19
- "and treatment.<BR>"
20
- "<B><font color='orange'>Interviewer to read</font></B>: Thank you for your "
21
- "participation. Your experiences in this trial are important to us and we "
22
- "would like to hear about them. Your answers will help us improve future trials. "
23
- "There are no right or wrong answers. Your answers will be kept anonymous and "
24
- "will not impact your participation in this trial."
25
- )
26
-
27
- form = SpfqForm
28
-
29
- fieldsets = (
30
- (None, {"fields": ("subject_visit", "report_datetime")}),
31
- (
32
- "Section A: Your experience before you started the study",
33
- {
34
- "description": "Please select one response for each of the following items.",
35
- "fields": ("a01", "a02", "a03", "a04"),
36
- },
37
- ),
38
- (
39
- "Section B: Your experience during the trial",
40
- {
41
- "description": "Please select one response for each of the following items.",
42
- "fields": (
43
- "b01",
44
- "b02",
45
- "b03",
46
- "b04",
47
- "b05",
48
- "b06",
49
- "b07",
50
- "b08",
51
- "b09",
52
- "b10",
53
- ),
54
- },
55
- ),
56
- (
57
- "Section C: Your experience at the end of the trial",
58
- {
59
- "description": "Please select one response for each of the following items.",
60
- "fields": (
61
- "c01",
62
- "c02",
63
- "c03",
64
- "c04",
65
- "c05",
66
- "c06",
67
- "c07",
68
- "c08",
69
- "c09",
70
- "c10",
71
- ),
72
- },
73
- ),
74
- crf_status_fieldset,
75
- audit_fieldset_tuple,
76
- )
77
-
78
- radio_fields = { # noqa: RUF012
79
- "a01": admin.VERTICAL,
80
- "a02": admin.VERTICAL,
81
- "a03": admin.VERTICAL,
82
- "a04": admin.VERTICAL,
83
- "b01": admin.VERTICAL,
84
- "b02": admin.VERTICAL,
85
- "b03": admin.VERTICAL,
86
- "b04": admin.VERTICAL,
87
- "b05": admin.VERTICAL,
88
- "b06": admin.VERTICAL,
89
- "b07": admin.VERTICAL,
90
- "b08": admin.VERTICAL,
91
- "b09": admin.VERTICAL,
92
- "b10": admin.VERTICAL,
93
- "c01": admin.VERTICAL,
94
- "c02": admin.VERTICAL,
95
- "c03": admin.VERTICAL,
96
- "c04": admin.VERTICAL,
97
- "c05": admin.VERTICAL,
98
- "c06": admin.VERTICAL,
99
- "c07": admin.VERTICAL,
100
- "c08": admin.VERTICAL,
101
- "c09": admin.VERTICAL,
102
- "c10": admin.VERTICAL,
103
- }
@@ -1,65 +0,0 @@
1
- from django import forms
2
- from django.core.exceptions import ObjectDoesNotExist
3
- from edc_crf.crf_form_validator import CrfFormValidator
4
- from edc_crf.modelform_mixins import CrfModelFormMixin
5
- from edc_registration.models import RegisteredSubject
6
-
7
- from meta_consent.models import SubjectConsentSpfq
8
- from meta_rando.models import SpfqList
9
-
10
- from ..models import Spfq
11
-
12
-
13
- class SpfqFormValidator(CrfFormValidator):
14
- pass
15
-
16
-
17
- class SpfqForm(CrfModelFormMixin, forms.ModelForm):
18
- form_validator_cls = SpfqFormValidator
19
-
20
- def clean(self):
21
- cleaned_data = super().clean()
22
-
23
- try:
24
- RegisteredSubject.objects.get(
25
- subject_identifier=cleaned_data.get("subject_identifier"),
26
- initials=cleaned_data.get("initials"),
27
- gender=cleaned_data.get("gender"),
28
- )
29
- except ObjectDoesNotExist as e:
30
- raise forms.ValidationError(
31
- {
32
- "__all__": (
33
- "Subject not known to the META trial. "
34
- "Check that the identifier, initials and gender match the patient "
35
- "register from the main META trial."
36
- )
37
- }
38
- ) from e
39
- try:
40
- SpfqList.objects.get(
41
- subject_identifier=cleaned_data.get("subject_identifier"),
42
- )
43
- except ObjectDoesNotExist as e:
44
- raise forms.ValidationError(
45
- {
46
- "__all__": (
47
- "Subject not found. A subject with this identifier "
48
- "has not been selected for the sub-study."
49
- )
50
- }
51
- ) from e
52
-
53
- try:
54
- SubjectConsentSpfq.objects.get(
55
- subject_identifier=cleaned_data.get("subject_identifier"),
56
- )
57
- except ObjectDoesNotExist as e:
58
- raise forms.ValidationError(
59
- {"__all__": "Subject not consented for the sub-study."}
60
- ) from e
61
- return cleaned_data
62
-
63
- class Meta:
64
- model = Spfq
65
- fields = "__all__"
@@ -1,190 +0,0 @@
1
- from django.db import models
2
- from edc_constants.choices import DIFFICULT_TO_EASY_CHOICE, DISAGREE_TO_AGREE_CHOICE, YES_NO
3
- from edc_model.models import BaseUuidModel
4
-
5
- from ..choices import (
6
- LESS_EXPECTED_TO_MORE_EXPECTED_CHOICE,
7
- NOT_AT_ALL_TO_HIGHLY_CHOICE,
8
- NOT_AT_ALL_TO_SEVERE_CHOICE,
9
- )
10
- from ..model_mixins import CrfModelMixin
11
-
12
-
13
- class Spfq(CrfModelMixin, BaseUuidModel):
14
- a01 = models.CharField(
15
- verbose_name="I understood the treatment process in this trial",
16
- max_length=25,
17
- choices=DISAGREE_TO_AGREE_CHOICE,
18
- help_text="for example: when and how to take or use a treatment",
19
- )
20
- a02 = models.CharField(
21
- verbose_name=(
22
- "The information given to me before "
23
- "I joined the trial was everything I wanted to know"
24
- ),
25
- max_length=25,
26
- choices=DISAGREE_TO_AGREE_CHOICE,
27
- help_text=(
28
- "for example: visits and procedures, "
29
- "time commitment, who to contact with questions"
30
- ),
31
- )
32
- a03 = models.CharField(
33
- verbose_name=(
34
- "The information given to me before I "
35
- "joined the trial was easy for me to understand"
36
- ),
37
- max_length=25,
38
- choices=DISAGREE_TO_AGREE_CHOICE,
39
- help_text=(
40
- "for example: visits and procedures, "
41
- "time commitment, who to contact with questions"
42
- ),
43
- )
44
- a04 = models.CharField(
45
- verbose_name=(
46
- "I felt comfortable that I could ask any questions before I joined the trial"
47
- ),
48
- max_length=25,
49
- choices=DISAGREE_TO_AGREE_CHOICE,
50
- )
51
- b01 = models.CharField(
52
- verbose_name="Overall I was satisfied with the trial site",
53
- max_length=25,
54
- choices=DISAGREE_TO_AGREE_CHOICE,
55
- help_text=(
56
- "for example: comfort and privacy of treatment area, "
57
- "waiting area, parking, ease of access to the site"
58
- ),
59
- )
60
- b02 = models.CharField(
61
- verbose_name="My trial visits were well organized",
62
- max_length=25,
63
- choices=DISAGREE_TO_AGREE_CHOICE,
64
- )
65
- b03 = models.CharField(
66
- verbose_name="My trial visits were scheduled at a convenient time for me",
67
- max_length=25,
68
- choices=DISAGREE_TO_AGREE_CHOICE,
69
- )
70
- b04 = models.CharField(
71
- verbose_name="The staff treated me with respect",
72
- max_length=25,
73
- choices=DISAGREE_TO_AGREE_CHOICE,
74
- )
75
- b05 = models.CharField(
76
- verbose_name="I felt comfortable that I could ask questions during the trial",
77
- max_length=25,
78
- choices=DISAGREE_TO_AGREE_CHOICE,
79
- )
80
- b06 = models.CharField(
81
- verbose_name=(
82
- "I was satisfied with the answers I have received to my questions during the trial"
83
- ),
84
- max_length=25,
85
- choices=DISAGREE_TO_AGREE_CHOICE,
86
- )
87
- b07 = models.CharField(
88
- verbose_name="The time taken to collect data was acceptable to me",
89
- max_length=25,
90
- choices=YES_NO,
91
- help_text="for example: in person visits, questionnaires, forms",
92
- )
93
- b08 = models.CharField(
94
- verbose_name="The impact the trial has had on my daily activities is acceptable",
95
- max_length=25,
96
- choices=YES_NO,
97
- help_text="for example: household chores, work commitments, eating",
98
- )
99
- b09 = models.CharField(
100
- verbose_name="The way in which trial data is being collected is acceptable to me",
101
- max_length=25,
102
- choices=YES_NO,
103
- help_text=(
104
- "for example: in person, online questionnaire, "
105
- "diary, wearable sensors, monitoring machines, technology"
106
- ),
107
- )
108
- b10 = models.CharField(
109
- verbose_name=(
110
- "Optional: I am being kept informed of the results of "
111
- "my medical tests done during the trial, including during screening"
112
- ),
113
- max_length=25,
114
- choices=DISAGREE_TO_AGREE_CHOICE,
115
- help_text="for example: blood tests, scans etc.",
116
- )
117
-
118
- c01 = models.CharField(
119
- verbose_name="I was informed when I had completed the trial",
120
- max_length=25,
121
- choices=YES_NO,
122
- )
123
-
124
- c02 = models.CharField(
125
- verbose_name=(
126
- "I was informed of any future opportunities to "
127
- "access the overall trial results if I wanted to"
128
- ),
129
- max_length=25,
130
- choices=YES_NO,
131
- )
132
-
133
- c03 = models.CharField(
134
- verbose_name="How easy was it to take the medication?",
135
- max_length=25,
136
- choices=DIFFICULT_TO_EASY_CHOICE,
137
- )
138
-
139
- c04 = models.CharField(
140
- verbose_name="Did you experience any burden or side effects?",
141
- max_length=25,
142
- choices=NOT_AT_ALL_TO_SEVERE_CHOICE,
143
- )
144
-
145
- c05 = models.CharField(
146
- verbose_name="How acceptable was it to take the drug?",
147
- max_length=25,
148
- choices=NOT_AT_ALL_TO_HIGHLY_CHOICE,
149
- )
150
-
151
- c06 = models.CharField(
152
- verbose_name="How easy was it to fit the medication into your routine?",
153
- max_length=25,
154
- choices=DIFFICULT_TO_EASY_CHOICE,
155
- )
156
-
157
- c07 = models.CharField(
158
- verbose_name="How burdensome was taking part in the trial?",
159
- max_length=25,
160
- choices=NOT_AT_ALL_TO_SEVERE_CHOICE,
161
- )
162
-
163
- c08 = models.CharField(
164
- verbose_name=(
165
- "Overall, I was satisfied with the information "
166
- "I received about future support after the trial"
167
- ),
168
- max_length=25,
169
- choices=DISAGREE_TO_AGREE_CHOICE,
170
- help_text="for example: future treatment, follow-up contact details",
171
- )
172
-
173
- c09 = models.CharField(
174
- verbose_name="Overall, I was satisfied with my trial experience",
175
- max_length=25,
176
- choices=DISAGREE_TO_AGREE_CHOICE,
177
- )
178
-
179
- c10 = models.CharField(
180
- verbose_name=(
181
- "Compared to when the trial started, the overall "
182
- "commitment required was similar to what I expected"
183
- ),
184
- max_length=25,
185
- choices=LESS_EXPECTED_TO_MORE_EXPECTED_CHOICE,
186
- )
187
-
188
- class Meta(CrfModelMixin.Meta, BaseUuidModel.Meta):
189
- verbose_name = "Feedback Questionnaire (SPFQ)"
190
- verbose_name_plural = "Feedback Questionnaires (SPFQ)"