solis: add referential endpoint (#21481)

This commit is contained in:
Thomas NOËL 2018-02-06 08:38:14 +01:00
parent ba0bdaa80a
commit 44cfbe918e
2 changed files with 132 additions and 0 deletions

View File

@ -15,16 +15,34 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import json
import re
import unicodedata
from django.db import models
from django.template.loader import get_template
from django.utils.translation import ugettext_lazy as _
from django.utils.http import urlencode
from passerelle.base.models import BaseResource
from passerelle.utils.api import endpoint
from passerelle.utils.jsonresponse import APIError
def simplify(s):
'''
Simplify a string, trying to transform it to lower ascii chars (a-z, 0-9)
and minimize spaces. Used to compare strings on ?q=something requests.
'''
if not s:
return ''
if not isinstance(s, unicode):
s = unicode(s, 'utf-8', 'ignore')
s = unicodedata.normalize('NFKD', s).encode('ascii', 'ignore')
s = re.sub(r'[^\w\s\'-]', '', s)
s = re.sub(r'[\s\'_-]+', ' ', s)
return s.strip().lower()
def keystore_upload_to(instance, filename):
return '%s/%s/keystore/%s' % (instance.get_connector_slug(), instance.id, filename)
@ -253,6 +271,63 @@ class Solis(BaseResource):
'information': information})
return {'data': users}
@endpoint(name='referential', perm='can_access',
pattern=r'^(?P<module>[\w-]+)/(?P<name>[\w-]+)/$',
example_pattern='{module}/{name}/',
description=_('Get class/name references'),
parameters={
'module': {'description': _('Referential module: asg, civi, trans'),
'example_value': 'trans'},
'name': {'description': _('Referential name in this module'),
'example_value': 'lieu'},
'codePays': {'example_value': '79'},
'codeDepartement': {'example_value': '80'},
'codeCommune': {'example_value': '21'},
'q': {'description': _('Returns only items whose text matches'),
'example_value': 'claudel'},
'ignore': {'description': _('Do not return items with this id, '
'or multiple ids separated with commas'),
'example_value': '9999'},
})
def referential(self, request, module, name, q=None, ignore=None, **kwargs):
endpoint = 'referentiels/%s/%s' % (module, name)
args = [(code, value) for code, value in kwargs.items() if code.startswith('code')]
if args:
endpoint += '?' + urlencode(args)
content = self.get_json(endpoint)
if (not isinstance(content, dict) or len(content) != 1 or
not isinstance(content.values()[0], list)):
raise APIError('response is not a dictionnary with only one key '
'and whose value is a list', data={'json_content': content})
items = content.values()[0]
if not all(isinstance(item, dict) and item.get('code') for item in items):
raise APIError('items must be dictionnaries with a "code" key',
data={'json_content': content})
for item in items:
item['id'] = item['code']
item['text'] = item.get('libelle', item['id'])
if ignore:
ignore_ids = [ignore_id.strip() for ignore_id in ignore.split(',')
if ignore_id.strip()]
if q:
q = simplify(q)
def condition(item):
if ignore and item['id'] in ignore_ids:
return False
if q and q not in simplify(item['text']):
return False
return True
items = filter(condition, items)
return {'data': items}
class SolisAPALink(models.Model):
resource = models.ForeignKey(Solis)

View File

