0002-toulouse_axel-endpoint-to-get-possible-days-for-an-a.patch
passerelle/contrib/toulouse_axel/models.py | ||
---|---|---|
26 | 26 |
from django.core.cache import cache |
27 | 27 |
from django.db import models |
28 | 28 |
from django.http import HttpResponse |
29 |
from django.utils.dates import WEEKDAYS |
|
29 | 30 |
from django.utils.encoding import force_text |
30 | 31 |
from django.utils.translation import ugettext_lazy as _ |
31 | 32 | |
... | ... | |
1009 | 1010 |
'xml_response': e.xml_response}) |
1010 | 1011 |
return {'data': True} |
1011 | 1012 | |
1012 |
def get_children_activities(self, dui, reference_year): |
|
1013 |
def get_children_activities(self, dui, reference_year, activity_types=None): |
|
1014 |
activity_types = activity_types or ['MAT', 'MIDI', 'SOIR', 'GARD'] |
|
1013 | 1015 |
try: |
1014 | 1016 |
result = enfants_activites(self, { |
1015 | 1017 |
'DUI': { |
1016 | 1018 |
'IDDUI': dui, |
1017 | 1019 |
'ANNEEREFERENCE': str(reference_year), |
1018 |
'TYPESACTIVITES': 'MAT,MIDI,SOIR,GARD',
|
|
1020 |
'TYPESACTIVITES': ','.join(activity_types),
|
|
1019 | 1021 |
} |
1020 | 1022 |
}) |
1021 | 1023 |
except AxelError as e: |
... | ... | |
1028 | 1030 |
children_activities = result.json_response['DATA']['PORTAIL']['DUI'].get('ENFANT', []) |
1029 | 1031 |
return {child['IDPERSONNE']: child for child in children_activities} |
1030 | 1032 | |
1031 |
def get_child_activities(self, dui, reference_year, child_id): |
|
1032 |
children_activities = self.get_children_activities(dui=dui, reference_year=reference_year) |
|
1033 |
def get_child_activities(self, dui, reference_year, child_id, activity_types=None): |
|
1034 |
children_activities = self.get_children_activities( |
|
1035 |
dui=dui, reference_year=reference_year, activity_types=activity_types) |
|
1033 | 1036 | |
1034 | 1037 |
if child_id not in children_activities: |
1035 | 1038 |
raise APIError('Child not found', err_code='not-found') |
... | ... | |
1056 | 1059 |
return {} |
1057 | 1060 |
return {child_id: bool(child.get('ACTIVITE', [])) for child_id, child in children_activities.items()} |
1058 | 1061 | |
1059 |
def get_booking_data(self, dui, child_id, booking_date): |
|
1062 |
def get_booking_data(self, dui, child_id, booking_date, activity_types=None):
|
|
1060 | 1063 |
reference_year = utils.get_reference_year_from_date(booking_date) |
1061 | 1064 | |
1062 | 1065 |
# first get activities information for the child |
1063 | 1066 |
child_activities = self.get_child_activities( |
1064 | 1067 |
dui=dui, |
1065 | 1068 |
reference_year=reference_year, |
1066 |
child_id=child_id) |
|
1069 |
child_id=child_id, |
|
1070 |
activity_types=activity_types) |
|
1067 | 1071 | |
1068 | 1072 |
# then get booking of the requested week for the child |
1069 | 1073 |
activity_ids = [act['IDACTIVITE'] for act in child_activities.get('ACTIVITE', [])] |
... | ... | |
1159 | 1163 |
'idpersonne': {'description': _('Child ID')}, |
1160 | 1164 |
'booking_date': {'description': _('Booking date')}, |
1161 | 1165 |
}) |
1162 |
def clae_booking_info(self, request, NameID, idpersonne, booking_date): |
|
1166 |
def clae_booking_info(self, request, NameID, idpersonne, booking_date, activity_types=None):
|
|
1163 | 1167 |
link = self.get_link(NameID) |
1164 | 1168 |
try: |
1165 | 1169 |
booking_date = datetime.datetime.strptime(booking_date, utils.json_date_format) |
1166 | 1170 |
except ValueError: |
1167 | 1171 |
raise APIError('bad date format, should be YYYY-MM-DD', err_code='bad-request', http_status=400) |
1168 | 1172 | |
1169 |
booking_data = self.get_booking_data(dui=link.dui, child_id=idpersonne, booking_date=booking_date) |
|
1173 |
booking_data = self.get_booking_data(dui=link.dui, child_id=idpersonne, booking_date=booking_date, activity_types=activity_types)
|
|
1170 | 1174 | |
1171 | 1175 |
return {'data': booking_data} |
1172 | 1176 | |
... | ... | |
1178 | 1182 |
'idpersonne': {'description': _('Child ID')}, |
1179 | 1183 |
'booking_date': {'description': _('Booking date')}, |
1180 | 1184 |
}) |
1181 |
def clae_booking_activities_info(self, request, NameID, idpersonne, booking_date): |
|
1182 |
return {'data': self.clae_booking_info(request, NameID, idpersonne, booking_date)['data'].get('ACTIVITE', [])} |
|
1185 |
def clae_booking_activities_info(self, request, NameID, idpersonne, booking_date, activity_types=None): |
|
1186 |
return {'data': self.clae_booking_info( |
|
1187 |
request, NameID, idpersonne, booking_date, activity_types=activity_types)['data'].get('ACTIVITE', [])} |
|
1188 | ||
1189 |
@endpoint( |
|
1190 |
description=_("Get list of possible days for an activity"), |
|
1191 |
perm='can_access', |
|
1192 |
parameters={ |
|
1193 |
'NameID': {'description': _('Publik ID')}, |
|
1194 |
'idpersonne': {'description': _('Child ID')}, |
|
1195 |
'activity_type': {'description': _('Activity type (MAT, MIDI, SOIR, GARD)')}, |
|
1196 |
'booking_date': {'description': _('Booking date')}, |
|
1197 |
}) |
|
1198 |
def clae_booking_activity_possible_days(self, request, NameID, idpersonne, activity_type, booking_date): |
|
1199 |
if activity_type not in ['MAT', 'MIDI', 'SOIR', 'GARD']: |
|
1200 |
raise APIError('bad activity_type, should be MAT, MIDI, SOIR or GARD', err_code='bad-request', http_status=400) |
|
1201 |
activities = self.clae_booking_activities_info(request, NameID, idpersonne, booking_date, activity_types=[activity_type])['data'] |
|
1202 |
if not activities: |
|
1203 |
return {'data': []} |
|
1204 |
activity = activities[0] |
|
1205 |
activity_days = [] |
|
1206 |
for i, day in enumerate(['monday', 'tuesday', 'wednesday', 'thursday', 'friday']): |
|
1207 |
activity_days.append({ |
|
1208 |
'id': '{}-{}-{}-{}'.format(idpersonne, activity_type, activity['id'], day), |
|
1209 |
'text': WEEKDAYS[i], |
|
1210 |
'disabled': activity['booking']['days'][day] is None, |
|
1211 |
'prefill': activity['booking']['days'][day], |
|
1212 |
'details': activity, |
|
1213 |
}) |
|
1214 |
return {'data': activity_days} |
|
1183 | 1215 | |
1184 | 1216 |
@endpoint( |
1185 | 1217 |
description=_("CLAE/Cantine booking"), |
tests/test_toulouse_axel.py | ||
---|---|---|
2506 | 2506 |
] |
2507 | 2507 | |
2508 | 2508 | |
2509 |
def test_clae_booking_activity_possible_days_endpoint_axel_error(app, resource): |
|
2510 |
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42') |
|
2511 |
with mock.patch('passerelle.contrib.toulouse_axel.models.enfants_activites') as operation: |
|
2512 |
operation.side_effect = AxelError('FooBar') |
|
2513 |
resp = app.get('/toulouse-axel/test/clae_booking_activity_possible_days?NameID=yyy&idpersonne=3535&booking_date=2020-01-20&activity_type=MAT') |
|
2514 |
assert resp.json['err_desc'] == "Axel error: FooBar" |
|
2515 |
assert resp.json['err'] == 'error' |
|
2516 | ||
2517 |
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/child_activities.xml') |
|
2518 |
with open(filepath) as xml: |
|
2519 |
content = xml.read() |
|
2520 |
with mock_getdata(content, 'EnfantsActivites'): |
|
2521 |
with mock.patch('passerelle.contrib.toulouse_axel.models.reservation_periode') as operation: |
|
2522 |
operation.side_effect = AxelError('FooBar') |
|
2523 |
resp = app.get('/toulouse-axel/test/clae_booking_activity_possible_days?NameID=yyy&idpersonne=3535&booking_date=2020-01-20&activity_type=MAT') |
|
2524 |
assert resp.json['err_desc'] == "Axel error: FooBar" |
|
2525 |
assert resp.json['err'] == 'error' |
|
2526 | ||
2527 | ||
2528 |
@pytest.mark.parametrize('value', ['foo', '20/01/2020', '2020']) |
|
2529 |
def test_clae_booking_activity_possible_days_endpoint_bad_date_format(app, resource, value): |
|
2530 |
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42') |
|
2531 |
resp = app.get('/toulouse-axel/test/clae_booking_activity_possible_days?NameID=yyy&idpersonne=3535&booking_date=%s&activity_type=MAT' % value, status=400) |
|
2532 |
assert resp.json['err_desc'] == "bad date format, should be YYYY-MM-DD" |
|
2533 |
assert resp.json['err'] == 'bad-request' |
|
2534 | ||
2535 | ||
2536 |
def test_clae_booking_activity_possible_days_endpoint_activity_type(app, resource): |
|
2537 |
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42') |
|
2538 |
resp = app.get('/toulouse-axel/test/clae_booking_activity_possible_days?NameID=yyy&idpersonne=3535&booking_date=2020-01-20&activity_type=FOO', status=400) |
|
2539 |
assert resp.json['err_desc'] == "bad activity_type, should be MAT, MIDI, SOIR or GARD" |
|
2540 |
assert resp.json['err'] == 'bad-request' |
|
2541 | ||
2542 | ||
2543 |
def test_clae_booking_activity_possible_days_endpoint_no_result(app, resource, child_activities_data): |
|
2544 |
resp = app.get('/toulouse-axel/test/clae_booking_activity_possible_days?NameID=yyy&idpersonne=3535&booking_date=2020-01-20&activity_type=MAT') |
|
2545 |
assert resp.json['err_desc'] == "Person not found" |
|
2546 |
assert resp.json['err'] == 'not-found' |
|
2547 | ||
2548 |
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42') |
|
2549 |
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/child_activities.xml') |
|
2550 |
with open(filepath) as xml: |
|
2551 |
content = xml.read() |
|
2552 |
with mock_getdata(content, 'EnfantsActivites'): |
|
2553 |
with mock.patch('passerelle.contrib.toulouse_axel.models.reservation_periode') as operation: |
|
2554 |
operation.side_effect = AxelError('FooBar') |
|
2555 |
resp = app.get('/toulouse-axel/test/clae_booking_activity_possible_days?NameID=yyy&idpersonne=4242&booking_date=2020-01-20&activity_type=MAT') |
|
2556 |
assert resp.json['err_desc'] == "Child not found" |
|
2557 |
assert resp.json['err'] == 'not-found' |
|
2558 | ||
2559 |
content = """<PORTAIL> |
|
2560 |
<DUI> |
|
2561 |
<IDDUI>XXX</IDDUI> |
|
2562 |
<ENFANT> |
|
2563 |
<IDPERSONNE>4242</IDPERSONNE> |
|
2564 |
<ACTIVITE> |
|
2565 |
<ANNEEREFERENCE>2019</ANNEEREFERENCE> |
|
2566 |
<IDACTIVITE>A19P1M1</IDACTIVITE> |
|
2567 |
<JOUR>00000</JOUR> |
|
2568 |
</ACTIVITE> |
|
2569 |
</ENFANT> |
|
2570 |
</DUI> |
|
2571 |
</PORTAIL>""" |
|
2572 |
activities = child_activities_data['ENFANT'][0] |
|
2573 |
with mock_getdata(content, 'ReservationPeriode'): |
|
2574 |
with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities', return_value=activities): |
|
2575 |
resp = app.get('/toulouse-axel/test/clae_booking_activity_possible_days?NameID=yyy&idpersonne=3535&booking_date=2020-01-20&activity_type=MAT') |
|
2576 |
assert resp.json['err_desc'] == "Child not found" |
|
2577 |
assert resp.json['err'] == 'not-found' |
|
2578 | ||
2579 |
with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.clae_booking_activities_info') as activities_info: |
|
2580 |
activities_info.return_value = {'data': []} |
|
2581 |
resp = app.get('/toulouse-axel/test/clae_booking_activity_possible_days?NameID=yyy&idpersonne=3535&booking_date=2020-01-20&activity_type=MAT') |
|
2582 |
assert resp.json['err'] == 0 |
|
2583 |
assert resp.json['data'] == [] |
|
2584 | ||
2585 | ||
2586 |
def test_clae_booking_activity_possible_days_endpoint(app, resource, child_activities_data): |
|
2587 |
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42') |
|
2588 |
content = """<PORTAIL> |
|
2589 |
<DUI> |
|
2590 |
<IDDUI>XXX</IDDUI> |
|
2591 |
<ENFANT> |
|
2592 |
<IDPERSONNE>3535</IDPERSONNE> |
|
2593 |
<ACTIVITE> |
|
2594 |
<ANNEEREFERENCE>2019</ANNEEREFERENCE> |
|
2595 |
<IDACTIVITE>A19P1M1</IDACTIVITE> |
|
2596 |
<JOUR>10201</JOUR> |
|
2597 |
</ACTIVITE> |
|
2598 |
</ENFANT> |
|
2599 |
</DUI> |
|
2600 |
</PORTAIL>""" |
|
2601 |
activities = child_activities_data['ENFANT'][0] |
|
2602 |
with mock_getdata(content, 'ReservationPeriode'): |
|
2603 |
with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_child_activities', return_value=activities): |
|
2604 |
resp = app.get('/toulouse-axel/test/clae_booking_activity_possible_days?NameID=yyy&idpersonne=3535&booking_date=2020-01-20&activity_type=MAT') |
|
2605 |
assert resp.json['err'] == 0 |
|
2606 |
assert len(resp.json['data']) == 5 |
|
2607 |
assert set(resp.json['data'][0].keys()) == set(['id', 'text', 'disabled', 'prefill', 'details']) |
|
2608 |
assert resp.json['data'][0]['id'] == '3535-MAT-A19P1M1-monday' |
|
2609 |
assert resp.json['data'][1]['id'] == '3535-MAT-A19P1M1-tuesday' |
|
2610 |
assert resp.json['data'][2]['id'] == '3535-MAT-A19P1M1-wednesday' |
|
2611 |
assert resp.json['data'][3]['id'] == '3535-MAT-A19P1M1-thursday' |
|
2612 |
assert resp.json['data'][4]['id'] == '3535-MAT-A19P1M1-friday' |
|
2613 |
assert resp.json['data'][0]['text'] == 'Monday' |
|
2614 |
assert resp.json['data'][1]['text'] == 'Tuesday' |
|
2615 |
assert resp.json['data'][2]['text'] == 'Wednesday' |
|
2616 |
assert resp.json['data'][3]['text'] == 'Thursday' |
|
2617 |
assert resp.json['data'][4]['text'] == 'Friday' |
|
2618 |
assert resp.json['data'][0]['disabled'] is False |
|
2619 |
assert resp.json['data'][1]['disabled'] is False |
|
2620 |
assert resp.json['data'][2]['disabled'] is True |
|
2621 |
assert resp.json['data'][3]['disabled'] is False |
|
2622 |
assert resp.json['data'][4]['disabled'] is False |
|
2623 |
assert resp.json['data'][0]['prefill'] is True |
|
2624 |
assert resp.json['data'][1]['prefill'] is False |
|
2625 |
assert resp.json['data'][2]['prefill'] is None |
|
2626 |
assert resp.json['data'][3]['prefill'] is False |
|
2627 |
assert resp.json['data'][4]['prefill'] is True |
|
2628 | ||
2629 | ||
2509 | 2630 |
def test_are_children_registered_axel_error(resource): |
2510 | 2631 |
with mock.patch('passerelle.contrib.toulouse_axel.models.enfants_activites') as operation: |
2511 | 2632 |
operation.side_effect = AxelError('FooBar') |
2512 |
- |