From 61731032b65fb667df2b4fed449b186d30e7d1a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= Date: Mon, 29 Jun 2020 10:17:38 +0200 Subject: [PATCH] toulouse-axel: endpoint to get bookable years (#44451) --- passerelle/contrib/toulouse_axel/models.py | 64 ++++++++++++++++++++-- passerelle/contrib/toulouse_axel/utils.py | 1 - tests/test_toulouse_axel.py | 58 ++++++++++++++++++++ 3 files changed, 116 insertions(+), 7 deletions(-) diff --git a/passerelle/contrib/toulouse_axel/models.py b/passerelle/contrib/toulouse_axel/models.py index f551d805..69f5f5ca 100644 --- a/passerelle/contrib/toulouse_axel/models.py +++ b/passerelle/contrib/toulouse_axel/models.py @@ -974,6 +974,58 @@ class ToulouseAxel(BaseResource): @endpoint( display_category='CAN-CLA', display_order=1, + description=_("Get the list of reference years available for bookings"), + perm='can_access', + parameters={ + 'NameID': {'description': _('Publik ID')}, + 'pivot_date': {'description': _('Pivot date (format MM-DD). After this date, next year is available.')}, + }) + def clae_years(self, request, NameID, pivot_date): + link = self.get_link(NameID) + + today = datetime.date.today() + reference_year = utils.get_reference_year_from_date(today) + + # get pivot date + try: + pivot_date = datetime.datetime.strptime('%s-%s' % (reference_year, pivot_date), utils.json_date_format).date() + except ValueError: + raise APIError('bad date format, should be MM-DD', err_code='bad-request', http_status=400) + # adjust pivot year + if pivot_date.month <= 7: + # between january and july, reference year is the year just before + pivot_date = pivot_date.replace(year=reference_year + 1) + + data = [{ + 'id': str(reference_year), + 'text': '%s/%s' % (reference_year, reference_year + 1), + 'type': 'encours', + 'refdate': today.strftime(utils.json_date_format) + }] + if today < pivot_date: + # date pivot not in the past, return only current year + return {'data': data} + children_activities = self.get_children_activities(dui=link.dui, reference_year=reference_year + 1) + if not children_activities: + # no activities for next year, return only current year + return {'data': data} + try: + next_ref_date = today.replace(year=today.year + 1) + except ValueError: + # 02/29 ? + next_ref_date = today + datetime.timedelta(days=366) + # return also next year + data.append({ + 'id': str(reference_year + 1), + 'text': '%s/%s' % (reference_year + 1, reference_year + 2), + 'type': 'suivante', + 'refdate': next_ref_date.strftime(utils.json_date_format) + }) + return {'data': data} + + @endpoint( + display_category='CAN-CLA', + display_order=2, description=_("Get information about CLAE activities of all children for the year"), perm='can_access', parameters={ @@ -996,7 +1048,7 @@ class ToulouseAxel(BaseResource): @endpoint( display_category='CAN-CLA', - display_order=2, + display_order=3, description=_("Get the list of CLAE booked activities of a child, for a period"), perm='can_access', parameters={ @@ -1069,7 +1121,7 @@ class ToulouseAxel(BaseResource): @endpoint( display_category='CAN-CLA', - display_order=3, + display_order=4, description=_("Get possible days to book an activity of a child, for a period"), perm='can_access', parameters={ @@ -1145,7 +1197,7 @@ class ToulouseAxel(BaseResource): @endpoint( display_category='CAN-CLA', - display_order=4, + display_order=5, description=_("Get annual possible days to book an activity of a child"), perm='can_access', parameters={ @@ -1189,7 +1241,7 @@ class ToulouseAxel(BaseResource): @endpoint( display_category='CAN-CLA', - display_order=5, + display_order=6, description=_("Get booked days for an activity of a child, for a period"), perm='can_access', parameters={ @@ -1205,7 +1257,7 @@ class ToulouseAxel(BaseResource): @endpoint( display_category='CAN-CLA', - display_order=6, + display_order=7, description=_("CLAE/Cantine booking"), perm='can_access', parameters={ @@ -1330,7 +1382,7 @@ class ToulouseAxel(BaseResource): @endpoint( display_category='CAN-CLA', - display_order=7, + display_order=8, description=_("CLAE/Cantine annual booking"), perm='can_access', parameters={ diff --git a/passerelle/contrib/toulouse_axel/utils.py b/passerelle/contrib/toulouse_axel/utils.py index e060ca17..defa88e4 100644 --- a/passerelle/contrib/toulouse_axel/utils.py +++ b/passerelle/contrib/toulouse_axel/utils.py @@ -210,7 +210,6 @@ def normalize_invoice(invoice, dui, historical=False, vendor_base=None): def get_reference_year_from_date(booking_date): if booking_date.month <= 7: # between january and july, reference year is the year just before - # (september) return booking_date.year - 1 return booking_date.year diff --git a/tests/test_toulouse_axel.py b/tests/test_toulouse_axel.py index 289b2f37..4167398d 100644 --- a/tests/test_toulouse_axel.py +++ b/tests/test_toulouse_axel.py @@ -2266,6 +2266,64 @@ def test_pay_invoice_endpoint(app, resource): } +def test_clae_years_endpoint_axel_error(app, resource): + Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42') + with mock.patch('passerelle.contrib.toulouse_axel.schemas.enfants_activites') as operation: + operation.side_effect = AxelError('FooBar') + resp = app.get('/toulouse-axel/test/clae_years?NameID=yyy&pivot_date=06-15') + assert resp.json['err_desc'] == "Axel error: FooBar" + assert resp.json['err'] == 'error' + + +@pytest.mark.parametrize('value', ['foo', '20/01/2020', '15/06', '06']) +def test_clae_years_endpoint_bad_date_format(app, resource, value): + Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42') + resp = app.get('/toulouse-axel/test/clae_years?NameID=yyy&pivot_date=%s' % value, status=400) + assert resp.json['err_desc'] == "bad date format, should be MM-DD" + assert resp.json['err'] == 'bad-request' + + +def test_clae_years_endpoint_no_result(app, resource): + resp = app.get('/toulouse-axel/test/clae_years?NameID=yyy&pivot_date=06-15') + assert resp.json['err_desc'] == "Person not found" + assert resp.json['err'] == 'not-found' + + +@pytest.mark.parametrize('today,pivot,next_year,next_date', [ + ('2019-08-01', '08-01', True, '2020-08-01'), + ('2019-08-01', '08-02', False, None), + ('2020-07-31', '07-31', True, '2021-07-31'), + ('2020-07-30', '07-31', False, None), + ('2020-06-14', '06-15', False, None), + ('2020-06-15', '06-15', True, '2021-06-15'), + ('2020-06-16', '06-15', True, '2021-06-16'), + ('2020-02-29', '02-01', True, '2021-03-01'), +]) +def test_clae_years_endpoint(app, resource, today, pivot, next_year, next_date): + Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42') + filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/child_activities.xml') + with open(filepath) as xml: + content = xml.read() + with mock_getdata(content, 'EnfantsActivites'): + with freezegun.freeze_time(today): + resp = app.get('/toulouse-axel/test/clae_years?NameID=yyy&pivot_date=%s' % pivot) + assert resp.json['data'][0] == {'id': '2019', 'text': '2019/2020', 'type': 'encours', 'refdate': today} + if next_year: + assert len(resp.json['data']) == 2 + assert resp.json['data'][1] == {'id': '2020', 'text': '2020/2021', 'type': 'suivante', 'refdate': next_date} + else: + assert len(resp.json['data']) == 1 + + +@freezegun.freeze_time('2020-06-30') +def test_clae_years_endpoint_noactivities(app, resource): + Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42') + with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_children_activities', return_value={}) as mock_activities: + resp = app.get('/toulouse-axel/test/clae_years?NameID=yyy&pivot_date=06-15') + assert mock_activities.call_args_list == [mock.call(dui='XXX', reference_year=2020)] + assert len(resp.json['data']) == 1 + + def test_clae_children_activities_info_endpoint_axel_error(app, resource): Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42') with mock.patch('passerelle.contrib.toulouse_axel.schemas.enfants_activites') as operation: