zoo/tests/test_nanterre_saga.py

253 lines
9.6 KiB
Python

# -*- coding: utf-8 -*-
import decimal
import httmock
import xml.etree.ElementTree as ET
import requests
from zoo.zoo_nanterre import utils
from django.utils.http import urlencode
from django.urls import reverse
def test_utils(db):
utils.set_saga_sequence(42)
assert utils.get_next_saga_sequence() == 42
def test_tiers_saga(app, settings, nanterre_classic_family, freezer):
freezer.move_to('2017-10-20')
settings.ZOO_NANTERRE_APPLICATIONS['saga']['url'] = 'http://saga.example.com/ws/'
settings.ZOO_NANTERRE_APPLICATIONS['saga']['base_uri'] = 'foobar'
settings.ZOO_NANTERRE_APPLICATIONS['saga']['num_service'] = '69'
f = nanterre_classic_family
def xml_literal(node, content):
elt = ET.Element('root')
elt.attrib['xmlns'] = 'ns'
sub = ET.SubElement(elt, node)
sub.text = content
return ET.tostring(elt)
f['jean'].content['cles_de_federation']['technocarte'] = '1234'
f['jean'].save()
f['marie'].content['cles_de_federation']['technocarte'] = '4567'
f['marie'].save()
assert 'saga_tiers' not in f['jean'].content['cles_de_federation']
# Définition du début de la séquence des codes tiers
utils.set_saga_sequence(42)
# Calcul du code tiers pour Jean
response = app.get(reverse('rsu-api-saga-tiers', kwargs={
'application': 'technocarte',
'identifier': '1234'
}))
assert response.json['code'] == 'RG0000000000042'
f['jean'].refresh_from_db()
assert 'saga_tiers' in f['jean'].content['cles_de_federation']
response = app.get(reverse('rsu-api-saga-tiers', kwargs={
'application': 'technocarte',
'identifier': '1234'
}))
assert response.json['code'] == 'RG0000000000042'
# Calcul du code tiers pour Marie
response = app.get(reverse('rsu-api-saga-tiers', kwargs={
'application': 'technocarte',
'identifier': '4567'
}))
assert response.json['code'] == 'RG0000000000043'
f['marie'].refresh_from_db()
assert 'saga_tiers' in f['marie'].content['cles_de_federation']
# Mock du web-service SAGA, répond vite celui là
@httmock.urlmatch()
def saga_ok(url, request):
assert url.netloc == 'saga.example.com'
assert url.path.startswith('/foobar/')
if '<num_service>' in request.body:
assert '<num_service>69</num_service>' in request.body
if 'codeTiersFedere' in request.body:
return xml_literal('codeTiersFedereReturn',
'<code_tiers_federe>XYZ</code_tiers_federe>')
elif 'etatFactureParTiersFedere' in request.body:
return xml_literal('etatFactureParTiersFedereReturn',
u'''
<factures>
<facture date_facture="10/10/2017" date_limite_recouvrement="20/10/2017"
etat="en cours" incident_paiement="paiement" montant_initial="10.00"
reste_a_payer="1.0" num="34">
<creances>
<creance imputation="1234" montant="1.2" libelle="PISCINE" num_creance="123"/>
</creances>
</facture>
<facture date_facture="10/10/2017" date_limite_recouvrement="18/10/2017"
etat="en cours" incident_paiement="paiement" montant_initial="10.00"
reste_a_payer="1.0" num="34">
<creances>
<creance imputation="1234" montant="1.2" libelle="PISCINE" num_creance="123"/>
</creances>
</facture>
<facture date_facture="10/10/2017" date_limite_recouvrement="20/10/2017"
etat="soldée" incident_paiement="paiement" montant_initial="10.00"
reste_a_payer="2.0" num="35">
<creances>
<creance imputation="1234" montant="3.2" libelle="PISCINE" num_creance="123"/>
</creances>
</facture>
<facture date_facture="10/10/2017" date_limite_recouvrement="20/10/2017"
etat="transmise" incident_paiement="paiement" montant_initial="10.00"
reste_a_payer="2.0" num="36">
<creances>
<creance imputation="1234" montant="3.2" libelle="PISCINE" num_creance="123"/>
</creances>
</facture>
<facture date_facture="10/10/2017" date_limite_recouvrement="20/10/2017"
etat="dépassée" incident_paiement="paiement" montant_initial="10.00"
reste_a_payer="2.0" num="37">
<creances>
<creance imputation="1234" montant="3.2" libelle="PISCINE" num_creance="123"/>
</creances>
</facture>
</factures>''')
elif 'Transaction' in request.body:
return xml_literal('TransactionReturn',
'<url>http://tipi.org/</url>')
elif 'PageRetourAsynchrone' in request.body:
return xml_literal('PageRetourAsynchroneReturn',
'''<ok code_tiers="A1" email="johndoe@example.com" etat="paye" num_service="22222">
<factures>
<facture montant_initial="16.00" num="00012-A1"/>
</factures>
</ok>''')
elif 'PageRetourSynchrone' in request.body:
return xml_literal('PageRetourSynchroneReturn',
'''<ok code_tiers="A1" email="johndoe@example.com" etat="paye" num_service="22222">
<factures>
<facture montant_initial="16.00" num="00013-A1"/>
</factures>
</ok>''')
else:
raise NotImplementedError
@httmock.urlmatch()
def saga_connection_error(url, request):
raise requests.ConnectionError('no DNS')
with httmock.HTTMock(saga_connection_error):
response = app.get(reverse('rsu-api-saga-factures', kwargs={
'identifier': f['jean'].id,
}))
assert response.json['err'] == 1
assert len(response.json['errors']) == 1
assert 'ConnectionError' in response.json['errors'][0]
with httmock.HTTMock(saga_ok):
response = app.get(reverse('rsu-api-saga-factures', kwargs={
'identifier': f['jean'].id,
}))
assert response.json['err'] == 0
assert len(response.json['data']) == 10
assert response.json['data'][0]['extra']['redevable']
num = response.json['data'][0]['num']
num2 = response.json['data'][1]['num']
response = app.get(reverse('rsu-api-saga-factures', kwargs={
'identifier': f['jean'].id,
}) + '?' + urlencode({'etats': u'tresorerie'}))
assert response.json['err'] == 0
assert len(response.json['data']) == 6
response = app.get(reverse('rsu-api-saga-factures', kwargs={
'identifier': f['jean'].id,
}) + '?' + urlencode([('etats', u'whatever'), ('etats', u'soldée')]))
assert response.json['err'] == 0
assert len(response.json['data']) == 2
response = app.post_json(
reverse('rsu-api-saga-transaction', kwargs={
'identifier': f['jean'].id,
}),
params={
'num_factures': [num, num2],
'urlretour_asynchrone': 'http://async.example.com/coin',
'urlretour_synchrone': 'http://async.example.com/coin',
'email': 'john.doe@example.com',
}
)
assert response.json['err'] == 0
assert 'tipi' in response.json['data']['url']
response = app.post_json(
reverse('rsu-api-saga-retour-asynchrone'),
params={
'idop': '1234',
}
)
assert response.json['err'] == 0
data = response.json['data']
assert data['code_tiers'] == 'A1'
assert data['email'] == 'johndoe@example.com'
assert data['num_service'] == '22222'
assert data['etat'] == 'paye'
assert data['factures']
assert len(data['factures']) == 1
assert data['factures'][0]['num'] == '00012-A1'
assert decimal.Decimal(data['factures'][0]['montant_initial']) == 16
response = app.post_json(
reverse('rsu-api-saga-retour-synchrone'),
params={
'idop': '1234',
}
)
assert response.json['err'] == 0
data = response.json['data']
assert data['code_tiers'] == 'A1'
assert data['email'] == 'johndoe@example.com'
assert data['num_service'] == '22222'
assert data['etat'] == 'paye'
assert data['factures']
assert len(data['factures']) == 1
assert data['factures'][0]['num'] == '00013-A1'
assert decimal.Decimal(data['factures'][0]['montant_initial']) == 16
@httmock.urlmatch()
def saga_retour_erreur(url, request):
assert url.netloc == 'saga.example.com'
assert url.path.startswith('/foobar/')
if 'PageRetourAsynchrone' in request.body:
return xml_literal('PageRetourAsynchroneReturn',
u'<erreur>Ça va pas du tout</erreur>')
elif 'PageRetourSynchrone' in request.body:
return xml_literal('PageRetourSynchroneReturn',
u'<erreur>Ça va pas du tout</erreur>')
else:
raise NotImplementedError
with httmock.HTTMock(saga_retour_erreur):
response = app.post_json(
reverse('rsu-api-saga-retour-synchrone'),
params={
'idop': '1234',
}
)
assert response.json['err'] == 1
assert response.json['errors'] == [u'SAGA erreur: Ça va pas du tout']
response = app.post_json(
reverse('rsu-api-saga-retour-asynchrone'),
params={
'idop': '1234',
}
)
assert response.json['err'] == 1
assert response.json['errors'] == [u'SAGA erreur: Ça va pas du tout']