diff --git a/castellum/locale/de/LC_MESSAGES/django.po b/castellum/locale/de/LC_MESSAGES/django.po index 907dd2bffdc1764676255afea7f0cf6d367c3f9a..92e7e24752d329912cfea86a138aea811a3448d4 100644 --- a/castellum/locale/de/LC_MESSAGES/django.po +++ b/castellum/locale/de/LC_MESSAGES/django.po @@ -2056,8 +2056,8 @@ msgid "Type" msgstr "Typ" #: castellum/studies/forms.py:114 -msgid "One time invitation" -msgstr "Einmalige Einladung" +msgid "Anonymous invitation" +msgstr "Anonyme Einladung" #: castellum/studies/forms.py:131 msgid "All subjects will be reminded {} days before each appointment." @@ -2263,8 +2263,8 @@ msgid "Excluded studies" msgstr "Ausgeschlossene Studien" #: castellum/studies/models.py:172 -msgid "Is a one time invitation" -msgstr "Ist eine einmalige Einladung" +msgid "Is an anonymous invitation" +msgstr "Ist eine anonyme Einladung" #: castellum/studies/models.py:174 msgid "" @@ -3005,8 +3005,8 @@ msgid "UUID" msgstr "UUID" #: castellum/subjects/models.py:64 -msgid "Does not want to participate in one time invitations" -msgstr "Möchte nicht an einmaligen Einladungen teilnehmen" +msgid "Does not want to participate in anonymous invitations" +msgstr "Möchte nicht an anonymen Einladungen teilnehmen" #: castellum/subjects/models.py:69 msgid "Does not want to participate in the following study types" diff --git a/castellum/recruitment/filter_queries.py b/castellum/recruitment/filter_queries.py index 34d42596d828bfcd69425a4dbd13a05278163e43..86805d52fbe1c375f5ed65cad3f105f0ace47b33 100644 --- a/castellum/recruitment/filter_queries.py +++ b/castellum/recruitment/filter_queries.py @@ -88,8 +88,8 @@ def study_exclusion(study): def study_disinterest(study): """Exclude subjects who are disinterested in this study's study type.""" - if study.is_onetime_invitation: - return models.Q(onetime_invitation_disinterest=False) + if study.is_anonymous_invitation: + return models.Q(anonymous_invitation_disinterest=False) else: return ~models.Q(study_type_disinterest__in=study.study_type.all()) diff --git a/castellum/recruitment/forms.py b/castellum/recruitment/forms.py index 8f906b44871162c23133ff3d6b209d2b59f67d00..33ea48b62d5b5c20d069ecd3b2274a37f75fa6e2 100644 --- a/castellum/recruitment/forms.py +++ b/castellum/recruitment/forms.py @@ -136,7 +136,7 @@ class AttributesForm(forms.ModelForm): class Meta: model = Subject - fields = ['study_type_disinterest', 'onetime_invitation_disinterest'] + fields = ['study_type_disinterest', 'anonymous_invitation_disinterest'] widgets = { 'study_type_disinterest': forms.CheckboxSelectMultiple(), } @@ -154,10 +154,10 @@ class AttributesForm(forms.ModelForm): if key + '_answer_declined' in self.data: cleaned_data[key] = ANSWER_DECLINED study_type_disinterest = cleaned_data.pop('study_type_disinterest') - onetime_invitation_disinterest = cleaned_data.pop('onetime_invitation_disinterest') + anonymous_invitation_disinterest = cleaned_data.pop('anonymous_invitation_disinterest') return { 'study_type_disinterest': study_type_disinterest, - 'onetime_invitation_disinterest': onetime_invitation_disinterest, + 'anonymous_invitation_disinterest': anonymous_invitation_disinterest, 'attributes': cleaned_data, } diff --git a/castellum/recruitment/migrations/0040_change_anonymous_invitation_participation_status.py b/castellum/recruitment/migrations/0040_change_anonymous_invitation_participation_status.py new file mode 100644 index 0000000000000000000000000000000000000000..fde289e0f7a31aae3b31f7d7a88c8541c8dccf92 --- /dev/null +++ b/castellum/recruitment/migrations/0040_change_anonymous_invitation_participation_status.py @@ -0,0 +1,25 @@ +from django.db import migrations + +STUDY_FINISHED = 2 +PARTICIPATION_AWAITING_RESPONSE = 5 + + +def migrate_data(apps, schema_editor): + Study = apps.get_model('studies', 'Study') + + for study in Study.objects.filter(is_anonymous_invitation=True): + if study.status == STUDY_FINISHED: + study.participation_set.all().delete() + else: + study.participation_set.all().update(status=PARTICIPATION_AWAITING_RESPONSE) + + +class Migration(migrations.Migration): + dependencies = [ + ('recruitment', '0039_subject_uuid_foreign_key'), + ('studies', '0046_rename_study_is_onetime_invitation'), + ] + + operations = [ + migrations.RunPython(migrate_data), + ] diff --git a/castellum/recruitment/mixins.py b/castellum/recruitment/mixins.py index 0136e2f5aad3466f7e6e71eaa71d7deecadd601a..ee49a0c4935f76fa0683d51242d321a2b5291e98 100644 --- a/castellum/recruitment/mixins.py +++ b/castellum/recruitment/mixins.py @@ -22,7 +22,6 @@ import datetime import logging import random from typing import List -from typing import Optional from django.conf import settings from django.contrib import messages @@ -183,7 +182,6 @@ class BaseFollowUpFeed(BaseCalendarFeed): class BaseMailRecruitmentView(StudyMixin, PermissionRequiredMixin, FormView): template_name = 'recruitment/mail.html' form_class = SendMailForm - participation_status: Optional[int] = None def personalize_mail_body(self, mail_body, contact): return mail_body.replace('{name}', contact.full_name) @@ -191,12 +189,6 @@ class BaseMailRecruitmentView(StudyMixin, PermissionRequiredMixin, FormView): def create_participations(self, batch_size): subjects = get_recruitable(self.study) - attempts = 0 - if self.participation_status in [ - Participation.NOT_REACHED, Participation.AWAITING_RESPONSE - ]: - attempts = 1 - participations = [] with MailContext('recruitment') as ctx: while len(participations) < batch_size and subjects: @@ -216,8 +208,8 @@ class BaseMailRecruitmentView(StudyMixin, PermissionRequiredMixin, FormView): participations.append(Participation( study=self.study, subject=pick, - status=self.participation_status, - attempts=attempts, + status=Participation.AWAITING_RESPONSE, + attempts=1, )) return participations diff --git a/castellum/recruitment/templates/recruitment/attributes_form.html b/castellum/recruitment/templates/recruitment/attributes_form.html index e85b477c32554f3eaa496939b5e9392ea2c1ef6d..f86204f0db3893fdaffcade60a6f11090ca3df57 100644 --- a/castellum/recruitment/templates/recruitment/attributes_form.html +++ b/castellum/recruitment/templates/recruitment/attributes_form.html @@ -44,7 +44,7 @@ {% endfor %} {% bootstrap_field form.study_type_disinterest %} - {% bootstrap_field form.onetime_invitation_disinterest %} + {% bootstrap_field form.anonymous_invitation_disinterest %}
diff --git a/castellum/recruitment/views.py b/castellum/recruitment/views.py index cb95d5ae7196f75e82a13f1439a564eeff551e3b..045745377320cdfc46774cf198df5a5c4ac3e5cc 100644 --- a/castellum/recruitment/views.py +++ b/castellum/recruitment/views.py @@ -318,7 +318,6 @@ class RecruitmentViewOpen(RecruitmentView): class MailRecruitmentView(BaseMailRecruitmentView): permission_required = 'recruitment.recruit' study_status = [Study.EXECUTION] - participation_status = Participation.AWAITING_RESPONSE tab = 'mail' def get_context_data(self, **kwargs): diff --git a/castellum/studies/forms.py b/castellum/studies/forms.py index 478f58391e9ff12074ed0506d021a1813200a417..13052f90f4c96f5dbedada53de6d3f096b3c639c 100644 --- a/castellum/studies/forms.py +++ b/castellum/studies/forms.py @@ -58,7 +58,7 @@ class StudyForm(forms.ModelForm): 'consent', 'min_subject_count', 'exportable_attributes', - 'is_onetime_invitation', + 'is_anonymous_invitation', ] help_texts = { 'announce_status_changes': format_lazy( @@ -71,7 +71,7 @@ class StudyForm(forms.ModelForm): super().__init__(*args, **kwargs) if self.instance.pk: - del self.fields['is_onetime_invitation'] + del self.fields['is_anonymous_invitation'] if self.instance.pk: self.fields['tags'].initial = list(self.instance.tags) @@ -111,14 +111,14 @@ class StudyFilterForm(forms.Form): type = forms.ModelChoiceField( label=_('Type'), queryset=StudyType.objects, empty_label=None ) - is_onetime_invitation = forms.BooleanField(label=_('One time invitation')) + is_anonymous_invitation = forms.BooleanField(label=_('Anonymous invitation')) start = forms.DateTimeField() end = forms.DateTimeField() def clean(self): cleaned_data = super().clean() - if self.data.get('type') == 'onetime_invitation': - cleaned_data['is_onetime_invitation'] = True + if self.data.get('type') == 'anonymous_invitation': + cleaned_data['is_anonymous_invitation'] = True return cleaned_data diff --git a/castellum/studies/migrations/0046_rename_study_is_onetime_invitation.py b/castellum/studies/migrations/0046_rename_study_is_onetime_invitation.py new file mode 100644 index 0000000000000000000000000000000000000000..16b6f6a7a0a12ce3cd4f5043fcb1f63c028321dd --- /dev/null +++ b/castellum/studies/migrations/0046_rename_study_is_onetime_invitation.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.12 on 2022-03-14 11:14 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('studies', '0045_help_texts'), + ] + + operations = [ + migrations.RenameField( + model_name='study', + old_name='is_onetime_invitation', + new_name='is_anonymous_invitation', + ), + migrations.AlterField( + model_name='study', + name='is_anonymous_invitation', + field=models.BooleanField(default=False, help_text='Use this if you want to skip the usual recruitment workflow and just send an email to subjects, e.g. to invite them to an anonymous online survey.', verbose_name='Is an anonymous invitation'), + ), + ] diff --git a/castellum/studies/mixins.py b/castellum/studies/mixins.py index 1281184180c9de8824df13ccc2d133237820d1b9..45b7261d3a80247c32c79356f9bb4c6c592ae71e 100644 --- a/castellum/studies/mixins.py +++ b/castellum/studies/mixins.py @@ -33,8 +33,8 @@ class StudyMixin: - check ``access_study`` permission (basically allow access only to study members) - check that status is in ``study_status`` and matches - ``is_onetime_invitation``, otherwise return 404 - - check that is_onetime_invitation has desired value + ``is_anonymous_invitation``, otherwise return 404 + - check that is_anonymous_invitation has desired value - check that is_filter_trial has desired value - use study as permission object @@ -42,15 +42,15 @@ class StudyMixin: """ study_status: List[int] = [] - is_onetime_invitation: Optional[bool] = None + is_anonymous_invitation: Optional[bool] = None is_filter_trial: Optional[bool] = None def get_study(self): qs = Study.objects.all() if self.study_status: qs = qs.filter(status__in=self.study_status) - if self.is_onetime_invitation is not None: - qs = qs.filter(is_onetime_invitation=self.is_onetime_invitation) + if self.is_anonymous_invitation is not None: + qs = qs.filter(is_anonymous_invitation=self.is_anonymous_invitation) if self.is_filter_trial is not None: qs = qs.filter(is_filter_trial=self.is_filter_trial) key = 'study_pk' if 'study_pk' in self.kwargs else 'pk' diff --git a/castellum/studies/models.py b/castellum/studies/models.py index 1bd3970c5ddce738e801d2085df1e5ba98a7e7b5..a784afc613a73cf36c6a0d87803db77594cf093a 100644 --- a/castellum/studies/models.py +++ b/castellum/studies/models.py @@ -168,8 +168,8 @@ class Study(models.Model): 'studies.Study', verbose_name=_('Excluded studies'), related_name='+', blank=True ) - is_onetime_invitation = models.BooleanField( - _('Is a one time invitation'), + is_anonymous_invitation = models.BooleanField( + _('Is an anonymous invitation'), help_text=_( 'Use this if you want to skip the usual recruitment workflow and just send an ' 'email to subjects, e.g. to invite them to an anonymous online survey.' diff --git a/castellum/studies/templates/studies/study_base.html b/castellum/studies/templates/studies/study_base.html index 2bdb4a31cf2bd4702b460e50777b2e9f9875fed3..c04a10b257ffc0345443ed3df1435faadb38c50c 100644 --- a/castellum/studies/templates/studies/study_base.html +++ b/castellum/studies/templates/studies/study_base.html @@ -47,7 +47,7 @@ {% csrf_token %} - {% if not study.is_onetime_invitation %} + {% if not study.is_anonymous_invitation %} {% if study.status == study.EXECUTION %} diff --git a/castellum/studies/templates/studies/study_recruitmentsettings_base.html b/castellum/studies/templates/studies/study_recruitmentsettings_base.html index 3bdbf455c945c6aeb286152061ea23acfbb1e249..f05b848c1408e2eaf193ff9f68ab6334b386fca8 100644 --- a/castellum/studies/templates/studies/study_recruitmentsettings_base.html +++ b/castellum/studies/templates/studies/study_recruitmentsettings_base.html @@ -21,7 +21,7 @@ {% endif %} {% translate 'Excluded studies' %} - {% if not study.is_onetime_invitation %} + {% if not study.is_anonymous_invitation %} {% translate 'Inclusion/exclusion criteria' %} {% endif %} {% translate 'Mail Settings' %} diff --git a/castellum/studies/templates/studies/study_recruitmentsettings_form.html b/castellum/studies/templates/studies/study_recruitmentsettings_form.html index 6947f723aa63d961d8cb4a74170db4874641725c..4bb52ddbbea467e3194b3342f20856d14c2023c6 100644 --- a/castellum/studies/templates/studies/study_recruitmentsettings_form.html +++ b/castellum/studies/templates/studies/study_recruitmentsettings_form.html @@ -10,7 +10,7 @@ {% include 'utils/form_errors.html' with form=form %} {% csrf_token %} - {% if study.is_onetime_invitation or study.is_filter_trial %} + {% if study.is_anonymous_invitation or study.is_filter_trial %} {{ form.recruitment_text.as_hidden }} {% else %} {% bootstrap_field form.recruitment_text %} diff --git a/castellum/studies/views/members.py b/castellum/studies/views/members.py index 1bb7c84ac6eb27fa0e5e7327b3e00b73bc828503..fd439506dd62736598937cf2d6abfe24fc5963bf 100644 --- a/castellum/studies/views/members.py +++ b/castellum/studies/views/members.py @@ -39,7 +39,7 @@ class StudyMembersView(StudyMixin, PermissionRequiredMixin, SingleObjectMixin, F pk_url_kwarg = 'study_pk' template_name = 'studies/study_members.html' permission_required = 'studies.change_study' - is_onetime_invitation = False + is_anonymous_invitation = False is_filter_trial = False tab = 'members' @@ -88,7 +88,7 @@ class StudyMembersView(StudyMixin, PermissionRequiredMixin, SingleObjectMixin, F class StudyMembershipRemoveView(StudyMixin, PermissionRequiredMixin, DeleteView): model = StudyMembership permission_required = 'studies.change_study' - is_onetime_invitation = False + is_anonymous_invitation = False is_filter_trial = False tab = 'members' diff --git a/castellum/studies/views/recruitment.py b/castellum/studies/views/recruitment.py index d1fb922f5beefbcc8c4ffa9b7b42bc482e0bcb85..2a01f1bfb4ab1db14886fb103f3a46d0c7e10186 100644 --- a/castellum/studies/views/recruitment.py +++ b/castellum/studies/views/recruitment.py @@ -135,7 +135,7 @@ class StudyExclusionCriteriaView(StudyMixin, PermissionRequiredMixin, UpdateView template_name = 'studies/study_exclusioncriteria.html' fields = ['exclusion_criteria'] permission_required = 'studies.change_study' - is_onetime_invitation = False + is_anonymous_invitation = False is_filter_trial = False tab = 'recruitmentsettings' subtab = 'exclusioncriteria' @@ -195,8 +195,7 @@ class StudyMailSettingsView(StudyMixin, PermissionRequiredMixin, UpdateView): class OneTimeInvitationMailRecruitmentView(BaseMailRecruitmentView): permission_required = 'studies.change_study' - is_onetime_invitation = True - participation_status = Participation.INVITED + is_anonymous_invitation = True base_template = 'studies/study_base.html' tab = 'mail' diff --git a/castellum/studies/views/sessions.py b/castellum/studies/views/sessions.py index c6b3e692d44fb7f554ec9357a1cd3db2da7a6cc5..9cee438ca8b84855e0af5aef3422fca9d41811db 100644 --- a/castellum/studies/views/sessions.py +++ b/castellum/studies/views/sessions.py @@ -52,7 +52,7 @@ class StudySessionsView(StudyMixin, PermissionRequiredMixin, UpdateView): 'sessions_end', ] permission_required = 'studies.change_study' - is_onetime_invitation = False + is_anonymous_invitation = False is_filter_trial = False tab = 'sessions' @@ -73,7 +73,7 @@ class StudySessionFormMixin(StudyMixin, PermissionRequiredMixin): model = StudySession form_class = SessionForm permission_required = 'studies.change_study' - is_onetime_invitation = False + is_anonymous_invitation = False is_filter_trial = False tab = 'sessions' @@ -104,7 +104,7 @@ class StudySessionUpdateView(StudySessionFormMixin, UpdateView): class StudySessionDeleteView(StudyMixin, PermissionRequiredMixin, DeleteView): model = StudySession permission_required = 'studies.change_study' - is_onetime_invitation = False + is_anonymous_invitation = False is_filter_trial = False tab = 'sessions' diff --git a/castellum/studies/views/studies.py b/castellum/studies/views/studies.py index 771aefd8f3998f74f9a6ee30e1e45c6adc57704e..eacc9f63410538b07330c4c252569fcca6c35775 100644 --- a/castellum/studies/views/studies.py +++ b/castellum/studies/views/studies.py @@ -159,8 +159,8 @@ class StudyIndexView(LoginRequiredMixin, ListView): qs = qs.filter(status=self.form.cleaned_data['status']) if self.form.cleaned_data.get('type'): qs = qs.filter(studysession__type=self.form.cleaned_data['type']) - if self.form.cleaned_data.get('is_onetime_invitation'): - qs = qs.filter(is_onetime_invitation=True) + if self.form.cleaned_data.get('is_anonymous_invitation'): + qs = qs.filter(is_anonymous_invitation=True) if self.form.cleaned_data.get('start'): qs = qs.filter(sessions_end__gte=self.form.cleaned_data['start'].date()) if self.form.cleaned_data.get('end'): @@ -219,7 +219,7 @@ class StudyCreateView(PermissionRequiredMixin, CreateView): StudyMembership.objects.get_or_create(user=self.request.user, study=self.object) - if self.object.is_onetime_invitation: + if self.object.is_anonymous_invitation: self.object.complete_matches_only = True self.object.save() @@ -292,7 +292,7 @@ class StudyCreateView(PermissionRequiredMixin, CreateView): initial['consent'] = self.duplicate.consent initial['min_subject_count'] = self.duplicate.min_subject_count initial['exportable_attributes'] = list(self.duplicate.exportable_attributes.all()) - initial['is_onetime_invitation'] = self.duplicate.is_onetime_invitation + initial['is_anonymous_invitation'] = self.duplicate.is_anonymous_invitation return initial def get_context_data(self, **kwargs): @@ -374,7 +374,7 @@ class StudyDeleteView(StudyMixin, PermissionRequiredMixin, DeleteView): class StudyStartRecruitmentView(StudyMixin, PermissionRequiredMixin, View): permission_required = 'studies.view_study' - is_onetime_invitation = False + is_anonymous_invitation = False is_filter_trial = False def post(self, request, study_pk): @@ -420,7 +420,7 @@ class StudyFinishRecruitmentView(StudyMixin, PermissionRequiredMixin, View): class StudyDomainsMixin(StudyMixin, PermissionRequiredMixin): permission_required = 'studies.change_study' - is_onetime_invitation = False + is_anonymous_invitation = False is_filter_trial = False tab = 'domains' diff --git a/castellum/subjects/migrations/0036_rename_subject_onetime_invitation_disinterest.py b/castellum/subjects/migrations/0036_rename_subject_onetime_invitation_disinterest.py new file mode 100644 index 0000000000000000000000000000000000000000..e6d20dc15ea086ef5f39899009061da887d0b639 --- /dev/null +++ b/castellum/subjects/migrations/0036_rename_subject_onetime_invitation_disinterest.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.12 on 2022-03-14 11:14 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('subjects', '0035_consent_underage_when_given'), + ] + + operations = [ + migrations.RenameField( + model_name='subject', + old_name='onetime_invitation_disinterest', + new_name='anonymous_invitation_disinterest', + ), + migrations.AlterField( + model_name='subject', + name='anonymous_invitation_disinterest', + field=models.BooleanField(default=False, verbose_name='Does not want to participate in anonymous invitations'), + ), + ] diff --git a/castellum/subjects/models.py b/castellum/subjects/models.py index 7448a94d77683712c525201f3a9b8ca6b1269fcb..b2f9fe91c2ec71159027b51bc927b844f234ff4e 100644 --- a/castellum/subjects/models.py +++ b/castellum/subjects/models.py @@ -60,8 +60,8 @@ class Subject(TimeStampedModel): uuid = models.UUIDField(_('UUID'), default=uuid.uuid4, primary_key=True) attributes = models.JSONField(_('Recruitment attributes'), encoder=DjangoJSONEncoder) - onetime_invitation_disinterest = models.BooleanField( - _('Does not want to participate in one time invitations'), + anonymous_invitation_disinterest = models.BooleanField( + _('Does not want to participate in anonymous invitations'), default=False, ) study_type_disinterest = models.ManyToManyField( @@ -200,7 +200,7 @@ class Subject(TimeStampedModel): return not self.has_consent_or_waiting and ( completed > (1 if settings.CASTELLUM_DATE_OF_BIRTH_ATTRIBUTE_ID else 0) or self.study_type_disinterest.exists() - or self.onetime_invitation_disinterest + or self.anonymous_invitation_disinterest ) @property diff --git a/castellum/subjects/templates/subjects/subject_export.html b/castellum/subjects/templates/subjects/subject_export.html index 7b15cd494df1c8c70efde58be3b73df034ab6cc0..36f37605e0dbba2213905a7e585b863618b3b605 100644 --- a/castellum/subjects/templates/subjects/subject_export.html +++ b/castellum/subjects/templates/subjects/subject_export.html @@ -154,8 +154,8 @@
{{ subject|verbose_name:'study_type_disinterest' }}
{{ subject|display:'study_type_disinterest' }}
-
{{ subject|verbose_name:'onetime_invitation_disinterest' }}
-
{{ subject|display:'onetime_invitation_disinterest' }}
+
{{ subject|verbose_name:'anonymous_invitation_disinterest' }}
+
{{ subject|display:'anonymous_invitation_disinterest' }}
{{ subject|verbose_name:'not_available_until' }}
{{ subject|display:'not_available_until' }}
diff --git a/castellum/subjects/views.py b/castellum/subjects/views.py index d7087b576e50f43d7944c98cf562ef90fc1b1915..314508b079611dc9b444ab41e37a29ca9179add0 100644 --- a/castellum/subjects/views.py +++ b/castellum/subjects/views.py @@ -409,7 +409,7 @@ class DeleteRecruitmentDataView(SubjectMixin, PermissionRequiredMixin, DetailVie ) attributes[desc.json_key] = self.subject.attributes[desc.json_key] - self.subject.onetime_invitation_disinterest = False + self.subject.anonymous_invitation_disinterest = False self.subject.attributes = attributes self.subject.save() diff --git a/tests/recruitment/migrations/test_0040_change_anonymous_invitation_participation_status.py b/tests/recruitment/migrations/test_0040_change_anonymous_invitation_participation_status.py new file mode 100644 index 0000000000000000000000000000000000000000..3caa9e05801653f7f720e3867705c9ed2fa5752f --- /dev/null +++ b/tests/recruitment/migrations/test_0040_change_anonymous_invitation_participation_status.py @@ -0,0 +1,39 @@ +import pytest +from model_bakery import baker +from tests.markers import skip_old_migration + + +@pytest.mark.django_db(databases=['default', 'contacts']) +@skip_old_migration('0.73.0') +def test_change_status(migrator): + old_state = migrator.apply_initial_migration([ + ('recruitment', '0039_subject_uuid_foreign_key'), + ('studies', '0046_rename_study_is_onetime_invitation'), + ]) + Study = old_state.apps.get_model('studies', 'Study') + Participation = old_state.apps.get_model('recruitment', 'Participation') + + EDIT = 1 + FINISHED = 2 + + INVITED = 3 + AWAITING_RESPONSE = 5 + + study1 = baker.make(Study, is_anonymous_invitation=True, status=EDIT) + participation1 = baker.make(Participation, study=study1, status=INVITED) + + study2 = baker.make(Study, is_anonymous_invitation=True, status=FINISHED) + participation2 = baker.make(Participation, study=study2, status=INVITED) + + new_state = migrator.apply_tested_migration( + ('recruitment', '0040_change_anonymous_invitation_participation_status') + ) + Participation = new_state.apps.get_model('recruitment', 'Participation') + + participation1 = Participation.objects.filter(pk=participation1.pk).first() + participation2 = Participation.objects.filter(pk=participation2.pk).first() + + assert participation1.status == AWAITING_RESPONSE + assert participation2 is None + + migrator.reset()