Skip to content

Commit 61c6f36

Browse files
committed
feat(custmer): track vatin validation errors for existing customers
1 parent e733186 commit 61c6f36

File tree

5 files changed

+48
-5
lines changed

5 files changed

+48
-5
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Generated by Django 5.2.8 on 2025-12-12 07:33
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
dependencies = [
8+
("CRM", "0005_alter_interaction_origin"),
9+
]
10+
11+
operations = [
12+
migrations.AlterField(
13+
model_name="interaction",
14+
name="origin",
15+
field=models.IntegerField(
16+
choices=[
17+
(1, "Outbound e-mail"),
18+
(2, "Merged customer"),
19+
(3, "Attachment exchanged in Zammad"),
20+
(4, "VIES validation"),
21+
],
22+
verbose_name="Origin",
23+
),
24+
),
25+
]

weblate_web/crm/models.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class Origin(models.IntegerChoices):
1414
EMAIL = 1, "Outbound e-mail"
1515
MERGE = 2, "Merged customer"
1616
ZAMMAD_ATTACHMENT = 3, "Attachment exchanged in Zammad"
17+
VIES = 4, "VIES validation"
1718

1819
timestamp = models.DateTimeField(default=timezone.now, verbose_name="Timestamp")
1920
origin = models.IntegerField(choices=Origin, verbose_name="Origin")

weblate_web/payments/models.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,18 @@ def merge(self, other: Customer, *, user: User | None = None) -> None:
324324
)
325325
other.delete()
326326

327+
def validate_vatin(self):
328+
from weblate_web.crm.models import Interaction # noqa: PLC0415
329+
330+
try:
331+
validate_vatin(self.vat)
332+
except ValidationError as error:
333+
self.interaction_set.create(
334+
origin=Interaction.Origin.VIES,
335+
summary=error.code or str(error.message),
336+
)
337+
raise
338+
327339

328340
RECURRENCE_CHOICES = [
329341
("y", gettext_lazy("Annual")),

weblate_web/payments/validators.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,21 @@ def validate_vatin(value: str | VATIN) -> None:
5454
vatin.verify_country_code()
5555
except ValidationError as error:
5656
msg = _("{} is not a valid country code for any European Union member.")
57-
raise ValidationError(msg.format(vatin.country_code)) from error
57+
raise ValidationError(
58+
msg.format(vatin.country_code), code="Invalid country"
59+
) from error
5860
try:
5961
vatin.verify_regex()
6062
except ValidationError as error:
6163
msg = _("{} does not match the country's VAT ID specifications.")
62-
raise ValidationError(msg.format(vatin)) from error
64+
raise ValidationError(msg.format(vatin), code="Invalid VAT syntax") from error
6365

6466
if not vies_data["valid"]:
6567
retry_errors = {"MS_UNAVAILABLE", "MS_MAX_CONCURRENT_REQ", "TIMEOUT"}
6668
retry_codes = {"soap:Server", "other:Error", "env:Server"}
69+
code = "{}: {}".format(
70+
vies_data.get("fault_code"), vies_data.get("fault_message")
71+
)
6772
if (
6873
vies_data.get("fault_message") in retry_errors
6974
or vies_data.get("fault_code") in retry_codes
@@ -78,4 +83,4 @@ def validate_vatin(value: str | VATIN) -> None:
7883
)
7984
else:
8085
msg = _("{} is not a valid VAT ID.").format(vatin)
81-
raise ValidationError(msg)
86+
raise ValidationError(msg, code=code)

weblate_web/views.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@
8787
)
8888
from weblate_web.payments.forms import CustomerForm
8989
from weblate_web.payments.models import Customer, Payment
90-
from weblate_web.payments.validators import cache_vies_data, validate_vatin
90+
from weblate_web.payments.validators import cache_vies_data
9191
from weblate_web.remote import get_activity
9292
from weblate_web.utils import (
9393
AUTO_ORIGIN,
@@ -411,7 +411,7 @@ def validate_customer(self, customer: Customer) -> HttpResponse | None:
411411
# often broken, so all repeating payments without a validation
412412
if customer.vat and not self.object.repeat:
413413
try:
414-
validate_vatin(customer.vat)
414+
customer.validate_vatin()
415415
except ValidationError:
416416
messages.warning(
417417
self.request,

0 commit comments

Comments
 (0)