Statistik: Neupartner zaehlen im Monat der Zahlung, nicht der Registrierung

Wer Ende August registriert und am 1. September bezahlt hat, tauchte in keiner
Neupartner-Zaehlung auf: Der August-Snapshot wurde um 04:45 eingefroren, da
fehlte noch das Abrechnungskonto; im September lag active_date im falschen
Monat. Betroffen sind 2026 acht Partner, auch im Recruiting ihrer Sponsoren.

Kundenentscheidung 16.09.2026: der Zeitpunkt der Zahlung ist massgeblich.

Neue Spalte users.partner_paid_at, gesetzt bei der ersten Kontozahlung
(Payment::paymentStatusPaidAction) und bei manueller Freischaltung durch den
Admin — nur, solange sie leer ist; Verlaengerung und Wiederherstellung aendern
sie nicht. Bestehende Partner werden per Migration aus der ersten bezahlten
Registrierungsbestellung rueckgefuellt (Zeitstempel der Punktebuchung, ersatzweise
Bestelldatum, ohne Bestellung das Aktivierungsdatum). Bewusst nicht
payment_account minus ein Jahr: das ergaebe bei Verlaengerern den Jahrestag der
Erstzahlung.

User::scopeNewPartnerIn() und isNewPartnerIn() lesen jetzt partner_paid_at —
damit Kachel, Recruiter-Ranking, Top 3 und Neupartner-Liste gleichermassen.
Die Liste und der CSV-Export zeigen "Bezahlt am" neben "Registriert am".

Unveraendert: die Teamstruktur haengt weiter an active_date (auch im
Provisionsbaum). Wer ist neu dazugekommen und wer gehoert zur Linie sind zwei
verschiedene Fragen.

Die eingefrorenen Monate Januar bis August enthalten sieben dieser Partner
nicht; ob sie per --force neu gebaut werden, ist eine Entscheidung — siehe
dev/2026-07-22/neupartner-zahlungsmonat.md.

Mit drin: die handgebaute SQLite-Tabelle in BackofficeDashboardServiceTest
kannte status_reason aus d6efe56 noch nicht.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kevin 2026-09-16 14:48:01 +00:00
parent cf0311afc1
commit b7e8bbd951
21 changed files with 547 additions and 20 deletions

View file

