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>
63 lines
2.5 KiB
PHP
63 lines
2.5 KiB
PHP
<?php
|
|
|
|
namespace App\Mail;
|
|
|
|
use App\Services\UserUtil;
|
|
use App\User;
|
|
use Illuminate\Bus\Queueable;
|
|
use Illuminate\Mail\Mailable;
|
|
use Illuminate\Queue\SerializesModels;
|
|
|
|
/**
|
|
* Mail an den Sponsor beim harten Cut (Entwicklungsplan B2, Stufe 2): welche Kunden
|
|
* und Teampartner des ausgeschiedenen Beraters jetzt endgültig bei ihm liegen, mit
|
|
* Vorname, Nachname, Telefon und E-Mail. Beim Sponsor des harten Cuts steht der
|
|
* Berater selbst als neuer Kunde mit auf der Liste.
|
|
*/
|
|
class SponsorTransferMail extends Mailable
|
|
{
|
|
use Queueable, SerializesModels;
|
|
|
|
/**
|
|
* Die Listen heissen bewusst nicht `customers`/`team`: oeffentliche Eigenschaften
|
|
* eines Mailables landen in der View und wuerden die aufbereiteten Listen aus
|
|
* build() ueberschreiben.
|
|
*
|
|
* @param list<array{first_name: string, last_name: string, phone: string, email: string}> $customerRows
|
|
* @param list<array{first_name: string, last_name: string, phone: string, email: string}> $teamRows
|
|
*/
|
|
public function __construct(
|
|
public User $sponsor,
|
|
public User $consultant,
|
|
public array $customerRows,
|
|
public array $teamRows,
|
|
public bool $consultantBecomesCustomer,
|
|
) {}
|
|
|
|
public function build(): self
|
|
{
|
|
$name = trim($this->consultant->account?->first_name.' '.$this->consultant->account?->last_name) ?: $this->consultant->email;
|
|
|
|
$customers = $this->customerRows;
|
|
if ($this->consultantBecomesCustomer) {
|
|
array_unshift($customers, [
|
|
'first_name' => (string) $this->consultant->account?->first_name,
|
|
'last_name' => (string) $this->consultant->account?->last_name,
|
|
'phone' => trim((string) $this->consultant->account?->getPhoneNumber()),
|
|
'email' => UserUtil::stripDeletePrefix($this->consultant->email),
|
|
]);
|
|
}
|
|
|
|
return $this->subject(__('suspension.transfer_subject', ['name' => $name]))
|
|
->view('emails.consultant_suspension')
|
|
->with([
|
|
'headline' => __('suspension.transfer_subject', ['name' => $name]),
|
|
'salutation' => __('email.hello').' '.($this->sponsor->account?->first_name ?? ''),
|
|
'paragraphs' => [__('suspension.transfer_intro', ['name' => $name])],
|
|
'customers' => $customers,
|
|
'team' => $this->teamRows,
|
|
'greetings' => __('email.greetings'),
|
|
'sender' => __('email.sender'),
|
|
]);
|
|
}
|
|
}
|