atal: use the right soap methods (#34175)
This commit is contained in:
parent
223dcd7e5e
commit
caf4899f99
|
@ -1,5 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# passerelle - uniform access to multiple data sources and services
|
||||
# Copyright (C) 2019 Entr'ouvert
|
||||
#
|
||||
|
@ -16,74 +14,25 @@
|
|||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import base64
|
||||
|
||||
from django.db import models
|
||||
from django.utils.six.moves import urllib
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
import lxml.etree
|
||||
from zeep import helpers
|
||||
from zeep.exceptions import Fault
|
||||
|
||||
from passerelle.base.models import BaseResource
|
||||
from passerelle.utils.api import endpoint
|
||||
from passerelle.utils.jsonresponse import APIError
|
||||
from . import schemas
|
||||
|
||||
|
||||
INSERT_DEMANDE_BY_TYPE_SCHEMA = {
|
||||
"$schema": "http://json-schema.org/draft-03/schema#",
|
||||
"title": "",
|
||||
"description": "",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"contact_nom": {
|
||||
"description": "Nom du contact",
|
||||
"required": True
|
||||
},
|
||||
"contact_tel": {
|
||||
"description": "Téléphone du contact",
|
||||
"type": "string",
|
||||
},
|
||||
"contact_email": {
|
||||
"description": "Email du contact",
|
||||
"type": "string",
|
||||
},
|
||||
"contact_adresse": {
|
||||
"description": "Adresse du contact",
|
||||
"type": "string",
|
||||
},
|
||||
"demande_objet": {
|
||||
"description": "Objet de la demande",
|
||||
"type": "string",
|
||||
},
|
||||
"demande_lieu": {
|
||||
"description": "Lieu de la demande",
|
||||
"type": "string",
|
||||
},
|
||||
"demande_description": {
|
||||
"description": "Description de la demande",
|
||||
"type": "string",
|
||||
},
|
||||
"remote_adresse": {
|
||||
"description": "",
|
||||
"type": "string"
|
||||
},
|
||||
"code_equipement": {
|
||||
"description": "Code de l'équipement",
|
||||
"type": "string"
|
||||
},
|
||||
"code_service_demandeur": {
|
||||
"description": "Code du service demandeur",
|
||||
"type": "string"
|
||||
},
|
||||
"date_souhaite": {
|
||||
"description": "Date souhaitée",
|
||||
"type": "string"
|
||||
},
|
||||
"type_demande": {
|
||||
"description": "Type demande",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
def process_response(demande_number):
|
||||
if not demande_number.startswith('DIT'):
|
||||
raise APIError(demande_number)
|
||||
return {'data': {'demande_number': demande_number}}
|
||||
|
||||
|
||||
class ATALConnector(BaseResource):
|
||||
|
@ -98,7 +47,10 @@ class ATALConnector(BaseResource):
|
|||
def _soap_call(self, wsdl, method, **kwargs):
|
||||
wsdl_url = urllib.parse.urljoin(self.base_soap_url, '%s?wsdl' % wsdl)
|
||||
client = self.soap_client(wsdl_url=wsdl_url)
|
||||
return getattr(client.service, method)(**kwargs)
|
||||
try:
|
||||
return getattr(client.service, method)(**kwargs)
|
||||
except Fault as e:
|
||||
raise APIError(unicode(e))
|
||||
|
||||
def _basic_ref(self, wsdl, method):
|
||||
soap_res = self._soap_call(wsdl=wsdl, method=method)
|
||||
|
@ -107,15 +59,15 @@ class ATALConnector(BaseResource):
|
|||
res.append({'id': elem.code, 'text': elem.libelle})
|
||||
return {'data': res}
|
||||
|
||||
@endpoint(methods=['get'], perm='can_access')
|
||||
@endpoint(methods=['get'], perm='can_access', name='get-type-activite')
|
||||
def get_type_activite(self, request):
|
||||
return self._basic_ref('VilleAgileService', 'getTypeActivite')
|
||||
|
||||
@endpoint(methods=['get'], perm='can_access')
|
||||
@endpoint(methods=['get'], perm='can_access', name='get-type-de-voie')
|
||||
def get_type_de_voie(self, request):
|
||||
return self._basic_ref('VilleAgileService', 'getTypeDeVoie')
|
||||
|
||||
@endpoint(methods=['get'], perm='can_access')
|
||||
@endpoint(methods=['get'], perm='can_access', name='get-types-equipement')
|
||||
def get_types_equipement(self, request):
|
||||
soap_res = self._soap_call(wsdl='VilleAgileService', method='getTypesEquipement')
|
||||
tree = lxml.etree.fromstring(soap_res.encode('utf-8')).getroottree()
|
||||
|
@ -126,44 +78,124 @@ class ATALConnector(BaseResource):
|
|||
return {'data': res}
|
||||
|
||||
@endpoint(
|
||||
perm='can_access',
|
||||
perm='can_access', name='insert-action-comment',
|
||||
post={
|
||||
'description': _('Insert Demande By Type'),
|
||||
'description': 'Insert action comment',
|
||||
'request_body': {
|
||||
'schema': {
|
||||
'application/json': INSERT_DEMANDE_BY_TYPE_SCHEMA
|
||||
'application/json': schemas.INSERT_ACTION_COMMENT
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
def insert_demande_by_type(self, request, post_data):
|
||||
def insert_action_comment(self, request, post_data):
|
||||
demande_number = self._soap_call(
|
||||
wsdl='DemandeService', method='insertDemandeByType',
|
||||
contactNom=post_data['contact_nom'],
|
||||
contactTelephone=post_data['contact_telephone'],
|
||||
contactCourriel=post_data['contact_email'],
|
||||
contactAdresse=post_data['contact_adresse'], demandeObjet=post_data['demande_objet'],
|
||||
demandeLieu=post_data['demande_lieu'],
|
||||
demandeDescription=post_data['demande_description'],
|
||||
remoteAddress=post_data['remote_adresse'], codeEquipement=post_data['code_equipement'],
|
||||
codeServiceDemandeur=post_data['code_service_demandeur'],
|
||||
dateSouhaitee=post_data['date_souhaite'], typeDemande=post_data['type_demande']
|
||||
wsdl='DemandeService', method='insertActionComment',
|
||||
numeroDemande=post_data['numero_demande'],
|
||||
commentaire=post_data['commentaire']
|
||||
)
|
||||
return {'data': {'demande_number': demande_number}}
|
||||
return process_response(demande_number)
|
||||
|
||||
@endpoint(
|
||||
perm='can_access', name='insert-demande-complet-by-type',
|
||||
post={
|
||||
'description': 'Insert demande complet by type',
|
||||
'request_body': {
|
||||
'schema': {
|
||||
'application/json': schemas.INSERT_DEMANDE_COMPLET_BY_TYPE
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
def insert_demande_complet_by_type(self, request, post_data):
|
||||
data = {}
|
||||
for recv, send in [
|
||||
('type_demande', 'typeDemande'),
|
||||
('code_service_demandeur', 'codeServiceDemandeur'),
|
||||
('date_saisie', 'dateSaisie'),
|
||||
('date_demande', 'dateDemande'),
|
||||
('date_souhaite', 'dateSouhaitee'),
|
||||
('date_butoir', 'dateButoir'),
|
||||
('contact_civilite', 'contactCivilite'),
|
||||
('contact_nom', 'contactNom'),
|
||||
('contact_prenom', 'contactPrenom'),
|
||||
('contact_tel', 'contactTelephone'),
|
||||
('contact_mobile', 'contactMobile'),
|
||||
('contact_email', 'contactCourriel'),
|
||||
('contact_info_compl', 'contactInfoCompl'),
|
||||
('demande_type_support', 'demandeTypeDeSupport'),
|
||||
('contact_adresse', 'contactAdresse'),
|
||||
('contact_adresse_compl', 'contactAdresseCompl'),
|
||||
('contact_code_postal', 'contactCodePostal'),
|
||||
('contact_ville', 'contactVille'),
|
||||
('contact_organisme', 'contactOrganisme'),
|
||||
('contact_titre', 'contactTitre'),
|
||||
('code_equipement', 'codeEquipement'),
|
||||
('code_mairie_equipement', 'codeMairieEquipement'),
|
||||
('code_sig_equipement', 'codeSIGEquipement'),
|
||||
('code_collectivite_equipement', 'codeCollectiviteEquipement'),
|
||||
('code_quartier_equipement', 'codeQuartierEquipement'),
|
||||
('code_type_equipement', 'codeTypeEquipement'),
|
||||
('demande_lieu', 'demandeLieu'),
|
||||
('coord_x', 'coordX'),
|
||||
('coord_y', 'coordY'),
|
||||
('demande_priorite', 'demandePriorite'),
|
||||
('demande_objet', 'demandeObjet'),
|
||||
('demande_description', 'demandeDescription'),
|
||||
('demande_commentaire', 'demandeCommentaire'),
|
||||
('demande_mots_cles', 'demandeMotsCles'),
|
||||
('code_thematique', 'codeThematiqueATAL'),
|
||||
('code_priorite', 'codePrioriteATAL'),
|
||||
('demande_thematique', 'demandeThematique'),
|
||||
('code_projet', 'codeProjetATAL'),
|
||||
]:
|
||||
if recv in post_data:
|
||||
data[send] = post_data[recv]
|
||||
|
||||
demande_number = self._soap_call(
|
||||
wsdl='DemandeService', method='insertDemandeCompletByType', **data
|
||||
)
|
||||
return process_response(demande_number)
|
||||
|
||||
@endpoint(
|
||||
methods=['get'], perm='can_access', example_pattern='{demande_number}/',
|
||||
pattern='^(?P<demande_number>\w+)/$',
|
||||
pattern='^(?P<demande_number>\w+)/$', name='retrieve-etat-travaux',
|
||||
parameters={
|
||||
'demande_number': {
|
||||
'description': _('Demande number'), 'example_value': 'DIT18050001'
|
||||
}
|
||||
}
|
||||
)
|
||||
def retrieve_details_demande(self, request, demande_number, **kwargs):
|
||||
if not demande_number:
|
||||
raise APIError('A demande_number parameter must be specified')
|
||||
def retrieve_etat_travaux(self, request, demande_number):
|
||||
soap_res = self._soap_call(
|
||||
wsdl='DemandeService', method='retrieveDetailsDemande',
|
||||
demandeNumberParam=demande_number)
|
||||
wsdl='DemandeService', method='retrieveEtatTravaux',
|
||||
numero=demande_number)
|
||||
return {'data': helpers.serialize_object(soap_res)}
|
||||
|
||||
@endpoint(
|
||||
perm='can_access',
|
||||
post={
|
||||
'description': 'Upload a file',
|
||||
'request_body': {
|
||||
'schema': {
|
||||
'application/json': schemas.UPLOAD
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
def upload(self, request, post_data):
|
||||
try:
|
||||
content = base64.b64decode(post_data['file']['content'])
|
||||
except TypeError:
|
||||
raise APIError('Invalid base64 string')
|
||||
|
||||
data = {
|
||||
'donneesFichier': content,
|
||||
'numeroDemande': post_data['numero_demande'],
|
||||
'nomFichier': post_data['nom_fichier']
|
||||
}
|
||||
self._soap_call(
|
||||
wsdl='ChargementPiecesJointesService', method='upload',
|
||||
**data
|
||||
)
|
||||
return {}
|
||||
|
|
|
@ -0,0 +1,189 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# passerelle - uniform access to multiple data sources and services
|
||||
# Copyright (C) 2019 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
INSERT_DEMANDE_COMPLET_BY_TYPE = {
|
||||
'$schema': 'http://json-schema.org/draft-03/schema#',
|
||||
'type': 'object',
|
||||
'additionalProperties': False,
|
||||
'properties': {
|
||||
'type_demande': {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
},
|
||||
'code_service_demandeur': {
|
||||
'type': 'string',
|
||||
},
|
||||
'date_saisie': {
|
||||
'type': 'string',
|
||||
},
|
||||
'date_demande': {
|
||||
'type': 'string',
|
||||
},
|
||||
'date_souhaite': {
|
||||
'type': 'string',
|
||||
},
|
||||
'date_butoir': {
|
||||
'type': 'string',
|
||||
},
|
||||
'contact_civilite': {
|
||||
'type': 'string',
|
||||
},
|
||||
'contact_nom': {
|
||||
'type': 'string',
|
||||
},
|
||||
'contact_prenom': {
|
||||
'type': 'string',
|
||||
},
|
||||
'contact_tel': {
|
||||
'type': 'string',
|
||||
},
|
||||
'contact_mobile': {
|
||||
'type': 'string',
|
||||
},
|
||||
'contact_email': {
|
||||
'type': 'string',
|
||||
},
|
||||
'contact_info_compl': {
|
||||
'type': 'string',
|
||||
},
|
||||
'demande_type_support': {
|
||||
'type': 'string',
|
||||
},
|
||||
'contact_adresse': {
|
||||
'type': 'string',
|
||||
},
|
||||
'contact_adresse_compl': {
|
||||
'type': 'string',
|
||||
},
|
||||
'contact_code_postal': {
|
||||
'type': 'string',
|
||||
},
|
||||
'contact_ville': {
|
||||
'type': 'string',
|
||||
},
|
||||
'contact_organisme': {
|
||||
'type': 'string',
|
||||
},
|
||||
'contact_titre': {
|
||||
'type': 'string',
|
||||
},
|
||||
'code_equipement': {
|
||||
'type': 'string',
|
||||
},
|
||||
'code_mairie_equipement': {
|
||||
'type': 'string',
|
||||
},
|
||||
'code_sig_equipement': {
|
||||
'type': 'string',
|
||||
},
|
||||
'code_collectivite_equipement': {
|
||||
'type': 'string',
|
||||
},
|
||||
'code_quartier_equipement': {
|
||||
'type': 'string',
|
||||
},
|
||||
'code_type_equipement': {
|
||||
'type': 'string',
|
||||
},
|
||||
'demande_lieu': {
|
||||
'type': 'string',
|
||||
},
|
||||
'coord_x': {
|
||||
'type': 'string',
|
||||
},
|
||||
'coord_y': {
|
||||
'type': 'string',
|
||||
},
|
||||
'demande_priorite': {
|
||||
'type': 'string',
|
||||
},
|
||||
'demande_objet': {
|
||||
'type': 'string',
|
||||
},
|
||||
'demande_description': {
|
||||
'type': 'string',
|
||||
},
|
||||
'demande_commentaire': {
|
||||
'type': 'string',
|
||||
},
|
||||
'remote_adresse': {
|
||||
'type': 'string'
|
||||
},
|
||||
'demande_mots_cles': {
|
||||
'type': 'string'
|
||||
},
|
||||
'code_thematique': {
|
||||
'type': 'string',
|
||||
},
|
||||
'code_priorite': {
|
||||
'type': 'string'
|
||||
},
|
||||
'demande_thematique': {
|
||||
'type': 'string'
|
||||
},
|
||||
'code_projet': {
|
||||
'type': 'string'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INSERT_ACTION_COMMENT = {
|
||||
'$schema': 'http://json-schema.org/draft-03/schema#',
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'numero_demande': {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
},
|
||||
'commentaire': {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UPLOAD = {
|
||||
'$schema': 'http://json-schema.org/draft-03/schema#',
|
||||
'definitions': {
|
||||
'file': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'content': {
|
||||
'type': 'string',
|
||||
'required': True
|
||||
},
|
||||
},
|
||||
'required': True
|
||||
}
|
||||
},
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'file': {
|
||||
'$ref': '#/definitions/file'
|
||||
},
|
||||
'numero_demande': {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
},
|
||||
'nom_fichier': {
|
||||
'type': 'string',
|
||||
'required': True,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
import base64
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
import mock
|
||||
import pytest
|
||||
|
@ -42,7 +44,7 @@ REFS = [
|
|||
|
||||
def test_get_type_activite(app, connector, monkeypatch):
|
||||
mock_soap_call = mock_atal_soap_call(monkeypatch, return_value=REFS)
|
||||
response = app.get('/atal/slug-atal/get_type_activite')
|
||||
response = app.get('/atal/slug-atal/get-type-activite')
|
||||
assert response.json == {
|
||||
'err': 0,
|
||||
'data': [
|
||||
|
@ -56,7 +58,7 @@ def test_get_type_activite(app, connector, monkeypatch):
|
|||
|
||||
def test_get_type_de_voie(app, connector, monkeypatch):
|
||||
mock_soap_call = mock_atal_soap_call(monkeypatch, return_value=REFS)
|
||||
response = app.get('/atal/slug-atal/get_type_de_voie')
|
||||
response = app.get('/atal/slug-atal/get-type-de-voie')
|
||||
assert response.json == {
|
||||
'err': 0,
|
||||
'data': [
|
||||
|
@ -77,7 +79,7 @@ def test_get_types_equipement(app, connector, monkeypatch):
|
|||
</types>
|
||||
"""
|
||||
mock_soap_call = mock_atal_soap_call(monkeypatch, return_value=return_value)
|
||||
response = app.get('/atal/slug-atal/get_types_equipement')
|
||||
response = app.get('/atal/slug-atal/get-types-equipement')
|
||||
assert response.json == {
|
||||
'err': 0,
|
||||
'data': [
|
||||
|
@ -89,53 +91,57 @@ def test_get_types_equipement(app, connector, monkeypatch):
|
|||
assert call_params['method'] == 'getTypesEquipement'
|
||||
|
||||
|
||||
def test_insert_demande_by_type(app, connector, monkeypatch):
|
||||
def test_insert_demande_complet_by_type(app, connector, monkeypatch):
|
||||
mock_soap_call = mock_atal_soap_call(monkeypatch, return_value='DIT19050001')
|
||||
params = {
|
||||
'contact_nom': 'John Doe',
|
||||
'contact_telephone': '0101010101',
|
||||
'contact_email': 'john@doe.com',
|
||||
'contact_adresse': '1 doe street',
|
||||
'demande_objet': 'sarah connor',
|
||||
'demande_lieu': 'LA',
|
||||
'demande_description': 'poker face',
|
||||
'remote_adresse': 'hollywood bd',
|
||||
'code_equipement': 'MAC10',
|
||||
'code_service_demandeur': 'skynet',
|
||||
'date_souhaite': 'now',
|
||||
'type_demande': 'scary'
|
||||
'numero_demande': 'DIT19050001',
|
||||
'commentaire': 'aaa'
|
||||
}
|
||||
response = app.post_json('/atal/slug-atal/insert_demande_by_type', params=params)
|
||||
response = app.post_json('/atal/slug-atal/insert-action-comment', params=params)
|
||||
assert response.json == {
|
||||
'err': 0,
|
||||
'data': {'demande_number': 'DIT19050001'}
|
||||
}
|
||||
call_params = mock_soap_call.call_args.kwargs
|
||||
assert call_params['wsdl'] == 'DemandeService'
|
||||
assert call_params['method'] == 'insertDemandeByType'
|
||||
assert call_params['contactNom'] == 'John Doe'
|
||||
assert call_params['contactTelephone'] == '0101010101'
|
||||
assert call_params['contactCourriel'] == 'john@doe.com'
|
||||
assert call_params['contactAdresse'] == '1 doe street'
|
||||
assert call_params['demandeObjet'] == 'sarah connor'
|
||||
assert call_params['demandeLieu'] == 'LA'
|
||||
assert call_params['demandeDescription'] == 'poker face'
|
||||
assert call_params['remoteAddress'] == 'hollywood bd'
|
||||
assert call_params['codeEquipement'] == 'MAC10'
|
||||
assert call_params['codeServiceDemandeur'] == 'skynet'
|
||||
assert call_params['dateSouhaitee'] == 'now'
|
||||
assert call_params['typeDemande'] == 'scary'
|
||||
assert call_params['method'] == 'insertActionComment'
|
||||
assert call_params['numeroDemande'] == 'DIT19050001'
|
||||
assert call_params['commentaire'] == 'aaa'
|
||||
|
||||
|
||||
def test_retrieve_details_demande(app, connector, monkeypatch):
|
||||
mock_soap_call = mock_atal_soap_call(
|
||||
monkeypatch, return_value=dict(code='code1', libelle='elem1'))
|
||||
response = app.get('/atal/slug-atal/retrieve_details_demande/DIT19050001/')
|
||||
def test_upload(app, connector, monkeypatch):
|
||||
mock_soap_call = mock_atal_soap_call(monkeypatch, return_value=None)
|
||||
base64_str = 'eyJsYXN0X2NoZWNrIjoiMjAxOS0wNC0xMFQxMjowODoyOVoiL' + \
|
||||
'CJweXBpX3ZlcnNpb24iOiIxOS4wLjMifQ=='
|
||||
params = {
|
||||
'numero_demande': 'DIT19050001',
|
||||
'nom_fichier': 'data.json',
|
||||
'file': {
|
||||
'content': base64_str
|
||||
}
|
||||
}
|
||||
response = app.post_json('/atal/slug-atal/upload', params=params)
|
||||
assert response.json == {
|
||||
'err': 0,
|
||||
'data': {'code': 'code1', 'libelle': 'elem1'}
|
||||
'err': 0
|
||||
}
|
||||
call_params = mock_soap_call.call_args.kwargs
|
||||
assert call_params['wsdl'] == 'DemandeService'
|
||||
assert call_params['method'] == 'retrieveDetailsDemande'
|
||||
assert call_params['demandeNumberParam'] == 'DIT19050001'
|
||||
assert call_params['wsdl'] == 'ChargementPiecesJointesService'
|
||||
assert call_params['method'] == 'upload'
|
||||
assert call_params['numeroDemande'] == 'DIT19050001'
|
||||
assert call_params['nomFichier'] == 'data.json'
|
||||
assert call_params['donneesFichier'] == base64.b64decode(base64_str)
|
||||
|
||||
params = {
|
||||
'numero_demande': 'DIT19050001',
|
||||
'nom_fichier': 'data.json',
|
||||
'file': {
|
||||
'content': 'invalidbase64'
|
||||
}
|
||||
}
|
||||
response = app.post_json('/atal/slug-atal/upload', params=params)
|
||||
assert response.json == {
|
||||
'data': None,
|
||||
'err': 1,
|
||||
'err_class': 'passerelle.utils.jsonresponse.APIError',
|
||||
'err_desc': 'Invalid base64 string'
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue