mivita/app/Mail/SponsorTransferMail.php
Kevin 0b8f8abeeb 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>
2026-09-23 15:44:45 +00:00

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'),
]);
}
}