@ -22,6 +22,7 @@ Plan und Tickets: [`dev/_tickets/entwicklungsplan-protokoll-september-2026.md`](
| [monatsabschluss-eingefrorene-statistik.md](monatsabschluss-eingefrorene-statistik.md) | Warum ein abgerechneter Monat vollständig eingefroren wird — Statistik, Team-Struktur, Detaillisten. Grenzen und Betriebsbefehle. |
| [audit-statistiken-2026-09-09-bewertung.md, Abschnitt 8](audit-statistiken-2026-09-09-bewertung.md) | Stornoregel: ein Storno mindert nur den Monat der Ursprungsbestellung. Settings-Schalter für den Ausnahmefall. |
| [audit-statistiken-2026-09-09-bewertung.md, Abschnitt 14](audit-statistiken-2026-09-09-bewertung.md) | Abo-Zustand: Berater wechseln ihn nur über Pause und Kündigung, nie über ein Aktiv-Feld. Jeder Wechsel wird zentral protokolliert. |
| [neupartner-zahlungsmonat.md](neupartner-zahlungsmonat.md) | Neupartner zählen im Monat der **Zahlung**, nicht der Registrierung (`partner_paid_at`). Gilt für Kachel, Recruiting, Top 3 und Liste. |
## Prüfungen vom September 2026

View file

@ -143,3 +143,25 @@ Die Monatsspalte erscheint nur, solange kein anderer Monat gefiltert ist; für e
wäre sie irreführend.
**Deployment:** nur Dateien, keine Migration, kein Skript. Danach `php artisan view:clear`.
---
## Nachtrag 16.09.2026 — Neupartner zählen im Monat der Zahlung
Regeländerung nach Kundenentscheidung, Einzelheiten in
[neupartner-zahlungsmonat.md](neupartner-zahlungsmonat.md). Auslöser: Partner 1623, Ende August
registriert, am 1. September bezahlt, in keinem Monat gezählt.
**Deployment:**
```bash
php artisan migrate # neue Spalte users.partner_paid_at + Rueckfuellung (ca. 10 s)
php artisan view:clear
```
Optional und bewusst zu entscheiden — die eingefrorenen Monate Januar bis August enthalten sieben
Partner nicht, die unter der neuen Regel dorthin gehören:
```bash
php artisan backoffice:store-statistics-snapshots --force
```

View file

@ -0,0 +1,86 @@
# Neupartner zählen im Monat der Zahlung
**Entscheidung der Kundin, 16.09.2026.** Ein neuer Vertriebspartner gehört in den Monat, in dem
er **bezahlt** hat — nicht in den Monat seiner Registrierung. Das gilt für jede Stelle, die
Neupartner zählt: Kachel, Recruiter-Ranking, Top 3 „Recruiter des Monats", Neupartner-Liste,
CSV-Export.
## Der Fall, der es ausgelöst hat
Partner 1623 (Sponsor 454): registriert am 28.08., erster Zahlungslink abgelaufen, zweiter am
**01.09. um 06:49** bezahlt. Der Snapshot für August wurde am 01.09. um 04:45 eingefroren — da
hatte er noch kein Abrechnungskonto und fiel im August raus. Im September lag sein
Aktivierungsdatum im falschen Monat. **Er tauchte nirgends auf**, auch nicht beim Recruiting
seines Sponsors.
Das ist kein Einzelfall: 2026 betrifft es **8 Partner**, jeweils Ende des Monats registriert und
Anfang des Folgemonats bezahlt — 2 im Januar, 1 im April, 1 im Juni, 3 im Juli, 1 im September.
## Was sich geändert hat
Die Neupartner-Regel hing an `users.active_date` (Abschluss der Registrierung). Neu ist die Spalte
**`users.partner_paid_at`**: der Zeitpunkt der ersten Kontozahlung.
| | vorher | jetzt |
| --- | --- | --- |
| Neupartner im Monat X | `active_date` in X | `partner_paid_at` in X |
| Abrechnungskonto gültig am Stichtag | ja | ja, unverändert |
| Mitgliedsebene gesetzt | ja | ja, unverändert |
Die Regel steht an **einer** Stelle — `User::scopeNewPartnerIn()` und das PHP-Gegenstück
`User::isNewPartnerIn()` — und alle Zählungen gehen darüber.
**Gesetzt wird `partner_paid_at`** bei der ersten Kontozahlung (`Payment::paymentStatusPaidAction`,
Produktaktion `payment_for_account`) und bei manueller Kontofreischaltung durch den Admin. Beides
über `UserUtil::markPartnerPaid()`, das den Wert **nur setzt, solange er leer ist**. Eine
Verlängerung oder eine Wiederherstellung ändert ihn nicht — sonst würde ein alter Partner in der
Neupartner-Statistik wieder auftauchen.
**Rückgefüllt** wurde per Migration aus der ersten bezahlten Registrierungsbestellung
(`shopping_orders.payment_for = 1`): die Punktebuchung dazu entsteht im Moment der Zahlung, deren
Zeitstempel ist der Wert. Ohne Buchung das Änderungsdatum der Bestellung; ohne Bestellung (Konto
vom Admin freigeschaltet, 14 Fälle) das Aktivierungsdatum. **Nicht** verwendet wurde
`payment_account` minus ein Jahr: bei Verlängerungen wird vom alten Ablaufdatum aus verlängert, das
Ergebnis wäre der Jahrestag der Erstzahlung und jeder Verlängerer ein „Neupartner".
## Was sich nicht geändert hat
**Die Teamstruktur.** Ob jemand zum Monatsende zur Linie gehört, hängt weiterhin an `active_date` —
so auch im Provisionsbaum. Das ist eine andere Frage als „wer ist neu dazugekommen": Partner 1623
steht im September in der Struktur seines Sponsors, und er ist der September-Neupartner. Ein Partner,
der am 28.09. registriert und am 02.10. bezahlt, steht im September schon in der Struktur, zählt aber
erst im Oktober als neu.
**Provisionen, Gutschriften, Marketingplan.** Unberührt. Die Migration fügt eine leere Spalte hinzu
und füllt sie; keine vorhandene Zeile wird sonst geändert.
## Wiederhergestellte Partner
Vier Partner haben ein `active_date` Jahre **nach** ihrer Registrierungszahlung (414, 522, 610,
663) — sie wurden offenbar wiederhergestellt, und `restoreUser()` setzt `active_date` neu. Unter der
alten Regel zählten sie als Neupartner im Monat der Wiederherstellung. Unter der neuen Regel zählen
sie im Monat ihrer ursprünglichen Zahlung (2021–2023), also **nicht** als Neupartner 2026. Das ist
fachlich richtig, wenn eine Wiederherstellung keine Neuwerbung ist. Falls die Kundin das anders
sieht, müsste `restoreUser()` den Wert zurücksetzen — bewusst nicht gemacht.
## Die eingefrorenen Monate
Die Snapshots Januar bis August wurden mit der **alten** Regel gebaut. Sieben der acht
Partner von oben fehlen darin vollständig — in beiden Monaten. Der Snapshot friert bewusst ein
(siehe [monatsabschluss-eingefrorene-statistik.md](monatsabschluss-eingefrorene-statistik.md)), ein
Neuaufbau ist deshalb eine Entscheidung, keine Routine:
```bash
php artisan backoffice:store-statistics-snapshots --force
```
Damit landen die sieben in ihren Zahlungsmonaten. Wie am 10.09. gilt: der Neuaufbau friert die
Teamstruktur des **Ausführungstags** ein, nicht die des damaligen Monatsendes. Wer seit dem 10.09.
verschoben wurde oder dazukam, steht danach an seiner heutigen Stelle in den historischen Zahlen.
## Sichtprüfung nach dem Deploy
- Backoffice → September → Neupartner-Liste: Partner 1623 steht drin, Spalte „Bezahlt am" =
01.09.2026, „Registriert am" = 28.08.2026.
- Recruiter-Ranking September: Sponsor 454 hat ihn angerechnet.
- Backoffice → August (eingefroren): unverändert, solange kein Neuaufbau läuft.