Abo: Kreditkarte aktualisieren (CRM, Portal, Berater-Link) + Admin-Abo-Löschung

- Karten-Update ohne Abbuchung via PAYONE creditcardcheck/pseudocardpan
  (AboPaymentMethodService, CardUpdateResult/CreditCardCheckData-DTOs)
- Eingabe nur durch Abo-Inhaber: CRM- und Portal-Formular + zeitlich
  begrenzter Berater→Kunde-Link (AboCardUpdateLink + Mail)
- Änderungshistorie in user_abo_card_changes, Anzeige im Admin-Abo-Detail
- Admin: Abo löschen (destroy) inkl. Test
- Portal-Fix: myOrderCreate wirft 404 statt TypeError bei ungültiger ID
- VIP-Sichtbarkeitstests für Einmalartikel-Fenster ergänzt
- Enthält bereits die Freeze-Guards für den Stripe-Notbetrieb (Folge-Commit)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Kevin 2026-07-08 15:56:19 +00:00
parent 63c36555a5
commit 671022a28d
36 changed files with 2366 additions and 26 deletions

View file

@ -3,11 +3,13 @@
namespace App\Exceptions;
use App\Services\Payment\Payone\Exceptions\PayoneTransportException;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer;
use Symfony\Component\ErrorHandler\Exception\FlattenException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Throwable;
@ -54,9 +56,9 @@ class Handler extends ExceptionHandler
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @return \Symfony\Component\HttpFoundation\Response
* @return Response
*
* @throws \Throwable
* @throws Throwable
*/
public function render($request, Throwable $exception)
{
@ -73,9 +75,9 @@ class Handler extends ExceptionHandler
* Convert an authentication exception into a response.
*
* @param \Illuminate\Http\Request $request
* @return \Symfony\Component\HttpFoundation\Response
* @return Response
*/
protected function unauthenticated($request, \Illuminate\Auth\AuthenticationException $exception)
protected function unauthenticated($request, AuthenticationException $exception)
{
if ($request->expectsJson()) {
return response()->json(['message' => $exception->getMessage()], 401);
@ -102,7 +104,7 @@ class Handler extends ExceptionHandler
public function sendEmail(Throwable $exception)
{
try {
$e = FlattenException::create($exception);
$e = FlattenException::createFromThrowable($exception);
$handler = new HtmlErrorRenderer(true); // boolean, true raises debug flag...
$css = $handler->getStylesheet();
$content = $handler->getBody($e);