0002-lingo-allow-requiring-individual-payment-for-regie-4.patch
combo/apps/lingo/forms.py | ||
---|---|---|
87 | 87 |
class Meta: |
88 | 88 |
model = Regie |
89 | 89 |
fields = ['label', 'slug', 'description', 'payment_backend', 'is_default', |
90 |
'webservice_url', 'extra_fees_ws_url', 'payment_min_amount', 'text_on_success'] |
|
90 |
'webservice_url', 'extra_fees_ws_url', 'payment_min_amount', 'text_on_success', |
|
91 |
'individual_payment'] |
|
91 | 92 | |
92 | 93 |
def __init__(self, *args, **kwargs): |
93 | 94 |
super(RegieForm, self).__init__(*args, **kwargs) |
combo/apps/lingo/migrations/0041_regie_individual_payment.py | ||
---|---|---|
1 |
# -*- coding: utf-8 -*- |
|
2 |
# Generated by Django 1.11.18 on 2020-09-23 12:46 |
|
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', '0040_auto_20200608_1222'), |
|
12 |
] |
|
13 | ||
14 |
operations = [ |
|
15 |
migrations.AddField( |
|
16 |
model_name='regie', |
|
17 |
name='individual_payment', |
|
18 |
field=models.BooleanField(default=False, verbose_name='Indiviual payment'), |
|
19 |
), |
|
20 |
] |
combo/apps/lingo/models.py | ||
---|---|---|
143 | 143 |
payment_backend = models.ForeignKey( |
144 | 144 |
PaymentBackend, on_delete=models.CASCADE, verbose_name=_('Payment backend')) |
145 | 145 |
transaction_options = JSONField(blank=True, verbose_name=_('Transaction Options')) |
146 |
individual_payment = models.BooleanField(default=False, verbose_name=_('Indiviual payment')) |
|
146 | 147 | |
147 | 148 |
def is_remote(self): |
148 | 149 |
return self.webservice_url != '' |
combo/apps/lingo/templates/lingo/combo/basket.html | ||
---|---|---|
14 | 14 |
{% if item.user_cancellable %} |
15 | 15 |
<a rel="popup" href="{% url 'lingo-cancel-item' pk=item.id %}">({% trans 'remove' %})</a> |
16 | 16 |
{% endif %} |
17 |
{% if regie_info.regie.individual_payment %} |
|
18 |
<button id="{{ item.pk }}" formaction="{% url 'lingo-pay' item_pk=item.pk %}">{% trans "Pay" %}</button> |
|
19 |
{% endif %} |
|
17 | 20 |
</li> |
18 | 21 |
{% endfor %} |
19 |
<li><strong>{% trans "Total:" %}</strong> {{ regie_info.total }} €</li> |
|
20 | 22 |
</ul> |
23 |
{% if not regie_info.regie.individual_payment %} |
|
24 |
<p class="lingo-total"><strong>{% trans "Total:" %}</strong> {{ regie_info.total }} €</p> |
|
21 | 25 |
<button>{% trans "Pay" %}</button> |
26 |
{% endif %} |
|
22 | 27 |
</form> |
23 | 28 |
{% endfor %} |
24 | 29 |
{% endif %} |
combo/apps/lingo/urls.py | ||
---|---|---|
66 | 66 |
name='api-transaction-status' |
67 | 67 |
), |
68 | 68 |
url(r'^lingo/pay$', PayView.as_view(), name='lingo-pay'), |
69 |
url(r'^lingo/pay/(?P<item_pk>\w+)/$$', PayView.as_view(), name='lingo-pay'), |
|
69 | 70 |
url(r'^lingo/cancel/(?P<pk>\w+)/$', CancelItemView.as_view(), name='lingo-cancel-item'), |
70 | 71 |
url(r'^lingo/callback/(?P<regie_pk>\w+)/$', CallbackView.as_view(), name='lingo-callback'), |
71 | 72 |
url(r'^lingo/callback-payment-backend/(?P<payment_backend_pk>\w+)/$', |
combo/apps/lingo/views.py | ||
---|---|---|
470 | 470 |
regie = Regie.objects.get(id=regie_id) |
471 | 471 |
regie.compute_extra_fees(user=user) |
472 | 472 |
items = BasketItem.get_items_to_be_paid(user=user).filter(regie=regie) |
473 |
if 'item_pk' in kwargs: |
|
474 |
items = items.filter(pk=kwargs['item_pk']) |
|
475 | ||
476 |
if regie.individual_payment and len(items) > 1: |
|
477 |
messages.error(request, _('Grouping basket items is not allowed.')) |
|
478 |
return HttpResponseRedirect(next_url) |
|
473 | 479 | |
474 | 480 |
if items: |
475 | 481 |
capture_date = items[0].capture_date |
tests/test_lingo_cells.py | ||
---|---|---|
95 | 95 |
item.save() |
96 | 96 |
assert cell.get_badge(context) == {'badge': u'123.45€'} |
97 | 97 | |
98 |
def test_basket_cell_individual_payment(regie, user): |
|
99 |
regie.individual_payment = True |
|
100 |
regie.save() |
|
101 |
page = Page(title='xxx', slug='test_basket_cell', template_name='standard') |
|
102 |
page.save() |
|
103 |
cell = LingoBasketCell(page=page, placeholder='content', order=0) |
|
104 | ||
105 |
item = BasketItem.objects.create(user=user, regie=regie, subject='foo', amount=123) |
|
106 |
item2 = BasketItem.objects.create(user=user, regie=regie, subject='bar', amount=123) |
|
107 | ||
108 |
context = {'request': RequestFactory(user=user).get('/')} |
|
109 |
context['request'].user = user |
|
110 |
assert cell.is_relevant(context) |
|
111 | ||
112 |
content = cell.render(context) |
|
113 |
assert content.count('Pay') == 2 |
|
114 |
assert '/lingo/pay/%s/' % item.pk in content |
|
115 |
assert not 'Total' in content |
|
116 | ||
98 | 117 |
def test_recent_transaction_cell(regie, user): |
99 | 118 |
page = Page(title='xxx', slug='test_basket_cell', template_name='standard') |
100 | 119 |
page.save() |
tests/test_lingo_payment.py | ||
---|---|---|
1531 | 1531 |
else: |
1532 | 1532 |
assert transaction.bank_transaction_date == transaction_date |
1533 | 1533 |
assert 'new transaction_date for transaction' in caplog.text |
1534 | ||
1535 | ||
1536 |
def test_successfull_items_individual_payment(app, basket_page, regie, user): |
|
1537 |
regie.individual_payment = True |
|
1538 |
regie.save() |
|
1539 |
item = BasketItem.objects.create(user=user, regie=regie, amount=42, subject='foo item') |
|
1540 |
item2 = BasketItem.objects.create(user=user, regie=regie, amount=84, subject='bar item') |
|
1541 | ||
1542 |
resp = login(app).get('/test_basket_cell/') |
|
1543 |
assert 'foo item' in resp.text |
|
1544 |
assert 'bar item' in resp.text |
|
1545 | ||
1546 |
# webtest does not support html5 forms, need to do submit by hand |
|
1547 |
form_data = dict(resp.form.submit_fields()) |
|
1548 |
submit_url = resp.pyquery.find('#%s' % item.pk).attr('formaction') |
|
1549 |
resp = app.post(submit_url, params=form_data) |
|
1550 | ||
1551 |
# successful payment |
|
1552 |
qs = urlparse.parse_qs(urlparse.urlparse(resp.location).query) |
|
1553 |
args = {'transaction_id': qs['transaction_id'][0], 'signed': True, 'ok': True, 'reason': 'Paid'} |
|
1554 |
with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as request: |
|
1555 |
resp = app.get(get_url(True, 'lingo-callback', regie), params=args) |
|
1556 | ||
1557 |
resp = app.get('/test_basket_cell/') |
|
1558 |
assert 'foo item' not in resp.text |
|
1559 |
assert 'bar item' in resp.text |
tox.ini | ||
---|---|---|
32 | 32 |
vobject |
33 | 33 |
django-ratelimit<3 |
34 | 34 |
git+http://git.entrouvert.org/debian/django-ckeditor.git |
35 |
pyquery |
|
35 | 36 |
commands = |
36 | 37 |
./getlasso3.sh |
37 | 38 |
python manage.py compilemessages |
38 |
- |