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>
290 lines
16 KiB
PHP
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> {{ __('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() !!} {!! 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
|