Projet

Général

Profil

0001-lingo-new-page-to-display-payments-in-error-21626.patch

Lauréline Guérin, 02 décembre 2019 10:26

Télécharger (11,5 ko)

Voir les différences:

Subject: [PATCH 1/3] lingo: new page to display payments in error (#21626)

 combo/apps/lingo/manager_views.py             |  32 ++++-
 .../lingo/basketitem_error_list.html          |  50 +++++++
 .../templates/lingo/transaction_list.html     |   1 +
 combo/apps/lingo/urls.py                      |   8 +-
 tests/test_lingo_manager.py                   | 130 ++++++++++++++++++
 5 files changed, 216 insertions(+), 5 deletions(-)
 create mode 100644 combo/apps/lingo/templates/lingo/basketitem_error_list.html
combo/apps/lingo/manager_views.py
20 20

  
21 21
from django.core.urlresolvers import reverse_lazy
22 22
from django.db.models import Q
23
from django.db.models.expressions import RawSQL
23 24
from django.utils import six
24
from django.utils.timezone import make_aware
25
from django.utils.timezone import make_aware, now
25 26
from django.views.generic import CreateView, UpdateView, ListView, DeleteView
26 27
from django.http import HttpResponse
27 28
from django.template.response import TemplateResponse
......
30 31

  
31 32
from .forms import RegieForm
32 33
from .forms import TransactionExportForm
33
from .models import PaymentBackend, Regie, Transaction
34
from .models import BasketItem, PaymentBackend, Regie, Transaction
34 35

  
35 36

  
36 37
class RegieListView(ListView):
......
103 104
        return qs
104 105

  
105 106

  
107
class BasketItemErrorListView(ListView):
108
    model = BasketItem
109
    template_name = 'lingo/basketitem_error_list.html'
110
    paginate_by = 10
111

  
112
    def get_queryset(self):
113
        raw = (
114
            'SELECT %s FROM lingo_transaction '
115
            'INNER JOIN lingo_transaction_items '
116
            'ON "lingo_transaction"."id" = "lingo_transaction_items"."transaction_id" '
117
            'AND "lingo_transaction_items"."basketitem_id"="lingo_basketitem"."id" '
118
            'ORDER BY start_date DESC LIMIT 1')
119
        queryset = (
120
            BasketItem.objects
121
            .annotate(bank_transaction_id=RawSQL(raw % 'bank_transaction_id', []))
122
            .annotate(transaction_status=RawSQL(raw % 'status', []))
123
            .order_by())
124
        queryset1 = (
125
            queryset
126
            .filter(
127
                notification_date__isnull=True,
128
                cancellation_date__isnull=True,
129
                payment_date__lt=now() - datetime.timedelta(minutes=300)))
130
        queryset2 = queryset.filter(transaction_status=eopayment.ERROR)
131
        return queryset1.union(queryset2).order_by('-creation_date')
132

  
133

  
106 134
def download_transactions_csv(request):
107 135
    if request.method == 'POST':
108 136
        form = TransactionExportForm(data=request.POST)
combo/apps/lingo/templates/lingo/basketitem_error_list.html
1
{% extends "lingo/manager_base.html" %}
2
{% load i18n %}
3

  
4
{% block appbar %}
5
<h2>{% trans 'Payments in error' %}</h2>
6
{% endblock %}
7

  
8
{% block breadcrumb %}
9
{{ block.super }}
10
<a href="{% url 'lingo-manager-payment-error-list' %}">{% trans 'Payments in error' %}</a>
11
{% endblock %}
12

  
13
{% block content %}
14

  
15
{% if object_list %}
16
<table class="main">
17
<thead>
18
  <tr>
19
   <th>{% trans 'Item' %}</th>
20
   <th>{% trans 'Amount' %}</th>
21
   <th colspan="2">{% trans 'Date' %}</th>
22
  </tr>
23
</thead>
24
<tbody>
25
{% for object in object_list %}
26
<tr>
27
  <td><a href="{{ object.source_url }}">{{ object.subject }}</a></td>
28
  <td class="price">{{ object.amount }} €</td>
29
  <td>{{ object.payment_date }}</td>
30
  <td>
31
    {% if object.transaction_status != 99 %}
32
      <a href="{% url 'lingo-manager-homepage' %}?q={{ object.bank_transaction_id }}">{% trans "See transaction" %}</a>
33
    {% endif %}
34
  </td>
35
</tr>
36
{% endfor %}
37
</tbody>
38
</table>
39

  
40
{% include "gadjo/pagination.html" %}
41

  
42
{% else %}
43
<div class="big-msg-info">
44
  {% blocktrans %}
45
  This site doesn't have any payment in error yet.
46
  {% endblocktrans %}
47
</div>
48
{% endif %}
49

  
50
{% endblock %}
combo/apps/lingo/templates/lingo/transaction_list.html
4 4
{% block appbar %}
5 5
<h2>{% trans 'Transactions' %}</h2>
6 6
<span class="actions">
7
<a href="{% url 'lingo-manager-payment-error-list' %}">{% trans 'Payments in error' %}</a>
7 8
<a href="{% url 'lingo-manager-paymentbackend-list' %}">{% trans 'Payment backends' %}</a>
8 9
<a href="{% url 'lingo-manager-regie-list' %}">{% trans 'Regies' %}</a>
9 10
<a rel="popup" href="{% url 'lingo-manager-transactions-download' %}" data-autoclose-dialog="true">{% trans 'download CSV' %}</a>
combo/apps/lingo/urls.py
23 23
                    RemoveBasketItemApiView, ValidateTransactionApiView,
24 24
                    CancelTransactionApiView, SelfInvoiceView, BasketItemPayView)
