Numéro d'ordre unique sur chaque reçu fiscal mécénat

Volunteer.mecenat_receipt_number (migration 0020, unique) : année du
paiement + rang sur 5 chiffres (202600001…), une seule numérotation pour
toutes les éditions, repartant à 1 chaque année. Attribué à la
confirmation du paiement, ou au premier export pour les bénévoles payés
avant (dans l'ordre des paiements), puis jamais réattribué — un reçu
regénéré garde son numéro. Attribution sérialisée par un verrou
pg_advisory_xact_lock (webhook et sondage peuvent confirmer deux
paiements à la fois). Imprimé centré dans la case « Numéro d'ordre du
reçu » en page 1 du cerfa.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
AdamThomas
2026-10-03 13:48:05 +02:00
co-authored by Claude Opus 5.5
parent 5a0209ce43
commit ccd769d04e
10 changed files with 214 additions and 16 deletions
+13 -2
View File
@@ -7,9 +7,10 @@ import io
import uuid
import pytest
from pypdf import PdfReader
from app.auth.rate_limit import form_submission_limiter, pending_status_limiter
from app.models import FormTemplate, PendingFormSubmission, Role, local_now
from app.models import FormTemplate, PendingFormSubmission, Role, Volunteer, local_now
from app.sumup import SumUpCheckout
from tests.factories import make_artist, make_position
from tests.mail import plain_text
@@ -920,7 +921,9 @@ def _attachments(message) -> list:
]
def test_mecenat_payment_emails_the_filled_cerfa(raw_client, client, edition, monkeypatch, outbox):
def test_mecenat_payment_emails_the_filled_cerfa(
raw_client, client, edition, session, monkeypatch, outbox
):
client.put(_form_url(edition, "/fields"), json={"fields": ["WILLING_TO_PAY_FEE", "EMAIL"]})
client.patch(
_form_url(edition), json={"sumup_merchant_code": _MERCHANT, "sumup_api_key": _API_KEY}
@@ -960,6 +963,14 @@ def test_mecenat_payment_emails_the_filled_cerfa(raw_client, client, edition, mo
assert attachments[0].get_content().startswith(b"%PDF")
assert "reçu fiscal" in plain_text(outbox[0])
# Numéro d'ordre attribué à la promotion, et imprimé sur le cerfa joint.
volunteer_id = _pending_status(raw_client, edition, token)["volunteer_id"]
volunteer = session.get(Volunteer, uuid.UUID(volunteer_id))
expected = f"{volunteer.fee_paid_at.year}00001"
assert volunteer.mecenat_receipt_number == expected
reader = PdfReader(io.BytesIO(attachments[0].get_content()))
assert expected in reader.pages[0].extract_text()
def test_classic_payment_email_has_no_cerfa(raw_client, client, edition, monkeypatch, outbox):
client.put(_form_url(edition, "/fields"), json={"fields": ["WILLING_TO_PAY_FEE", "EMAIL"]})