Projet

Général

Profil

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

Lauréline Guérin, 06 décembre 2019 10:10

Télécharger (12,8 ko)

Voir les différences:

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

 combo/apps/lingo/manager_views.py             |  33 +++-
 .../lingo/basketitem_error_list.html          |  50 ++++++
 .../templates/lingo/transaction_list.html     |   1 +
 combo/apps/lingo/urls.py                      |   8 +-
 tests/test_lingo_manager.py                   | 166 ++++++++++++++++++
 5 files changed, 253 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
            .filter(regie__webservice_url='')
124
            .order_by())
125
        queryset1 = (
126
            queryset
127
            .filter(
128
                notification_date__isnull=True,
129
                cancellation_date__isnull=True,
130
                payment_date__lt=now() - datetime.timedelta(minutes=300)))
131
        queryset2 = queryset.filter(transaction_status=eopayment.ERROR)
132
        return queryset1.union(queryset2).order_by('-creation_date')
133

  
134

  
106 135
def download_transactions_csv(request):
107 136
    if request.method == 'POST':
108 137
        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>{% if object.source_url %}<a href="{{ object.source_url }}">{{ object.subject }}</a>{% else %}{{ object.subject }}{% endif %}</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.
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',
234
        slug='test-regie',
235
        payment_backend=payment_backend)
236
    user = User.objects.create_user('dimebag', 'dime@bag.pan', 'pwd')
237
    regie_with_webservice_url = Regie.objects.create(
238
        label='test-regie2',
239
        slug='test-regie2',
240
        payment_backend=payment_backend,
241
        webservice_url='http://example.net')
242

  
243
    date_now = now()
244
    date_in_past = date_now - datetime.timedelta(minutes=300)
245

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

  
269
    # item with payment_date and notification_date, status ERROR
270
    # => displayed
271
    item2 = BasketItem.objects.create(
272
        user=user,
273
        regie=regie,
274
        subject='item 2',
275
        source_url='',
276
        amount=2,
277
        payment_date=date_in_past,
278
        notification_date=date_in_past)
279
    transaction21 = Transaction.objects.create(
280
        status=eopayment.ERROR,
281
        order_id='order id 2.1',
282
        bank_transaction_id='bank_id_21',
283
        amount=2)
284
    transaction21.items.add(item2)
285
    transaction22 = Transaction.objects.create(
286
        status=eopayment.ERROR,
287
        order_id='order id 2.2',
288
        bank_transaction_id='bank_id_22',
289
        amount=2)
290
    transaction22.items.add(item2)
291
    # the same but for the other regie
292
    item2_bis = BasketItem.objects.create(
293
        user=user,
294
        regie=regie_with_webservice_url,
295
        subject='item 2 bis',
296
        source_url='',
297
        amount=22222,
298
        payment_date=date_in_past,
299
        notification_date=date_in_past)
300
    transaction2_bis = Transaction.objects.create(
301
        status=eopayment.ERROR,
302
        order_id='order id 2 bis',
303
        bank_transaction_id='bank_id_2_bis',
304
        amount=22222)
305
    transaction2_bis.items.add(item2_bis)
306

  
307
    # item without dates, status ERROR
308
    # => displayed
309
    item3 = BasketItem.objects.create(
310
        user=user,
311
        regie=regie,
312
        subject='item 3',
313
        source_url='http://example.net/3',
314
        amount=3)
315
    transaction3 = Transaction.objects.create(
316
        status=eopayment.ERROR,
317
        order_id='order id 3',
318
        bank_transaction_id='bank_id_3',
319
        amount=3)
320
    transaction3.items.add(item3)
321

  
322
    # item with payment_date but no notification_date, too young
323
    # => not displayed
324
    item4 = BasketItem.objects.create(
325
        user=user,
326
        regie=regie,
327
        subject='item 4',
328
        source_url='http://example.net/4',
329
        amount=4,
330
        payment_date=date_now,
331
        notification_date=None)
332
    transaction4 = Transaction.objects.create(
333
        order_id='order id 4',
334
        bank_transaction_id='bank_id_4',
335
        amount=4)
336
    transaction4.items.add(item4)
337

  
338
    # item with payment_date but no notification_date, in the past
339
    # => displayed
340
    item5 = BasketItem.objects.create(
341
        user=user,
342
        regie=regie,
343
        subject='item 5',
344
        source_url='http://example.net/5',
345
        amount=5,
346
        payment_date=date_in_past,
347
        notification_date=None)
348
    transaction5 = Transaction.objects.create(
349
        order_id='order id 5',
350
        bank_transaction_id='bank_id_5',
351
        amount=5)
352
    transaction5.items.add(item5)
353
    # the same but for the other regie
354
    item5_bis = BasketItem.objects.create(
355
        user=user,
356
        regie=regie_with_webservice_url,
357
        subject='item 5 bis',
358
        source_url='http://example.net/5_bis',
359
        amount=55555,
360
        payment_date=date_in_past,
361
        notification_date=None)
362
    transaction5_bis = Transaction.objects.create(
363
        order_id='order id 5 bis',
364
        bank_transaction_id='bank_id_5_bis',
365
        amount=55555)
366
    transaction5_bis.items.add(item5_bis)
367

  
368
    # item with payment_date, no notification_date, but a cancellation_date, in the past
369
    # => not displayed
370
    item6 = BasketItem.objects.create(
371
        user=user,
372
        regie=regie,
373
        subject='item 6',
374
        source_url='http://example.net/6',
375
        amount=6,
376
        payment_date=date_in_past,
377
        notification_date=None,
378
        cancellation_date=date_now)
379
    transaction6 = Transaction.objects.create(
380
        order_id='order id 6',
381
        bank_transaction_id='bank_id_6',
382
        amount=6)
383
    transaction6.items.add(item6)
384

  
385
    app = login(app)
386
    resp = app.get('/manage/lingo/payments/error/', status=200)
387
    assert list(resp.context['object_list']) == [item5, item3, item2]
388
    assert '<a href="%s">' % item5.source_url in resp.text
389
    assert '<a href="%s">' % item3.source_url in resp.text
390
    assert '<a href="%s">' % item2.source_url not in resp.text
391
    assert '/manage/lingo/?q=%s' % transaction5.bank_transaction_id in resp.text
392
    assert '/manage/lingo/?q=%s' % transaction3.bank_transaction_id not in resp.text
393
    assert '/manage/lingo/?q=%s' % transaction22.bank_transaction_id not in resp.text
394

  
395

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