Abo-Recovery: fehlgeschlagene Folgezahlung im Checkout nachholen
- Pay-now-Flow: bei fehlgeschlagenem Abo (Status 3) begleicht der Inhaber die offene Rechnung im Standard-Checkout mit frei waehlbarer, abo-faehiger Zahlart (nur eigenes Abo: Berater me-View + Kundenportal), payNow-Controller + Routen - AboRecoveryCheckoutService baut die ShoppingInstance aus den Abo-Artikeln; neue Spalte shopping_orders.recovery_user_abo_id verknuepft Bestellung<->Abo - Bei Erfolg: AboHelper::advanceAboAfterRecoveryPayment schreibt das Abo fort (Status->2, next_date) und uebernimmt die gewaehlte Zahlart als neues Token fuer kuenftige Abbuchungen - Neue Pay-now-Fehlermail (AboPaymentFailedMail) ersetzt die generische Fehlermail im Abo-Cron; Link fuehrt auf die Abo-Detailseite (CRM bzw. Portal) - Retry-/"extern erledigt"-Buttons nur noch fuer Admins; tote user/portal- Retry-Routen entfernt - Checkout: Recovery-Hinweis statt "Abschluss des Abonnements", Lieferadresse vorbelegt, korrekter Zurueck-Link (Abo statt Shop) - UserAbo::selfServiceDetailUrl zentralisiert die Abo-URL (Mail, Back-Links) - Test-Command abo:test-recovery; Tests fuer payNow, Advance-Logik, Fehlermail Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
78db952130
commit
0660f4e0a0
28 changed files with 1535 additions and 181 deletions
|
|
@ -43,9 +43,26 @@
|
|||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if ($view === 'me' && $user_abo->status === 3 && $user_abo->active)
|
||||
<div class="card mt-3 mb-3 border-info">
|
||||
<div class="card-body">
|
||||
<h6 class="font-weight-bold text-info">{{ __('abo.pay_now_title') }}</h6>
|
||||
<p class="mb-2">{{ __('abo.pay_now_copy') }}</p>
|
||||
<form method="POST" action="{{ route('user_abos_pay_now', [$view, $user_abo->id]) }}">
|
||||
@csrf
|
||||
<button type="submit" class="btn btn-info">
|
||||
<i class="ion ion-md-card mr-1"></i>{{ __('abo.pay_now_button') }}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card">
|
||||
@include('admin.abo._detail')
|
||||
</div>
|
||||
|
||||
<div class="card mt-3">
|
||||
@include('admin.abo._detail_abo_info')
|
||||
</div>
|
||||
|
|
@ -103,7 +120,10 @@
|
|||
</div>
|
||||
@else
|
||||
<div class="card mt-3">
|
||||
@include('admin.abo._order_abo', ['add_only_mode' => $addOnlyMode, 'change_locked' => $aboChangeLocked])
|
||||
@include('admin.abo._order_abo', [
|
||||
'add_only_mode' => $addOnlyMode,
|
||||
'change_locked' => $aboChangeLocked,
|
||||
])
|
||||
</div>
|
||||
|
||||
<div id="holder_html_view_comp_product">
|
||||
|
|
@ -121,7 +141,52 @@
|
|||
@include('admin.abo._executions')
|
||||
</div>
|
||||
|
||||
@include('admin.abo._retry_payment_modal', ['retryAction' => route('user_abos_retry_payment', [$view, $user_abo->id])])
|
||||
@if ($user_abo->isCreditCard())
|
||||
<div class="card mt-3 mb-3">
|
||||
<div class="card-body">
|
||||
<h6 class="font-weight-bold">{{ __('abo.payment_method') }}</h6>
|
||||
<p class="mb-2">
|
||||
{{ __('payment.credit_card') }}@if ($user_abo->maskedCard())
|
||||
: {{ $user_abo->maskedCard() }}
|
||||
@endif
|
||||
</p>
|
||||
@if ($view === 'me' && $user_abo->canUpdatePaymentMethod())
|
||||
<a href="{{ route('user_abos_payment_method_edit', [$view, $user_abo->id]) }}"
|
||||
class="btn btn-sm btn-primary">
|
||||
{{ __('abo.update_payment_method') }}
|
||||
</a>
|
||||
@endif
|
||||
|
||||
@if ($view === 'ot' && $user_abo->canUpdatePaymentMethod())
|
||||
<form method="POST" action="{{ route('user_abos_payment_method_send_link', [$view, $user_abo->id]) }}"
|
||||
class="d-inline">
|
||||
@csrf
|
||||
<button type="submit" class="btn btn-sm btn-outline-primary">
|
||||
<i class="ion ion-md-mail mr-1"></i>{{ __('abo.card_update_link_button') }}
|
||||
</button>
|
||||
</form>
|
||||
@endif
|
||||
|
||||
@if ($user_abo->card_changes->isNotEmpty())
|
||||
<div class="mt-3">
|
||||
<small class="text-muted d-block mb-1">{{ __('abo.card_change_history') }}</small>
|
||||
<ul class="list-unstyled mb-0 small">
|
||||
@foreach ($user_abo->card_changes->take(5) as $change)
|
||||
<li>
|
||||
<i class="ion ion-md-time text-muted mr-1"></i>
|
||||
{{ $change->created_at->format('d.m.Y H:i') }}@if ($change->masked_card)
|
||||
— {{ $change->masked_card }}
|
||||
@endif
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
|
||||
<a href="{{ route('user_abos', [$view]) }}" class="btn btn-sm btn-default float-right">{{ __('back') }}</a>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue