teamnet axel: use GenericConnectorView (#23593)
This commit is contained in:
parent
ca597a7c3b
commit
0d894dadbb
|
@ -14,12 +14,14 @@
|
|||
# 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 logging
|
||||
import base64
|
||||
import xml.etree.ElementTree as ET
|
||||
from datetime import datetime
|
||||
import json
|
||||
import logging
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from django.db import models
|
||||
from django.http import HttpResponse, HttpResponseNotFound
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.encoding import smart_text
|
||||
|
||||
|
@ -27,7 +29,9 @@ from django.utils.encoding import smart_text
|
|||
from jsonfield import JSONField
|
||||
|
||||
from passerelle.base.models import BaseResource
|
||||
from passerelle.utils.api import endpoint
|
||||
from passerelle.utils.jsonresponse import APIError
|
||||
from passerelle.views import WrongParameter
|
||||
|
||||
from . import soap
|
||||
from .utils import normalize_person, normalize_invoice
|
||||
|
@ -42,6 +46,12 @@ DATE_IN_FORMAT = '%Y-%m-%dT%H:%M:%S'
|
|||
DATE_OUT_FORMAT = '%d/%m/%Y %H:%M:%S'
|
||||
|
||||
|
||||
def get_name_id(request):
|
||||
if 'NameID' not in request.GET:
|
||||
raise WrongParameter(['NameID'], [])
|
||||
return request.GET['NameID']
|
||||
|
||||
|
||||
class TeamnetAxel(BaseResource):
|
||||
wsdl_url = models.CharField(
|
||||
max_length=128, blank=False,
|
||||
|
@ -93,7 +103,7 @@ class TeamnetAxel(BaseResource):
|
|||
return xml_result.find('DATA')
|
||||
|
||||
# Axel authentication
|
||||
def auth(self, login, pwd):
|
||||
def authenticate(self, login, pwd):
|
||||
'''return False or an AXEL user dict:
|
||||
{
|
||||
"login": "23060A",
|
||||
|
@ -123,7 +133,21 @@ class TeamnetAxel(BaseResource):
|
|||
return False
|
||||
return data
|
||||
|
||||
def get_famille(self, idfamille, annee=None):
|
||||
def get_family_id(self, request):
|
||||
nameid = get_name_id(request)
|
||||
links = Link.objects.filter(resource=self, nameid=nameid)
|
||||
if len(links) > 1:
|
||||
raise APIError('multiple links')
|
||||
if not links:
|
||||
return None
|
||||
user = self.authenticate(links[0].login, links[0].pwd)
|
||||
if not user:
|
||||
raise APIError('authentication failed')
|
||||
if 'idfamille' not in user:
|
||||
raise APIError('user without idfamille')
|
||||
return user['idfamille']
|
||||
|
||||
def get_family_data(self, idfamille, annee=None):
|
||||
xml_famille = ET.Element('FAMILLE')
|
||||
ET.SubElement(xml_famille, 'IDFAMILLE').text = idfamille
|
||||
if annee:
|
||||
|
@ -138,11 +162,75 @@ class TeamnetAxel(BaseResource):
|
|||
individu['text'] = '%(prenom)s %(nom)s' % individu
|
||||
adults = [normalize_person(i) for i in individus if i['indtype'] in (ADULT1, ADULT2)]
|
||||
children = [normalize_person(i) for i in individus if i['indtype'] == CHILD]
|
||||
return {
|
||||
'family': idfamille,
|
||||
'adults': adults,
|
||||
'children': children,
|
||||
}
|
||||
return {'family': idfamille, 'adults': adults, 'children': children}
|
||||
|
||||
@endpoint(perm='can_access')
|
||||
def ping(self, request, *args, **kwargs):
|
||||
try:
|
||||
client = soap.get_client(self)
|
||||
except (Exception, ) as exc:
|
||||
raise APIError('Client Error: %s' % exc.message)
|
||||
res = {'ping': 'pong'}
|
||||
if 'debug' in request.GET:
|
||||
res['client'] = soap.client_to_jsondict(client)
|
||||
return {'data': res}
|
||||
|
||||
@endpoint(perm='can_access')
|
||||
def auth(self, request, *args, **kwargs):
|
||||
login = request.GET.get('login')
|
||||
pwd = request.GET.get('pwd')
|
||||
return {'data': self.authenticate(login, pwd)}
|
||||
|
||||
@endpoint(name='family', perm='can_access')
|
||||
def family_data(self, request, *args, **kwargs):
|
||||
idfamille = self.get_family_id(request)
|
||||
if not idfamille:
|
||||
return {'data': None}
|
||||
data = self.get_family_data(idfamille)
|
||||
return {'data': data}
|
||||
|
||||
@endpoint(name='family', perm='can_access', pattern='^adults/$')
|
||||
def family_adults(self, request, *args, **kwargs):
|
||||
idfamille = self.get_family_id(request)
|
||||
if not idfamille:
|
||||
return {'data': None}
|
||||
data = self.get_family_data(idfamille)
|
||||
return {'data': data.get('adults')}
|
||||
|
||||
@endpoint(name='family', perm='can_access', pattern='^children/$')
|
||||
def family_children(self, request, *args, **kwargs):
|
||||
idfamille = self.get_family_id(request)
|
||||
if not idfamille:
|
||||
return {'data': None}
|
||||
data = self.get_family_data(idfamille)
|
||||
return {'data': data.get('children')}
|
||||
|
||||
@endpoint(name='family', perm='can_access', pattern='^link/$')
|
||||
def family_link(self, request, *args, **kwargs):
|
||||
nameid = get_name_id(request)
|
||||
login = request.GET.get('login')
|
||||
pwd = request.GET.get('password')
|
||||
user = self.authenticate(login, pwd)
|
||||
if not user:
|
||||
raise APIError('authentication failed')
|
||||
if 'idfamille' not in user:
|
||||
raise APIError('user without idfamille')
|
||||
famille = self.get_family_data(user['idfamille'])
|
||||
Link.objects.update_or_create(
|
||||
resource=self, nameid=nameid, defaults={'login': login, 'pwd': pwd})
|
||||
user['_famille'] = famille
|
||||
user['_nameid'] = nameid
|
||||
return {'data': user}
|
||||
|
||||
@endpoint(name='family', perm='can_access', pattern='^unlink/$')
|
||||
def family_unlink(self, request, *args, **kwargs):
|
||||
nameid = get_name_id(request)
|
||||
logins = [v['login'] for v in Link.objects.filter(resource=self, nameid=nameid).values('login')]
|
||||
Link.objects.filter(resource=self, nameid=nameid).delete()
|
||||
if logins:
|
||||
return {'data': {'login_was': logins}}
|
||||
else:
|
||||
return {'data': None}
|
||||
|
||||
def get_teamnet_payable_invoices(self, regie_id, family_id):
|
||||
operation = 'FacturesApayerRegie'
|
||||
|
@ -157,6 +245,15 @@ class TeamnetAxel(BaseResource):
|
|||
payable_invoices.update(normalize_invoice(i.attrib, family_id))
|
||||
return payable_invoices
|
||||
|
||||
@endpoint(name='regie', pattern='^(?P<regie_id>\w+)/invoices/$')
|
||||
def active_invoices(self, request, regie_id, **kwargs):
|
||||
family_id = self.get_family_id(request)
|
||||
if not family_id:
|
||||
return {'data': []}
|
||||
invoices = self.get_teamnet_payable_invoices(regie_id, family_id)
|
||||
invoices = sorted([p for i, p in invoices.iteritems()], key=lambda i: i['created'], reverse=True)
|
||||
return {'data': invoices}
|
||||
|
||||
def get_teamnet_historical_invoices(self, regie_id, family_id):
|
||||
"""
|
||||
returns historical invoices for a given regie.
|
||||
|
@ -175,54 +272,59 @@ class TeamnetAxel(BaseResource):
|
|||
historical_invoices.update(normalize_invoice(i.attrib, family_id, historical=True))
|
||||
return historical_invoices
|
||||
|
||||
def get_payable_invoices(self, regie_id, family_id):
|
||||
"""
|
||||
returns payable invoices list sorted by creation date
|
||||
"""
|
||||
@endpoint(name='regie', perm='can_access', pattern='^(?P<regie_id>\w+)/invoices/history/$')
|
||||
def invoices_history(self, request, regie_id, **kwargs):
|
||||
family_id = self.get_family_id(request)
|
||||
if not family_id:
|
||||
return []
|
||||
invoices = self.get_teamnet_payable_invoices(regie_id, family_id)
|
||||
return sorted([p for i, p in invoices.iteritems()], key=lambda i: i['created'], reverse=True)
|
||||
|
||||
def get_historical_invoices(self, regie_id, family_id):
|
||||
"""
|
||||
Removes the invoices from get_teamnet_historical_invoices which are in
|
||||
get_teamnet_payable_invoices, as the Teamnet webservices mixes them.
|
||||
|
||||
Returns historical invoices list sorted by creation date.
|
||||
"""
|
||||
if not family_id:
|
||||
return []
|
||||
return {'data': []}
|
||||
payable = self.get_teamnet_payable_invoices(regie_id, family_id)
|
||||
historical = self.get_teamnet_historical_invoices(regie_id, family_id)
|
||||
historical = [v for i, v in historical.iteritems() if i not in payable]
|
||||
return sorted(historical, key=lambda i: i['created'], reverse=True)
|
||||
invoices = sorted(historical, key=lambda i: i['created'], reverse=True)
|
||||
return {'data': invoices}
|
||||
|
||||
def get_invoice(self, regie_id, invoice_id):
|
||||
@endpoint(name='regie', perm='can_access',
|
||||
pattern='^(?P<regie_id>\w+)/invoice/(?P<invoice_id>[\w,-]+)/$')
|
||||
def get_invoice_details(self, request, regie_id, invoice_id, **kwargs):
|
||||
family_id, i = invoice_id.split('-', 1)
|
||||
payable = self.get_teamnet_payable_invoices(regie_id, family_id)
|
||||
if invoice_id in payable:
|
||||
return payable[invoice_id]
|
||||
return {'data': payable[invoice_id]}
|
||||
historical = self.get_teamnet_historical_invoices(regie_id, family_id)
|
||||
if invoice_id in historical:
|
||||
return historical[invoice_id]
|
||||
return {'data': historical[invoice_id]}
|
||||
return {'data': None}
|
||||
|
||||
def get_invoice_pdf(self, invoice_id):
|
||||
@endpoint(name='regie', perm='can_access',
|
||||
pattern='^(?P<regie_id>\w+)/invoice/(?P<invoice_id>[\w,-]+)/pdf/$')
|
||||
def invoice_pdf(self, request, regie_id, invoice_id, **kwargs):
|
||||
family_id, invoice = invoice_id.split('-', 1)
|
||||
invoice_xml = ET.Element('FACTUREPDF')
|
||||
ET.SubElement(invoice_xml, 'IDFAMILLE').text = family_id
|
||||
ET.SubElement(ET.SubElement(invoice_xml, 'FACTURES'), 'NOFACTURE').text = invoice
|
||||
data = self.get_data('FacturesPDF', invoice_xml)
|
||||
pdf = data.find('PORTAIL/PDF')
|
||||
return base64.b64decode(pdf.get('FILE'))
|
||||
b64content = base64.b64decode(pdf.get('FILE'))
|
||||
if not b64content:
|
||||
return HttpResponseNotFound()
|
||||
response = HttpResponse(content_type='application/pdf')
|
||||
response['Content-Disposition'] = 'attachment; filename="%s.pdf"' % invoice_id
|
||||
response.write(b64content)
|
||||
return response
|
||||
|
||||
@endpoint(name='regie', methods=['post'],
|
||||
perm='can_access', pattern='^(?P<regie_id>\w+)/invoice/(?P<invoice_id>[\w,-]+)/pay/$')
|
||||
def pay_invoice(self, request, regie_id, invoice_id, **kwargs):
|
||||
data = json.loads(request.body)
|
||||
transaction_id = data.get('transaction_id')
|
||||
transaction_date = data.get('transaction_date')
|
||||
email = data.get('email')
|
||||
|
||||
def pay_invoice(self, regie_id, invoice_id, transaction_id,
|
||||
transaction_date, email=None):
|
||||
family_id, invoice = invoice_id.split('-', 1)
|
||||
payable_invoices = self.get_teamnet_payable_invoices(regie_id, family_id)
|
||||
|
||||
if invoice_id not in payable_invoices:
|
||||
return False
|
||||
return {'data': False}
|
||||
|
||||
invoice_to_pay = payable_invoices[invoice_id]
|
||||
t_date = datetime.strptime(transaction_date, DATE_IN_FORMAT)
|
||||
|
@ -244,7 +346,7 @@ class TeamnetAxel(BaseResource):
|
|||
ET.SubElement(payment_xml, 'CODERETOUR')
|
||||
ET.SubElement(ET.SubElement(payment_xml, 'FACTURE'), 'NOFACTURE').text = invoice
|
||||
self.get_data('PaiementFactures', payment_xml)
|
||||
return True
|
||||
return {'data': True}
|
||||
|
||||
|
||||
class Link(models.Model):
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
{% extends "passerelle/manage/service_view.html" %}
|
||||
{% load i18n passerelle %}
|
||||
|
||||
{% block description %}
|
||||
{% endblock %}
|
||||
|
||||
{% block endpoints %}
|
||||
<h4>{% trans "Family related" %}</h4>
|
||||
<ul>
|
||||
<li>{% trans 'Check WSDL availability:' %} <a href="{% url 'teamnet-axel-ping' slug=object.slug %}"
|
||||
>{{ site_base_uri }}{% url 'teamnet-axel-ping' slug=object.slug %}</a>[?debug]</li>
|
||||
<li>{% trans 'Authentication:' %} <a href="{% url 'teamnet-axel-auth' slug=object.slug %}"
|
||||
>{{ site_base_uri }}{% url 'teamnet-axel-auth' slug=object.slug %}?login=...&pwd=...</a></li>
|
||||
<li>{% trans 'Link:' %} <a href="{% url 'teamnet-axel-link' slug=object.slug %}"
|
||||
>{{ site_base_uri }}{% url 'teamnet-axel-link' slug=object.slug %}?NameID=...&login=...&pwd=...</a></li>
|
||||
<li>{% trans 'Unlink:' %} <a href="{% url 'teamnet-axel-unlink' slug=object.slug %}"
|
||||
>{{ site_base_uri }}{% url 'teamnet-axel-unlink' slug=object.slug %}?NameID=...</a></li>
|
||||
<li>{% trans 'Get all family informations:' %} <a href="{% url 'teamnet-axel-family' slug=object.slug %}"
|
||||
>{{ site_base_uri }}{% url 'teamnet-axel-family' slug=object.slug %}?NameID=...</a></li>
|
||||
<li>{% trans 'Get specific family informations (list of children):' %}
|
||||
<a href="{% url 'teamnet-axel-family-filtered' slug=object.slug key='key' %}"
|
||||
>{{ site_base_uri }}{% url 'teamnet-axel-family-filtered' slug=object.slug key='key' %}?NameID=...</a>
|
||||
<em>key</em> is <em>adults</em> or <em>children</em></li>
|
||||
</ul>
|
||||
|
||||
<h4>{% trans "Invoices related" %}</h4>
|
||||
<ul>
|
||||
<li>{% trans 'Get invoice history list:' %}
|
||||
{% url 'teamnet-axel-invoices-history' regie_id='42' slug=object.slug as invoices_history_url %}
|
||||
<a href="{{ invoices_history_url }}">
|
||||
{{ site_base_uri }}{{ invoices_history_url }}?NameID=...
|
||||
</a> <em>42</em> {% trans 'is regie identifier' %}
|
||||
</li>
|
||||
<li>{% trans 'Get invoice list:' %}
|
||||
{% url 'teamnet-axel-invoices' regie_id='42' slug=object.slug as invoices_url %}
|
||||
<a href="{{ invoices_url }}">
|
||||
{{ site_base_uri }}{{ invoices_url }}?NameID=...
|
||||
</a> <em>42</em> {% trans 'is regie identifier' %}
|
||||
</li>
|
||||
<li>{% trans 'Show invoice details:' %}
|
||||
{% url 'teamnet-axel-invoice' slug=object.slug regie_id='42' invoice_id='2345-20150916' as invoice_details_url %}
|
||||
<a href="{{ invoice_details_url }}">
|
||||
{{ site_base_uri }}{{ invoice_details_url }}
|
||||
</a>
|
||||
<em>42</em> {% trans 'is regie identifier' %},
|
||||
<em>2345</em> {% trans 'is family identifier' %},
|
||||
<em>20150916</em> {% trans 'is invoice identifier' %}
|
||||
</li>
|
||||
<li>{% trans 'Get invoice pdf:' %}
|
||||
{% url 'teamnet-axel-invoice-pdf' slug=object.slug regie_id='42' invoice_id='2345-20150916' as invoice_download_url %}
|
||||
<a href="{{ invoice_download_url }}">
|
||||
{{ site_base_uri }}{{ invoice_download_url }}
|
||||
</a>
|
||||
</li>
|
||||
<li>{% trans 'Pay invoice:' %}
|
||||
{% url 'teamnet-axel-invoice-payment' slug=object.slug regie_id='42' invoice_id='2345-20150808' as payment_url %}
|
||||
<a href="{{ payment_url }}">
|
||||
{{ site_base_uri }}{{ payment_url }}?NameID=...
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
{% block security %}
|
||||
<p>
|
||||
{% trans 'Access is limited to the following API users:' %}
|
||||
</p>
|
||||
{% access_rights_table resource=object permission='can_access' %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,60 @@
|
|||
{% extends "passerelle/manage/service_view.html" %}
|
||||
{% load i18n passerelle %}
|
||||
|
||||
{% block endpoints %}
|
||||
<h4>{% trans "Family related" %}</h4>
|
||||
<ul>
|
||||
{% url "generic-endpoint" connector="teamnet-axel" slug=object.slug endpoint="ping" as endpoint_ping %}
|
||||
<li>{% trans 'Check WSDL availability:' %} <a href="{{ endpoint_ping }}">{{ endpoint_ping }}</a>[?debug]</li>
|
||||
|
||||
{% url "generic-endpoint" connector="teamnet-axel" slug=object.slug endpoint="auth" as endpoint_auth %}
|
||||
<li>{% trans 'Authentication:' %} <a href="{{ endpoint_auth }}?login=foo&password=bar">{{ endpoint_auth }}?login=foo&password=bar</a></li>
|
||||
|
||||
{% url "generic-endpoint" connector="teamnet-axel" slug=object.slug endpoint="family" rest="link/" as endpoint_link %}
|
||||
<li>{% trans 'Link:' %} <a href="{{ endpoint_link }}?NameID=...&login=foo&password=bar">{{ endpoint_link }}?NameID=...&login=foo&password=bar</a></li>
|
||||
|
||||
{% url "generic-endpoint" connector="teamnet-axel" slug=object.slug endpoint="family" rest="unlink/" as endpoint_unlink %}
|
||||
<li>{% trans 'Unlink:' %} <a href="{{ endpoint_unlink }}?NameID=...">{{ endpoint_unlink }}?NameID=...</a></li>
|
||||
|
||||
{% url "generic-endpoint" connector="teamnet-axel" slug=object.slug endpoint="family" rest="" as endpoint_family %}
|
||||
<li>{% trans 'Get all family informations:' %} <a href="{{ endpoint_family }}?NameID">{{ endpoint_family }}?NameID=...</a></li>
|
||||
|
||||
{% url "generic-endpoint" connector="teamnet-axel" slug=object.slug endpoint="family" rest="adults/" as endpoint_family %}
|
||||
<li>{% trans 'Get family adults informations:' %} <a href="{{ endpoint_family }}?NameID">{{ endpoint_family }}?NameID=...</a></li>
|
||||
{% url "generic-endpoint" connector="teamnet-axel" slug=object.slug endpoint="family" rest="children/" as endpoint_family %}
|
||||
<li>{% trans 'Get family children informations:' %} <a href="{{ endpoint_family }}?NameID">{{ endpoint_family }}?NameID=...</a></li>
|
||||
</ul>
|
||||
|
||||
<h4>{% trans "Invoices related" %}</h4>
|
||||
<ul>
|
||||
<li>{% trans 'Get invoice history list:' %}
|
||||
{% url "generic-endpoint" connector="teamnet-axel" slug=object.slug endpoint="regie" rest="42/invoices/history/" as invoices_history_url %}
|
||||
<a href="{{ invoices_history_url }}?NameID"> {{ invoices_history_url }}?NameID=...</a>
|
||||
<em>42</em> {% trans 'is regie identifier' %}
|
||||
</li>
|
||||
|
||||
<li>{% trans 'Get invoice list:' %}
|
||||
{% url "generic-endpoint" connector="teamnet-axel" slug=object.slug endpoint="regie" rest="42/invoices/" as invoices_url %}
|
||||
<a href="{{ invoices_url }}?NameID"> {{ invoices_url }}?NameID=... </a>
|
||||
<em>42</em> {% trans 'is regie identifier' %}
|
||||
</li>
|
||||
|
||||
<li>{% trans 'Show invoice details:' %}
|
||||
{% url "generic-endpoint" connector="teamnet-axel" slug=object.slug endpoint="regie" rest="42/invoices/2345-20150916/" as invoice_details_url %}
|
||||
<a href="{{ invoice_details_url }}"> {{ site_base_uri }}{{ invoice_details_url }} </a>
|
||||
<em>42</em> {% trans 'is regie identifier' %},
|
||||
<em>2345</em> {% trans 'is family identifier' %},
|
||||
<em>20150916</em> {% trans 'is invoice identifier' %}
|
||||
</li>
|
||||
|
||||
<li>{% trans 'Get invoice pdf:' %}
|
||||
{% url "generic-endpoint" connector="teamnet-axel" slug=object.slug endpoint="regie" rest="42/invoices/2345-20150916/pdf/" as invoice_download_url %}
|
||||
<a href="{{ invoice_download_url }}"> {{ site_base_uri }}{{ invoice_download_url }} </a>
|
||||
</li>
|
||||
|
||||
<li>{% trans 'Pay invoice:' %}
|
||||
{% url "generic-endpoint" connector="teamnet-axel" slug=object.slug endpoint="regie" rest="42/invoices/2345-20150916/pay/" as payment_url %}
|
||||
<a href="{{ payment_url }}"> {{ site_base_uri }}{{ payment_url }}?NameID=... </a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endblock %}
|
|
@ -1,47 +0,0 @@
|
|||
# passerelle.contrib.teamnet_axel
|
||||
# Copyright (C) 2015 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/>.
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from .views import (AuthView, FamilyView, HistoryInvoicesView, InvoiceView,
|
||||
InvoicesView, InvoicePayView, InvoicePDFView, LinkView,
|
||||
PingView, UnlinkView)
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^(?P<slug>[\w,-]+)/ping/$', PingView.as_view(),
|
||||
name='teamnet-axel-ping'),
|
||||
url(r'^(?P<slug>[\w,-]+)/auth/$', AuthView.as_view(),
|
||||
name='teamnet-axel-auth'),
|
||||
url(r'^(?P<slug>[\w,-]+)/family/link/$', LinkView.as_view(),
|
||||
name='teamnet-axel-link'),
|
||||
url(r'^(?P<slug>[\w,-]+)/family/unlink/$', UnlinkView.as_view(),
|
||||
name='teamnet-axel-unlink'),
|
||||
url(r'^(?P<slug>[\w,-]+)/family/$', FamilyView.as_view(),
|
||||
name='teamnet-axel-family'),
|
||||
url(r'^(?P<slug>[\w,-]+)/family/(?P<key>[\w,-]+)/$', FamilyView.as_view(),
|
||||
name='teamnet-axel-family-filtered'),
|
||||
url(r'^(?P<slug>[\w,-]+)/regie/(?P<regie_id>[\w,-]+)/invoices/history/$', HistoryInvoicesView.as_view(),
|
||||
name='teamnet-axel-invoices-history'),
|
||||
url(r'^(?P<slug>[\w,-]+)/regie/(?P<regie_id>[\w,-]+)/invoices/$', InvoicesView.as_view(),
|
||||
name='teamnet-axel-invoices'),
|
||||
url(r'^(?P<slug>[\w,-]+)/regie/(?P<regie_id>[\w,-]+)/invoice/(?P<invoice_id>[\w,-]+)/$', InvoiceView.as_view(),
|
||||
name='teamnet-axel-invoice'),
|
||||
url(r'^(?P<slug>[\w,-]+)/regie/(?P<regie_id>[\w,-]+)/invoice/(?P<invoice_id>[\w,-]+)/pdf/$', InvoicePDFView.as_view(),
|
||||
name='teamnet-axel-invoice-pdf'),
|
||||
url(r'^(?P<slug>[\w,-]+)/regie/(?P<regie_id>[\w,-]+)/invoice/(?P<invoice_id>[\w,-]+)/pay/$',
|
||||
InvoicePayView.as_view(),
|
||||
name='teamnet-axel-invoice-payment'),
|
||||
]
|
|
@ -1,177 +0,0 @@
|
|||
# passerelle.contrib.teamnet_axel
|
||||
# Copyright (C) 2015 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/>.
|
||||
|
||||
import json
|
||||
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from django.views.generic import DetailView as GenericDetailView
|
||||
from django.http import HttpResponse, HttpResponseNotFound
|
||||
|
||||
from passerelle import utils
|
||||
from passerelle.views import WrongParameter
|
||||
|
||||
from .models import TeamnetAxel, Link, APIError
|
||||
from . import soap
|
||||
|
||||
|
||||
def get_name_id(request):
|
||||
if 'NameID' not in request.GET:
|
||||
raise WrongParameter(['NameID'], [])
|
||||
return request.GET['NameID']
|
||||
|
||||
|
||||
class DetailView(GenericDetailView):
|
||||
model = TeamnetAxel
|
||||
|
||||
def get_data(self, request, *args, **kwargs):
|
||||
raise NotImplementedError
|
||||
|
||||
@utils.protected_api('can_access')
|
||||
@utils.to_json()
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
data = self.get_data(request, *args, **kwargs)
|
||||
if isinstance(data, HttpResponse):
|
||||
return data
|
||||
return {'data': data}
|
||||
|
||||
|
||||
class PingView(DetailView):
|
||||
|
||||
def get_data(self, request, *args, **kwargs):
|
||||
try:
|
||||
client = soap.get_client(self.object)
|
||||
except (Exception, ) as exc:
|
||||
raise APIError('Client Error: %s' % exc.message)
|
||||
res = {'ping': 'pong'}
|
||||
if 'debug' in request.GET:
|
||||
res['client'] = soap.client_to_jsondict(client)
|
||||
return res
|
||||
|
||||
|
||||
class AuthView(DetailView):
|
||||
|
||||
def get_data(self, request, *args, **kwargs):
|
||||
login = request.GET.get('login')
|
||||
pwd = request.GET.get('password')
|
||||
return self.object.auth(login, pwd)
|
||||
|
||||
|
||||
class LinkView(DetailView):
|
||||
|
||||
def get_data(self, request, *args, **kwargs):
|
||||
nameid = get_name_id(request)
|
||||
login = request.GET.get('login')
|
||||
pwd = request.GET.get('password')
|
||||
user = self.object.auth(login, pwd)
|
||||
if not user:
|
||||
raise APIError('authentication failed')
|
||||
if 'idfamille' not in user:
|
||||
raise APIError('user without idfamille')
|
||||
famille = self.object.get_famille(user['idfamille'])
|
||||
Link.objects.update_or_create(
|
||||
resource=self.object, nameid=nameid, defaults={'login': login, 'pwd': pwd})
|
||||
user['_famille'] = famille
|
||||
user['_nameid'] = nameid
|
||||
return user
|
||||
|
||||
|
||||
class UnlinkView(DetailView):
|
||||
|
||||
def get_data(self, request, *args, **kwargs):
|
||||
nameid = get_name_id(request)
|
||||
logins = [v['login'] for v in Link.objects.filter(resource=self.object, nameid=nameid).values('login')]
|
||||
Link.objects.filter(resource=self.object, nameid=nameid).delete()
|
||||
if logins:
|
||||
return {'login_was': logins}
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
class FamilyView(DetailView):
|
||||
|
||||
def get_family_id(self, request):
|
||||
nameid = get_name_id(request)
|
||||
links = Link.objects.filter(resource=self.object, nameid=nameid)
|
||||
if len(links) > 1:
|
||||
raise APIError('multiple links')
|
||||
if not links:
|
||||
return None
|
||||
user = self.object.auth(links[0].login, links[0].pwd)
|
||||
if not user:
|
||||
raise APIError('authentication failed')
|
||||
if 'idfamille' not in user:
|
||||
raise APIError('user without idfamille')
|
||||
return user['idfamille']
|
||||
|
||||
def get_data(self, request, *args, **kwargs):
|
||||
family_id = self.get_family_id(request)
|
||||
if not family_id:
|
||||
return
|
||||
famille = self.object.get_famille(family_id)
|
||||
if 'key' not in kwargs:
|
||||
return famille
|
||||
else:
|
||||
return famille.get(kwargs['key'])
|
||||
|
||||
|
||||
class InvoicesView(FamilyView):
|
||||
|
||||
def get_data(self, request, regie_id, **kwargs):
|
||||
return self.object.get_payable_invoices(regie_id, self.get_family_id(request))
|
||||
|
||||
|
||||
class HistoryInvoicesView(FamilyView):
|
||||
|
||||
def get_data(self, request, regie_id, **kwargs):
|
||||
return self.object.get_historical_invoices(regie_id, self.get_family_id(request))
|
||||
|
||||
|
||||
class InvoiceView(DetailView):
|
||||
|
||||
def get_data(self, request, *args, **kwargs):
|
||||
return self.object.get_invoice(kwargs['regie_id'], kwargs['invoice_id'])
|
||||
|
||||
|
||||
class InvoicePDFView(DetailView):
|
||||
|
||||
def get_data(self, request, *args, **kwargs):
|
||||
invoice_id = kwargs['invoice_id']
|
||||
pdf = self.object.get_invoice_pdf(invoice_id)
|
||||
if not pdf:
|
||||
return HttpResponseNotFound()
|
||||
|
||||
response = HttpResponse(content_type='application/pdf')
|
||||
response['Content-Disposition'] = 'attachment; filename="%s.pdf"' % invoice_id
|
||||
response.write(pdf)
|
||||
return response
|
||||
|
||||
|
||||
class InvoicePayView(DetailView):
|
||||
|
||||
@method_decorator(csrf_exempt)
|
||||
def dispatch(self, *args, **kwargs):
|
||||
return super(InvoicePayView, self).dispatch(*args, **kwargs)
|
||||
|
||||
@utils.to_json()
|
||||
@utils.protected_api('can_access')
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
data = json.loads(request.body)
|
||||
return {'data': self.object.pay_invoice(kwargs['regie_id'],
|
||||
kwargs['invoice_id'], data['transaction_id'],
|
||||
data['transaction_date'])}
|
|
@ -162,7 +162,7 @@ INVOICE_PAYMENT_RESPONSE = '''
|
|||
|
||||
|
||||
def test_authentication_failed(app, setup):
|
||||
with mock.patch('passerelle.contrib.teamnet_axel.views.FamilyView.get_family_id') as mocked:
|
||||
with mock.patch('passerelle.contrib.teamnet_axel.models.TeamnetAxel.get_family_id') as mocked:
|
||||
mocked.side_effect = APIError('authentication failed')
|
||||
NameID = 'abcd' * 8
|
||||
resp = app.get('/teamnet-axel/test/family/', params={'NameID': NameID})
|
||||
|
|
Loading…
Reference in New Issue