make BillingInfo.phone_number non-nullable

This commit is contained in:
imperosol
2026-06-02 12:54:31 +02:00
parent 30a3911fa1
commit e629b36465
8 changed files with 43 additions and 79 deletions
+1 -30
View File
@@ -16,7 +16,6 @@ from __future__ import annotations
import hmac
from datetime import datetime
from enum import Enum
from typing import Self
from dict2xml import dict2xml
@@ -40,30 +39,6 @@ from counter.models import (
)
class BillingInfoState(Enum):
VALID = 1
EMPTY = 2
MISSING_PHONE_NUMBER = 3
@classmethod
def from_model(cls, info: BillingInfo | None) -> BillingInfoState:
if info is None:
return cls.EMPTY
for attr in [
"first_name",
"last_name",
"address_1",
"zip_code",
"city",
"country",
]:
if getattr(info, attr) == "":
return cls.EMPTY
if info.phone_number is None:
return cls.MISSING_PHONE_NUMBER
return cls.VALID
class Basket(models.Model):
"""Basket is built when the user connects to an eboutic page."""
@@ -162,11 +137,7 @@ class Basket(models.Model):
if self.is_expired:
raise ValueError("This method cannot be called on an expired basket.")
customer = user.customer
if (
not hasattr(user.customer, "billing_infos")
or BillingInfoState.from_model(user.customer.billing_infos)
!= BillingInfoState.VALID
):
if not hasattr(user.customer, "billing_infos"):
raise BillingInfo.DoesNotExist
cart = {
"shoppingcart": {"total": {"totalQuantity": min(self.items.count(), 99)}}
@@ -24,7 +24,7 @@
x-cloak
>
{% csrf_token %}
{{ form.as_p() }}
{{ form }}
<br>
<input
type="submit" class="btn btn-blue clickable"
+2 -5
View File
@@ -37,12 +37,9 @@ class TestBillingInfo:
def test_edit_infos(self, client: Client, payload: dict[str, str]):
user = subscriber_user.make()
baker.make(BillingInfo, customer=user.customer)
baker.make(BillingInfo, customer=user.customer, phone_number="06 01 02 03 04")
client.force_login(user)
response = client.post(
reverse("eboutic:billing_infos"),
payload,
)
response = client.post(reverse("eboutic:billing_infos"), payload)
user.refresh_from_db()
infos = BillingInfo.objects.get(customer__user=user)
assert response.status_code == 302
+10 -21
View File
@@ -58,7 +58,7 @@ from counter.models import (
Selling,
get_eboutic,
)
from eboutic.models import Basket, BasketItem, BillingInfoState, Invoice, InvoiceItem
from eboutic.models import Basket, BasketItem, Invoice, InvoiceItem
if TYPE_CHECKING:
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey
@@ -187,7 +187,7 @@ def payment_result(request, result: str) -> HttpResponse:
class BillingInfoFormFragment(
LoginRequiredMixin, FragmentMixin, SuccessMessageMixin, UpdateView
):
"""Update billing info"""
"""Update or create billing info"""
model = BillingInfo
form_class = BillingInfoForm
@@ -218,26 +218,15 @@ class BillingInfoFormFragment(
def get_context_data(self, **kwargs):
kwargs = super().get_context_data(**kwargs)
kwargs["billing_infos_state"] = BillingInfoState.from_model(self.object)
kwargs["action"] = reverse("eboutic:billing_infos")
match BillingInfoState.from_model(self.object):
case BillingInfoState.EMPTY:
messages.warning(
self.request,
_(
"You must fill your billing infos if you want to pay with your credit card"
),
)
case BillingInfoState.MISSING_PHONE_NUMBER:
messages.warning(
self.request,
_(
"The Crédit Agricole changed its policy related to the billing "
+ "information that must be provided in order to pay with a credit card. "
+ "If you want to pay with your credit card, you must add a phone number "
+ "to the data you already provided.",
),
)
if not self.object:
messages.warning(
self.request,
_(
"You must fill your billing infos "
"if you want to pay with your credit card"
),
)
return kwargs
def get_success_url(self, **kwargs):