Logs de diagnostic et rapprochement SumUp ↔ bénévole
ci-cd / build-backend (push) Successful in 38s
ci-cd / build-frontend (push) Successful in 20s
ci-cd / deploy (push) Successful in 13s

- Une ligne de log par requête (route modèle, statut, durée, code d'erreur,
  compte), identifiant X-Request-ID repris dans chaque log et affiché à
  l'utilisateur sous une erreur, exceptions non gérées tracées (500 JSON)
- Journal d'accès d'uvicorn coupé : il exposait le jeton du formulaire public
- Logs métier : paiement SumUp, connexion, import, plannings, solveur
- Nom du bénévole dans la description du checkout SumUp
- Code et identifiant de transaction SumUp enregistrés au paiement
  (migration 0023), affichés sur la fiche et dans l'export Excel

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
AdamThomas
2026-10-12 18:54:35 +02:00
co-authored by Claude Opus 5.5
parent d722a81a87
commit d0fa1e109c
27 changed files with 798 additions and 16 deletions
+41 -1
View File
@@ -37,7 +37,7 @@ import { ErrorNote, Loading } from '@/components/state';
import { feeMode } from '@/lib/fee';
import { foldAccents } from '@/lib/planning';
import { t } from '@/i18n';
import { shortDayLabel } from '@/lib/time';
import { datePart, shortDayLabel, timePart } from '@/lib/time';
import { cx } from '@/lib/cx';
const MAP_FIELDS: Array<{ key: ImportFieldKey; required: boolean }> = [
@@ -273,6 +273,7 @@ function FeeSection({
{volunteer.fee_payment_label} — {volunteer.fee_amount} €
</p>
) : null}
{volunteer.fee_payment_status === 'PAID' ? <FeeTransaction volunteer={volunteer} /> : null}
{volunteer.mecenat_address ? (
<p className="font-mono text-[10.5px] leading-relaxed opacity-70">
{t('config.vol.mecenatAddress')} : {volunteer.mecenat_address},{' '}
@@ -298,6 +299,45 @@ function FeeSection({
);
}
/**
* Rapprochement avec SumUp : date du paiement et transaction qui l'a réglé.
* Le code (`TEENSK4W2K`) est celui que montre le tableau de bord SumUp —
* c'est lui qu'on y recherche pour retrouver le paiement de ce bénévole.
* Absent pour un paiement confirmé avant que l'appli ne l'enregistre.
*/
function FeeTransaction({ volunteer }: { volunteer: VolunteerRead }) {
const paidAt = volunteer.fee_paid_at;
return (
<dl className="grid grid-cols-[auto_1fr] gap-x-[10px] gap-y-[3px] font-mono text-[10.5px]">
{paidAt ? (
<>
<dt className="opacity-70">{t('config.vol.fee.paidAt')}</dt>
<dd>
{datePart(paidAt).split('-').reverse().join('/')} {timePart(paidAt)}
</dd>
</>
) : null}
<dt className="flex items-center gap-[4px] opacity-70">
{t('config.vol.fee.transaction')}{' '}
<HelpTip text={t('config.vol.fee.transactionHint')} />
</dt>
<dd className="min-w-0">
{volunteer.fee_transaction_code ? (
<span className="select-all break-all font-bold">{volunteer.fee_transaction_code}</span>
) : (
<span className="opacity-60">{t('config.vol.fee.transactionUnknown')}</span>
)}
</dd>
{volunteer.fee_transaction_id ? (
<>
<dt className="opacity-70">{t('config.vol.fee.transactionId')}</dt>
<dd className="min-w-0 select-all break-all opacity-70">{volunteer.fee_transaction_id}</dd>
</>
) : null}
</dl>
);
}
/**
* Postes dont ce bénévole est référent (`Position.lead_account_id`). Cocher
* un poste crée ou met à niveau son accès de connexion en RÉFÉRENT (LEAD) —