lingo: new page to display payments in error (#21626)

This commit is contained in:
Lauréline Guérin 2019-11-29 15:35:09 +01:00
parent 850bab5600
commit 964d0a87aa
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
5 changed files with 253 additions and 5 deletions

View File

@ -20,8 +20,9 @@ from dateutil import parser as date_parser
from django.core.urlresolvers import reverse_lazy
from django.db.models import Q
from django.db.models.expressions import RawSQL
from django.utils import six
from django.utils.timezone import make_aware
from django.utils.timezone import make_aware, now
from django.views.generic import CreateView, UpdateView, ListView, DeleteView
from django.http import HttpResponse
from django.template.response import TemplateResponse
@ -30,7 +31,7 @@ import eopayment
from .forms import RegieForm
from .forms import TransactionExportForm
from .models import PaymentBackend, Regie, Transaction
from .models import BasketItem, PaymentBackend, Regie, Transaction
class RegieListView(ListView):
@ -103,6 +104,34 @@ class TransactionListView(ListView):
return qs
class BasketItemErrorListView(ListView):
model = BasketItem
template_name = 'lingo/basketitem_error_list.html'
paginate_by = 10
def get_queryset(self):
raw = (
'SELECT %s FROM lingo_transaction '
'INNER JOIN lingo_transaction_items '
'ON "lingo_transaction"."id" = "lingo_transaction_items"."transaction_id" '
'AND "lingo_transaction_items"."basketitem_id"="lingo_basketitem"."id" '
'ORDER BY start_date DESC LIMIT 1')
queryset = (
BasketItem.objects
.annotate(bank_transaction_id=RawSQL(raw % 'bank_transaction_id', []))
.annotate(transaction_status=RawSQL(raw % 'status', []))
.filter(regie__webservice_url='')
.order_by())
queryset1 = (
queryset
.filter(
notification_date__isnull=True,
cancellation_date__isnull=True,
payment_date__lt=now() - datetime.timedelta(minutes=300)))
queryset2 = queryset.filter(transaction_status=eopayment.ERROR)
return queryset1.union(queryset2).order_by('-creation_date')
def download_transactions_csv(request):
if request.method == 'POST':
form = TransactionExportForm(data=request.POST)

View File

@ -0,0 +1,50 @@
{% extends "lingo/manager_base.html" %}
{% load i18n %}
{% block appbar %}
<h2>{% trans 'Payments in error' %}</h2>
{% endblock %}
{% block breadcrumb %}
{{ block.super }}
<a href="{% url 'lingo-manager-payment-error-list' %}">{% trans 'Payments in error' %}</a>
{% endblock %}
{% block content %}
{% if object_list %}
<table class="main">
<thead>
<tr>
<th>{% trans 'Item' %}</th>
<th>{% trans 'Amount' %}</th>
<th colspan="2">{% trans 'Date' %}</th>
</tr>
</thead>
<tbody>
{% for object in object_list %}
<tr>
<td>{% if object.source_url %}<a href="{{ object.source_url }}">{{ object.subject }}</a>{% else %}{{ object.subject }}{% endif %}</td>
<td class="price">{{ object.amount }} €</td>
<td>{{ object.payment_date }}</td>
<td>
{% if object.transaction_status != 99 %}
<a href="{% url 'lingo-manager-homepage' %}?q={{ object.bank_transaction_id }}">{% trans "See transaction" %}</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% include "gadjo/pagination.html" %}
{% else %}
<div class="big-msg-info">
{% blocktrans %}
This site doesn't have any payment in error.
{% endblocktrans %}
</div>
{% endif %}
{% endblock %}

View File

@ -4,6 +4,7 @@
{% block appbar %}
<h2>{% trans 'Transactions' %}</h2>
<span class="actions">
<a href="{% url 'lingo-manager-payment-error-list' %}">{% trans 'Payments in error' %}</a>
<a href="{% url 'lingo-manager-paymentbackend-list' %}">{% trans 'Payment backends' %}</a>
<a href="{% url 'lingo-manager-regie-list' %}">{% trans 'Regies' %}</a>
<a rel="popup" href="{% url 'lingo-manager-transactions-download' %}" data-autoclose-dialog="true">{% trans 'download CSV' %}</a>

View File

