Berater faellt aus (B2): pausieren nach 2 Tagen, Rueckgabe bei Zahlung, harter Cut am 28. Tag
Entwicklungsplan September, B2 (Protokoll 08.09., Rueckmeldung 14.09., R3): - Ablauftag + 2 Kalendertage (Nachtlauf): Team, Kunden, Kundenabos und Portal-Logins gehen umkehrbar an den naechsten aktiven Sponsor, jede Umhaengung in consultant_suspension_transfers protokolliert. Kurzinfo an den Sponsor ohne Listen, keine Mail an das Firmenkonto. - Zahlung bis Tag 27: Berater aktiv, Team und Kundendaten zurueck (nur was noch beim Sponsor liegt); Umsaetze der Zwischenzeit bleiben dort. - Tag 28: was noch am Berater haengt geht endgueltig an den Sponsor, Berater wird dessen Kunde (ohne Duplikat) und geloescht; Listen-Mail mit Vorname, Nachname, Telefon, E-Mail an jeden haltenden Sponsor. - Cron, Zahlungseingang und Admin-Ablaufdatum laufen ueber ConsultantSuspensionService; user:cleanup --dry-run listet beide Stufen. - Mail 35 und Dashboard nennen Pausentag und Frist; Fristen in config/mivita.php (cleanup_suspend_days, cleanup_delete_days). - Nebenbefunde: Kernel referenziert UserCleanUp, user:restore aus der User-Bereinigung laeuft nur noch einmal. - Testschema: shopping_users.auth_user_id nullable wie auf Produktion (Migration aendert nur, wo die Spalte noch NOT NULL ist). - Uebersicht fuer die Kundin: dev/_tickets/2026-09-23-mitgliedschaft- ablauf-uebersicht.md. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
03ad249eeb
commit
bb57522b70
29 changed files with 1528 additions and 193 deletions
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
/**
|
||||
* Protokoll der Kundendaten, die beim Pausieren eines Beraters (Ablauf der
|
||||
* Mitgliedschaft, Entwicklungsplan B2) vorübergehend beim Sponsor liegen:
|
||||
* Kunden (shopping_users), Kundenabos (user_abos) und Portal-Logins (customers).
|
||||
*
|
||||
* Zahlt der Berater innerhalb der Frist, gibt das Protokoll genau diese
|
||||
* Datensätze zurück; beim harten Cut ist es die Quelle der Sponsor-Mail.
|
||||
*/
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('consultant_suspension_transfers', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->unsignedInteger('consultant_id')->comment('pausierter Berater, bisheriger member_id');
|
||||
$table->unsignedInteger('sponsor_id')->comment('Sponsor, der die Datensaetze voruebergehend erhaelt');
|
||||
$table->string('record_type', 20)->comment('shopping_user, user_abo oder customer');
|
||||
$table->unsignedBigInteger('record_id');
|
||||
$table->timestamp('returned_at')->nullable()->comment('Rueckgabe an den Berater nach Zahlung');
|
||||
$table->timestamps();
|
||||
|
||||
$table->index(['consultant_id', 'returned_at']);
|
||||
$table->index(['record_type', 'record_id']);
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('consultant_suspension_transfers');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
use App\Services\UserUtil;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
/**
|
||||
* `shopping_users.auth_user_id` ist auf Produktion längst nullable — Kunden ohne
|
||||
* Login und der beim harten Cut angelegte Kundendatensatz eines ausgeschiedenen
|
||||
* Beraters ({@see UserUtil::setUserToClient()}) haben keinen.
|
||||
* Die Ursprungsmigration legt die Spalte aber NOT NULL an, sodass Testdatenbank und
|
||||
* Neuinstallationen anders reagieren als Produktion (wie `status_turnover`,
|
||||
* Migration 2026_09_09_140000).
|
||||
*
|
||||
* Ändert nur, wo die Spalte noch NOT NULL ist; auf Produktion also nichts.
|
||||
*/
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
$column = collect(Schema::getColumns('shopping_users'))->firstWhere('name', 'auth_user_id');
|
||||
|
||||
if ($column === null || $column['nullable']) {
|
||||
return;
|
||||
}
|
||||
|
||||
Schema::table('shopping_users', function (Blueprint $table) {
|
||||
$table->unsignedInteger('auth_user_id')->nullable()->change();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
// Bewusst leer: Produktion war schon vorher nullable, ein Zurückdrehen würde
|
||||
// bestehende Kundendatensätze ohne Login ungültig machen.
|
||||
}
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue