Projet

Général

Profil

0001-lingo-allow-arbitrary-date-for-deferred-payment-2704.patch

Emmanuel Cazenave, 10 octobre 2018 16:42

Télécharger (8,18 ko)

Voir les différences:

Subject: [PATCH] lingo: allow arbitrary date for deferred payment (#27045)

 .../0032_basketitem_capture_date.py           | 20 ++++++
 combo/apps/lingo/models.py                    |  1 +
 combo/apps/lingo/views.py                     | 34 ++++++++--
 tests/test_lingo_payment.py                   | 65 +++++++++++++++++++
 4 files changed, 115 insertions(+), 5 deletions(-)
 create mode 100644 combo/apps/lingo/migrations/0032_basketitem_capture_date.py
combo/apps/lingo/migrations/0032_basketitem_capture_date.py
1
# -*- coding: utf-8 -*-
2
# Generated by Django 1.11.15 on 2018-10-05 15:33
3
from __future__ import unicode_literals
4

  
5
from django.db import migrations, models
6

  
7

  
8
class Migration(migrations.Migration):
9

  
10
    dependencies = [
11
        ('lingo', '0031_basketitem_waiting_date'),
12
    ]
13

  
14
    operations = [
15
        migrations.AddField(
16
            model_name='basketitem',
17
            name='capture_date',
18
            field=models.DateField(null=True),
19
        ),
20
    ]
combo/apps/lingo/models.py
327 327
    waiting_date = models.DateTimeField(null=True)
328 328
    payment_date = models.DateTimeField(null=True)
329 329
    notification_date = models.DateTimeField(null=True)
330
    capture_date = models.DateField(null=True)
330 331

  
331 332
    class Meta:
332 333
        ordering = ['regie', 'extra_fee', 'subject']
combo/apps/lingo/views.py
26 26
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseBadRequest
27 27
from django.http import HttpResponseForbidden, Http404, JsonResponse
28 28
from django.template.response import TemplateResponse
29
from django.utils import timezone
29
from django.utils import timezone, dateparse
30 30
from django.utils.encoding import force_text
31 31
from django.views.decorators.csrf import csrf_exempt
32 32
from django.views.generic import View, DetailView, ListView, TemplateView
......
161 161
        item.subject = request_body.get('display_name')
162 162
        item.source_url = request_body.get('url') or ''
163 163

  
164
        if 'capture_date' in request_body:
165
            try:
166
                # parse_date returns None when the string format is invalid
167
                capture_date_err = False
168
                item.capture_date = dateparse.parse_date(request_body['capture_date'])
169
            except TypeError:
170
                capture_date_err = True
171
            if item.capture_date is None or capture_date_err:
172
                return HttpResponseBadRequest(
173
                    'Bad format for capture date, it should be yyyy-mm-dd.')
174

  
164 175
        item.save()
165 176
        item.regie.compute_extra_fees(user=item.user)
166 177

  
......
328 339
        transaction.amount = total_amount
329 340

  
330 341
        payment = get_eopayment_object(request, regie)
331

  
332
        (order_id, kind, data) = payment.request(total_amount, email=email,
333
                                            first_name=firstname,
334
                                            last_name=lastname)
342
        kwargs = {
343
            'email': email, 'first_name': firstname, 'last_name': lastname
344
        }
345
        if items:
346
            capture_date = items[0].capture_date
347
            if capture_date:
348
                kwargs['capture_date'] = capture_date.isoformat()
349
        (order_id, kind, data) = payment.request(total_amount, **kwargs)
335 350
        logger = logging.getLogger(__name__)
336 351
        logger.info(u'emitted payment request with id %s', smart_text(order_id), extra={
337 352
            'eopayment_order_id': smart_text(order_id), 'eopayment_data': repr(data)})
......
382 397
            regie.compute_extra_fees(user=user)
383 398
            items = BasketItem.get_items_to_be_paid(user=user).filter(regie=regie)
384 399

  
400
        if items:
401
            capture_date = items[0].capture_date
402
            for item in items:
403
                if item.capture_date != capture_date:
404
                    messages.error(
405
                        request,
406
                        _(u'Invalid grouping for basket items: different capture dates.'))
407
                    return HttpResponseRedirect(next_url)
408

  
385 409
        if not user and not request.POST.get('email'):
386 410
            messages.warning(request, _(u'You must give an email address.'))
387 411
            return HttpResponseRedirect(request.POST.get('item_url'))
tests/test_lingo_payment.py
233 233
    resp = app.post_json(url, params=data, status=400)
234 234
    assert resp.text == 'Unknown regie'
235 235

  
236

  
237
def test_basket_item_with_capture_date(app, user, regie, basket_page, monkeypatch):
238
    User.objects.get_or_create(email=user.email)
239
    url = '%s?email=%s' % (reverse('api-add-basket-item'), user.email)
240
    capture_date = timezone.now().date()
241
    data = {
242
        'amount': 10, 'capture_date': capture_date.isoformat(),
243
        'display_name': 'test item'
244
    }
245
    url = sign_url(url, settings.LINGO_API_SIGN_KEY)
246
    resp = app.post_json(url, params=data)
247
    assert resp.status_code == 200
248
    assert BasketItem.objects.all()[0].capture_date == capture_date
249

  
250
    resp = login(app).get('/test_basket_cell/')
251
    import eopayment
252
    eopayment_mock = mock.Mock(
253
        return_value=('orderid', eopayment.URL, 'http://dummy-payment.demo.entrouvert.com/'))
254
    monkeypatch.setattr(eopayment.Payment, 'request', eopayment_mock)
255
    resp = resp.form.submit()
256
    assert resp.status_code == 302
257
    location = urlparse.urlparse(resp.location)
258
    assert location.path == '/'
259
    assert location.hostname == 'dummy-payment.demo.entrouvert.com'
260
    eopayment_mock.assert_called_once_with(
261
        Decimal(10), email=user.email, first_name=user.first_name, last_name=user.last_name,
262
        capture_date=capture_date.isoformat())
263

  
264

  
265
@pytest.mark.parametrize("invalid_capture_date", [8, '', 'not-a-date'])
266
def test_add_basket_capture_date_format(app, user, regie, invalid_capture_date):
267
    url = '%s?email=%s' % (reverse('api-add-basket-item'), user.email)
268
    data = {'amount': 10, 'display_name': 'test item'}
269
    data['capture_date'] = invalid_capture_date
270
    url = sign_url(url, settings.LINGO_API_SIGN_KEY)
271
    resp = app.post_json(url, params=data, status=400)
272
    assert 'Bad format for capture date, it should be yyyy-mm-dd.' in resp.content
273

  
274

  
275
def test_cant_pay_if_different_capture_date(app, basket_page, regie, user):
276
    capture1 = (timezone.now() + timedelta(days=1)).date()
277
    capture2 = (timezone.now() + timedelta(days=2)).date()
278
    items = {
279
        'item1': {
280
            'amount': '10.5', 'capture_date': capture1.isoformat(),
281
            'source_url': 'http://example.org/item/1'
282
        },
283
        'item2': {
284
            'amount': '42', 'capture_date': capture2.isoformat(),
285
            'source_url': 'http://example.org/item/2'},
286
    }
287
    b_items = []
288
    for subject, details in items.items():
289
        b_item = BasketItem.objects.create(
290
            user=user, regie=regie, subject=subject, **details)
291
        b_items.append(b_item.pk)
292

  
293
    resp = login(app).get('/test_basket_cell/')
294
    resp = resp.form.submit()
295
    assert resp.status_code == 302
296
    assert urlparse.urlparse(resp.location).path == '/test_basket_cell/'
297
    resp = resp.follow()
298
    assert "Invalid grouping for basket items: different capture dates." in resp.content
299

  
300

  
236 301
def test_pay_single_basket_item(app, key, regie, user, john_doe):
237 302
    page = Page(title='xxx', slug='index', template_name='standard')
238 303
    page.save()
239
-