25 25
from .manager_views import (RegieListView, RegieCreateView, RegieUpdateView,
26
                            RegieDeleteView, TransactionListView, download_transactions_csv,
27
                            PaymentBackendListView, PaymentBackendCreateView,
28
                            PaymentBackendUpdateView, PaymentBackendDeleteView)
26
                            RegieDeleteView, TransactionListView, BasketItemErrorListView,
27
                            download_transactions_csv, PaymentBackendListView,
28
                            PaymentBackendCreateView, PaymentBackendUpdateView,
29
                            PaymentBackendDeleteView)
29 30

  
30 31
lingo_manager_urls = [
31 32
    url('^$', TransactionListView.as_view(), name='lingo-manager-homepage'),
33
    url('^payments/error/$', BasketItemErrorListView.as_view(), name='lingo-manager-payment-error-list'),
32 34
    url('^transactions/download-csv/$', download_transactions_csv, name='lingo-manager-transactions-download'),
33 35
    url('^regies/$', RegieListView.as_view(), name='lingo-manager-regie-list'),
34 36
    url('^regies/add/$', RegieCreateView.as_view(), name='lingo-manager-regie-add'),
tests/test_lingo_manager.py
227 227
    assert resp.text.count('<tr') == 0
228 228
    assert 'No transactions found matching' in resp.text
229 229

  
230

  
231
def test_basketitem_error_list(app, admin_user, payment_backend):
232
    regie = Regie.objects.create(
233
        label='test-regie', slug='test-regie', payment_backend=payment_backend)
234
    user = User.objects.create_user('dimebag', 'dime@bag.pan', 'pwd')
235

  
236
    date_now = now()
237
    date_in_past = date_now - datetime.timedelta(minutes=300)
238

  
239
    # item with payment_date and notification_date, status PAID
240
    # => not displayed
241
    item1 = BasketItem.objects.create(
242
        user=user,
243
        regie=regie,
244
        subject='item 1',
245
        source_url='http://example.net/1',
246
        amount=1,
247
        payment_date=date_in_past,
248
        notification_date=date_in_past)
249
    transaction11 = Transaction.objects.create(
250
        status=eopayment.ERROR,
251
        order_id='order id 1.1',
252
        bank_transaction_id='bank_id_11',
253
        amount=1)
254
    transaction11.items.add(item1)
255
    transaction12 = Transaction.objects.create(
256
        status=eopayment.PAID,
257
        order_id='order id 1.2',
258
        bank_transaction_id='bank_id_12',
259
        amount=1)
260
    transaction12.items.add(item1)
261

  
262
    # item with payment_date and notification_date, status ERROR
263
    # => displayed
264
    item2 = BasketItem.objects.create(
265
        user=user,
266
        regie=regie,
267
        subject='item 2',
268
        source_url='http://example.net/2',
269
        amount=2,
270
        payment_date=date_in_past,
271
        notification_date=date_in_past)
272
    transaction21 = Transaction.objects.create(
273
        status=eopayment.ERROR,
274
        order_id='order id 2.1',
275
        bank_transaction_id='bank_id_21',
276
        amount=2)
277
    transaction21.items.add(item2)
278
    transaction22 = Transaction.objects.create(
279
        status=eopayment.ERROR,
280
        order_id='order id 2.2',
281
        bank_transaction_id='bank_id_22',
282
        amount=2)
283
    transaction22.items.add(item2)
284

  
285
    # item without dates, status ERROR
286
    # => displayed
287
    item3 = BasketItem.objects.create(
288
        user=user,
289
        regie=regie,
290
        subject='item 3',
291
        source_url='http://example.net/3',
292
        amount=3)
293
    transaction3 = Transaction.objects.create(
294
        status=eopayment.ERROR,
295
        order_id='order id 3',
296
        bank_transaction_id='bank_id_3',
297
        amount=3)
298
    transaction3.items.add(item3)
299

  
300
    # item with payment_date but no notification_date, too young
301
    # => not displayed
302
    item4 = BasketItem.objects.create(
303
        user=user,
304
        regie=regie,
305
        subject='item 4',
306
        source_url='http://example.net/4',
307
        amount=4,
308
        payment_date=date_now,
309
        notification_date=None)
310
    transaction4 = Transaction.objects.create(
311
        order_id='order id 4',
312
        bank_transaction_id='bank_id_4',
313
        amount=4)
314
    transaction4.items.add(item4)
315

  
316
    # item with payment_date but no notification_date, in the past
317
    # => displayed
318
    item5 = BasketItem.objects.create(
319
        user=user,
320
        regie=regie,
321
        subject='item 5',
322
        source_url='http://example.net/5',
323
        amount=5,
324
        payment_date=date_in_past,
325
        notification_date=None)
326
    transaction5 = Transaction.objects.create(
327
        order_id='order id 5',
328
        bank_transaction_id='bank_id_5',
329
        amount=5)
330
    transaction5.items.add(item5)
331

  
332
    # item with payment_date, no notification_date, but a cancellation_date, in the past
333
    # => not displayed
334
    item6 = BasketItem.objects.create(
335
        user=user,
336
        regie=regie,
337
        subject='item 6',
338
        source_url='http://example.net/6',
339
        amount=6,
340
        payment_date=date_in_past,
341
        notification_date=None,
342
        cancellation_date=date_now)
343
    transaction6 = Transaction.objects.create(
344
        order_id='order id 6',
345
        bank_transaction_id='bank_id_6',
346
        amount=6)
347
    transaction6.items.add(item6)
348

  
349
    app = login(app)
350
    resp = app.get('/manage/lingo/payments/error/', status=200)
351
    assert list(resp.context['object_list']) == [item5, item3, item2]
352
    assert '<a href="%s">' % item5.source_url in resp.text
353
    assert '<a href="%s">' % item3.source_url in resp.text
354
    assert '<a href="%s">' % item2.source_url in resp.text
355
    assert '/manage/lingo/?q=%s' % transaction5.bank_transaction_id in resp.text
356
    assert '/manage/lingo/?q=%s' % transaction3.bank_transaction_id not in resp.text
357
    assert '/manage/lingo/?q=%s' % transaction22.bank_transaction_id not in resp.text
358

  
359

  
230 360
def test_configure_tipi_cell(app, admin_user):
231 361
    page = Page(title='tipi', slug='tipi', template_name='standard')
232 362
    page.save()
233
-