toulouse-maelis: désactiver le cache sur le catalogue général des activités (#75652) #156

Merged
nroche merged 5 commits from wip/75652-bypass-cache-on-activity-catalog into main 2023-03-29 18:20:21 +02:00
2 changed files with 91 additions and 33 deletions

View File

@ -28,6 +28,7 @@ from django.utils import dateformat
from django.utils.dateparse import parse_date
from django.utils.text import slugify
from django.utils.timezone import now
from requests import RequestException
from zeep.helpers import serialize_object
from zeep.wsse.username import UsernameToken
@ -110,7 +111,7 @@ class ToulouseMaelis(BaseResource, HTTPResource):
assert self.call('Site', 'isWSRunning')
assert self.call('Ape', 'isWSRunning')
def update_referential(self, referential_name, data, id_key, text_key):
def update_referential(self, referential_name, data, id_key, text_key, delete=True):
last_update = now()
for item in data or []:
text = item[text_key] or ''
@ -128,7 +129,9 @@ class ToulouseMaelis(BaseResource, HTTPResource):
'updated': last_update,
},
)
self.referential.filter(referential_name=referential_name, updated__lt=last_update).delete()
if delete:
# delete extraneous items
self.referential.filter(referential_name=referential_name, updated__lt=last_update).delete()
def get_referential_data(self, service_name, referential_name):
try:
@ -186,6 +189,15 @@ class ToulouseMaelis(BaseResource, HTTPResource):
id_key, text_key = 'schoolYear', 'schoolYear'
self.update_referential(referential_name, data, id_key, text_key)
def get_activity_catalog_raw(self, year):
return self.call(
'Activity',
'readActivityList',
schoolyear=year,
dateStartCalend='%s-09-01' % year,
dateEndCalend='%s-08-31' % (year + 1),
)
def update_activity_referentials(self):
for referential_name in ('ActivityNatureType',):
id_key, text_key = 'code', 'libelle'
@ -195,19 +207,12 @@ class ToulouseMaelis(BaseResource, HTTPResource):
# put activity catalog per year as referential
data = []
reference_year = utils.get_reference_year_from_date(datetime.date.today())
for year in range(reference_year, reference_year + 1):
response = self.call(
'Activity',
'readActivityList',
schoolyear=year,
dateStartCalend='%s-09-01' % year,
dateEndCalend='%s-09-01' % (year + 1),
)
for year in range(reference_year, reference_year + 2):
data.append(
{
'id': str(year),
'text': '%s-%s' % (year, year + 1),
'data': response,
'data': self.get_activity_catalog_raw(year),
}
)
self.update_referential('ActivityCatalog', data, 'id', 'text')
@ -2388,6 +2393,22 @@ class ToulouseMaelis(BaseResource, HTTPResource):
day_names = ['Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi', 'Dimanche']
all_criterias = {key: {'text': value, 'data': {}} for key, value in labels.items()}
criterias = {key: {'text': value, 'data': {}} for key, value in labels.items()}
# do not use cache, except on timeout
try:
response = self.get_activity_catalog_raw(reference_year)
except RequestException:
pass
else:
data = [
{
'id': str(reference_year),
'text': '%s-%s' % (reference_year, reference_year + 1),
'data': response,
}
]
self.update_referential('ActivityCatalog', data, 'id', 'text', delete=False)
catalogs = self.get_referential('ActivityCatalog', id=reference_year)
activities = catalogs[0]['data'] if catalogs else []

View File

