mirror of
https://github.com/Crocmagnon/checkout.git
synced 2024-11-22 08:08:04 +01:00
Remove no payment method as option
This commit is contained in:
parent
1dec9c0bb6
commit
0f0e4f854a
8 changed files with 57 additions and 58 deletions
|
@ -36,9 +36,7 @@ class Command(BaseCommand):
|
||||||
methods_weights = [random.randint(1, 6) for _ in range(len(payment_methods))]
|
methods_weights = [random.randint(1, 6) for _ in range(len(payment_methods))]
|
||||||
products_weights = [1 / product.display_order for product in products]
|
products_weights = [1 / product.display_order for product in products]
|
||||||
for _ in range(count):
|
for _ in range(count):
|
||||||
method = None
|
method = random.choices(payment_methods, weights=methods_weights)[0]
|
||||||
if random.random() < 0.99: # noqa: PLR2004
|
|
||||||
method = random.choices(payment_methods, weights=methods_weights)[0]
|
|
||||||
basket = Basket.objects.create(payment_method=method)
|
basket = Basket.objects.create(payment_method=method)
|
||||||
items_in_basket = int(random.normalvariate(3, 2))
|
items_in_basket = int(random.normalvariate(3, 2))
|
||||||
if items_in_basket > len(products):
|
if items_in_basket > len(products):
|
||||||
|
|
35
src/purchase/migrations/0014_alter_basket_payment_method.py
Normal file
35
src/purchase/migrations/0014_alter_basket_payment_method.py
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
# Generated by Django 4.1.7 on 2023-03-27 16:22
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
def delete_baskets_without_payment_method(apps, schema_editor):
|
||||||
|
Basket = apps.get_model("purchase", "Basket") # noqa: N806
|
||||||
|
Basket.objects.using(schema_editor.connection.alias).filter(
|
||||||
|
payment_method=None,
|
||||||
|
).delete()
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("purchase", "0013_remove_basketitem_unique_product_per_basket_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
# Remove baskets with no payment method
|
||||||
|
migrations.RunPython(
|
||||||
|
delete_baskets_without_payment_method,
|
||||||
|
migrations.RunPython.noop,
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="basket",
|
||||||
|
name="payment_method",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.PROTECT,
|
||||||
|
related_name="baskets",
|
||||||
|
to="purchase.paymentmethod",
|
||||||
|
verbose_name="payment method",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -179,17 +179,14 @@ class BasketQuerySet(models.QuerySet):
|
||||||
def turnover(self) -> int:
|
def turnover(self) -> int:
|
||||||
return self.priced().aggregate(total=Sum("price"))["total"]
|
return self.priced().aggregate(total=Sum("price"))["total"]
|
||||||
|
|
||||||
def no_payment_method(self) -> BasketQuerySet:
|
|
||||||
return self.filter(payment_method=None)
|
|
||||||
|
|
||||||
|
|
||||||
class Basket(Model):
|
class Basket(Model):
|
||||||
payment_method = models.ForeignKey(
|
payment_method = models.ForeignKey(
|
||||||
to=PaymentMethod,
|
to=PaymentMethod,
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
related_name="baskets",
|
related_name="baskets",
|
||||||
null=True,
|
null=False,
|
||||||
blank=True,
|
blank=False,
|
||||||
verbose_name=_("payment method"),
|
verbose_name=_("payment method"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<div class="row row-cols-2 row-cols-xl-6 row-cols-lg-5 row-cols-md-4 row-cols-sm-3 g-4">
|
<div class="row row-cols-2 row-cols-xl-6 row-cols-lg-5 row-cols-md-4 row-cols-sm-3 g-4">
|
||||||
{% for basket in baskets %}
|
{% for basket in baskets %}
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card h-100 {% if not basket.payment_method %}bg-warning text-black{% endif %}">
|
<div class="card h-100">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">{% blocktranslate with basket_id=basket.id %}Basket #{{ basket_id }}{% endblocktranslate %}</h5>
|
<h5 class="card-title">{% blocktranslate with basket_id=basket.id %}Basket #{{ basket_id }}{% endblocktranslate %}</h5>
|
||||||
<p class="card-text">
|
<p class="card-text">
|
||||||
|
|
|
@ -35,9 +35,6 @@
|
||||||
|
|
||||||
<h2>{% translate "Turnover by payment method" %}</h2>
|
<h2>{% translate "Turnover by payment method" %}</h2>
|
||||||
{% include "purchase/snippets/report_payment_methods.html" %}
|
{% include "purchase/snippets/report_payment_methods.html" %}
|
||||||
|
|
||||||
<h2>{% translate "Baskets without payment method" %}</h2>
|
|
||||||
{% include "purchase/snippets/report_no_payment_method.html" %}
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block extrascript %}
|
{% block extrascript %}
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
{% load i18n %}
|
|
||||||
{% load purchase %}
|
|
||||||
|
|
||||||
<table class="table table-hover table-sm">
|
|
||||||
<thead><tr>
|
|
||||||
<th scope="col">{% translate "Basket" %}</th>
|
|
||||||
<th scope="col">{% translate "Price" %}</th>
|
|
||||||
</tr></thead>
|
|
||||||
<tbody>
|
|
||||||
{% for basket in no_payment_method %}
|
|
||||||
<tr>
|
|
||||||
<th scope="row">
|
|
||||||
<a href="{% url "purchase:update" basket.id %}">
|
|
||||||
{{ basket }}
|
|
||||||
</a>
|
|
||||||
</th>
|
|
||||||
<td>{{ basket.price|currency }}</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
|
@ -114,14 +114,21 @@ def test_cashier_create_and_update_basket( # noqa: PLR0915
|
||||||
chain.double_click(price_input).perform()
|
chain.double_click(price_input).perform()
|
||||||
price_input.send_keys("401")
|
price_input.send_keys("401")
|
||||||
|
|
||||||
# Don't add payment method
|
# Add payment method
|
||||||
|
selenium.find_element(By.TAG_NAME, "html").send_keys(Keys.END)
|
||||||
|
time.sleep(1)
|
||||||
|
selenium.find_element(
|
||||||
|
By.CSS_SELECTOR,
|
||||||
|
f'input[type="radio"][value="{payment_methods[1].pk}"]',
|
||||||
|
).click()
|
||||||
|
|
||||||
# Save
|
# Save
|
||||||
selenium.find_element(By.ID, "submit-id-submit").click()
|
selenium.find_element(By.ID, "submit-id-submit").click()
|
||||||
|
|
||||||
# Assert entries saved in DB (new basket with proper products)
|
# Assert entries saved in DB (new basket with proper products)
|
||||||
assert Basket.objects.count() == 1
|
assert Basket.objects.count() == 1
|
||||||
basket = Basket.objects.priced().first()
|
basket = Basket.objects.priced().first()
|
||||||
assert basket.payment_method is None
|
assert basket.payment_method == payment_methods[1]
|
||||||
assert basket.items.count() == 4
|
assert basket.items.count() == 4
|
||||||
assert basket.items.get(product=products[0]).quantity == 2
|
assert basket.items.get(product=products[0]).quantity == 2
|
||||||
assert (
|
assert (
|
||||||
|
@ -150,10 +157,6 @@ def test_cashier_create_and_update_basket( # noqa: PLR0915
|
||||||
created_message = selenium.find_element(By.CSS_SELECTOR, ".messages .alert-success")
|
created_message = selenium.find_element(By.CSS_SELECTOR, ".messages .alert-success")
|
||||||
assert created_message.text == "Panier correctement créé."
|
assert created_message.text == "Panier correctement créé."
|
||||||
|
|
||||||
# Assert message in red for missing payment method
|
|
||||||
missing_payment = selenium.find_element(By.CSS_SELECTOR, ".alert.alert-danger")
|
|
||||||
assert missing_payment.text == "Moyen de paiement manquant."
|
|
||||||
|
|
||||||
# Assert ID, price, date & product quantities
|
# Assert ID, price, date & product quantities
|
||||||
# Selected products have a green background
|
# Selected products have a green background
|
||||||
title = selenium.find_element(By.TAG_NAME, "h1")
|
title = selenium.find_element(By.TAG_NAME, "h1")
|
||||||
|
@ -193,11 +196,6 @@ def test_cashier_create_and_update_basket( # noqa: PLR0915
|
||||||
quantity = int(quantity_input.get_attribute("value"))
|
quantity = int(quantity_input.get_attribute("value"))
|
||||||
assert quantity == 3
|
assert quantity == 3
|
||||||
|
|
||||||
# Add payment method
|
|
||||||
selenium.find_element(By.TAG_NAME, "html").send_keys(Keys.END)
|
|
||||||
time.sleep(1)
|
|
||||||
selenium.find_element(By.ID, f"id_payment_method_{payment_methods[1].pk}").click()
|
|
||||||
|
|
||||||
# Save
|
# Save
|
||||||
selenium.find_element(By.ID, "submit-id-submit").click()
|
selenium.find_element(By.ID, "submit-id-submit").click()
|
||||||
|
|
||||||
|
@ -275,34 +273,30 @@ def test_baskets_list(live_server: LiveServer, selenium: WebDriver):
|
||||||
pk=basket_with_payment_method.pk,
|
pk=basket_with_payment_method.pk,
|
||||||
)
|
)
|
||||||
with freezegun.freeze_time("2022-09-24 19:02:00+0200"):
|
with freezegun.freeze_time("2022-09-24 19:02:00+0200"):
|
||||||
basket_no_payment_method = BasketWithItemsFactory(payment_method=None)
|
another_basket = BasketWithItemsFactory()
|
||||||
basket_no_payment_method = Basket.objects.priced().get(
|
another_basket = Basket.objects.priced().get(
|
||||||
pk=basket_no_payment_method.pk,
|
pk=another_basket.pk,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Login
|
# Login
|
||||||
url = reverse("purchase:list")
|
url = reverse("purchase:list")
|
||||||
login(live_server, selenium, cashier, url)
|
login(live_server, selenium, cashier, url)
|
||||||
|
|
||||||
# Assert first basket (last created) has yellow background
|
|
||||||
# Assert basket info displayed
|
# Assert basket info displayed
|
||||||
displayed_baskets = selenium.find_elements(By.CSS_SELECTOR, ".card.h-100")
|
displayed_baskets = selenium.find_elements(By.CSS_SELECTOR, ".card.h-100")
|
||||||
first_basket = displayed_baskets[0]
|
first_basket = displayed_baskets[0]
|
||||||
assert "bg-warning" in first_basket.get_attribute("class")
|
|
||||||
text = first_basket.text.replace("\n", " ")
|
text = first_basket.text.replace("\n", " ")
|
||||||
assert f"n°{basket_no_payment_method.pk} " in text
|
assert f"n°{another_basket.pk} " in text
|
||||||
expected_articles_count = basket_no_payment_method.items.count()
|
expected_articles_count = another_basket.items.count()
|
||||||
assert f" {expected_articles_count} article" in text
|
assert f" {expected_articles_count} article" in text
|
||||||
expected_price = basket_no_payment_method.price / 100
|
expected_price = another_basket.price / 100
|
||||||
assert f" {expected_price:.2f}€" in text
|
assert f" {expected_price:.2f}€" in text
|
||||||
expected_payment_method = "-"
|
expected_payment_method = another_basket.payment_method.name
|
||||||
assert f" {expected_payment_method} " in text
|
assert f" {expected_payment_method} " in text
|
||||||
assert "19:02" in text
|
assert "19:02" in text
|
||||||
|
|
||||||
# Assert second basket (first created) doesn't have yellow background
|
|
||||||
# Assert basket info displayed including payment method
|
# Assert basket info displayed including payment method
|
||||||
second_basket = displayed_baskets[1]
|
second_basket = displayed_baskets[1]
|
||||||
assert "bg-warning" not in second_basket.get_attribute("class")
|
|
||||||
text = second_basket.text.replace("\n", " ")
|
text = second_basket.text.replace("\n", " ")
|
||||||
assert f"n°{basket_with_payment_method.pk} " in text
|
assert f"n°{basket_with_payment_method.pk} " in text
|
||||||
expected_articles_count = basket_with_payment_method.items.count()
|
expected_articles_count = basket_with_payment_method.items.count()
|
||||||
|
@ -321,7 +315,7 @@ def test_baskets_list(live_server: LiveServer, selenium: WebDriver):
|
||||||
|
|
||||||
# Assert object deleted in DB
|
# Assert object deleted in DB
|
||||||
assert Basket.objects.count() == 1
|
assert Basket.objects.count() == 1
|
||||||
assert Basket.objects.first() == basket_no_payment_method
|
assert Basket.objects.first() == another_basket
|
||||||
|
|
||||||
# Assert redirected to list view
|
# Assert redirected to list view
|
||||||
wait.until(
|
wait.until(
|
||||||
|
@ -336,7 +330,7 @@ def test_baskets_list(live_server: LiveServer, selenium: WebDriver):
|
||||||
redirect_url = live_reverse(
|
redirect_url = live_reverse(
|
||||||
live_server,
|
live_server,
|
||||||
"purchase:update",
|
"purchase:update",
|
||||||
pk=basket_no_payment_method.pk,
|
pk=another_basket.pk,
|
||||||
)
|
)
|
||||||
wait.until(lambda driver: driver.current_url == redirect_url)
|
wait.until(lambda driver: driver.current_url == redirect_url)
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,6 @@ def reports(request):
|
||||||
"average_basket_by_day": average_basket_by_day,
|
"average_basket_by_day": average_basket_by_day,
|
||||||
"products": products,
|
"products": products,
|
||||||
"payment_methods": PaymentMethod.objects.with_turnover().with_sold(),
|
"payment_methods": PaymentMethod.objects.with_turnover().with_sold(),
|
||||||
"no_payment_method": Basket.objects.no_payment_method().priced(),
|
|
||||||
}
|
}
|
||||||
return TemplateResponse(request, template_name, context)
|
return TemplateResponse(request, template_name, context)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue