Abo Einmalprodukte: Phase 4 - Ausfuehrung, Purge & User-Retry

- UserMakeOrder: bestaetigte Einmal-Artikel in den Yard, is_abo_addon
  auf ShoppingOrderItem; amount bleibt reiner Abo-Betrag (Reihenfolge)
- AboOneTimeService::purgeAfterExecution: loescht alle Einmal-Artikel
  und rechnet Comp-Produkte neu - nur im Erfolgszweig (Cron + Retry)
- User-Retry in Sales Center und Portal mit Berechtigungspruefung,
  gemeinsames Confirm-Modal; Admin-Retry unveraendert
- Tests: AboMakeOrderOneTimeTest, AboUserRetryTest; Plan-Doku Phase 4

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Kevin 2026-06-08 15:32:27 +00:00
parent 8288ea59ac
commit ee04146217
14 changed files with 536 additions and 19 deletions

View file

@ -0,0 +1,49 @@
@if ($user_abo->status === 3 && $user_abo->active)
<div class="text-right mt-3">
<button type="button" class="btn btn-warning" data-toggle="modal" data-target="#modal-retry-abo-payment">
<span class="fa fa-redo"></span> {{ __('abo.retry_payment') }}
</button>
</div>
<div class="modal fade" id="modal-retry-abo-payment" tabindex="-1" role="dialog" aria-labelledby="modal-retry-abo-payment-label" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
{!! Form::open(['action' => $retryAction]) !!}
<div class="modal-header">
<h5 class="modal-title" id="modal-retry-abo-payment-label">{{ __('abo.retry_payment') }}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="alert alert-warning">
<strong>{{ __('abo.retry_payment_confirm_title') }}</strong><br>
{{ __('abo.retry_payment_confirm_copy') }}
</div>
<table class="table table-sm mb-0">
<tr>
<td class="font-weight-bold">{{ __('navigation.abo') }}:</td>
<td>#{{ $user_abo->id }}</td>
</tr>
<tr>
<td class="font-weight-bold">{{ __('tables.payment') }}:</td>
<td>{{ $user_abo->getPaymentType() }}</td>
</tr>
<tr>
<td class="font-weight-bold">{{ __('tables.amount') }}:</td>
<td>{{ $user_abo->getFormattedAmount() }} </td>
</tr>
<tr>
<td class="font-weight-bold">{{ __('tables.next_date') }}:</td>
<td>{{ $user_abo->next_date }}</td>
</tr>
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{{ __('close') }}</button>
<button type="submit" class="btn btn-warning">{{ __('abo.retry_payment_confirm_button') }}</button>
</div>
{!! Form::close() !!}
</div>
</div>
</div>
@endif

View file

@ -7,6 +7,15 @@
<span class="text-muted">{{ '#' . $user_abo->payone_userid }}</span>
</h4>
@if (Session::has('alert-success'))
<div class="col-sm-12">
<div class="alert alert-success p-2 mt-2">
<ul>
<li>{{ Session::get('alert-success') }}</li>
</ul>
</div>
</div>
@endif
@if (Session::has('alert-error'))
<div class="col-sm-12">
<div class="alert alert-danger p-2 mt-2">
@ -90,6 +99,7 @@
@include('admin.abo._executions')
</div>
@include('admin.abo._retry_payment_modal', ['retryAction' => route('portal_abos_retry_payment', [$user_abo->id])])
<a href="{{ route('portal.my_subscriptions') }}" class="btn btn-sm btn-default float-right">{{ __('abo.back') }}</a>

View file

@ -16,6 +16,15 @@
</h4>
@if (Session::has('alert-success'))
<div class="col-sm-12">
<div class="alert alert-success p-2 mt-2">
<ul>
<li>{{ Session::get('alert-success') }}</li>
</ul>
</div>
</div>
@endif
@if (Session::has('alert-error'))
<div class="col-sm-12">
<div class="alert alert-danger p-2 mt-2">
@ -107,6 +116,7 @@
@include('admin.abo._executions')
</div>
@include('admin.abo._retry_payment_modal', ['retryAction' => route('user_abos_retry_payment', [$view, $user_abo->id])])
<a href="{{ route('user_abos', [$view]) }}" class="btn btn-sm btn-default float-right">{{ __('back') }}</a>