@ -23,12 +23,12 @@ import pytest
import responses
from django.db import transaction
from django.utils.dateparse import parse_date
from requests.exceptions import ConnectionError
from requests.exceptions import ConnectionError, ReadTimeout
from zeep import Settings
from zeep.helpers import serialize_object
from passerelle.contrib.toulouse_maelis.models import Link, Referential, ToulouseMaelis
from passerelle.contrib.toulouse_maelis.utils import get_public_criterias, json_date_format
from passerelle.contrib.toulouse_maelis.utils import get_public_criterias
from passerelle.utils.jsonresponse import APIError
from passerelle.utils.soap import SOAPError
from passerelle.utils.templates import render_to_string
@ -499,6 +499,10 @@ def test_cron(db):
'YearSchool',
]
assert [
(x.item_id, x.item_text) for x in Referential.objects.filter(referential_name='ActivityCatalog').all()
] == [('2022', '2022-2023'), ('2023', '2023-2024')]
def test_link(family_service, con, app):
def request_check(request):
@ -5247,15 +5251,13 @@ def test_get_public_criterias(start_dob, end_dob, expected):
assert expected == [x[1] for x in result]
def test_read_activity_list(con, app, freezer):
freezer.move_to('2023-01-01 12:00')
def test_read_activity_list(activity_service, con, app):
activity_service.add_soap_response('readActivityList', get_xml_file('R_read_activity_list.xml'))
url = get_endpoint('read-activity-list')
con.loisir_nature_codes = '4,L,, S '
con.save()
params = {
'ref_date': datetime.date.today().strftime(json_date_format),
}
params = {'ref_date': '2023-01-01'}
resp = app.get(url, params=params)
assert resp.json['err'] == 0
assert len(resp.json['data']) == 4
@ -5299,21 +5301,10 @@ def test_read_activity_list(con, app, freezer):
resp = app.get(url, params=params)
assert resp.json['err'] == 0
assert len(resp.json['data']) == 0
con.loisir_nature_codes = '4,L,, S '
con.save()
resp = app.get(url, params=params)
assert resp.json['err'] == 0
assert len(resp.json['data']) == 4
params['ref_date'] = '1970-01-01'
resp = app.get(url, params=params)
assert resp.json['err'] == 0
assert len(resp.json['data']) == 0
assert resp.json == {
'data': [],
'meta': {
'reference_year': 1969,
'reference_year': 2022,
'all_criterias': {
'nature': {'text': "Nature de l'activité", 'data': {}, 'order': []},
'type': {'text': "Type de l'activité", 'data': {}, 'order': []},
@ -5326,10 +5317,56 @@ def test_read_activity_list(con, app, freezer):
}
def test_read_activity_list_no_nature(con, app, freezer):
freezer.move_to('2023-01-01 12:00')
@mock.patch('passerelle.utils.Request.get')
def test_read_activity_list_cache(mocked_get, con, app):
mocked_get.return_value = ACTIVITY_SERVICE_WSDL
url = get_endpoint('read-activity-list')
params = {'ref_date': datetime.date.today().strftime(json_date_format)}
params = {'ref_date': '1970-01-01'}
assert [x.item_id for x in Referential.objects.filter(referential_name='ActivityCatalog')] == [
'2022',
'2023',
]
with mock.patch('passerelle.utils.Request.post') as mocked_post:
mocked_post.side_effect = ReadTimeout('timeout')
resp = app.get(url, params=params)
assert resp.json['err'] == 0
assert len(resp.json['data']) == 0
assert [x.item_id for x in Referential.objects.filter(referential_name='ActivityCatalog')] == [
'2022',
'2023',
]
with mock.patch('passerelle.utils.Request.post') as mocked_post:
mocked_post.return_value = FakedResponse(
content=get_xml_file('R_read_activity_list.xml'), status_code=200
)
resp = app.get(url, params=params)
assert resp.json['err'] == 0
assert len(resp.json['data']) == 4
assert [x.item_id for x in Referential.objects.filter(referential_name='ActivityCatalog')] == [
'1969',
'2022',
'2023',
]
with mock.patch('passerelle.utils.Request.post') as mocked_post:
mocked_post.side_effect = ReadTimeout('timeout')
resp = app.get(url, params=params)
assert resp.json['err'] == 0
assert len(resp.json['data']) == 4
@mock.patch('passerelle.utils.Request.get')
@mock.patch('passerelle.utils.Request.post')
def test_read_activity_list_no_nature(mocked_post, mocked_get, con, app):
mocked_get.return_value = ACTIVITY_SERVICE_WSDL
mocked_post.side_effect = ReadTimeout('timeout')
url = get_endpoint('read-activity-list')
params = {'ref_date': '2023-01-01'}
# Empty activity type return by referential
def mocked_reply(referential_name, id=None):