From 914daae62b9cd563ec7d0b897d6f43a4fbe2f6cc Mon Sep 17 00:00:00 2001 From: bbonf Date: Thu, 14 Nov 2024 10:51:22 +0100 Subject: [PATCH 1/4] changed experiment duration from free-text field to minutes (integer) --- integration_tests/test_invite.py | 17 +++-- lab/conftest.py | 2 +- lab/experiments/email.py | 4 +- lab/experiments/forms/experiment_forms.py | 2 - .../locale/en/LC_MESSAGES/django.po | 5 +- .../locale/nl/LC_MESSAGES/django.po | 5 +- ..._experiment_confirmation_email_and_more.py | 33 +++++++++ lab/experiments/models/appointment_models.py | 6 +- lab/experiments/models/experiment_models.py | 4 +- lab/experiments/templates/call/home.html | 4 +- .../experiments/detail_parts/info.html | 4 +- lab/experiments/test_exclusion.py | 70 ++++++++++++------- lab/experiments/test_views.py | 8 +-- lab/experiments/views/call_views.py | 5 +- lab/integration_tests/conftest.py | 5 +- lab/integration_tests/test_experiments.py | 4 +- parent/parent/templates/parent/overview.html | 2 +- 17 files changed, 117 insertions(+), 63 deletions(-) create mode 100644 lab/experiments/migrations/0023_alter_experiment_confirmation_email_and_more.py diff --git a/integration_tests/test_invite.py b/integration_tests/test_invite.py index 50266814..5904aeea 100644 --- a/integration_tests/test_invite.py +++ b/integration_tests/test_invite.py @@ -33,7 +33,7 @@ def test_cancel_appointment_from_email(apps, participant, mailbox, link_from_mai DefaultCriteria = apps.lab.get_model('experiments', 'DefaultCriteria') User = apps.lab.get_model('main', 'User') Appointment = apps.lab.get_model('experiments', 'Appointment') - experiment = Experiment.objects.create(defaultcriteria=DefaultCriteria.objects.create()) + experiment = Experiment.objects.create(duration=10, session_duration=20) # somewhat abusing the get_model() calls above to setup django for the following to work from experiments.models import make_appointment @@ -41,10 +41,9 @@ def test_cancel_appointment_from_email(apps, participant, mailbox, link_from_mai leader = User.objects.first() # admin start = timezone.now() - end = start + timedelta(hours=1) experiment.leaders.add(leader) experiment.save() - appointment = make_appointment(experiment, participant, leader, start, end) + appointment = make_appointment(experiment, participant, leader, start) send_appointment_mail(appointment, prepare_appointment_mail(appointment)) @@ -71,7 +70,8 @@ def test_appointment_in_parent_overview(apps, participant, mailbox, page, login_ Experiment = apps.lab.get_model('experiments', 'Experiment') DefaultCriteria = apps.lab.get_model('experiments', 'DefaultCriteria') User = apps.lab.get_model('main', 'User') - experiment = Experiment.objects.create(defaultcriteria=DefaultCriteria.objects.create(), + experiment = Experiment.objects.create(duration=10, + session_duration=20, name='Test Experiment') # somewhat abusing the get_model() calls above to setup django for the following to work @@ -79,10 +79,9 @@ def test_appointment_in_parent_overview(apps, participant, mailbox, page, login_ leader = User.objects.first() # admin start = timezone.now() - end = start + timedelta(hours=1) experiment.leaders.add(leader) experiment.save() - appointment = make_appointment(experiment, participant, leader, start, end) + appointment = make_appointment(experiment, participant, leader, start) login_as(participant.email) try: @@ -99,7 +98,8 @@ def test_past_appointment_not_in_parent_overview(apps, participant, mailbox, pag Experiment = apps.lab.get_model('experiments', 'Experiment') DefaultCriteria = apps.lab.get_model('experiments', 'DefaultCriteria') User = apps.lab.get_model('main', 'User') - experiment = Experiment.objects.create(defaultcriteria=DefaultCriteria.objects.create(), + experiment = Experiment.objects.create(duration=10, + session_duration=20, name='Test Experiment') # somewhat abusing the get_model() calls above to setup django for the following to work @@ -107,10 +107,9 @@ def test_past_appointment_not_in_parent_overview(apps, participant, mailbox, pag leader = User.objects.first() # admin start = timezone.now() - timedelta(days=30) - end = start + timedelta(hours=1) experiment.leaders.add(leader) experiment.save() - appointment = make_appointment(experiment, participant, leader, start, end) + appointment = make_appointment(experiment, participant, leader, start) login_as(participant.email) try: diff --git a/lab/conftest.py b/lab/conftest.py index 74b4da58..14ad253a 100644 --- a/lab/conftest.py +++ b/lab/conftest.py @@ -9,7 +9,7 @@ @pytest.fixture def sample_experiment(admin_user, db): - yield admin_user.experiments.create(defaultcriteria=DefaultCriteria.objects.create()) + yield admin_user.experiments.create(duration=15, session_duration=30) @pytest.fixture diff --git a/lab/experiments/email.py b/lab/experiments/email.py index dd9a8c50..2abd579f 100644 --- a/lab/experiments/email.py +++ b/lab/experiments/email.py @@ -43,8 +43,8 @@ def __init__(self, *args, **kwargs):

Het experiment
- Het experiment duurt maximaal {{experiment_duration}}. - Omdat we ook de procedure uitleggen en er achteraf tijd is voor vragen, zult u ongeveer {{session_duration}} kwijt zijn + Het experiment duurt maximaal {{experiment_duration}} minuten. + Omdat we ook de procedure uitleggen en er achteraf tijd is voor vragen, zult u ongeveer {{session_duration}} minuten kwijt zijn aan uw bezoek aan het Babylab. In de bijlage van deze mail vindt u meer informatie over het experiment en onze werkwijze.

diff --git a/lab/experiments/forms/experiment_forms.py b/lab/experiments/forms/experiment_forms.py index 408ff316..9726414b 100644 --- a/lab/experiments/forms/experiment_forms.py +++ b/lab/experiments/forms/experiment_forms.py @@ -48,8 +48,6 @@ class Meta: exclude = ("defaultcriteria",) widgets = { "name": forms.TextInput, - "duration": forms.TextInput, - "session_duration": forms.TextInput, "task_description": forms.Textarea( { "rows": 7, diff --git a/lab/experiments/locale/en/LC_MESSAGES/django.po b/lab/experiments/locale/en/LC_MESSAGES/django.po index bbf5add2..e0abeeaa 100644 --- a/lab/experiments/locale/en/LC_MESSAGES/django.po +++ b/lab/experiments/locale/en/LC_MESSAGES/django.po @@ -917,4 +917,7 @@ msgid "default_criteria:attribute:min_age" msgstr "Min. age" msgid "default_criteria:attribute:max_age" -msgstr "Max. age" \ No newline at end of file +msgstr "Max. age" + +msgid "experiments:duration:minutes" +msgstr "minutes" \ No newline at end of file diff --git a/lab/experiments/locale/nl/LC_MESSAGES/django.po b/lab/experiments/locale/nl/LC_MESSAGES/django.po index 8e08fa5e..9008921c 100644 --- a/lab/experiments/locale/nl/LC_MESSAGES/django.po +++ b/lab/experiments/locale/nl/LC_MESSAGES/django.po @@ -949,4 +949,7 @@ msgstr "Geëxcludeerd" #: experiments/models/appointment_models.py:38 msgid "experiments:appointment:outcome:canceled" -msgstr "Geannuleerd" \ No newline at end of file +msgstr "Geannuleerd" + +msgid "experiments:duration:minutes" +msgstr "minuten" \ No newline at end of file diff --git a/lab/experiments/migrations/0023_alter_experiment_confirmation_email_and_more.py b/lab/experiments/migrations/0023_alter_experiment_confirmation_email_and_more.py new file mode 100644 index 00000000..418576fd --- /dev/null +++ b/lab/experiments/migrations/0023_alter_experiment_confirmation_email_and_more.py @@ -0,0 +1,33 @@ +# Generated by Django 4.2.11 on 2024-11-14 09:09 + +from django.db import migrations, models +import experiments.email + + +class Migration(migrations.Migration): + + dependencies = [ + ("experiments", "0022_alter_experiment_confirmation_email"), + ] + + operations = [ + migrations.AlterField( + model_name="experiment", + name="confirmation_email", + field=models.TextField( + default='

Beste {{parent_name}},

\n

\n U heeft een afspraak gemaakt om mee te doen met het experiment:\n {{experiment_name}}

\n We verwachten u en {{participant_name}} op:

\n Datum: {{date}}
\n Tijd: {{time}} uur
\n Locatie: Janskerkhof 13a (let op: dit is de groene voordeur met de helling ervoor).
\n

\n

\n Gezondheidsklachten
\n Wij vragen u de afspraak te verzetten wanneer uw kind vlak voor de afspraak gehoorproblemen\n en/of oorontsteking heeft en dus mogelijk minder goed hoort.\n

\n

\n Aankomst in het Babylab
\n Als u aanbelt bij Janskerkhof 13a en via de intercom zegt dat u voor het Babylab komt, dan wordt de deur op afstand voor u geopend.\n Wanneer u binnenkomt, kunt u gelijk na de hal met de lift (of met de trap) naar beneden.\n Daar vindt u aan uw rechterhand de wachtkamer, waar u plaats kunt nemen. De onderzoeksassistent zal u daar komen ophalen.\n

\n

\n Het experiment
\n Het experiment duurt maximaal {{experiment_duration}} minuten.\n Omdat we ook de procedure uitleggen en er achteraf tijd is voor vragen, zult u ongeveer {{session_duration}} minuten kwijt zijn\n aan uw bezoek aan het Babylab. In de bijlage van deze mail vindt u meer informatie over het experiment en onze werkwijze.\n

\n

\n Het is belangrijk voor ons onderzoek dat er geen broertje of zusje meekomt tijdens het bezoek aan het lab.\n Als u hierover van tevoren een andere afspraak heeft gemaakt met de assistent van het Babylab, dan geldt uiteraard die afspraak.\n

\n

\n Afspraak verzetten/afzeggen
\n Als u deze afspraak wilt afzeggen, kunt u dat doen via deze link.\n Doe dat a.u.b. minstens 24 uur van tevoren. Als u vlak van tevoren ontdekt dat u verhinderd bent,\n neem dan contact op met de testleider ({{leader_name}}, email: babylab.ilslabs@uu.nl).\n

\n

\n Meer informatie over het Babylab, bijvoorbeeld de routebeschrijving, kunt u vinden op de\n website van het Babylab.\n Wij danken u alvast hartelijk voor uw medewerking. Zonder uw deelname kunnen wij geen onderzoek doen!\n

\n

\n Vriendelijke groet,

\n Het team van het Babylab voor Taalonderzoek\n

', + help_text=experiments.email.AppointmentConfirmEmail.help_text, + verbose_name="experiment:attribute:confirmation_email", + ), + ), + migrations.AlterField( + model_name="experiment", + name="duration", + field=models.IntegerField(verbose_name="experiment:attribute:duration"), + ), + migrations.AlterField( + model_name="experiment", + name="session_duration", + field=models.IntegerField(verbose_name="experiment:attribute:session_duration"), + ), + ] diff --git a/lab/experiments/models/appointment_models.py b/lab/experiments/models/appointment_models.py index 138eb13e..086af65e 100644 --- a/lab/experiments/models/appointment_models.py +++ b/lab/experiments/models/appointment_models.py @@ -1,4 +1,4 @@ -from datetime import datetime +from datetime import datetime, timedelta from cdh.mail.classes import TemplateEmail from django.db import models @@ -108,10 +108,12 @@ def is_canceled(self): return self.outcome == Appointment.Outcome.CANCELED -def make_appointment(experiment: Experiment, participant: Participant, leader: User, start: datetime, end: datetime): +def make_appointment(experiment: Experiment, participant: Participant, leader: User, start: datetime): if leader not in experiment.leaders.all(): raise ValueError(f'{leader} is not a leader in the experiment "{experiment}"') + # appointment end is determined by the experiment's session duration + end = start + timedelta(minutes=experiment.session_duration) timeslot = TimeSlot.objects.create(start=start, end=end, experiment=experiment) appointment = Appointment.objects.create( participant=participant, timeslot=timeslot, experiment=experiment, leader=leader diff --git a/lab/experiments/models/experiment_models.py b/lab/experiments/models/experiment_models.py index 9545b7f6..97276953 100644 --- a/lab/experiments/models/experiment_models.py +++ b/lab/experiments/models/experiment_models.py @@ -25,9 +25,9 @@ def _get_dt_2_hours_ago() -> datetime: class Experiment(models.Model): name = models.TextField(_("experiment:attribute:name")) - duration = models.TextField(_("experiment:attribute:duration")) + duration = models.IntegerField(_("experiment:attribute:duration")) - session_duration = models.TextField(_("experiment:attribute:session_duration")) + session_duration = models.IntegerField(_("experiment:attribute:session_duration")) # how many participants are aimed for recruitment_target = models.PositiveIntegerField( diff --git a/lab/experiments/templates/call/home.html b/lab/experiments/templates/call/home.html index 019110a3..1eb3ec74 100644 --- a/lab/experiments/templates/call/home.html +++ b/lab/experiments/templates/call/home.html @@ -57,11 +57,11 @@

Experiment details

{% get_verbose_field_name "experiments" "Experiment" "duration" %} - {{ experiment.duration }} + {{ experiment.duration }} {% translate "experiments:duration:minutes" %} {% get_verbose_field_name "experiments" "Experiment" "session_duration" %} - {{ experiment.session_duration }} + {{ experiment.session_duration }} {% translate "experiments:duration:minutes" %} {% get_verbose_field_name "experiments" "Experiment" "location" %} diff --git a/lab/experiments/templates/experiments/detail_parts/info.html b/lab/experiments/templates/experiments/detail_parts/info.html index ac4f27c5..298fbc1f 100644 --- a/lab/experiments/templates/experiments/detail_parts/info.html +++ b/lab/experiments/templates/experiments/detail_parts/info.html @@ -58,7 +58,7 @@ {% trans 'experiment:attribute:duration' %} - {{ experiment.duration }} + {{ experiment.duration }} {% translate "experiments:duration:minutes" %} @@ -66,7 +66,7 @@ {% trans 'experiment:attribute:session_duration' %} - {{ experiment.session_duration }} + {{ experiment.session_duration }} {% translate "experiments:duration:minutes" %} diff --git a/lab/experiments/test_exclusion.py b/lab/experiments/test_exclusion.py index 1bae0f0f..9f2d9fb8 100644 --- a/lab/experiments/test_exclusion.py +++ b/lab/experiments/test_exclusion.py @@ -8,9 +8,9 @@ def test_excluded_experiment(admin_user, sample_participant): - experiment_1 = admin_user.experiments.create(defaultcriteria=DefaultCriteria.objects.create()) - experiment_2 = admin_user.experiments.create(defaultcriteria=DefaultCriteria.objects.create()) - experiment_3 = admin_user.experiments.create(defaultcriteria=DefaultCriteria.objects.create()) + experiment_1 = admin_user.experiments.create(duration=10, session_duration=20) + experiment_2 = admin_user.experiments.create(duration=10, session_duration=20) + experiment_3 = admin_user.experiments.create(duration=10, session_duration=20) # mark participant as having participated in experiment #1 timeslot = TimeSlot.objects.create( @@ -29,8 +29,8 @@ def test_excluded_experiment(admin_user, sample_participant): def test_required_experiment(admin_user, sample_participant): - experiment_1 = admin_user.experiments.create(defaultcriteria=DefaultCriteria.objects.create()) - experiment_2 = admin_user.experiments.create(defaultcriteria=DefaultCriteria.objects.create()) + experiment_1 = admin_user.experiments.create(duration=10, session_duration=20) + experiment_2 = admin_user.experiments.create(duration=10, session_duration=20) # cannot participate in #2 unless participated in #1 experiment_2.required_experiments.add(experiment_1) @@ -50,9 +50,9 @@ def test_required_experiment(admin_user, sample_participant): def test_required_experiment_multiple(admin_user, sample_participant): - experiment_1 = admin_user.experiments.create(defaultcriteria=DefaultCriteria.objects.create()) - experiment_2 = admin_user.experiments.create(defaultcriteria=DefaultCriteria.objects.create()) - experiment_3 = admin_user.experiments.create(defaultcriteria=DefaultCriteria.objects.create()) + experiment_1 = admin_user.experiments.create(duration=10, session_duration=20) + experiment_2 = admin_user.experiments.create(duration=10, session_duration=20) + experiment_3 = admin_user.experiments.create(duration=10, session_duration=20) # cannot participat in #3 unless participated in #1 and #2 experiment_3.required_experiments.add(experiment_1) @@ -82,7 +82,9 @@ def set_participant_field(participant, field_name, value): def test_parent_criterion_required(admin_user, sample_participant): for criterion in ["dyslexic_parent", "tos_parent"]: - experiment = admin_user.experiments.create(defaultcriteria=DefaultCriteria.objects.create(**{criterion: "Y"})) + experiment = admin_user.experiments.create( + duration=10, session_duration=20, defaultcriteria=DefaultCriteria.objects.create(**{criterion: "Y"}) + ) for value in [Participant.WhichParent.FEMALE, Participant.WhichParent.MALE, Participant.WhichParent.BOTH]: set_participant_field(sample_participant, criterion, value) assert sample_participant in get_eligible_participants_for_experiment( @@ -97,7 +99,9 @@ def test_parent_criterion_required(admin_user, sample_participant): def test_parent_criterion_excluded(admin_user, sample_participant): for criterion in ["dyslexic_parent", "tos_parent"]: - experiment = admin_user.experiments.create(defaultcriteria=DefaultCriteria.objects.create(**{criterion: "N"})) + experiment = admin_user.experiments.create( + duration=10, session_duration=20, defaultcriteria=DefaultCriteria.objects.create(**{criterion: "N"}) + ) for value in [ Participant.WhichParent.FEMALE, Participant.WhichParent.MALE, @@ -113,7 +117,7 @@ def test_parent_criterion_excluded(admin_user, sample_participant): def test_parent_criterion_indifferent(admin_user, sample_participant): for criterion in ["dyslexic_parent", "tos_parent"]: - experiment = admin_user.experiments.create(defaultcriteria=DefaultCriteria.objects.create()) + experiment = admin_user.experiments.create(duration=10, session_duration=20) for value in [choice[0] for choice in Participant.WhichParent.choices]: set_participant_field(sample_participant, criterion, value) assert sample_participant in get_eligible_participants_for_experiment( @@ -121,7 +125,7 @@ def test_parent_criterion_indifferent(admin_user, sample_participant): ), f"Participant with field {criterion} set to {value} is missing from eligible set" experiment = admin_user.experiments.create( - defaultcriteria=DefaultCriteria.objects.create(**{criterion: ["Y", "N"]}) + duration=10, session_duration=20, defaultcriteria=DefaultCriteria.objects.create(**{criterion: ["Y", "N"]}) ) for value in [choice[0] for choice in Participant.WhichParent.choices]: set_participant_field(sample_participant, criterion, value) @@ -138,14 +142,16 @@ def test_participant_criteria(admin_user, sample_participant): set_participant_field(sample_participant, criterion_name, option) # indifferent - experiment = admin_user.experiments.create(defaultcriteria=DefaultCriteria.objects.create()) + experiment = admin_user.experiments.create(duration=10, session_duration=20) assert sample_participant in get_eligible_participants_for_experiment( experiment ), f"Participant with field {criterion_name} set to {option} is missing from eligible set" # included experiment = admin_user.experiments.create( - defaultcriteria=DefaultCriteria.objects.create(**{criterion_name: [option]}) + duration=10, + session_duration=20, + defaultcriteria=DefaultCriteria.objects.create(**{criterion_name: [option]}), ) assert sample_participant in get_eligible_participants_for_experiment( experiment @@ -153,7 +159,9 @@ def test_participant_criteria(admin_user, sample_participant): # excluded experiment = admin_user.experiments.create( - defaultcriteria=DefaultCriteria.objects.create(**{criterion_name: list(options - set([option]))}) + duration=10, + session_duration=20, + defaultcriteria=DefaultCriteria.objects.create(**{criterion_name: list(options - set([option]))}), ) assert sample_participant not in get_eligible_participants_for_experiment( experiment @@ -168,36 +176,46 @@ def test_multilingual_criterion(admin_user, sample_participant): sample_participant.data.languages.set([en, nl]) # indifferent - experiment = admin_user.experiments.create(defaultcriteria=DefaultCriteria.objects.create()) + experiment = admin_user.experiments.create(duration=10, session_duration=20) assert sample_participant in get_eligible_participants_for_experiment(experiment) # included - experiment = admin_user.experiments.create(defaultcriteria=DefaultCriteria.objects.create(multilingual=["Y"])) + experiment = admin_user.experiments.create( + duration=10, session_duration=20, defaultcriteria=DefaultCriteria.objects.create(multilingual=["Y"]) + ) assert sample_participant in get_eligible_participants_for_experiment(experiment) # excluded - experiment = admin_user.experiments.create(defaultcriteria=DefaultCriteria.objects.create(multilingual=["N"])) + experiment = admin_user.experiments.create( + duration=10, session_duration=20, defaultcriteria=DefaultCriteria.objects.create(multilingual=["N"]) + ) assert sample_participant not in get_eligible_participants_for_experiment(experiment) # monolingual participant sample_participant.data.languages.set([en]) # indifferent - experiment = admin_user.experiments.create(defaultcriteria=DefaultCriteria.objects.create()) + experiment = admin_user.experiments.create(duration=10, session_duration=20) assert sample_participant in get_eligible_participants_for_experiment(experiment) # included - experiment = admin_user.experiments.create(defaultcriteria=DefaultCriteria.objects.create(multilingual=["N"])) + experiment = admin_user.experiments.create( + duration=10, session_duration=20, defaultcriteria=DefaultCriteria.objects.create(multilingual=["N"]) + ) assert sample_participant in get_eligible_participants_for_experiment(experiment) # excluded - experiment = admin_user.experiments.create(defaultcriteria=DefaultCriteria.objects.create(multilingual=["Y"])) + experiment = admin_user.experiments.create( + duration=10, session_duration=20, defaultcriteria=DefaultCriteria.objects.create(multilingual=["Y"]) + ) assert sample_participant not in get_eligible_participants_for_experiment(experiment) def test_age_filters(admin_user, sample_participant): experiment = admin_user.experiments.create( - defaultcriteria=DefaultCriteria.objects.create(min_age_days=5, min_age_months=3) + duration=10, + session_duration=20, + defaultcriteria=DefaultCriteria.objects.create(min_age_days=5, min_age_months=3), ) # too young @@ -211,7 +229,9 @@ def test_age_filters(admin_user, sample_participant): assert sample_participant in get_eligible_participants_for_experiment(experiment) experiment = admin_user.experiments.create( - defaultcriteria=DefaultCriteria.objects.create(max_age_days=5, max_age_months=3) + duration=10, + session_duration=20, + defaultcriteria=DefaultCriteria.objects.create(max_age_days=5, max_age_months=3), ) # too old @@ -225,9 +245,11 @@ def test_age_filters(admin_user, sample_participant): assert sample_participant in get_eligible_participants_for_experiment(experiment) experiment = admin_user.experiments.create( + duration=10, + session_duration=20, defaultcriteria=DefaultCriteria.objects.create( min_age_days=5, min_age_months=3, max_age_days=15, max_age_months=6 - ) + ), ) # too old diff --git a/lab/experiments/test_views.py b/lab/experiments/test_views.py index 757c2486..09a7bbef 100644 --- a/lab/experiments/test_views.py +++ b/lab/experiments/test_views.py @@ -21,7 +21,7 @@ class AppointmentTests(TestCase): @classmethod def setUpTestData(cls): cls.user = User.objects.create(username="test", is_staff=True) - cls.experiment = Experiment.objects.create() + cls.experiment = Experiment.objects.create(duration=15, session_duration=30) cls.experiment.leaders.add(cls.user) cls.participant = Participant.objects.create( @@ -35,7 +35,6 @@ def test_appointment_confirm(self): data = { "experiment": self.experiment.pk, "start": timezone.now() + timedelta(days=1), - "end": timezone.now() + timedelta(days=1, hours=1), "leader": self.user.pk, "participant": self.participant.pk, } @@ -49,7 +48,6 @@ def test_appointment_confirm_fail_in_past(self): data = { "experiment": self.experiment.pk, "start": timezone.now() - timedelta(hours=2), - "end": timezone.now() - timedelta(hours=1), "leader": self.user.pk, "participant": self.participant.pk, } @@ -71,7 +69,6 @@ def test_appointment_confirm_when_eligible_age(self): data = { "experiment": self.experiment.pk, "start": timezone.now() + timedelta(days=7), - "end": timezone.now() + timedelta(days=7, hours=1), "leader": self.user.pk, "participant": self.participant.pk, } @@ -92,7 +89,6 @@ def test_appointment_confirm_fail_when_ineligible(self): data = { "experiment": self.experiment.pk, "start": timezone.now() + timedelta(days=7), - "end": timezone.now() + timedelta(days=7, hours=1), "leader": self.user.pk, "participant": self.participant.pk, } @@ -107,7 +103,7 @@ class InviteTests(TestCase): @classmethod def setUpTestData(cls): cls.user = User.objects.create(username="test", is_staff=True) - cls.experiment = Experiment.objects.create() + cls.experiment = Experiment.objects.create(duration=15, session_duration=30) cls.experiment.leaders.add(cls.user) cls.participant = Participant.objects.create( diff --git a/lab/experiments/views/call_views.py b/lab/experiments/views/call_views.py index 0b12cc5e..8330ae0b 100644 --- a/lab/experiments/views/call_views.py +++ b/lab/experiments/views/call_views.py @@ -93,9 +93,8 @@ def create(self, request, *args, **kwargs): raise PermissionDenied start = parse_datetime(request.data["start"]) - end = parse_datetime(request.data["end"]) - if end < start or start < timezone.now(): + if start < timezone.now(): raise BadRequest("Invalid appointment time") participant = Participant.objects.get(pk=request.data["participant"]) @@ -110,7 +109,7 @@ def create(self, request, *args, **kwargs): pk=request.data["leader"], ) - appointment = make_appointment(experiment, participant, leader, start, end) + appointment = make_appointment(experiment, participant, leader, start) return JsonResponse(self.serializer_class(appointment).data) def check_age_at_appointment(self, participant: Participant, experiment: Experiment, start: datetime.date) -> bool: diff --git a/lab/integration_tests/conftest.py b/lab/integration_tests/conftest.py index e0440657..2c2e2368 100644 --- a/lab/integration_tests/conftest.py +++ b/lab/integration_tests/conftest.py @@ -44,10 +44,9 @@ def as_leader(page, django_user_model, live_server): @pytest.fixture def sample_experiment(admin_user, db, sample_location): yield admin_user.experiments.create( - defaultcriteria=DefaultCriteria.objects.create(), name="sample experiment", - duration="10 minutes", - session_duration="30 minutes", + duration=10, + session_duration=30, recruitment_target=50, task_description="task description", responsible_researcher="dr. Lin Guist", diff --git a/lab/integration_tests/test_experiments.py b/lab/integration_tests/test_experiments.py index 2a2282b0..ebf76a67 100644 --- a/lab/integration_tests/test_experiments.py +++ b/lab/integration_tests/test_experiments.py @@ -11,8 +11,8 @@ def test_create_experiment(page, as_admin, sample_leader, sample_location): page.get_by_role("link", name="Create experiment").click() page.get_by_role("textbox", name="Name").fill("Experiment name") - page.get_by_role("textbox", name="Task duration").fill("10 minutes") - page.get_by_role("textbox", name="Session duration").fill("25 minutes") + page.get_by_role("textbox", name="Task duration").fill("10") + page.get_by_role("textbox", name="Session duration").fill("25") page.get_by_role("spinbutton", name="Recruitment target").fill("30") page.locator('select[name="location"]').select_option(sample_location.name) diff --git a/parent/parent/templates/parent/overview.html b/parent/parent/templates/parent/overview.html index bd105a5b..81d05f41 100644 --- a/parent/parent/templates/parent/overview.html +++ b/parent/parent/templates/parent/overview.html @@ -27,7 +27,7 @@
{{ appointment.experiment }}
Participant: {{ appointment.participant }}
Datum: {{ appointment.start|date:"l d M Y, H:i"|lower }}
Tijd: {{ appointment.start|time }}
-
Totale duur bezoek: {{ appointment.session_duration }}
+
Totale duur bezoek: {{ appointment.session_duration }} minuten
Naam onderzoeker: {{ appointment.leader }}
Telefoonnummer onderzoeker: {{ appointment.contact_phone }}
From 8a44b4841d02ba96aa5cab9a0822594cf149f64b Mon Sep 17 00:00:00 2001 From: bbonf Date: Thu, 14 Nov 2024 12:33:33 +0100 Subject: [PATCH 2/4] appointment end should be determined by start + duration --- babex-vue/src/api.ts | 1 - .../src/components/agenda/AgendaCalendar.vue | 6 ++++-- .../src/components/agenda/AppointmentForm.vue | 2 +- babex-vue/src/components/invite/CallHome.vue | 20 +++++++++---------- lab/agenda/views.py | 2 +- lab/experiments/models/appointment_models.py | 4 ++++ lab/experiments/serializers.py | 5 +++-- lab/integration_tests/test_experiments.py | 4 ++-- 8 files changed, 24 insertions(+), 20 deletions(-) diff --git a/babex-vue/src/api.ts b/babex-vue/src/api.ts index 3ac63e92..0b8f9781 100644 --- a/babex-vue/src/api.ts +++ b/babex-vue/src/api.ts @@ -217,7 +217,6 @@ class GenericApiPart extends ApiPart { interface AppointmentCreate { start: Date, - end: Date, experiment: number, leader: number, participant: number, diff --git a/babex-vue/src/components/agenda/AgendaCalendar.vue b/babex-vue/src/components/agenda/AgendaCalendar.vue index ed895e25..1d229fc8 100644 --- a/babex-vue/src/components/agenda/AgendaCalendar.vue +++ b/babex-vue/src/components/agenda/AgendaCalendar.vue @@ -20,7 +20,7 @@ // optional experiment id for limiting feeds experiment?: number, - scheduling?: boolean, + duration?: number, }>(); // from https://stackoverflow.com/a/64090995 @@ -130,7 +130,9 @@ allDaySlot: false, slotMinTime: "07:00:00", slotMaxTime: "20:00:00", - slotDuration: props.scheduling ? "00:15:00" : "00:30:00", + slotDuration: {minutes: props.duration ?? 30}, + defaultTimedEventDuration: {minutes: props.duration}, + forceEventDuration: props.duration ? true : false, eventTimeFormat: { hour: '2-digit', minute: '2-digit', diff --git a/babex-vue/src/components/agenda/AppointmentForm.vue b/babex-vue/src/components/agenda/AppointmentForm.vue index 7c9ee271..6a3efc99 100644 --- a/babex-vue/src/components/agenda/AppointmentForm.vue +++ b/babex-vue/src/components/agenda/AppointmentForm.vue @@ -101,7 +101,7 @@
{{ _('To:') }}
- +
diff --git a/babex-vue/src/components/invite/CallHome.vue b/babex-vue/src/components/invite/CallHome.vue index b3965d85..fc3b1c5c 100644 --- a/babex-vue/src/components/invite/CallHome.vue +++ b/babex-vue/src/components/invite/CallHome.vue @@ -1,6 +1,6 @@