@ -23,12 +23,14 @@ from .views import (RegiesApiView, AddBasketItemApiView, PayView, CallbackView,
RemoveBasketItemApiView, ValidateTransactionApiView,
CancelTransactionApiView, SelfInvoiceView, BasketItemPayView)
from .manager_views import (RegieListView, RegieCreateView, RegieUpdateView,
RegieDeleteView, TransactionListView, download_transactions_csv,
PaymentBackendListView, PaymentBackendCreateView,
PaymentBackendUpdateView, PaymentBackendDeleteView)
RegieDeleteView, TransactionListView, BasketItemErrorListView,
download_transactions_csv, PaymentBackendListView,
PaymentBackendCreateView, PaymentBackendUpdateView,
PaymentBackendDeleteView)
lingo_manager_urls = [
url('^$', TransactionListView.as_view(), name='lingo-manager-homepage'),
url('^payments/error/$', BasketItemErrorListView.as_view(), name='lingo-manager-payment-error-list'),
url('^transactions/download-csv/$', download_transactions_csv, name='lingo-manager-transactions-download'),
url('^regies/$', RegieListView.as_view(), name='lingo-manager-regie-list'),
url('^regies/add/$', RegieCreateView.as_view(), name='lingo-manager-regie-add'),

View File

@ -227,6 +227,172 @@ def test_transactions_search(app, admin_user):
assert resp.text.count('<tr') == 0
assert 'No transactions found matching' in resp.text
def test_basketitem_error_list(app, admin_user, payment_backend):
regie = Regie.objects.create(
label='test-regie',
slug='test-regie',
payment_backend=payment_backend)
user = User.objects.create_user('dimebag', 'dime@bag.pan', 'pwd')
regie_with_webservice_url = Regie.objects.create(
label='test-regie2',
slug='test-regie2',
payment_backend=payment_backend,
webservice_url='http://example.net')
date_now = now()
date_in_past = date_now - datetime.timedelta(minutes=300)
# item with payment_date and notification_date, status PAID
# => not displayed
item1 = BasketItem.objects.create(
user=user,
regie=regie,
subject='item 1',
source_url='http://example.net/1',
amount=1,
payment_date=date_in_past,
notification_date=date_in_past)
transaction11 = Transaction.objects.create(
status=eopayment.ERROR,
order_id='order id 1.1',
bank_transaction_id='bank_id_11',
amount=1)
transaction11.items.add(item1)
transaction12 = Transaction.objects.create(
status=eopayment.PAID,
order_id='order id 1.2',
bank_transaction_id='bank_id_12',
amount=1)
transaction12.items.add(item1)
# item with payment_date and notification_date, status ERROR
# => displayed
item2 = BasketItem.objects.create(
user=user,
regie=regie,
subject='item 2',
source_url='',
amount=2,
payment_date=date_in_past,
notification_date=date_in_past)
transaction21 = Transaction.objects.create(
status=eopayment.ERROR,
order_id='order id 2.1',
bank_transaction_id='bank_id_21',
amount=2)
transaction21.items.add(item2)
transaction22 = Transaction.objects.create(
status=eopayment.ERROR,
order_id='order id 2.2',
bank_transaction_id='bank_id_22',
amount=2)
transaction22.items.add(item2)
# the same but for the other regie
item2_bis = BasketItem.objects.create(
user=user,
regie=regie_with_webservice_url,
subject='item 2 bis',
source_url='',
amount=22222,
payment_date=date_in_past,
notification_date=date_in_past)
transaction2_bis = Transaction.objects.create(
status=eopayment.ERROR,
order_id='order id 2 bis',
bank_transaction_id='bank_id_2_bis',
amount=22222)
transaction2_bis.items.add(item2_bis)
# item without dates, status ERROR
# => displayed
item3 = BasketItem.objects.create(
user=user,
regie=regie,
subject='item 3',
source_url='http://example.net/3',
amount=3)
transaction3 = Transaction.objects.create(
status=eopayment.ERROR,
order_id='order id 3',
bank_transaction_id='bank_id_3',
amount=3)
transaction3.items.add(item3)
# item with payment_date but no notification_date, too young
# => not displayed
item4 = BasketItem.objects.create(
user=user,
regie=regie,
subject='item 4',
source_url='http://example.net/4',
amount=4,
payment_date=date_now,
notification_date=None)
transaction4 = Transaction.objects.create(
order_id='order id 4',
bank_transaction_id='bank_id_4',
amount=4)
transaction4.items.add(item4)
# item with payment_date but no notification_date, in the past
# => displayed
item5 = BasketItem.objects.create(
user=user,
regie=regie,
subject='item 5',
source_url='http://example.net/5',
amount=5,
payment_date=date_in_past,
notification_date=None)
transaction5 = Transaction.objects.create(
order_id='order id 5',
bank_transaction_id='bank_id_5',
amount=5)
transaction5.items.add(item5)
# the same but for the other regie
item5_bis = BasketItem.objects.create(
user=user,
regie=regie_with_webservice_url,
subject='item 5 bis',
source_url='http://example.net/5_bis',
amount=55555,
payment_date=date_in_past,
notification_date=None)
transaction5_bis = Transaction.objects.create(
order_id='order id 5 bis',
bank_transaction_id='bank_id_5_bis',
amount=55555)
transaction5_bis.items.add(item5_bis)
# item with payment_date, no notification_date, but a cancellation_date, in the past
# => not displayed
item6 = BasketItem.objects.create(
user=user,
regie=regie,
subject='item 6',
source_url='http://example.net/6',
amount=6,
payment_date=date_in_past,
notification_date=None,
cancellation_date=date_now)
transaction6 = Transaction.objects.create(
order_id='order id 6',
bank_transaction_id='bank_id_6',
amount=6)
transaction6.items.add(item6)
app = login(app)
resp = app.get('/manage/lingo/payments/error/', status=200)
assert list(resp.context['object_list']) == [item5, item3, item2]
assert '<a href="%s">' % item5.source_url in resp.text
assert '<a href="%s">' % item3.source_url in resp.text
assert '<a href="%s">' % item2.source_url not in resp.text
assert '/manage/lingo/?q=%s' % transaction5.bank_transaction_id in resp.text
assert '/manage/lingo/?q=%s' % transaction3.bank_transaction_id not in resp.text
assert '/manage/lingo/?q=%s' % transaction22.bank_transaction_id not in resp.text
def test_configure_tipi_cell(app, admin_user):
page = Page(title='tipi', slug='tipi', template_name='standard')
page.save()