mivita/resources/views/user/abo/index.blade.php
Kevin 8f4e105c0f Kundenabo-Seite: Vorschau taggenau, Liste mit den tatsaechlich gebuchten Punkten
Vorschau und Liste liessen sich nicht gegeneinander nachrechnen — zwei Ursachen,
beide hier behoben.

1. Die Vorschau nahm eine pauschale Monatssumme als Basis. Damit enthielt die
   Kachel zum 5. auch schon die Lieferungen vom 10. Jetzt zaehlt je Termin, was
   bis zu diesem Tag gebucht war, plus die bis dahin offenen Lieferungen.
   Buchungen nach dem letzten Liefertag (Nachzuegler, manuelle Gutschriften)
   haengen sich an die letzte Kachel, damit die den Monatsstand zeigt. Jede
   Kachel weist ihre Aufschluesselung aus ("457 abgerechnet + 131 offen").

   Beraterin 454 im September: 132 / 457 / 588 / 776 statt 0 / 0 / 131 / 319.

2. Die Liste zeigte nur den wiederkehrenden Abo-Inhalt. Einmal-Artikel und
   sonstige Zubuchungen einer Lieferung werden nach der Ausfuehrung aus dem Abo
   entfernt und tauchten deshalb nirgends mehr auf — bei Abo 266 waren das 43
   Punkte, bei Abo 418 rund 39. Neue Spalte "Diesen Monat" mit den je Abo
   tatsaechlich gebuchten Punkten, bei Abweichung mit dem Zusatz "+43 einmalig",
   dazu eine Summenzeile. Ein nicht zuordenbarer Rest (geloeschtes Abo, Buchung
   ohne Ausfuehrungsbezug) wird gesondert ausgewiesen, damit die Addition aufgeht.

   Die Spalte erscheint nur ohne Monatsfilter; fuer einen vergangenen Monat waere
   sie irrefuehrend.

Summe der Monatsspalte = Basis der letzten Kachel; Summe der Abo-Punkte der Abos
mit Termin 20./25. = deren offener Teil.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-11 08:19:35 +00:00

290 lines
16 KiB
PHP

