Audit 18.09.: Zahlungsdatum nur bei Zahlung, Neupartner-IDs im Snapshot, Pausenende folgt dem Termin

F1: partner_paid_at wird beim Rechnungskauf (paymentStatusPaidAction mit
paid=false) nicht mehr gesetzt, sondern erst bei der Rechnungszahlung; der
Backfill nimmt das Aktivierungsdatum nur noch ohne jede
Registrierungsbestellung (offene Rechnung bleibt leer).
F2: Snapshots speichern je Linie new_partner_ids, die Neupartner-Liste zeigt
genau diese; aeltere Snapshots ohne IDs rechnen mit der damaligen Regel
(Registrierungsmonat, scopeNewPartnerInByActiveDate), damit Kachel und Liste
uebereinstimmen. Keine Payload-Versionsaenderung, kein Neuaufbau noetig.
F3: Liefertag-/Termin-Aenderung waehrend einer Pause zieht paused_until mit;
eine Ausfuehrung loescht auch den paused_by_*-Grund.
F4: expiredCount der Firstlines-Seite (Controller, View, Sprachen) zum bereits
committeten Test nachgezogen.
F5: Backfills schreiben ohne updated_at (toBase()->update, timestamps=false).
Kuendigungsbestaetigung abo_cancel_confirm wird im Selfservice serverseitig
verlangt. AboStatusExplainer laedt die Historie je Abo und Aktion nur einmal.

Stellungnahme und Deploy-Folgen im Audit-Dokument, Regressionstests je Befund.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Kevin 2026-09-18 08:59:45 +00:00
parent d5ad1ba50b
commit 4899e3a890
27 changed files with 560 additions and 21 deletions

View file

@ -386,4 +386,5 @@ return [
'pause_cancel_locked_hint_zero' => 'Die Lieferung am :date wird heute ausgeführt. Pausieren oder Kündigen ist danach wieder möglich – bis 23:59 Uhr des Vortags einer Lieferung.',
'filter_next_from' => 'von',
'filter_next_to' => 'bis',
'cancel_confirm_required' => 'Bitte bestätige die Folgen der Kündigung über das Kästchen.',
];

View file

@ -165,6 +165,7 @@ return [
'annual_fee_group_due_3_months' => 'Fällig in ≤ 3 Monaten',
'firstlines' => 'Firstlines',
'firstlines_count_split' => ':active Berater · :total insgesamt',
'firstlines_count_expired' => ':count mit abgelaufener Jahresgebühr',
'firstlines_copy' => 'Deine direkten Teampartner mit Umsatz und Kontaktdaten - sortiert nach Punkten des gewählten Monats.',
'firstlines_none' => 'Du hast noch keine direkten Teampartner.',
'firstlines_points' => 'Umsatz (Punkte)',

View file

@ -383,4 +383,5 @@ return [
'pause_cancel_locked_hint_zero' => 'The delivery on :date is being executed today. Pausing or cancelling is possible again afterwards – until 11:59 pm the day before a delivery.',
'filter_next_from' => 'from',
'filter_next_to' => 'to',
'cancel_confirm_required' => 'Please confirm the consequences of the cancellation via the checkbox.',
];

View file

@ -165,6 +165,7 @@ return [
'annual_fee_group_due_3_months' => 'Due in ≤ 3 months',
'firstlines' => 'Firstlines',
'firstlines_count_split' => ':active consultants · :total in total',
'firstlines_count_expired' => ':count with an expired annual fee',
'firstlines_copy' => 'Your direct team partners with turnover and contact details - sorted by points of the selected month.',
'firstlines_none' => 'You do not have any direct team partners yet.',
'firstlines_points' => 'Turnover (points)',

View file

@ -383,4 +383,5 @@ return [
'pause_cancel_locked_hint_zero' => 'La entrega del :date se ejecuta hoy. Pausar o cancelar volverá a ser posible después, hasta las 23:59 del día anterior a una entrega.',
'filter_next_from' => 'desde',
'filter_next_to' => 'hasta',
'cancel_confirm_required' => 'Confirma las consecuencias de la cancelación mediante la casilla.',
];

View file

@ -165,6 +165,7 @@ return [
'annual_fee_group_due_3_months' => 'Vence en ≤ 3 meses',
'firstlines' => 'Firstlines',
'firstlines_count_split' => ':active asesores · :total en total',
'firstlines_count_expired' => ':count con la cuota anual vencida',
'firstlines_copy' => 'Tus socios directos con volumen y datos de contacto - ordenados por puntos del mes seleccionado.',
'firstlines_none' => 'Aún no tienes socios directos.',
'firstlines_points' => 'Volumen (puntos)',

View file

@ -383,4 +383,5 @@ return [
'pause_cancel_locked_hint_zero' => 'La livraison du :date est exécutée aujourd’hui. Suspendre ou résilier sera de nouveau possible ensuite – jusqu’à 23 h 59 la veille d’une livraison.',
'filter_next_from' => 'du',
'filter_next_to' => 'au',
'cancel_confirm_required' => 'Merci de confirmer les conséquences de la résiliation via la case à cocher.',
];

View file

@ -144,6 +144,7 @@ return [
'annual_fee_group_due_3_months' => 'Échéance dans ≤ 3 mois',
'firstlines' => 'Firstlines',
'firstlines_count_split' => ':active conseillers · :total au total',
'firstlines_count_expired' => ':count avec cotisation annuelle échue',
'firstlines_copy' => 'Tes partenaires directs avec chiffre d’affaires et coordonnées - triés par points du mois sélectionné.',
'firstlines_none' => 'Tu n’as pas encore de partenaires directs.',
'firstlines_points' => 'Chiffre d’affaires (points)',

View file

@ -10,7 +10,7 @@
<div class="row align-items-center">
<div class="col-md-8">
<span class="font-weight-bold">{{ __('team.firstlines') }}
({{ __('team.firstlines_count_split', ['active' => $activeCount, 'total' => count($rows)]) }})</span>
({{ __('team.firstlines_count_split', ['active' => $activeCount, 'total' => count($rows)]) }}@if ($expiredCount > 0), {{ __('team.firstlines_count_expired', ['count' => $expiredCount]) }}@endif)</span>
<div class="text-muted small">{{ __('team.firstlines_copy') }}</div>
</div>
<div class="col-md-4 mt-2 mt-md-0">