meta-edc 0.3.46__py3-none-any.whl → 0.3.48__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 (52) hide show
  1. meta_ae/tests/holidays.csv +1 -1
  2. meta_analytics/dataframes/screening/get_screening_df.py +1 -0
  3. meta_analytics/tables/enrolled/glucose.py +3 -1
  4. meta_consent/action_items.py +18 -1
  5. meta_consent/admin/__init__.py +1 -0
  6. meta_consent/admin/subject_consent_v1_ext_admin.py +45 -0
  7. meta_consent/baker_recipes.py +1 -0
  8. meta_consent/consents.py +14 -1
  9. meta_consent/constants.py +1 -0
  10. meta_consent/forms/__init__.py +1 -0
  11. meta_consent/forms/subject_consent_v1_ext_form.py +16 -0
  12. meta_consent/migrations/0026_historicalsubjectconsentv1ext_subjectconsentv1ext.py +544 -0
  13. meta_consent/migrations/0027_auto_20250111_0344.py +27 -0
  14. meta_consent/models/__init__.py +1 -0
  15. meta_consent/models/signals.py +18 -0
  16. meta_consent/models/subject_consent_v1_ext.py +29 -0
  17. meta_consent/tests/holidays.csv +1 -1
  18. meta_dashboard/templates/meta_dashboard/bootstrap3/buttons/eligibility_button.html +1 -1
  19. meta_dashboard/templates/meta_dashboard/bootstrap3/buttons/screening_button.html +1 -1
  20. meta_dashboard/templates/meta_dashboard/bootstrap3/subject/dashboard/sidebar.html +24 -0
  21. meta_dashboard/templates/meta_dashboard/bootstrap3/subject/dashboard.html +3 -0
  22. meta_dashboard/tests/holidays.csv +1 -1
  23. meta_dashboard/views/subject/dashboard/dashboard_view.py +11 -0
  24. meta_edc/celery_live.py +1 -3
  25. meta_edc/celery_uat.py +1 -3
  26. meta_edc/management/commands/update_forms_reference.py +6 -2
  27. meta_edc/settings/debug.py +2 -2
  28. meta_edc-0.3.48.dist-info/AUTHORS +0 -0
  29. {meta_edc-0.3.46.dist-info → meta_edc-0.3.48.dist-info}/METADATA +3 -3
  30. {meta_edc-0.3.46.dist-info → meta_edc-0.3.48.dist-info}/RECORD +52 -45
  31. {meta_edc-0.3.46.dist-info → meta_edc-0.3.48.dist-info}/WHEEL +1 -1
  32. meta_pharmacy/labels/draw_label_for_subject_with_barcode.py +4 -0
  33. meta_prn/tests/tests/test_dm_referral.py +1 -4
  34. meta_reports/templates/meta_reports/columns/subject_identifier_column.html +1 -1
  35. meta_reports/templates/meta_reports/endpoints_all_change_list_note.html +1 -1
  36. meta_reports/templates/meta_reports/endpoints_change_list_note.html +1 -1
  37. meta_screening/tests/holidays.csv +1 -1
  38. meta_screening/tests/meta_test_case_mixin.py +15 -0
  39. meta_subject/models/todo.txt +1 -1
  40. meta_subject/static/meta_subject/slider.css +1 -1
  41. meta_subject/templates/meta_subject/endpoint_review_instructions.html +1 -1
  42. meta_subject/templates/meta_subject/widgets/slider.html +0 -1
  43. meta_subject/tests/holidays.csv +1 -1
  44. meta_subject/tests/tests/test_medication_adherence.py +5 -1
  45. meta_subject/tests/tests/test_mnsi.py +33 -9
  46. meta_visit_schedule/visit_schedules/phase_three/schedule.py +2 -2
  47. tests/etc/randomization_list.csv +1 -1
  48. tests/etc/randomization_list_phase_three.csv +1 -1
  49. tests/holidays.csv +1 -1
  50. /meta_edc-0.3.46.dist-info/AUTHORS → /meta_analytics/notebooks/cleaning/__init__.py +0 -0
  51. {meta_edc-0.3.46.dist-info → meta_edc-0.3.48.dist-info}/LICENSE +0 -0
  52. {meta_edc-0.3.46.dist-info → meta_edc-0.3.48.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,544 @@
1
+ # Generated by Django 5.1.2 on 2025-01-11 00:43
2
+
3
+ import _socket
4
+ import django.db.models.deletion
5
+ import django_audit_fields.fields.hostname_modification_field
6
+ import django_audit_fields.fields.userfield
7
+ import django_audit_fields.fields.uuid_auto_field
8
+ import django_audit_fields.models.audit_model_mixin
9
+ import django_crypto_fields.fields.encrypted_text_field
10
+ import django_revision.revision_field
11
+ import edc_action_item.managers
12
+ import edc_sites.managers
13
+ import edc_utils.date
14
+ import simple_history.models
15
+ import uuid
16
+ from django.conf import settings
17
+ from django.db import migrations, models
18
+
19
+
20
+ class Migration(migrations.Migration):
21
+
22
+ dependencies = [
23
+ ("edc_action_item", "0037_remove_actionitem_reference_model_and_more"),
24
+ ("meta_consent", "0025_alter_historicalsubjectconsent_first_name_and_more"),
25
+ ("sites", "0002_alter_domain_unique"),
26
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
27
+ ]
28
+
29
+ operations = [
30
+ migrations.CreateModel(
31
+ name="HistoricalSubjectConsentV1Ext",
32
+ fields=[
33
+ (
34
+ "revision",
35
+ django_revision.revision_field.RevisionField(
36
+ blank=True,
37
+ editable=False,
38
+ help_text="System field. Git repository tag:branch:commit.",
39
+ max_length=75,
40
+ null=True,
41
+ verbose_name="Revision",
42
+ ),
43
+ ),
44
+ (
45
+ "created",
46
+ models.DateTimeField(
47
+ blank=True, default=django_audit_fields.models.audit_model_mixin.utcnow
48
+ ),
49
+ ),
50
+ (
51
+ "modified",
52
+ models.DateTimeField(
53
+ blank=True, default=django_audit_fields.models.audit_model_mixin.utcnow
54
+ ),
55
+ ),
56
+ (
57
+ "user_created",
58
+ django_audit_fields.fields.userfield.UserField(
59
+ blank=True,
60
+ help_text="Updated by admin.save_model",
61
+ max_length=50,
62
+ verbose_name="user created",
63
+ ),
64
+ ),
65
+ (
66
+ "user_modified",
67
+ django_audit_fields.fields.userfield.UserField(
68
+ blank=True,
69
+ help_text="Updated by admin.save_model",
70
+ max_length=50,
71
+ verbose_name="user modified",
72
+ ),
73
+ ),
74
+ (
75
+ "hostname_created",
76
+ models.CharField(
77
+ blank=True,
78
+ default=_socket.gethostname,
79
+ help_text="System field. (modified on create only)",
80
+ max_length=60,
81
+ verbose_name="Hostname created",
82
+ ),
83
+ ),
84
+ (
85
+ "hostname_modified",
86
+ django_audit_fields.fields.hostname_modification_field.HostnameModificationField(
87
+ blank=True,
88
+ help_text="System field. (modified on every save)",
89
+ max_length=50,
90
+ verbose_name="Hostname modified",
91
+ ),
92
+ ),
93
+ (
94
+ "device_created",
95
+ models.CharField(blank=True, max_length=10, verbose_name="Device created"),
96
+ ),
97
+ (
98
+ "device_modified",
99
+ models.CharField(
100
+ blank=True, max_length=10, verbose_name="Device modified"
101
+ ),
102
+ ),
103
+ (
104
+ "locale_created",
105
+ models.CharField(
106
+ blank=True,
107
+ help_text="Auto-updated by Modeladmin",
108
+ max_length=10,
109
+ null=True,
110
+ verbose_name="Locale created",
111
+ ),
112
+ ),
113
+ (
114
+ "locale_modified",
115
+ models.CharField(
116
+ blank=True,
117
+ help_text="Auto-updated by Modeladmin",
118
+ max_length=10,
119
+ null=True,
120
+ verbose_name="Locale modified",
121
+ ),
122
+ ),
123
+ (
124
+ "id",
125
+ django_audit_fields.fields.uuid_auto_field.UUIDAutoField(
126
+ blank=True,
127
+ db_index=True,
128
+ editable=False,
129
+ help_text="System auto field. UUID primary key.",
130
+ ),
131
+ ),
132
+ ("subject_identifier", models.CharField(db_index=True, max_length=50)),
133
+ (
134
+ "subject_identifier_as_pk",
135
+ models.UUIDField(default=uuid.uuid4, editable=False),
136
+ ),
137
+ (
138
+ "subject_identifier_aka",
139
+ models.CharField(
140
+ editable=False,
141
+ help_text="track a previously allocated identifier.",
142
+ max_length=50,
143
+ null=True,
144
+ verbose_name="Subject Identifier a.k.a",
145
+ ),
146
+ ),
147
+ (
148
+ "action_identifier",
149
+ models.CharField(blank=True, db_index=True, max_length=50, null=True),
150
+ ),
151
+ (
152
+ "parent_action_identifier",
153
+ models.CharField(
154
+ blank=True,
155
+ help_text="action identifier that links to parent reference model instance.",
156
+ max_length=30,
157
+ null=True,
158
+ ),
159
+ ),
160
+ (
161
+ "related_action_identifier",
162
+ models.CharField(
163
+ blank=True,
164
+ help_text="action identifier that links to related reference model instance.",
165
+ max_length=30,
166
+ null=True,
167
+ ),
168
+ ),
169
+ ("action_item_reason", models.TextField(editable=False, null=True)),
170
+ ("report_datetime", models.DateTimeField(default=edc_utils.date.get_utcnow)),
171
+ (
172
+ "agrees_to_extension",
173
+ models.CharField(
174
+ choices=[("Yes", "Yes"), ("No", "No")],
175
+ help_text="See above for the definition of extended followup.",
176
+ max_length=15,
177
+ verbose_name="Does the participant agree to extend followup as per the protocol amendment?",
178
+ ),
179
+ ),
180
+ (
181
+ "comment",
182
+ django_crypto_fields.fields.encrypted_text_field.EncryptedTextField(
183
+ blank=True,
184
+ help_text=" (Encryption: AES local)",
185
+ max_length=250,
186
+ null=True,
187
+ verbose_name="Comment",
188
+ ),
189
+ ),
190
+ (
191
+ "consent_extension_version",
192
+ models.CharField(
193
+ editable=False,
194
+ max_length=10,
195
+ null=True,
196
+ verbose_name="Consent extension version",
197
+ ),
198
+ ),
199
+ (
200
+ "consent_extension_definition_name",
201
+ models.CharField(
202
+ editable=False,
203
+ max_length=50,
204
+ null=True,
205
+ verbose_name="Consent extension definition",
206
+ ),
207
+ ),
208
+ (
209
+ "history_id",
210
+ models.UUIDField(
211
+ default=uuid.uuid4, editable=False, primary_key=True, serialize=False
212
+ ),
213
+ ),
214
+ ("history_date", models.DateTimeField(db_index=True)),
215
+ ("history_change_reason", models.CharField(max_length=100, null=True)),
216
+ (
217
+ "history_type",
218
+ models.CharField(
219
+ choices=[("+", "Created"), ("~", "Changed"), ("-", "Deleted")],
220
+ max_length=1,
221
+ ),
222
+ ),
223
+ (
224
+ "action_item",
225
+ models.ForeignKey(
226
+ blank=True,
227
+ db_constraint=False,
228
+ null=True,
229
+ on_delete=django.db.models.deletion.DO_NOTHING,
230
+ related_name="+",
231
+ to="edc_action_item.actionitem",
232
+ ),
233
+ ),
234
+ (
235
+ "history_user",
236
+ models.ForeignKey(
237
+ null=True,
238
+ on_delete=django.db.models.deletion.SET_NULL,
239
+ related_name="+",
240
+ to=settings.AUTH_USER_MODEL,
241
+ ),
242
+ ),
243
+ (
244
+ "parent_action_item",
245
+ models.ForeignKey(
246
+ blank=True,
247
+ db_constraint=False,
248
+ null=True,
249
+ on_delete=django.db.models.deletion.DO_NOTHING,
250
+ related_name="+",
251
+ to="edc_action_item.actionitem",
252
+ ),
253
+ ),
254
+ (
255
+ "related_action_item",
256
+ models.ForeignKey(
257
+ blank=True,
258
+ db_constraint=False,
259
+ null=True,
260
+ on_delete=django.db.models.deletion.DO_NOTHING,
261
+ related_name="+",
262
+ to="edc_action_item.actionitem",
263
+ ),
264
+ ),
265
+ (
266
+ "site",
267
+ models.ForeignKey(
268
+ blank=True,
269
+ db_constraint=False,
270
+ null=True,
271
+ on_delete=django.db.models.deletion.DO_NOTHING,
272
+ related_name="+",
273
+ to="sites.site",
274
+ ),
275
+ ),
276
+ (
277
+ "subject_consent",
278
+ models.ForeignKey(
279
+ blank=True,
280
+ db_constraint=False,
281
+ null=True,
282
+ on_delete=django.db.models.deletion.DO_NOTHING,
283
+ related_name="+",
284
+ to="meta_consent.subjectconsentv1",
285
+ ),
286
+ ),
287
+ ],
288
+ options={
289
+ "verbose_name": "historical Consent V1 Extension",
290
+ "verbose_name_plural": "historical Consent V1 Extension",
291
+ "ordering": ("-history_date", "-history_id"),
292
+ "get_latest_by": ("history_date", "history_id"),
293
+ },
294
+ bases=(simple_history.models.HistoricalChanges, models.Model),
295
+ ),
296
+ migrations.CreateModel(
297
+ name="SubjectConsentV1Ext",
298
+ fields=[
299
+ (
300
+ "revision",
301
+ django_revision.revision_field.RevisionField(
302
+ blank=True,
303
+ editable=False,
304
+ help_text="System field. Git repository tag:branch:commit.",
305
+ max_length=75,
306
+ null=True,
307
+ verbose_name="Revision",
308
+ ),
309
+ ),
310
+ (
311
+ "created",
312
+ models.DateTimeField(
313
+ blank=True, default=django_audit_fields.models.audit_model_mixin.utcnow
314
+ ),
315
+ ),
316
+ (
317
+ "modified",
318
+ models.DateTimeField(
319
+ blank=True, default=django_audit_fields.models.audit_model_mixin.utcnow
320
+ ),
321
+ ),
322
+ (
323
+ "user_created",
324
+ django_audit_fields.fields.userfield.UserField(
325
+ blank=True,
326
+ help_text="Updated by admin.save_model",
327
+ max_length=50,
328
+ verbose_name="user created",
329
+ ),
330
+ ),
331
+ (
332
+ "user_modified",
333
+ django_audit_fields.fields.userfield.UserField(
334
+ blank=True,
335
+ help_text="Updated by admin.save_model",
336
+ max_length=50,
337
+ verbose_name="user modified",
338
+ ),
339
+ ),
340
+ (
341
+ "hostname_created",
342
+ models.CharField(
343
+ blank=True,
344
+ default=_socket.gethostname,
345
+ help_text="System field. (modified on create only)",
346
+ max_length=60,
347
+ verbose_name="Hostname created",
348
+ ),
349
+ ),
350
+ (
351
+ "hostname_modified",
352
+ django_audit_fields.fields.hostname_modification_field.HostnameModificationField(
353
+ blank=True,
354
+ help_text="System field. (modified on every save)",
355
+ max_length=50,
356
+ verbose_name="Hostname modified",
357
+ ),
358
+ ),
359
+ (
360
+ "device_created",
361
+ models.CharField(blank=True, max_length=10, verbose_name="Device created"),
362
+ ),
363
+ (
364
+ "device_modified",
365
+ models.CharField(
366
+ blank=True, max_length=10, verbose_name="Device modified"
367
+ ),
368
+ ),
369
+ (
370
+ "locale_created",
371
+ models.CharField(
372
+ blank=True,
373
+ help_text="Auto-updated by Modeladmin",
374
+ max_length=10,
375
+ null=True,
376
+ verbose_name="Locale created",
377
+ ),
378
+ ),
379
+ (
380
+ "locale_modified",
381
+ models.CharField(
382
+ blank=True,
383
+ help_text="Auto-updated by Modeladmin",
384
+ max_length=10,
385
+ null=True,
386
+ verbose_name="Locale modified",
387
+ ),
388
+ ),
389
+ (
390
+ "id",
391
+ django_audit_fields.fields.uuid_auto_field.UUIDAutoField(
392
+ blank=True,
393
+ editable=False,
394
+ help_text="System auto field. UUID primary key.",
395
+ primary_key=True,
396
+ serialize=False,
397
+ ),
398
+ ),
399
+ ("subject_identifier", models.CharField(max_length=50, unique=True)),
400
+ (
401
+ "subject_identifier_as_pk",
402
+ models.UUIDField(default=uuid.uuid4, editable=False),
403
+ ),
404
+ (
405
+ "subject_identifier_aka",
406
+ models.CharField(
407
+ editable=False,
408
+ help_text="track a previously allocated identifier.",
409
+ max_length=50,
410
+ null=True,
411
+ verbose_name="Subject Identifier a.k.a",
412
+ ),
413
+ ),
414
+ (
415
+ "action_identifier",
416
+ models.CharField(blank=True, max_length=50, null=True, unique=True),
417
+ ),
418
+ (
419
+ "parent_action_identifier",
420
+ models.CharField(
421
+ blank=True,
422
+ help_text="action identifier that links to parent reference model instance.",
423
+ max_length=30,
424
+ null=True,
425
+ ),
426
+ ),
427
+ (
428
+ "related_action_identifier",
429
+ models.CharField(
430
+ blank=True,
431
+ help_text="action identifier that links to related reference model instance.",
432
+ max_length=30,
433
+ null=True,
434
+ ),
435
+ ),
436
+ ("action_item_reason", models.TextField(editable=False, null=True)),
437
+ ("report_datetime", models.DateTimeField(default=edc_utils.date.get_utcnow)),
438
+ (
439
+ "agrees_to_extension",
440
+ models.CharField(
441
+ choices=[("Yes", "Yes"), ("No", "No")],
442
+ help_text="See above for the definition of extended followup.",
443
+ max_length=15,
444
+ verbose_name="Does the participant agree to extend followup as per the protocol amendment?",
445
+ ),
446
+ ),
447
+ (
448
+ "comment",
449
+ django_crypto_fields.fields.encrypted_text_field.EncryptedTextField(
450
+ blank=True,
451
+ help_text=" (Encryption: AES local)",
452
+ max_length=250,
453
+ null=True,
454
+ verbose_name="Comment",
455
+ ),
456
+ ),
457
+ (
458
+ "consent_extension_version",
459
+ models.CharField(
460
+ editable=False,
461
+ max_length=10,
462
+ null=True,
463
+ verbose_name="Consent extension version",
464
+ ),
465
+ ),
466
+ (
467
+ "consent_extension_definition_name",
468
+ models.CharField(
469
+ editable=False,
470
+ max_length=50,
471
+ null=True,
472
+ verbose_name="Consent extension definition",
473
+ ),
474
+ ),
475
+ (
476
+ "action_item",
477
+ models.ForeignKey(
478
+ blank=True,
479
+ null=True,
480
+ on_delete=django.db.models.deletion.PROTECT,
481
+ to="edc_action_item.actionitem",
482
+ ),
483
+ ),
484
+ (
485
+ "parent_action_item",
486
+ models.ForeignKey(
487
+ blank=True,
488
+ null=True,
489
+ on_delete=django.db.models.deletion.PROTECT,
490
+ related_name="+",
491
+ to="edc_action_item.actionitem",
492
+ ),
493
+ ),
494
+ (
495
+ "related_action_item",
496
+ models.ForeignKey(
497
+ blank=True,
498
+ null=True,
499
+ on_delete=django.db.models.deletion.PROTECT,
500
+ related_name="+",
501
+ to="edc_action_item.actionitem",
502
+ ),
503
+ ),
504
+ (
505
+ "site",
506
+ models.ForeignKey(
507
+ null=True,
508
+ on_delete=django.db.models.deletion.PROTECT,
509
+ related_name="+",
510
+ to="sites.site",
511
+ ),
512
+ ),
513
+ (
514
+ "subject_consent",
515
+ models.ForeignKey(
516
+ on_delete=django.db.models.deletion.PROTECT,
517
+ to="meta_consent.subjectconsentv1",
518
+ ),
519
+ ),
520
+ ],
521
+ options={
522
+ "verbose_name": "Consent V1 Extension",
523
+ "verbose_name_plural": "Consent V1 Extension",
524
+ "abstract": False,
525
+ "default_permissions": ("add", "change", "delete", "view", "export", "import"),
526
+ "default_manager_name": "objects",
527
+ "indexes": [
528
+ models.Index(
529
+ fields=[
530
+ "action_identifier",
531
+ "action_item",
532
+ "related_action_item",
533
+ "parent_action_item",
534
+ ],
535
+ name="meta_consen_action__e05e9c_idx",
536
+ )
537
+ ],
538
+ },
539
+ managers=[
540
+ ("on_site", edc_sites.managers.CurrentSiteManager()),
541
+ ("objects", edc_action_item.managers.ActionIdentifierModelManager()),
542
+ ],
543
+ ),
544
+ ]
@@ -0,0 +1,27 @@
1
+ # Generated by Django 5.1.2 on 2025-01-11 00:44
2
+
3
+ from django.db import IntegrityError, migrations, transaction
4
+ from edc_registration.models import RegisteredSubject
5
+
6
+ from meta_consent.action_items import ConsentV1ExtensionAction
7
+
8
+
9
+ def update_action_item(apps, schema_editor):
10
+ for obj in RegisteredSubject.objects.filter(site_id=40):
11
+ try:
12
+ with transaction.atomic():
13
+ ConsentV1ExtensionAction(
14
+ subject_identifier=obj.subject_identifier,
15
+ skip_get_current_site=True,
16
+ )
17
+ except IntegrityError:
18
+ pass
19
+
20
+
21
+ class Migration(migrations.Migration):
22
+
23
+ dependencies = [
24
+ ("meta_consent", "0026_historicalsubjectconsentv1ext_subjectconsentv1ext"),
25
+ ]
26
+
27
+ operations = [migrations.RunPython(update_action_item)]
@@ -1,4 +1,5 @@
1
1
  from .signals import subject_consent_on_post_delete, subject_consent_on_post_save
2
2
  from .subject_consent import SubjectConsent
3
3
  from .subject_consent_v1 import SubjectConsentV1
4
+ from .subject_consent_v1_ext import SubjectConsentV1Ext
4
5
  from .subject_reconsent import SubjectReconsent
@@ -2,6 +2,7 @@ from django.core.exceptions import ValidationError
2
2
  from django.db.models.signals import post_delete, post_save
3
3
  from django.dispatch import receiver
4
4
  from edc_action_item import ActionItemDeleteError, delete_action_item
5
+ from edc_appointment.utils import refresh_appointments
5
6
  from edc_constants.constants import YES
6
7
  from edc_pharmacy.exceptions import PrescriptionAlreadyExists
7
8
  from edc_pharmacy.prescribe import create_prescription
@@ -11,10 +12,12 @@ from edc_visit_schedule.site_visit_schedules import site_visit_schedules
11
12
  from meta_edc.meta_version import get_meta_version
12
13
  from meta_screening.models import SubjectScreening
13
14
  from meta_subject.models import SubjectVisit
15
+ from meta_visit_schedule.constants import SCHEDULE, VISIT_SCHEDULE
14
16
 
15
17
  from ..action_items import ReconsentAction
16
18
  from .subject_consent import SubjectConsent
17
19
  from .subject_consent_v1 import SubjectConsentV1
20
+ from .subject_consent_v1_ext import SubjectConsentV1Ext
18
21
 
19
22
 
20
23
  @receiver(
@@ -83,6 +86,21 @@ def subject_consent_on_post_save(sender, instance, raw, created, **kwargs):
83
86
  pass
84
87
 
85
88
 
89
+ @receiver(
90
+ post_save,
91
+ weak=False,
92
+ sender=SubjectConsentV1Ext,
93
+ dispatch_uid="subject_consent_v1_ext_on_post_save",
94
+ )
95
+ def subject_consent_v1_ext_on_post_save(sender, instance, raw, created, **kwargs):
96
+ if not raw:
97
+ refresh_appointments(
98
+ subject_identifier=instance.subject_identifier,
99
+ visit_schedule_name=VISIT_SCHEDULE,
100
+ schedule_name=SCHEDULE,
101
+ )
102
+
103
+
86
104
  @receiver(
87
105
  post_delete,
88
106
  weak=False,
@@ -0,0 +1,29 @@
1
+ from django.db import models
2
+ from edc_action_item.models import ActionModelMixin
3
+ from edc_consent.model_mixins import ConsentExtensionModelMixin
4
+ from edc_model.models import BaseUuidModel
5
+ from edc_sites.model_mixins import SiteModelMixin
6
+
7
+ from ..constants import CONSENT_V1_EXTENSION_ACTION
8
+ from .subject_consent_v1 import SubjectConsentV1
9
+
10
+
11
+ class SubjectConsentV1Ext(
12
+ ConsentExtensionModelMixin, SiteModelMixin, ActionModelMixin, BaseUuidModel
13
+ ):
14
+ """A consent extension to allow a participant to extend followup
15
+ up to 48 months.
16
+ """
17
+
18
+ subject_consent = models.ForeignKey(SubjectConsentV1, on_delete=models.PROTECT)
19
+
20
+ action_name = CONSENT_V1_EXTENSION_ACTION
21
+
22
+ class Meta(
23
+ ConsentExtensionModelMixin.Meta,
24
+ SiteModelMixin.Meta,
25
+ ActionModelMixin.Meta,
26
+ BaseUuidModel.Meta,
27
+ ):
28
+ verbose_name = "Consent V1 Extension"
29
+ verbose_name_plural = "Consent V1 Extension"
@@ -12,4 +12,4 @@
12
12
  2019-12-01,Mawlid Day,tanzania
13
13
  2019-12-09,Independence Day,tanzania
14
14
  2019-12-25,Christmas Day,tanzania
15
- 2019-12-26,Boxing Day,tanzania
15
+ 2019-12-26,Boxing Day,tanzania
@@ -12,4 +12,4 @@
12
12
  </ul>
13
13
  {% endif %}
14
14
  </div>
15
- {% endif %}
15
+ {% endif %}
@@ -12,4 +12,4 @@
12
12
  class="btn btn-sm btn-{% if p3 == YES %}success{% elif p1 == YES and p2 == YES and p3 == TBD %}warning{% else %}default{% endif %}"
13
13
  {% if p3_enabled %}href="{{ href_p3 }}"{% else %} disabled {% endif %}>
14
14
  <i class="fas fa-pencil-alt fa-sm"></i> P3
15
- </a>
15
+ </a>