lingo: allow arbitrary date for deferred payment (#27045)

This commit is contained in:
Emmanuel Cazenave 2018-10-05 18:36:45 +02:00
parent 9a0b497f7a
commit d40cb57e27
4 changed files with 115 additions and 5 deletions

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.15 on 2018-10-05 15:33
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('lingo', '0031_basketitem_waiting_date'),
]
operations = [
migrations.AddField(
model_name='basketitem',
name='capture_date',
field=models.DateField(null=True),
),
]

View File

@ -327,6 +327,7 @@ class BasketItem(models.Model):
waiting_date = models.DateTimeField(null=True)
payment_date = models.DateTimeField(null=True)
notification_date = models.DateTimeField(null=True)
capture_date = models.DateField(null=True)
class Meta:
ordering = ['regie', 'extra_fee', 'subject']

View File

@ -26,7 +26,7 @@ from django.core.urlresolvers import reverse
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseBadRequest
from django.http import HttpResponseForbidden, Http404, JsonResponse
from django.template.response import TemplateResponse
from django.utils import timezone
from django.utils import timezone, dateparse
from django.utils.encoding import force_text
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import View, DetailView, ListView, TemplateView
@ -161,6 +161,17 @@ class AddBasketItemApiView(View):
item.subject = request_body.get('display_name')
item.source_url = request_body.get('url') or ''
if 'capture_date' in request_body:
try:
# parse_date returns None when the string format is invalid
capture_date_err = False
item.capture_date = dateparse.parse_date(request_body['capture_date'])
except TypeError:
capture_date_err = True
if item.capture_date is None or capture_date_err:
return HttpResponseBadRequest(
'Bad format for capture date, it should be yyyy-mm-dd.')
item.save()
item.regie.compute_extra_fees(user=item.user)
@ -328,10 +339,14 @@ class PayMixin(object):
transaction.amount = total_amount
payment = get_eopayment_object(request, regie)
(order_id, kind, data) = payment.request(total_amount, email=email,
first_name=firstname,
last_name=lastname)
kwargs = {
'email': email, 'first_name': firstname, 'last_name': lastname
}
if items:
capture_date = items[0].capture_date
if capture_date:
kwargs['capture_date'] = capture_date
(order_id, kind, data) = payment.request(total_amount, **kwargs)
logger = logging.getLogger(__name__)
logger.info(u'emitted payment request with id %s', smart_text(order_id), extra={
'eopayment_order_id': smart_text(order_id), 'eopayment_data': repr(data)})
@ -382,6 +397,15 @@ class PayView(PayMixin, View):
regie.compute_extra_fees(user=user)
items = BasketItem.get_items_to_be_paid(user=user).filter(regie=regie)
if items:
capture_date = items[0].capture_date
for item in items:
if item.capture_date != capture_date:
messages.error(
request,
_(u'Invalid grouping for basket items: different capture dates.'))
return HttpResponseRedirect(next_url)
if not user and not request.POST.get('email'):
messages.warning(request, _(u'You must give an email address.'))
return HttpResponseRedirect(request.POST.get('item_url'))

View File

@ -233,6 +233,71 @@ def test_add_amount_to_basket(app, key, regie, user):
resp = app.post_json(url, params=data, status=400)
assert resp.text == 'Unknown regie'
def test_basket_item_with_capture_date(app, user, regie, basket_page, monkeypatch):
User.objects.get_or_create(email=user.email)
url = '%s?email=%s' % (reverse('api-add-basket-item'), user.email)
capture_date = timezone.now().date()
data = {
'amount': 10, 'capture_date': capture_date.isoformat(),
'display_name': 'test item'
}
url = sign_url(url, settings.LINGO_API_SIGN_KEY)
resp = app.post_json(url, params=data)
assert resp.status_code == 200
assert BasketItem.objects.all()[0].capture_date == capture_date
resp = login(app).get('/test_basket_cell/')
import eopayment
eopayment_mock = mock.Mock(
return_value=('orderid', eopayment.URL, 'http://dummy-payment.demo.entrouvert.com/'))
monkeypatch.setattr(eopayment.Payment, 'request', eopayment_mock)
resp = resp.form.submit()
assert resp.status_code == 302
location = urlparse.urlparse(resp.location)
assert location.path == '/'
assert location.hostname == 'dummy-payment.demo.entrouvert.com'
eopayment_mock.assert_called_once_with(
Decimal(10), email=user.email, first_name=user.first_name, last_name=user.last_name,
capture_date=capture_date)
@pytest.mark.parametrize("invalid_capture_date", [8, '', 'not-a-date'])
def test_add_basket_capture_date_format(app, user, regie, invalid_capture_date):
url = '%s?email=%s' % (reverse('api-add-basket-item'), user.email)
data = {'amount': 10, 'display_name': 'test item'}
data['capture_date'] = invalid_capture_date
url = sign_url(url, settings.LINGO_API_SIGN_KEY)
resp = app.post_json(url, params=data, status=400)
assert 'Bad format for capture date, it should be yyyy-mm-dd.' in resp.content
def test_cant_pay_if_different_capture_date(app, basket_page, regie, user):
capture1 = (timezone.now() + timedelta(days=1)).date()
capture2 = (timezone.now() + timedelta(days=2)).date()
items = {
'item1': {
'amount': '10.5', 'capture_date': capture1.isoformat(),
'source_url': 'http://example.org/item/1'
},
'item2': {
'amount': '42', 'capture_date': capture2.isoformat(),
'source_url': 'http://example.org/item/2'},
}
b_items = []
for subject, details in items.items():
b_item = BasketItem.objects.create(
user=user, regie=regie, subject=subject, **details)
b_items.append(b_item.pk)
resp = login(app).get('/test_basket_cell/')
resp = resp.form.submit()
assert resp.status_code == 302
assert urlparse.urlparse(resp.location).path == '/test_basket_cell/'
resp = resp.follow()
assert "Invalid grouping for basket items: different capture dates." in resp.content
def test_pay_single_basket_item(app, key, regie, user, john_doe):
page = Page(title='xxx', slug='index', template_name='standard')
page.save()