panier: avoir un texte descriptif en haut du panier (#88504) #174

Merged
lguerin merged 2 commits from wip/88504-basket-information-message into main 2024-03-25 10:06:24 +01:00
7 changed files with 90 additions and 6 deletions

View File

@ -488,6 +488,7 @@ class BasketLineSerializer(serializers.ModelSerializer):
'user_first_name',
'user_last_name',
'information_message',
'cancel_information_message',
'group_items',
'form_url',
'validation_callback_url',

View File

@ -0,0 +1,20 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('basket', '0006_credit'),
]
operations = [
migrations.RenameField(
pmarillonnet marked this conversation as resolved
Review

Django opère un truc bizarre ici, au lieu de simplement rajouter un champ, il renomme un champ existant de même définition puis ajoute le champ disparu à l’occasion du renommage.

Django opère un truc bizarre ici, au lieu de simplement rajouter un champ, il renomme un champ existant de même définition puis ajoute le champ disparu à l’occasion du renommage.
Review

oui, c'est voulu, j'ai renommé le champ et ajouté un champ avec l'ancien nom :)

oui, c'est voulu, j'ai renommé le champ et ajouté un champ avec l'ancien nom :)
Review

Oulà oui pardon, le premier champ est déjà utilisé, ok :)
Lundi matin et la caféine n’a pas encore fait effet, désolé

Oulà oui pardon, le premier champ est déjà utilisé, ok :) Lundi matin et la caféine n’a pas encore fait effet, désolé
model_name='basketline',
old_name='information_message',
new_name='cancel_information_message',
),
migrations.AddField(
model_name='basketline',
name='information_message',
field=models.TextField(blank=True),
),
]

View File

@ -77,6 +77,14 @@ class Basket(models.Model):
def lines(self):
return self.basketline_set.filter(closed=True).order_by('pk')
def information_messages(self):
return sorted(list({li.information_message for li in self.lines if li.information_message}))
def cancel_information_messages(self):
return sorted(
list({li.cancel_information_message for li in self.lines if li.cancel_information_message})
)
@classmethod
def signal_paid_invoice(cls, invoice):
basket = cls.objects.filter(invoice=invoice).first()
@ -194,6 +202,7 @@ class BasketLine(models.Model):
user_last_name = models.CharField(max_length=250)
information_message = models.TextField(blank=True)
cancel_information_message = models.TextField(blank=True)
group_items = models.BooleanField(default=False)
closed = models.BooleanField(default=False)

View File

@ -11,10 +11,8 @@
<form method="post">
{% csrf_token %}
<p>{% trans "Are you sure you want to cancel this basket?" %}</p>
{% for line in basket.lines %}
{% if line.information_message %}
<p>{{ line.information_message }}</p>
{% endif %}
{% for message in basket.cancel_information_messages %}
<p>{{ message }}</p>
{% endfor %}
<div class="buttons">
<button class="submit-button">{% trans "Confirm cancellation" %}</button>

View File

@ -14,6 +14,9 @@
{% endif %}
<h1>{% trans "My basket" %}</h1>
</div>
{% for message in basket.information_messages %}
<p>{{ message }}</p>
{% endfor %}
<ul class="basket">
{% for line in basket.lines %}
{% for slug, label, description, quantity, unit_amount, total_amount in line.formatted_items %}

View File

@ -271,7 +271,8 @@ def test_add_line(app, user):
'user_external_id': 'user:1',
'user_first_name': 'First1',
'user_last_name': 'Last1',
'information_message': 'foo bar',
'information_message': 'foo baz',
'cancel_information_message': 'foo bar',
'form_url': 'http://form.com',
'validation_callback_url': 'http://validation.com',
'payment_callback_url': 'http://payment.com',
@ -287,7 +288,8 @@ def test_add_line(app, user):
assert line.user_external_id == 'user:1'
assert line.user_first_name == 'First1'
assert line.user_last_name == 'Last1'
assert line.information_message == 'foo bar'
assert line.information_message == 'foo baz'
assert line.cancel_information_message == 'foo bar'
assert line.group_items is False
assert line.form_url == 'http://form.com'
assert line.validation_callback_url == 'http://validation.com'
@ -331,6 +333,7 @@ def test_add_line(app, user):
assert line.user_first_name == 'First2'
assert line.user_last_name == 'Last2'
assert line.information_message == ''
assert line.cancel_information_message == ''
assert line.group_items is True
assert line.form_url == ''
assert line.validation_callback_url == ''

