mivita/resources/views/admin/abo/_detail.blade.php
Kevin 4709dfde55 Abo: Bestellung extern als erledigt markieren (ohne Rechnung/Inkasso)
Neue Admin-Funktion fuer angehaltene Abo-Bestellungen, die der Kunde
ausserhalb des Systems geliefert und verrechnet hat.

Aktion (AboExternalCompletionService):
- Punkte gutschreiben wie bei eingegangener Zahlung (SalesPointsVolume,
  idempotent gegen Doppelbuchung)
- UserAboOrder auf neuen gruenen Status 8 "extern erledigt"; paid bleibt false
- Bestellung: shipped=2 (Lieferung bestaetigt), keine Rechnung/kein Lieferschein
- Blockade aufheben: Abo zurueck auf status=2 (okay), aktiv, next_date neu,
  damit der naechste Termin regulaer laeuft
- wie bei regulaerer Ausfuehrung: IncentiveTracker + AboOneTimeService-Purge

Einstiegspunkte: Button + Bestaetigungs-Modal auf der Kunden-Bestelldetailseite
(SalesController) und auf der Abo-Detailseite (Admin\AboController@externDone,
Route admin_abos_extern_done). Status 8 (gruen) in UserAbo/UserAboOrder, Labels
de/en.

Tests: tests/Feature/AboExternalCompletionTest (Happy Path, Idempotenz,
bezahlt-/Nicht-Abo-Guards, Abo-Detail-Einstieg) - 5 gruen.

Zusaetzlich: docs/2026-06-11-test-suite-vorbestehende-fehler.md - Diagnose der
93 vorbestehenden (von master geerbten) Test-Suite-Fehler.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 08:11:45 +00:00

124 lines
5.4 KiB
PHP

<!-- Info -->
<div class="card-body pb-1">
<div class="row">
<div class="col-md-3 mb-3">
<div class="text-muted small">{{ __('tables.start_date') }}</div>
{{ $user_abo->start_date }}
</div>
<div class="col-md-3 mb-3">
<div class="text-muted small">{{ __('tables.next_date') }}</div>
<strong>{{ $user_abo->next_date }}</strong>
</div>
<div class="col-md-3 mb-3">
<div class="text-muted small">{{ __('tables.abo_delivery_day') }}</div>
<strong>{{ \App\Services\HTMLHelper::getAboStrLang($user_abo->abo_interval) }}</strong>
</div>
<div class="col-md-3 mb-3">
<div class="text-muted small">{{ __('tables.last_date') }}</div>
{{ $user_abo->last_date }}
</div>
</div>
</div>
<hr class="m-0">
<div class="card-body pb-1">
<div class="row">
<div class="col-md-3 mb-3">
<div class="text-muted small">{{ __('tables.status') }} / {{ __('tables.active') }}</div>
{!! $user_abo->getStatusFormated() !!} &nbsp;{!! get_active_badge($user_abo->active) !!}
@if ($user_abo->status === 3 && $user_abo->active)
<button type="button" class="btn btn-sm btn-danger mt-3" data-toggle="modal"
data-target="#modal-retry-abo-payment">
<span class="fa fa-redo"></span> {{ __('abo.retry_payment') }}
</button>
<button type="button" class="btn btn-sm btn-success mt-3" data-toggle="modal"
data-target="#modal-abo-extern-done">
<span class="fa fa-check"></span> {{ __('abo.extern_done') }}
</button>
@endif
</div>
<div class="col-md-3 mb-3">
<div class="text-muted small">{{ __('tables.abo_delivery') }}</div>
{{ $user_abo->getCountPaidOrders() }} / {{ \App\Models\Setting::getContentBySlug('abo-min-duration') }}
</div>
<div class="col-md-3 mb-3">
<div class="text-muted small">{{ __('tables.payment') }}</div>
{{ $user_abo->getPaymentType() }}
</div>
<div class="col-md-3 mb-3">
<div class="text-muted small">{{ __('tables.amount') }}</div>
<span class="text-nowrap" id="value-amount">{{ $user_abo->getFormattedAmount() }}</span> €
</div>
</div>
</div>
<hr class="m-0">
@if ($isAdmin)
<div class="card-body pb-1">
<div class="row">
<div class="col-md-3 mb-3">
<button type="button" class="btn btn-sm btn-secondary" data-toggle="modal"
data-target="#modals-load-content" data-id="{{ $user_abo->id }}" data-action="abo_update_settings"
data-view="admin" data-route="{{ route('modal_load') }}"><span
class="fa fa-edit"></span>{{ __('abo.abo_settings') }}</button>
</div>
<div class="col-md-6 mb-3">
@if (isset($user_abo->shopping_user) && $user_abo->shopping_user->member_id > 0)
<div class="text-muted small">{{ __('tables.adviser') }}</div>
{!! '<a href="' .
route('admin_lead_edit', [$user_abo->shopping_user->member_id]) .
'">' .
$user_abo->shopping_user->member->getFullName() .
'</a>' !!}
@endif
</div>
<div class="col-md-3 mb-3">
<div class="text-muted small">{{ __('tables.is_for') }}</div>
{!! $user_abo->getIsForFormated() !!}
@if ($user_abo->is_for === 'me')
<a class="btn btn-xs btn-secondary" href="{{ route('admin_lead_edit', $user_abo->user_id) }}"><i
class="fa fa-edit"></i></a>
@endif
@if ($user_abo->is_for === 'ot')
<a class="btn btn-xs btn-secondary"
href="{{ route('admin_customer_edit', $user_abo->shopping_user->id) }}"><i
class="fa fa-edit"></i></a>
@endif
</div>
</div>
</div>
@else
<div class="card-body pb-1">
<div class="row">
<div class="col-md-6 mb-3">
@if (App\Services\AboHelper::canEditAbo($user_abo, $view))
<button type="button" class="btn btn-sm btn-secondary" data-toggle="modal"
data-target="#modals-load-content" data-id="{{ $user_abo->id }}"
data-action="abo_update_settings" data-view="{{ $view }}"
data-route="{{ route('modal_load') }}"><span
class="fa fa-edit"></span>{{ __('abo.abo_settings') }}</button>
@endif
</div>
<div class="col-md-3 mb-3">
{!! $user_abo->getIsForFormated() !!}
@if ($user_abo->is_for === 'me')
<a class="btn btn-xs btn-secondary" href="{{ route('user_edit') }}"><i class="fa fa-edit"></i></a>
@endif
@if ($user_abo->is_for === 'ot')
<a class="btn btn-xs btn-secondary"
href="{{ route('user_customer_edit', $user_abo->shopping_user->id) }}"><i
class="fa fa-edit"></i></a>
@endif
</div>
</div>
</div>
@endif