diff --git a/ietf/api/tests.py b/ietf/api/tests.py index e61069b3f..3d3e3ac12 100644 --- a/ietf/api/tests.py +++ b/ietf/api/tests.py @@ -28,6 +28,8 @@ from ietf.doc.factories import IndividualDraftFactory, WgDraftFactory, WgRfcFact from ietf.group.factories import RoleFactory from ietf.meeting.factories import MeetingFactory, SessionFactory from ietf.meeting.models import Session +from ietf.nomcom.models import Volunteer, NomCom +from ietf.nomcom.factories import NomComFactory, nomcom_kwargs_for_year from ietf.person.factories import PersonFactory, random_faker from ietf.person.models import User from ietf.person.models import PersonalApiKey @@ -630,6 +632,7 @@ class CustomApiTests(TestCase): 'reg_type': 'hackathon', 'ticket_type': '', 'checkedin': 'False', + 'is_nomcom_volunteer': 'False', } url = urlreverse('ietf.api.views.api_new_meeting_registration') r = self.client.post(url, reg) @@ -691,6 +694,50 @@ class CustomApiTests(TestCase): missing_fields = [f.strip() for f in fields.split(',')] self.assertEqual(set(missing_fields), set(drop_fields)) + def test_api_new_meeting_registration_nomcom_volunteer(self): + '''Test that Volunteer is created if is_nomcom_volunteer=True + is submitted to API + ''' + meeting = MeetingFactory(type_id='ietf') + reg = { + 'apikey': 'invalid', + 'affiliation': "Alguma Corporação", + 'country_code': 'PT', + 'meeting': meeting.number, + 'reg_type': 'onsite', + 'ticket_type': '', + 'checkedin': 'False', + 'is_nomcom_volunteer': 'True', + } + person = PersonFactory() + reg['email'] = person.email().address + reg['first_name'] = person.first_name() + reg['last_name'] = person.last_name() + now = datetime.datetime.now() + if now.month > 10: + year = now.year + 1 + else: + year = now.year + # create appropriate group and nomcom objects + nomcom = NomComFactory.create(is_accepting_volunteers=True, **nomcom_kwargs_for_year(year)) + url = urlreverse('ietf.api.views.api_new_meeting_registration') + r = self.client.post(url, reg) + self.assertContains(r, 'Invalid apikey', status_code=403) + oidcp = PersonFactory(user__is_staff=True) + # Make sure 'oidcp' has an acceptable role + RoleFactory(name_id='robot', person=oidcp, email=oidcp.email(), group__acronym='secretariat') + key = PersonalApiKey.objects.create(person=oidcp, endpoint=url) + reg['apikey'] = key.hash() + r = self.client.post(url, reg) + nomcom = NomCom.objects.last() + self.assertContains(r, "Accepted, New registration", status_code=202) + # assert Volunteer exists + self.assertEqual(Volunteer.objects.count(), 1) + volunteer = Volunteer.objects.last() + self.assertEqual(volunteer.person, person) + self.assertEqual(volunteer.nomcom, nomcom) + self.assertEqual(volunteer.origin, 'registration') + def test_api_version(self): DumpInfo.objects.create(date=timezone.datetime(2022,8,31,7,10,1,tzinfo=datetime.timezone.utc), host='testapi.example.com',tz='UTC') url = urlreverse('ietf.api.views.version') diff --git a/ietf/api/views.py b/ietf/api/views.py index 9d832f6fa..e587b3712 100644 --- a/ietf/api/views.py +++ b/ietf/api/views.py @@ -1,7 +1,6 @@ # Copyright The IETF Trust 2017-2020, All Rights Reserved # -*- coding: utf-8 -*- - import json import pytz import re @@ -38,6 +37,7 @@ from ietf.doc.utils import fuzzy_find_documents from ietf.ietfauth.views import send_account_creation_email from ietf.ietfauth.utils import role_required from ietf.meeting.models import Meeting +from ietf.nomcom.models import Volunteer, NomCom from ietf.stats.models import MeetingRegistration from ietf.utils import log from ietf.utils.decorators import require_api_key @@ -140,7 +140,7 @@ def api_new_meeting_registration(request): def err(code, text): return HttpResponse(text, status=code, content_type='text/plain') required_fields = [ 'meeting', 'first_name', 'last_name', 'affiliation', 'country_code', - 'email', 'reg_type', 'ticket_type', 'checkedin'] + 'email', 'reg_type', 'ticket_type', 'checkedin', 'is_nomcom_volunteer'] fields = required_fields + [] if request.method == 'POST': # parameters: @@ -202,6 +202,19 @@ def api_new_meeting_registration(request): else: send_account_creation_email(request, email) response += ", Email sent" + + # handle nomcom volunteer + if data['is_nomcom_volunteer'] and object.person: + try: + nomcom = NomCom.objects.get(is_accepting_volunteers=True) + except (NomCom.DoesNotExist, NomCom.MultipleObjectsReturned): + nomcom = None + if nomcom: + Volunteer.objects.create( + nomcom=nomcom, + person=object.person, + affiliation=data['affiliation'], + origin='registration') return HttpResponse(response, status=202, content_type='text/plain') else: return HttpResponse(status=405) diff --git a/ietf/nomcom/migrations/0004_volunteer_origin_volunteer_time_volunteer_withdrawn.py b/ietf/nomcom/migrations/0004_volunteer_origin_volunteer_time_volunteer_withdrawn.py new file mode 100644 index 000000000..9eaebf206 --- /dev/null +++ b/ietf/nomcom/migrations/0004_volunteer_origin_volunteer_time_volunteer_withdrawn.py @@ -0,0 +1,27 @@ +# Generated by Django 4.2.7 on 2023-11-05 09:45 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("nomcom", "0003_alter_nomination_share_nominator"), + ] + + operations = [ + migrations.AddField( + model_name="volunteer", + name="origin", + field=models.CharField(default="datatracker", max_length=32), + ), + migrations.AddField( + model_name="volunteer", + name="time", + field=models.DateTimeField(auto_now_add=True, null=True, blank=True), + ), + migrations.AddField( + model_name="volunteer", + name="withdrawn", + field=models.DateTimeField(blank=True, null=True), + ), + ] diff --git a/ietf/nomcom/models.py b/ietf/nomcom/models.py index ee2eea2cc..51006a227 100644 --- a/ietf/nomcom/models.py +++ b/ietf/nomcom/models.py @@ -327,7 +327,10 @@ class Volunteer(models.Model): nomcom = ForeignKey('NomCom') person = ForeignKey(Person) affiliation = models.CharField(blank=True, max_length=255) - + time = models.DateTimeField(auto_now_add=True, null=True, blank=True) + origin = models.CharField(max_length=32, default='datatracker') + withdrawn = models.DateTimeField(blank=True, null=True) + def __str__(self): return f'{self.person} for {self.nomcom}'