@extends('layouts.layout-2')
@section('content')
<h4 class="font-weight-bold py-2 mb-2 d-flex justify-content-between align-items-center w-100 ">
<div>
@if($view === 'ot') {{ __('navigation.customerabos') }} @endif
@if($view === 'me') {{ __('navigation.myabos') }} @endif
/ {{ __('navigation.overview') }}
</div>
</h4>
@if(isset($chartData))
@include('user.abo._abo_chart')
@endif
@if($view === 'ot' && isset($filterMonth))
<div class="card mb-4">
<div class="card-body py-3">
<form method="GET" action="{{ url()->current() }}" class="form-inline">
<label class="text-muted small mr-2 mb-0">{{ __('abo.filter_added_period') }}</label>
<select name="month" class="form-control form-control-sm mr-2 mb-1">
<option value="0">{{ __('tables.all') }}</option>
@foreach($chartMonths as $monthNum => $monthName)
<option value="{{ $monthNum }}" {{ (int) $filterMonth === (int) $monthNum ? 'selected' : '' }}>{{ $monthName }}</option>
@endforeach
</select>
<select name="year" class="form-control form-control-sm mr-2 mb-1">
@foreach($chartYears as $y)
<option value="{{ $y }}" {{ (int) $filterYear === (int) $y ? 'selected' : '' }}>{{ $y }}</option>
@endforeach
</select>
<button type="submit" class="btn btn-sm btn-secondary mb-1">{{ __('abo.filter') }}</button>
@if($filterMonth)
<a href="{{ url()->current() }}?year={{ $filterYear }}" class="btn btn-sm btn-outline-secondary ml-2 mb-1">{{ __('abo.reset') }}</a>
@endif
</form>
</div>
</div>
@endif
@if (Session::has('alert-success'))
<div class="alert alert-success">
{{ Session::get('alert-success') }}
</div>
@endif
@if (Session::has('alert-error'))
<div class="alert alert-danger">
{{ Session::get('alert-error') }}
</div>
@endif
<div class="row">
<div class="col-12">
@php
$abo_payment_links = $abo_payment_links ?? collect();
@endphp
@if($view === 'ot' && $abo_payment_links->isNotEmpty())
@foreach($abo_payment_links as $paymentLink)
<div class="card mb-4 border-warning">
<div class="card-body pb-2">
<div class="row">
<div class="col-sm-7">
<h5 class="mb-1">
<a href="{{ route('user_order_payment_links_detail', [$paymentLink->identifier]) }}">
{{ __('navigation.abo') }} <span class="text-muted">#{{ $paymentLink->identifier }}</span>
</a>
{!! \App\Services\OrderPaymentService::getTypeBadge($paymentLink) !!}
</h5>
</div>
<div class="col-sm-5 text-right">
<a href="{{ route('user_order_payment_links_detail', [$paymentLink->identifier]) }}" class="btn btn-sm btn-secondary">
<span class="fa fa-edit"></span>{{ __('abo.abo_details') }}
</a>
@if(\App\Services\OrderPaymentService::canDeleteInstance($paymentLink))
{!! Form::open(['action' => route('user_abos_payment_link_delete', [$paymentLink->identifier]), 'class' => 'd-inline-block ml-1']) !!}
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('{{ __('confirm_delete') }}');">
<span class="fa fa-trash"></span> {{ __('delete') }}
</button>
{!! Form::close() !!}
@endif
</div>
</div>
</div>
<hr class="m-0">
<div class="card-body pb-1">
@if(\App\Services\OrderPaymentService::isPaymentFailed($paymentLink))
<div class="alert alert-danger mb-3">
<strong>{{ __('abo.pending_payment_failed_title') }}</strong><br>
{{ __('abo.payment_link_failed_copy') }}
</div>
@elseif(\App\Services\OrderPaymentService::isPaymentProcessing($paymentLink))
<div class="alert alert-info mb-3">
<strong>{{ __('abo.pending_payment_processing_title') }}</strong><br>
{{ __('abo.payment_link_processing_copy') }}
</div>
@else
<div class="alert alert-warning mb-3">
<strong>{{ __('abo.payment_link_sent_title') }}</strong><br>
{{ __('abo.payment_link_sent_copy') }}
</div>
@endif
<div class="row">
<div class="col-md-3 mb-3">
<div class="text-muted small">{{ __('tables.date') }}</div>
<div class="font-weight-bold">{{ $paymentLink->created_at->format('d.m.Y') }}</div>
</div>
<div class="col-md-3 mb-3">
<div class="text-muted small">{{ __('tables.status') }}</div>
{!! \App\Services\OrderPaymentService::getStatusBadge($paymentLink) !!}
</div>
<div class="col-md-3 mb-3">
<div class="text-muted small">{{ __('tables.amount') }}</div>
{{ $paymentLink->getAmountFormatted() }} €
</div>
<div class="col-md-3 mb-3">
<div class="text-muted small">{{ __('tables.email') }}</div>
{{ $paymentLink->shopping_data['billing_email'] ?? '-' }}
</div>
</div>
</div>
</div>
@endforeach
@endif
@if((!$user_abos || $user_abos->isEmpty()) && $abo_payment_links->isEmpty())
<div class="card mb-4">
<div class="card-body pb-2">
<div class="row">
<div class="col-sm-12">
<h5>{{ __('abo.abo_delivery') }}</h5>
</div>
<hr class="m-0">
<div class="col-sm-12 mb-4">
<a href="{{ route('user_order_my_delivery', ['abo-me']) }}" class="btn btn-secondary rounded-pill">
<span class="ion ion-md-add"></span>&nbsp; {{ __('abo.add_new_abo') }} </a>
</div>
</div>
</div>
</div>
@endif
@php
// Kundenabos laufen ueber die sortierbare Liste; als Karte bleiben nur
// die Ausnahmefaelle mit offener Erstzahlung, weil dort Aktionsbuttons
// haengen (Kundenwunsch 2026-09-07).
$cardAbos = $view === 'ot'
? collect($user_abos)->filter(fn ($abo) => $abo->isPendingInitialPayment())
: collect($user_abos);
$listAbos = $view === 'ot'
? collect($user_abos)->reject(fn ($abo) => $abo->isPendingInitialPayment())->values()
: collect();
@endphp
@foreach($cardAbos as $user_abo)
<div class="card mb-4">
@if($user_abo->isPendingInitialPayment())
<div class="card-body pb-0">
@if($user_abo->hasFailedInitialPayment())
<div class="alert alert-danger mb-3">
<strong>{{ __('abo.pending_payment_failed_title') }}</strong><br>
{{ __('abo.pending_payment_failed_copy') }}
{!! Form::open(['action' => route('user_abos_delete_pending', [$view, $user_abo->id]), 'class' => 'd-inline-block ml-2']) !!}
<button type="submit" class="btn btn-sm btn-danger">{{ __('abo.pending_delete_button') }}</button>
{!! Form::close() !!}
</div>
@elseif($user_abo->hasInitialPaymentStatus())
<div class="alert alert-info mb-3">
<strong>{{ __('abo.pending_payment_processing_title') }}</strong><br>
{{ __('abo.pending_payment_processing_copy') }}
</div>
@else
<div class="alert alert-warning mb-3">
<strong>{{ __('abo.pending_payment_waiting_title') }}</strong><br>
{{ __('abo.pending_payment_waiting_copy') }}
</div>
@endif
</div>
@endif
<div class="card-body pb-2">
<div class="row">
<div class="col-sm-6">
<h5 class="mb-1">
<a href="{{ route('user_abos_detail', [$view, $user_abo->id]) }}">
{{ __('navigation.abo') }} <span class="text-muted">{{ '#'.$user_abo->payone_userid }}</span>
</a>
</h5>
</div>
<div class="col-sm-6 text-right">
<a href="{{ route('user_abos_detail', [$view, $user_abo->id]) }}" class="btn btn-sm btn-secondary float-right">
<span class="fa fa-edit"></span>{{ __('abo.abo_details') }}
</a>
</div>
</div>
</div>
<hr class="m-0">
<div class="card-body pb-1">
<div class="row">
<div class="col-md-3 mb-2">
<div class="text-muted small">{{ __('tables.start_date') }}</div>
<div class="font-weight-bold">{{ $user_abo->start_date }}</div>
</div>
<div class="col-md-3 mb-2">
<div class="text-muted small">{{ __('tables.next_date') }} </div>
<div class="font-weight-bold">{{ $user_abo->next_date }}</div>
</div>
<div class="col-md-3 mb-2">
<div class="text-muted small">{{ __('tables.abo_delivery_day') }}</div>
<div class="font-weight-bold">{{ \App\Services\HTMLHelper::getAboStrLang($user_abo->abo_interval) }}</div>
</div>
<div class="col-md-3 mb-2">
<div class="text-muted small">{{ __('tables.last_date') }}</div>
<div class="font-weight-bold">{{ $user_abo->last_date }}</div>
</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) !!}
</div>
<div class="col-md-3 mb-3">
<div class="text-muted small">{{ __('tables.abo_delivery') }}</div>
{{ $user_abo->getCountOrders() }}
</div>
<div class="col-md-3 mb-3">
@if($view === 'ot')
<div class="text-muted small">{{ __('navigation.points') }}</div>
<strong class="text-primary">{{ $user_abo->getFormattedTotalPoints() }} Pkt.</strong>
@else
<div class="text-muted small">{{ __('tables.amount') }}</div>
{{ $user_abo->getFormattedAmount() }} €
@endif
</div>
<div class="col-md-3 mb-3">
<div class="text-muted small">{{ __('tables.payment') }}</div>
{{ $user_abo->getPaymentType() }}
</div>
</div>
</div>
@if($view === 'ot')
<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">{{ __('First name') }}</div>
@if($user_abo->shopping_user)
{{ $user_abo->shopping_user->billing_firstname }}
@endif
</div>
<div class="col-md-3 mb-3">
<div class="text-muted small">{{ __('Last name') }}</div>
@if($user_abo->shopping_user)
{{ $user_abo->shopping_user->billing_lastname }}
@endif
</div>
<div class="col-md-3 mb-3">
<div class="text-muted small">{{ __('E-Mail') }}</div>
@if($user_abo->shopping_user)
{{ $user_abo->shopping_user->billing_email }}
@endif
</div>
<div class="col-md-3 mb-3">
<div class="text-muted small">{{ __('tables.customer') }}</div>
@if($user_abo->shopping_user)
<a class="btn btn-sm btn-secondary" href="{{ route('user_customer_detail', $user_abo->shopping_user->id) }}"><i class="fa fa-edit"></i></a>
@endif
</div>
</div>
</div>
@endif
</div>
@endforeach
@if($view === 'ot' && $listAbos->isNotEmpty())
@include('user.abo._customer_abo_list', [
'listAbos' => $listAbos,
'customerAboForecast' => $customerAboForecast ?? null,
'customerAboBilled' => $customerAboBilled ?? null,
'customerAboBilledTotal' => $customerAboBilledTotal ?? null,
])
@endif
</div>
</div>
@endsection