From 8df75163cf7137aab5fb336f81504a6b28e3fe3c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Thu, 26 Mar 2020 16:25:51 +0100
Subject: [PATCH] toulouse_axel: add management dates in family info (#41033)

---
 passerelle/contrib/toulouse_axel/models.py | 33 +++++++++---
 tests/test_toulouse_axel.py                | 60 +++++++++++++++++++---
 2 files changed, 77 insertions(+), 16 deletions(-)

diff --git a/passerelle/contrib/toulouse_axel/models.py b/passerelle/contrib/toulouse_axel/models.py
index ac4d7ac0..095e2390 100644
--- a/passerelle/contrib/toulouse_axel/models.py
+++ b/passerelle/contrib/toulouse_axel/models.py
@@ -23,7 +23,7 @@ import re
 import xml.etree.ElementTree as ET
 from collections import namedtuple
 
-
+from django.core.cache import cache
 from django.db import models
 from django.http import HttpResponse
 from django.utils.encoding import force_text
@@ -388,10 +388,12 @@ class ToulouseAxel(BaseResource):
         except Lock.DoesNotExist:
             return {'key': key, 'locked': False}
 
-    @endpoint(
-        description=_("Get dates of the update management"),
-        perm='can_access')
-    def management_dates(self, request):
+    def get_management_dates(self):
+        cache_key = 'toulouse-axel-%s-management-dates' % self.pk
+        result = cache.get(cache_key)
+        if result is not None:
+            return result
+
         try:
             result = ref_date_gestion_dui(self)
         except AxelError as e:
@@ -400,7 +402,19 @@ class ToulouseAxel(BaseResource):
                 err_code='error',
                 data={'xml_request': e.xml_request,
                       'xml_response': e.xml_response})
-        return {'data': result.json_response['DATA']['PORTAIL']['DUIDATEGESTION']}
+        management_dates = {}
+        for key, value in result.json_response['DATA']['PORTAIL']['DUIDATEGESTION'].items():
+            management_dates[key] = value
+            management_dates[key.lower().replace('-', '_')] = value
+
+        cache.set(cache_key, management_dates, 3600)  # 1 hour
+        return management_dates
+
+    @endpoint(
+        description=_("Get dates of the update management"),
+        perm='can_access')
+    def management_dates(self, request):
+        return {'data': self.get_management_dates()}
 
     @endpoint(
         description=_('Create link between user and Toulouse Axel'),
@@ -487,7 +501,7 @@ class ToulouseAxel(BaseResource):
             raise APIError('Referential not found', err_code='not-found', http_status=404)
         return {'data': [{'id': key, 'text': val} for key, val in references.items()]}
 
-    def get_family_data(self, dui, check_registrations=False):
+    def get_family_data(self, dui, check_registrations=False, with_management_dates=False):
         try:
             result = ref_famille_dui(self, {'PORTAIL': {'DUI': {'IDDUI': dui}}})
         except AxelError as e:
@@ -515,6 +529,9 @@ class ToulouseAxel(BaseResource):
                 child['clae_cantine_current'] = children_registred_for_current_year.get(child['IDPERSONNE'])
                 child['clae_cantine_next'] = children_registred_for_next_year.get(child['IDPERSONNE'])
 
+        if with_management_dates:
+            family_data['management_dates'] = self.get_management_dates()
+
         family_data['SITUATIONFAMILIALE_label'] = utils.get_label(utils.situation_familiale_mapping, family_data['SITUATIONFAMILIALE'])
         for key in ['RL1', 'RL2']:
             if key not in family_data:
@@ -543,7 +560,7 @@ class ToulouseAxel(BaseResource):
         })
     def family_info(self, request, NameID):
         link = self.get_link(NameID)