@ -23,6 +23,7 @@ APAINFOS = {
'propositionPlanAide': '{"demandeAsg":[{"demande":{"type":"Allocation Personnalis\\u00e9e Autonomie","indexDemande":42,"nature":"Domicile"},"droit":{"dateDebut":"2016-08-23","dateFin":"2018-08-31"},"planAide":{"commentaire":"","prestationsPlanAide":{"prestationPlanAide":[{"tiers":{"tarif":12.8,"identite":"CCAS DE MERS LES BAINS","quantitatif":"Heure(s)","type":"Prestataire"},"quantite":84,"montant":1075.2,"prestation":"Aide humaine mandataire"},{"tiers":{"tarif":90,"identite":null,"quantitatif":"Mois","type":"Ind\\u00e9termin\\u00e9"},"quantite":1,"montant":90,"prestation":"Articles d\'hygi\\u00e8ne forfait 90"}]},"dateReponse":null,"datePropositionPlan":null,"avis":""},"complementDossier":{"dateDepot":"2016-06-22"},"suivi":{"dateDecision":"2016-08-23"}}]}',
}
APAREQUEST = '{"demandeAsg":{"visite":{"date":"2016-07-07","heure":"1330"},"demande":{"type":"Allocation Personnalis\\u00e9e Autonomie","indexDemande":42,"nature":"Domicile"},"droit":{"dateDebut":"2016-08-23","dateFin":"2018-08-31"},"complementDossier":{"dateArrivee":"2016-06-22","dateDossierComplet":"2016-06-22"},"suivi":{"dateDecision":"2016-08-23","decision":"Accord"}}}'
DEPARTEMENTS = '{"departements":[{"code":"1","libelle":"Ain","pays":{"code":"79","libelle":"France"}},{"code":"2","libelle":"Aisne","pays":{"code":"79","libelle":"France"}},{"code":"3","libelle":"Allier","pays":{"code":"79","libelle":"France"}},{"code":"4","libelle":"Alpes de Haute Provence","pays":{"code":"79","libelle":"France"}},{"code":"5","libelle":"Hautes Alpes","pays":{"code":"79","libelle":"France"}},{"code":"6","libelle":"Alpes Maritimes","pays":{"code":"79","libelle":"France"}},{"code":"7","libelle":"Ardèche","pays":{"code":"79","libelle":"France"}},{"code":"8","libelle":"Ardennes","pays":{"code":"79","libelle":"France"}}]}'
@pytest.fixture
@ -393,3 +394,59 @@ def test_solis_link_infos_unlink(app, solis):
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'unknown link'
assert resp.json['data'] is None
def test_solis_referentiels(app, solis):
# full opened access
api = ApiUser.objects.create(username='all', keytype='', key='')
obj_type = ContentType.objects.get_for_model(solis)
AccessRight.objects.create(codename='can_access', apiuser=api, resource_type=obj_type,
resource_pk=solis.pk)
with mock.patch('passerelle.utils.Request.get') as requests_get:
requests_get.return_value = utils.FakedResponse(content=DEPARTEMENTS, status_code=200)
url = utils.generic_endpoint_url('solis', 'referential', slug=solis.slug)
resp = app.get(url + '/trans/departement/', status=200)
assert requests_get.call_count == 1
assert requests_get.call_args[0][0].endswith('/solisapi/referentiels/trans/departement')
assert resp.json['err'] == 0
assert len(resp.json['data']) == 8
resp = app.get(url + '/trans/departement/?q=ardeche', status=200)
assert requests_get.call_args[0][0].endswith('/solisapi/referentiels/trans/departement')
assert resp.json['err'] == 0
assert len(resp.json['data']) == 1
assert resp.json['data'][0]['text'] == u'Ardèche'
resp = app.get(url + '/trans/departement/?q=arde', status=200)
assert resp.json['err'] == 0
assert len(resp.json['data']) == 2
assert (resp.json['data'][0]['text'], resp.json['data'][1]['text']) == (u'Ardèche', 'Ardennes')
resp = app.get(url + '/trans/departement/?q=arde&ignore=8', status=200)
assert resp.json['err'] == 0
assert len(resp.json['data']) == 1
assert resp.json['data'][0]['text'] == u'Ardèche'
resp = app.get(url + '/trans/departement/?q=arde&ignore=8,, 7', status=200)
assert resp.json['err'] == 0
assert len(resp.json['data']) == 0
resp = app.get(url + '/trans/departement/?codePays=79&foo=bar', status=200)
assert requests_get.call_args[0][0].endswith('/solisapi/referentiels/trans/departement?codePays=79')
requests_get.return_value = utils.FakedResponse(content='{"nada":0}', status_code=404,
reason='Not found')
resp = app.get(url + '/foo/bar/', status=200)
assert requests_get.call_args[0][0].endswith('/solisapi/referentiels/foo/bar')
assert resp.json['err'] == 1
assert resp.json['err_desc'] == "error status:404 'Not found', content:'{\"nada\":0}'"
assert resp.json['data'] == {'json_content': {'nada': 0}, 'status_code': 404}
requests_get.return_value = utils.FakedResponse(content='crash', status_code=500, reason='boum')
resp = app.get(url + '/foo/bar/', status=200)
assert requests_get.call_args[0][0].endswith('/solisapi/referentiels/foo/bar')
assert resp.json['err'] == 1
assert resp.json['err_desc'] == "error status:500 'boum', content:'crash'"
assert resp.json['data'] == {'json_content': None, 'status_code': 500}