toulouse_axel: get invoices (#38230)
This commit is contained in:
parent
cc85bdc81c
commit
18be45d1e8
|
@ -40,6 +40,33 @@ def test_link(conn, user):
|
|||
pprint.pprint(res)
|
||||
print('\n')
|
||||
|
||||
print("Get invoices")
|
||||
url = conn + '/invoices?NameID=%s' % name_id
|
||||
resp = requests.get(url)
|
||||
resp.raise_for_status()
|
||||
res = resp.json()
|
||||
assert res['err'] == 0
|
||||
pprint.pprint(res)
|
||||
print('\n')
|
||||
|
||||
data = res
|
||||
for invoice in data['data']:
|
||||
print("GET invoice info")
|
||||
url = conn + '/invoice/%s?NameID=%s' % (invoice['id'], name_id)
|
||||
resp = requests.get(url)
|
||||
resp.raise_for_status()
|
||||
res = resp.json()
|
||||
assert res['err'] == 0
|
||||
pprint.pprint(res)
|
||||
print('\n')
|
||||
|
||||
if res['data']['has_pdf']:
|
||||
print("GET invoice PDF")
|
||||
url = conn + '/invoice/%s/pdf?NameID=%s' % (invoice['id'], name_id)
|
||||
resp = requests.get(url)
|
||||
resp.raise_for_status()
|
||||
print('\n')
|
||||
|
||||
print("Deleting link")
|
||||
url = conn + '/unlink?NameID=%s' % name_id
|
||||
resp = requests.post(url)
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
# 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
|
||||
import copy
|
||||
import datetime
|
||||
import logging
|
||||
|
@ -23,6 +24,7 @@ import xml.etree.ElementTree as ET
|
|||
|
||||
|
||||
from django.db import models
|
||||
from django.http import HttpResponse
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
@ -70,10 +72,10 @@ def xml_schema_converter(name, root_element):
|
|||
|
||||
|
||||
class Operation(object):
|
||||
def __init__(self, operation):
|
||||
def __init__(self, operation, prefix='Dui/'):
|
||||
self.operation = operation
|
||||
self.request_converter = xml_schema_converter('Dui/Q_%s.xsd' % operation, 'PORTAIL')
|
||||
self.response_converter = xml_schema_converter('Dui/R_%s.xsd' % operation, 'PORTAILSERVICE')
|
||||
self.request_converter = xml_schema_converter('%sQ_%s.xsd' % (prefix, operation), 'PORTAIL')
|
||||
self.response_converter = xml_schema_converter('%sR_%s.xsd' % (prefix, operation), 'PORTAILSERVICE')
|
||||
self.name = re.sub(
|
||||
'(.?)([A-Z])',
|
||||
lambda s: s.group(1) + ('-' if s.group(1) else '') + s.group(2).lower(),
|
||||
|
@ -109,6 +111,8 @@ class Operation(object):
|
|||
|
||||
ref_verif_dui = Operation('RefVerifDui')
|
||||
ref_famille_dui = Operation('RefFamilleDui')
|
||||
ref_facture_a_payer = Operation('RefFactureAPayer')
|
||||
ref_facture_pdf = Operation('RefFacturePDF', prefix='')
|
||||
|
||||
|
||||
class ToulouseAxel(BaseResource):
|
||||
|
@ -169,6 +173,12 @@ class ToulouseAxel(BaseResource):
|
|||
raise APIError('Data conflict', err='conflict')
|
||||
return {'link': link.pk, 'created': created, 'dui': link.dui}
|
||||
|
||||
def get_link(self, name_id, error_status=200):
|
||||
try:
|
||||
return self.link_set.get(name_id=name_id)
|
||||
except Link.DoesNotExist:
|
||||
raise APIError('Person not found', err='not-found', http_status=error_status)
|
||||
|
||||
@endpoint(
|
||||
description=_('Delete link between user and Toulouse Axel'),
|
||||
methods=['post'],
|
||||
|
@ -177,21 +187,13 @@ class ToulouseAxel(BaseResource):
|
|||
'NameID': {'description': _('Publik ID')},
|
||||
})
|
||||
def unlink(self, request, NameID):
|
||||
try:
|
||||
link = self.link_set.get(name_id=NameID)
|
||||
except Link.DoesNotExist:
|
||||
raise APIError('Person not found', err='not-found')
|
||||
|
||||
link = self.get_link(NameID)
|
||||
link_id = link.pk
|
||||
link.delete()
|
||||
return {'link': link_id, 'deleted': True, 'dui': link.dui}
|
||||
|
||||
def get_family_data(self, name_id):
|
||||
try:
|
||||
link = self.link_set.get(name_id=name_id)
|
||||
except Link.DoesNotExist:
|
||||
raise APIError('Person not found', err='not-found')
|
||||
|
||||
link = self.get_link(name_id)
|
||||
try:
|
||||
result = ref_famille_dui(self, {'PORTAIL': {'DUI': {'IDDUI': link.dui}}})
|
||||
except AxelError as e:
|
||||
|
@ -224,6 +226,91 @@ class ToulouseAxel(BaseResource):
|
|||
|
||||
raise APIError('Child not found', err='not-found')
|
||||
|
||||
def get_invoices(self, name_id, error_status=200):
|
||||
link = self.get_link(name_id, error_status=error_status)
|
||||
try:
|
||||
result = ref_facture_a_payer(self, {'PORTAIL': {'DUI': {'IDDUI': link.dui}}})
|
||||
except AxelError as e:
|
||||
raise APIError('Axel error: %s' % e, err='error', http_status=error_status)
|
||||
data = result['DATA']['PORTAIL']['DUI']
|
||||
result = []
|
||||
for facture in data.get('FACTURES', []):
|
||||
result.append({
|
||||
'id': facture['IDFACTURE'],
|
||||
'label': facture['LIBELLE'],
|
||||
'amount': facture['RESTEAPAYER'],
|
||||
'total_amount': facture['MONTANTTOTAL'],
|
||||
'online_payment': True,
|
||||
'created': facture['DATEEMISSION'],
|
||||
'pay_limit_date': facture['DATEECHEANCE'],
|
||||
'has_pdf': True if facture['EXISTEPDF'] == '1' else False,
|
||||
'paid': False,
|
||||
'vendor': {'toulouse-axel': facture},
|
||||
})
|
||||
return result
|
||||
|
||||
def get_invoice(self, name_id, invoice_id, error_status=200):
|
||||
invoices_data = self.get_invoices(name_id, error_status=error_status)
|
||||
for invoice in invoices_data:
|
||||
if str(invoice['id']) == invoice_id:
|
||||
return invoice
|
||||
|
||||
@endpoint(
|
||||
description=_("Get invoices to pay"),
|
||||
perm='can_access',
|
||||
parameters={
|
||||
'NameID': {'description': _('Publik ID')},
|
||||
})
|
||||
def invoices(self, request, NameID):
|
||||
invoices_data = self.get_invoices(NameID)
|
||||
return {'data': invoices_data}
|
||||
|
||||
@endpoint(
|
||||
perm='can_access',
|
||||
pattern=r'^(?P<invoice_id>\w+)/?$',
|
||||
description=_('Get invoice details'),
|
||||
parameters={
|
||||
'NameID': {'description': _('Publik ID')},
|
||||
'invoice_id': {'description': _('Invoice identifier')}
|
||||
})
|
||||
def invoice(self, request, invoice_id, NameID):
|
||||
invoice = self.get_invoice(NameID, invoice_id)
|
||||
if invoice is None:
|
||||
raise APIError('Invoice not found', err='not-found')
|
||||
|
||||
return {'data': invoice}
|
||||
|
||||
@endpoint(
|
||||
name='invoice',
|
||||
perm='can_access',
|
||||
pattern=r'^(?P<invoice_id>\w+)/pdf/?$',
|
||||
description=_('Get invoice as a PDF file'),
|
||||
parameters={
|
||||
'NameID': {'description': _('Publik ID')},
|
||||
'invoice_id': {'description': _('Invoice identifier')}
|
||||
})
|
||||
def invoice_pdf(self, request, invoice_id, NameID):
|
||||
# check that invoice is related to current user
|
||||
invoice = self.get_invoice(NameID, invoice_id, error_status=404)
|
||||
if invoice is None:
|
||||
raise APIError('Invoice not found', err='not-found', http_status=404)
|
||||
# check that PDF is available
|
||||
if not invoice['has_pdf']:
|
||||
raise APIError('PDF not available', err='not-available', http_status=404)
|
||||
|
||||
try:
|
||||
result = ref_facture_pdf(self, {'PORTAIL': {'FACTUREPDF': {'IDFACTURE': int(invoice_id)}}})
|
||||
except AxelError as e:
|
||||
raise APIError('Axel error: %s' % e, err='error', http_status=404)
|
||||
|
||||
b64content = base64.b64decode(result['DATA']['PORTAIL']['PDF']['@FILE'])
|
||||
if not b64content:
|
||||
raise APIError('PDF error', err='error', http_status=404)
|
||||
response = HttpResponse(content_type='application/pdf')
|
||||
response['Content-Disposition'] = 'attachment; filename="%s.pdf"' % invoice_id
|
||||
response.write(b64content)
|
||||
return response
|
||||
|
||||
|
||||
class Link(models.Model):
|
||||
resource = models.ForeignKey(ToulouseAxel, on_delete=models.CASCADE)
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:all="urn:AllAxelTypes">
|
||||
|
||||
<xsd:import schemaLocation="../AllAxelTypes.xsd" namespace="urn:AllAxelTypes" />
|
||||
|
||||
<xsd:complexType name="DUIType">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="IDDUI" />
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="PORTAILType">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="DUI"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="IDDUI" type="all:IDENTREQUIREDType"/>
|
||||
|
||||
<xsd:element name="DUI" type="DUIType"/>
|
||||
|
||||
<xsd:element name="PORTAIL" type="PORTAILType"/>
|
||||
</xsd:schema>
|
|
@ -0,0 +1,74 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:all="urn:AllAxelTypes">
|
||||
|
||||
<xsd:import schemaLocation="../AllAxelTypes.xsd" namespace="urn:AllAxelTypes" />
|
||||
|
||||
<xsd:redefine schemaLocation="../R_ShemaResultat.xsd">
|
||||
<xsd:simpleType name="TYPEType">
|
||||
<xsd:restriction base="TYPEType">
|
||||
<xsd:enumeration value="RefFactureAPayer" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:complexType name="PORTAILType">
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="PORTAILType">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="DUI" minOccurs="0"/>
|
||||
</xsd:sequence>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:redefine>
|
||||
|
||||
<xsd:simpleType name="CHOIXType">
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="" />
|
||||
<xsd:enumeration value="1" />
|
||||
<xsd:enumeration value="0" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:complexType name="FACTURESType">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="NUMFACTURE" />
|
||||
<xsd:element ref="DATEEMISSION" />
|
||||
<xsd:element ref="DATEECHEANCE" />
|
||||
<xsd:element ref="LIBELLE" />
|
||||
<xsd:element ref="IDFACTURATION" />
|
||||
<xsd:element ref="MONTANTTOTAL" />
|
||||
<xsd:element ref="RESTEAPAYER" />
|
||||
<xsd:element ref="IDREGIE" />
|
||||
<xsd:element ref="EXISTEPDF" />
|
||||
<xsd:element ref="IDFACTURE" />
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="DUIType">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="IDDUI" />
|
||||
<xsd:element ref="CHOIXDEMAT" />
|
||||
<xsd:element ref="NBFACTURES" />
|
||||
<xsd:element ref="FACTURES" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="IDDUI" type="all:IDENTType"/>
|
||||
<xsd:element name="CHOIXDEMAT" type="CHOIXType"/>
|
||||
<xsd:element name="NBFACTURES" type="all:unsignedInt-or-empty"/>
|
||||
<xsd:element name="FACTURES" type="FACTURESType"/>
|
||||
|
||||
<xsd:element name="NUMFACTURE" type="xsd:unsignedInt"/>
|
||||
<xsd:element name="DATEEMISSION" type="all:DATEREQUIREDType"/>
|
||||
<xsd:element name="DATEECHEANCE" type="all:DATEREQUIREDType"/>
|
||||
<xsd:element name="LIBELLE" type="xsd:string"/>
|
||||
<xsd:element name="IDFACTURATION" type="all:IDType"/>
|
||||
<xsd:element name="MONTANTTOTAL" type="all:MONTANTType"/>
|
||||
<xsd:element name="RESTEAPAYER" type="all:MONTANTREQUIREDType"/>
|
||||
<xsd:element name="IDREGIE" type="all:IDType"/>
|
||||
<xsd:element name="EXISTEPDF" type="CHOIXType"/>
|
||||
<xsd:element name="IDFACTURE" type="xsd:unsignedInt"/>
|
||||
|
||||
|
||||
<xsd:element name="DUI" type="DUIType" />
|
||||
</xsd:schema>
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
|
||||
<xsd:complexType name="FACTUREPDFType">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="IDFACTURE" />
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="PORTAILType">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="FACTUREPDF" />
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="IDFACTURE" type="xsd:positiveInteger"/>
|
||||
<xsd:element name="FACTUREPDF" type="FACTUREPDFType"/>
|
||||
<xsd:element name="PORTAIL" type="PORTAILType"/>
|
||||
|
||||
</xsd:schema>
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
|
||||
<xsd:redefine schemaLocation="./R_ShemaResultat.xsd">
|
||||
<xsd:simpleType name="TYPEType">
|
||||
<xsd:restriction base="TYPEType">
|
||||
<xsd:enumeration value="RefFacturePDF" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:complexType name="PORTAILType">
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="PORTAILType">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="PDF" minOccurs="0"/>
|
||||
</xsd:sequence>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:redefine>
|
||||
|
||||
<xsd:complexType name="PDFType">
|
||||
<xsd:attribute ref="FILE"/>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:attribute name="FILE" type="xsd:string"/>
|
||||
|
||||
<xsd:element name="PDF" type="PDFType"/>
|
||||
|
||||
</xsd:schema>
|
|
@ -0,0 +1,31 @@
|
|||
<PORTAIL>
|
||||
<DUI>
|
||||
<IDDUI>XXX</IDDUI>
|
||||
<CHOIXDEMAT>0</CHOIXDEMAT>
|
||||
<NBFACTURES>2</NBFACTURES>
|
||||
<FACTURES>
|
||||
<NUMFACTURE>42</NUMFACTURE>
|
||||
<DATEEMISSION>12/11/2019</DATEEMISSION>
|
||||
<DATEECHEANCE>04/12/2019</DATEECHEANCE>
|
||||
<LIBELLE>PRESTATIONS PERISCOLAIRES SEPTEMBRE-OCTOBRE 2019</LIBELLE>
|
||||
<IDFACTURATION>4242-35AA</IDFACTURATION>
|
||||
<MONTANTTOTAL>44.94</MONTANTTOTAL>
|
||||
<RESTEAPAYER>44.94</RESTEAPAYER>
|
||||
<IDREGIE>MAREGIE</IDREGIE>
|
||||
<EXISTEPDF>1</EXISTEPDF>
|
||||
<IDFACTURE>42</IDFACTURE>
|
||||
</FACTURES>
|
||||
<FACTURES>
|
||||
<NUMFACTURE>43</NUMFACTURE>
|
||||
<DATEEMISSION>12/12/2019</DATEEMISSION>
|
||||
<DATEECHEANCE>04/01/2020</DATEECHEANCE>
|
||||
<LIBELLE>PRESTATIONS PERISCOLAIRES NOVEMBRE 2019</LIBELLE>
|
||||
<IDFACTURATION>4243-35AA</IDFACTURATION>
|
||||
<MONTANTTOTAL>44.94</MONTANTTOTAL>
|
||||
<RESTEAPAYER>44.94</RESTEAPAYER>
|
||||
<IDREGIE>MAREGIE</IDREGIE>
|
||||
<EXISTEPDF>0</EXISTEPDF>
|
||||
<IDFACTURE>43</IDFACTURE>
|
||||
</FACTURES>
|
||||
</DUI>
|
||||
</PORTAIL>
|
|
@ -25,6 +25,8 @@ from passerelle.contrib.toulouse_axel.models import (
|
|||
Link,
|
||||
ToulouseAxel,
|
||||
ref_famille_dui,
|
||||
ref_facture_a_payer,
|
||||
ref_facture_pdf,
|
||||
ref_verif_dui,
|
||||
)
|
||||
import utils
|
||||
|
@ -131,6 +133,36 @@ def test_operation_ref_famille_dui(resource, content):
|
|||
})
|
||||
|
||||
|
||||
@pytest.mark.parametrize('content', [
|
||||
'<PORTAIL><DUI/></PORTAIL>',
|
||||
])
|
||||
def test_operation_ref_facture_a_payer(resource, content):
|
||||
with mock_getdata(content, 'RefFactureAPayer'):
|
||||
with pytest.raises(AxelError):
|
||||
ref_facture_a_payer(resource, {
|
||||
'PORTAIL': {
|
||||
'DUI': {
|
||||
'IDDUI': 'XXX',
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@pytest.mark.parametrize('content', [
|
||||
"<PORTAIL><PDF FOO='BAR'></PDF></PORTAIL>",
|
||||
])
|
||||
def test_operation_ref_facture_pdf(resource, content):
|
||||
with mock_getdata(content, 'RefFacturePDF'):
|
||||
with pytest.raises(AxelError):
|
||||
ref_facture_pdf(resource, {
|
||||
'PORTAIL': {
|
||||
'FACTUREPDF': {
|
||||
'IDFACTURE': 42,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
def test_link_endpoint_nameid_empty(app, resource, params):
|
||||
resp = app.post_json('/toulouse-axel/test/link?NameID=', params=params, status=400)
|
||||
assert resp.json['err_desc'] == "NameID is empty"
|
||||
|
@ -306,3 +338,203 @@ def test_child_info_endpoint(app, resource):
|
|||
'SANITAIRE',
|
||||
'SEXE',
|
||||
])
|
||||
|
||||
|
||||
def test_invoices_endpoint_axel_error(app, resource):
|
||||
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.models.ref_facture_a_payer') as operation:
|
||||
operation.side_effect = AxelError('FooBar')
|
||||
resp = app.get('/toulouse-axel/test/invoices?NameID=yyy')
|
||||
assert resp.json['err_desc'] == "Axel error: FooBar"
|
||||
|
||||
|
||||
def test_invoices_endpoint_no_result(app, resource):
|
||||
resp = app.get('/toulouse-axel/test/invoices?NameID=yyy')
|
||||
assert resp.json['err_desc'] == "Person not found"
|
||||
|
||||
|
||||
def test_invoices_endpoint_no_invoices(app, resource):
|
||||
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
|
||||
content = '''<PORTAIL>
|
||||
<DUI>
|
||||
<IDDUI>XXX</IDDUI>
|
||||
<CHOIXDEMAT>0</CHOIXDEMAT>
|
||||
<NBFACTURES>0</NBFACTURES>
|
||||
</DUI>
|
||||
</PORTAIL>'''
|
||||
with mock_getdata(content, 'RefFactureAPayer'):
|
||||
resp = app.get('/toulouse-axel/test/invoices?NameID=yyy')
|
||||
assert resp.json['err'] == 0
|
||||
assert resp.json['data'] == []
|
||||
|
||||
|
||||
def test_invoices_endpoint(app, resource):
|
||||
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
|
||||
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/invoices.xml')
|
||||
with open(filepath) as xml:
|
||||
content = xml.read()
|
||||
with mock_getdata(content, 'RefFactureAPayer'):
|
||||
resp = app.get('/toulouse-axel/test/invoices?NameID=yyy')
|
||||
assert resp.json['err'] == 0
|
||||
assert resp.json['data'] == [
|
||||
{
|
||||
'id': 42,
|
||||
'label': 'PRESTATIONS PERISCOLAIRES SEPTEMBRE-OCTOBRE 2019',
|
||||
'amount': '44.94',
|
||||
'total_amount': '44.94',
|
||||
'online_payment': True,
|
||||
'created': '2019-11-12',
|
||||
'pay_limit_date': '2019-12-04',
|
||||
'has_pdf': True,
|
||||
'paid': False,
|
||||
'vendor': {
|
||||
'toulouse-axel': {
|
||||
'IDFACTURATION': '4242-35AA',
|
||||
'IDFACTURE': 42,
|
||||
'IDREGIE': 'MAREGIE',
|
||||
'DATEECHEANCE': '2019-12-04',
|
||||
'DATEEMISSION': '2019-11-12',
|
||||
'EXISTEPDF': '1',
|
||||
'LIBELLE': 'PRESTATIONS PERISCOLAIRES SEPTEMBRE-OCTOBRE 2019',
|
||||
'MONTANTTOTAL': '44.94',
|
||||
'NUMFACTURE': 42,
|
||||
'RESTEAPAYER': '44.94',
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
'id': 43,
|
||||
'label': 'PRESTATIONS PERISCOLAIRES NOVEMBRE 2019',
|
||||
'amount': '44.94',
|
||||
'total_amount': '44.94',
|
||||
'online_payment': True,
|
||||
'created': '2019-12-12',
|
||||
'pay_limit_date': '2020-01-04',
|
||||
'has_pdf': False,
|
||||
'paid': False,
|
||||
'vendor': {
|
||||
'toulouse-axel': {
|
||||
'IDFACTURATION': '4243-35AA',
|
||||
'IDFACTURE': 43,
|
||||
'DATEECHEANCE': '2020-01-04',
|
||||
'DATEEMISSION': '2019-12-12',
|
||||
'EXISTEPDF': '0',
|
||||
'IDREGIE': 'MAREGIE',
|
||||
'LIBELLE': 'PRESTATIONS PERISCOLAIRES NOVEMBRE 2019',
|
||||
'MONTANTTOTAL': '44.94',
|
||||
'NUMFACTURE': 43,
|
||||
'RESTEAPAYER': '44.94',
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
def test_invoice_endpoint_axel_error(app, resource):
|
||||
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.models.ref_facture_a_payer') as operation:
|
||||
operation.side_effect = AxelError('FooBar')
|
||||
resp = app.get('/toulouse-axel/test/invoice/42?NameID=yyy')
|
||||
assert resp.json['err_desc'] == "Axel error: FooBar"
|
||||
|
||||
|
||||
def test_invoice_endpoint_no_result(app, resource):
|
||||
resp = app.get('/toulouse-axel/test/invoice/42?NameID=yyy')
|
||||
assert resp.json['err_desc'] == "Person not found"
|
||||
|
||||
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
|
||||
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/invoices.xml')
|
||||
with open(filepath) as xml:
|
||||
content = xml.read()
|
||||
with mock_getdata(content, 'RefFactureAPayer'):
|
||||
resp = app.get('/toulouse-axel/test/invoice/35?NameID=yyy')
|
||||
assert resp.json['err_desc'] == "Invoice not found"
|
||||
|
||||
|
||||
def test_invoice_endpoint(app, resource):
|
||||
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
|
||||
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/invoices.xml')
|
||||
with open(filepath) as xml:
|
||||
content = xml.read()
|
||||
with mock_getdata(content, 'RefFactureAPayer'):
|
||||
resp = app.get('/toulouse-axel/test/invoice/42?NameID=yyy')
|
||||
assert resp.json['err'] == 0
|
||||
assert resp.json['data'] == {
|
||||
'id': 42,
|
||||
'label': 'PRESTATIONS PERISCOLAIRES SEPTEMBRE-OCTOBRE 2019',
|
||||
'amount': '44.94',
|
||||
'total_amount': '44.94',
|
||||
'online_payment': True,
|
||||
'created': '2019-11-12',
|
||||
'pay_limit_date': '2019-12-04',
|
||||
'has_pdf': True,
|
||||
'paid': False,
|
||||
'vendor': {
|
||||
'toulouse-axel': {
|
||||
'IDFACTURATION': '4242-35AA',
|
||||
'IDFACTURE': 42,
|
||||
'IDREGIE': 'MAREGIE',
|
||||
'DATEECHEANCE': '2019-12-04',
|
||||
'DATEEMISSION': '2019-11-12',
|
||||
'EXISTEPDF': '1',
|
||||
'LIBELLE': 'PRESTATIONS PERISCOLAIRES SEPTEMBRE-OCTOBRE 2019',
|
||||
'MONTANTTOTAL': '44.94',
|
||||
'NUMFACTURE': 42,
|
||||
'RESTEAPAYER': '44.94',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def test_invoice_pdf_endpoint_axel_error(app, resource):
|
||||
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.models.ref_facture_a_payer') as operation:
|
||||
operation.side_effect = AxelError('FooBar')
|
||||
resp = app.get('/toulouse-axel/test/invoice/42/pdf?NameID=yyy', status=404)
|
||||
assert resp.json['err_desc'] == "Axel error: FooBar"
|
||||
|
||||
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/invoices.xml')
|
||||
with open(filepath) as xml:
|
||||
content = xml.read()
|
||||
with mock_getdata(content, 'RefFactureAPayer'):
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.models.ref_facture_pdf') as operation:
|
||||
operation.side_effect = AxelError('FooBar')
|
||||
resp = app.get('/toulouse-axel/test/invoice/42/pdf?NameID=yyy', status=404)
|
||||
assert resp.json['err_desc'] == "Axel error: FooBar"
|
||||
|
||||
|
||||
def test_invoice_pdf_endpoint_no_result(app, resource):
|
||||
resp = app.get('/toulouse-axel/test/invoice/42/pdf?NameID=yyy', status=404)
|
||||
assert resp.json['err_desc'] == "Person not found"
|
||||
|
||||
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
|
||||
filepath = os.path.join(os.path.dirname(__file__), 'data/toulouse_axel/invoices.xml')
|
||||
with open(filepath) as xml:
|
||||
content = xml.read()
|
||||
with mock_getdata(content, 'RefFactureAPayer'):
|
||||
resp = app.get('/toulouse-axel/test/invoice/35/pdf?NameID=yyy', status=404)
|
||||
assert resp.json['err_desc'] == "Invoice not found"
|
||||
|
||||
with mock_getdata(content, 'RefFactureAPayer'):
|
||||
resp = app.get('/toulouse-axel/test/invoice/43/pdf?NameID=yyy', status=404)
|
||||
assert resp.json['err_desc'] == "PDF not available"
|
||||
|
||||
pdf_content = '''<PORTAIL>
|
||||
<PDF FILE=''></PDF>
|
||||
</PORTAIL>'''
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_invoice') as invoice:
|
||||
invoice.return_value = {'has_pdf': True}
|
||||
with mock_getdata(pdf_content, 'RefFacturePDF'):
|
||||
resp = app.get('/toulouse-axel/test/invoice/42/pdf?NameID=yyy', status=404)
|
||||
assert resp.json['err_desc'] == "PDF error"
|
||||
|
||||
|
||||
def test_invoice_pdf_endpoint(app, resource):
|
||||
Link.objects.create(resource=resource, name_id='yyy', dui='XXX', person_id='42')
|
||||
pdf_content = '''<PORTAIL>
|
||||
<PDF FILE='aGVsbG8gd29ybGQ='></PDF>
|
||||
</PORTAIL>'''
|
||||
with mock.patch('passerelle.contrib.toulouse_axel.models.ToulouseAxel.get_invoice') as invoice:
|
||||
invoice.return_value = {'has_pdf': True}
|
||||
with mock_getdata(pdf_content, 'RefFacturePDF'):
|
||||
app.get('/toulouse-axel/test/invoice/42/pdf?NameID=yyy')
|
||||
|
|
Loading…
Reference in New Issue