-        family_data = self.get_family_data(link.dui, check_registrations=True)
+        family_data = self.get_family_data(link.dui, check_registrations=True, with_management_dates=True)
         return {'data': family_data}
 
     @endpoint(
diff --git a/tests/test_toulouse_axel.py b/tests/test_toulouse_axel.py
index c88fc783..033930e1 100644
--- a/tests/test_toulouse_axel.py
+++ b/tests/test_toulouse_axel.py
@@ -477,7 +477,34 @@ def test_management_dates_endpoint(app, resource):
         resp = app.get('/toulouse-axel/test/management_dates')
     assert set(resp.json.keys()) == set(['err', 'data'])
     assert resp.json['err'] == 0
-    assert set(resp.json['data'].keys()) == set(['REPORT-REVENUS', 'EXTRACTION-FAMILLES', 'EXTRACTION-CAFPRO'])
+    assert set(resp.json['data'].keys()) == set([
+        'REPORT-REVENUS',
+        'report_revenus',
+        'EXTRACTION-FAMILLES',
+        'extraction_familles',
+        'EXTRACTION-CAFPRO',
+        'extraction_cafpro'
+    ])
+
+    # again - data are in cache
+    resp = app.get('/toulouse-axel/test/management_dates')
+    assert set(resp.json.keys()) == set(['err', 'data'])
+    assert resp.json['err'] == 0
+    assert set(resp.json['data'].keys()) == set([
+        'REPORT-REVENUS',
+        'report_revenus',
+        'EXTRACTION-FAMILLES',
+        'extraction_familles',
+        'EXTRACTION-CAFPRO',
+        'extraction_cafpro'
+    ])
+
+    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_management_dates') as management_dates:
+        management_dates.return_value = {'foo': 'bar'}
+        resp = app.get('/toulouse-axel/test/management_dates')
+    assert set(resp.json.keys()) == set(['err', 'data'])
+    assert resp.json['err'] == 0
+    assert resp.json['data'] == {'foo': 'bar'}
 
 
 def test_link_endpoint_nameid_empty(app, resource, link_params):
@@ -679,7 +706,7 @@ def test_referential_endpoint(app, resource, code, mapping):
     assert resp.json['data'] == expected
 
 
-def test_family_info_endpoint_axel_error(app, resource):
+def test_family_info_endpoint_axel_error(app, resource, family_data):
     Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
     with mock.patch('passerelle.contrib.toulouse_axel.models.ref_famille_dui') as operation:
         operation.side_effect = AxelError('FooBar')
@@ -687,6 +714,15 @@ def test_family_info_endpoint_axel_error(app, resource):
     assert resp.json['err_desc'] == "Axel error: FooBar"
     assert resp.json['err'] == 'error'
 
+    filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/family_info.xml')
+    with open(filepath) as xml:
+        content = xml.read()
+    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_management_dates') as management_dates:
+        management_dates.side_effect = APIError('Axel error: FooBar')
+        with mock_getdata(content, 'RefFamilleDui'):
+            resp = app.get('/toulouse-axel/test/family_info?NameID=yyy')
+    assert resp.json['err_desc'] == "Axel error: FooBar"
+
 
 def test_family_info_endpoint_no_result(app, resource):
     resp = app.get('/toulouse-axel/test/family_info?NameID=yyy')
@@ -699,8 +735,10 @@ def test_family_info_endpoint(app, resource):
     filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/family_info.xml')
     with open(filepath) as xml:
         content = xml.read()
-    with mock_getdata(content, 'RefFamilleDui'):
-        resp = app.get('/toulouse-axel/test/family_info?NameID=yyy')
+    with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_management_dates') as management_dates:
+        management_dates.return_value = {'foo': 'bar'}
+        with mock_getdata(content, 'RefFamilleDui'):
+            resp = app.get('/toulouse-axel/test/family_info?NameID=yyy')
     assert resp.json['err'] == 0
     assert set(resp.json['data'].keys()) == set([
         'ADRESSE',
@@ -717,6 +755,7 @@ def test_family_info_endpoint(app, resource):
         'SITUATIONFAMILIALE',
         'SITUATIONFAMILIALE_label',
         'TELFIXE',
+        'management_dates',
     ])
     assert resp.json['data']['ENFANT'][0]['id'] == '4242'
     assert resp.json['data']['ENFANT'][0]['text'] == 'foo foo'
@@ -728,11 +767,14 @@ def test_family_info_endpoint(app, resource):
     assert resp.json['data']['ENFANT'][0]['CONTACT'][2]['text'] == 'foo foo'
     assert resp.json['data']['ENFANT'][1]['id'] == '3535'
     assert resp.json['data']['ENFANT'][1]['text'] == 'foo foo'
+    assert resp.json['data']['management_dates'] == {'foo': 'bar'}
 
     with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.are_children_registered') as registered:
         registered.side_effect = [{'4242': True}, {}]
-        with mock_getdata(content, 'RefFamilleDui'):
-            resp = app.get('/toulouse-axel/test/family_info?NameID=yyy')
+        with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_management_dates') as management_dates:
+            management_dates.return_value = {'foo': 'bar'}
+            with mock_getdata(content, 'RefFamilleDui'):
+                resp = app.get('/toulouse-axel/test/family_info?NameID=yyy')
     assert resp.json['err'] == 0
     assert resp.json['data']['ENFANT'][0]['clae_cantine_current'] is True
     assert resp.json['data']['ENFANT'][0]['clae_cantine_next'] is None
@@ -741,8 +783,10 @@ def test_family_info_endpoint(app, resource):
 
     with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.are_children_registered') as registered:
         registered.side_effect = [{}, {'4242': False, '3535': True}]
-        with mock_getdata(content, 'RefFamilleDui'):
-            resp = app.get('/toulouse-axel/test/family_info?NameID=yyy')
+        with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_management_dates') as management_dates:
+            management_dates.return_value = {'foo': 'bar'}
+            with mock_getdata(content, 'RefFamilleDui'):
+                resp = app.get('/toulouse-axel/test/family_info?NameID=yyy')
     assert resp.json['err'] == 0
     assert resp.json['data']['ENFANT'][0]['clae_cantine_current'] is None
     assert resp.json['data']['ENFANT'][0]['clae_cantine_next'] is False
-- 
2.20.1