View File

@ -76,13 +76,16 @@ def test_basket_detail(app, simple_user):
line = BasketLine.objects.create(
basket=basket,
closed=False,
user_external_id='user:1',
user_first_name='First1',
user_last_name='Last1',
information_message='Lorem ipsum',
)
resp = app.get('/basket/')
assert 'My basket' in resp
assert len(resp.pyquery('ul.basket li')) == 0
assert len(resp.pyquery('ul.basket-amounts')) == 0
assert resp.text.count('<p>Lorem ipsum</p>') == 0
assert '/basket/invoice/pdf/' not in resp
assert '/basket/validate/' not in resp
assert '/basket/cancel/' not in resp
@ -94,6 +97,7 @@ def test_basket_detail(app, simple_user):
assert 'My basket' in resp
assert len(resp.pyquery('ul.basket li')) == 0
assert len(resp.pyquery('ul.basket-amounts li')) == 2
assert resp.text.count('<p>Lorem ipsum</p>') == 1
assert [PyQuery(li).text() for li in resp.pyquery('ul.basket-amounts li')] == [
'Basket amount: 6.00€',
'Amount to pay: 6.00€',
@ -233,6 +237,29 @@ def test_basket_detail(app, simple_user):
assert '/basket/validate/' not in resp
assert '/basket/cancel/' not in resp
# other lines with information_message
basket.status = 'open'
basket.save()
line = BasketLine.objects.create(
basket=basket,
closed=True,
user_external_id='user:2',
user_first_name='First2',
user_last_name='Last2',
information_message='Lorem ipsum',
)
line = BasketLine.objects.create(
basket=basket,
closed=True,
user_external_id='user:3',
user_first_name='First3',
user_last_name='Last3',
information_message='Lorem ipsum bis',
)
resp = app.get('/basket/')
assert resp.text.count('<p>Lorem ipsum</p>') == 1
assert resp.text.count('<p>Lorem ipsum bis</p>') == 1
def test_basket_invoice_pdf(app, simple_user):
resp = app.get('/basket/invoice/pdf/')
@ -831,6 +858,7 @@ def test_basket_cancel(app, simple_user):
basket=basket,
closed=False,
user_external_id='user:1',
cancel_information_message='Lorem ipsum',
)
app.get('/basket/cancel/', status=404)
@ -846,6 +874,7 @@ def test_basket_cancel(app, simple_user):
basket.payer_nameid = 'ab' * 16
basket.save()
resp = app.get('/basket/cancel/')
assert resp.text.count('<p>Lorem ipsum</p>') == 1
with mock.patch('lingo.utils.requests_wrapper.RequestsSession.send') as mock_send:
resp = resp.form.submit()
assert {x[0][0].url for x in mock_send.call_args_list} == set()
@ -900,6 +929,27 @@ def test_basket_cancel(app, simple_user):
basket.save()
app.get('/basket/cancel/')
# other lines with information_message
line = BasketLine.objects.create(
basket=basket,
closed=True,
user_external_id='user:3',
user_first_name='First3',
user_last_name='Last3',
cancel_information_message='Lorem ipsum',
)
line = BasketLine.objects.create(
basket=basket,
closed=True,
user_external_id='user:4',
user_first_name='First4',
user_last_name='Last4',
cancel_information_message='Lorem ipsum bis',
)
resp = app.get('/basket/cancel/')
assert resp.text.count('<p>Lorem ipsum</p>') == 1
assert resp.text.count('<p>Lorem ipsum bis</p>') == 1
def test_basket_status_js(app, simple_user):
resp = app.get('/basket/status.js')