A1: Jeder Monatstag ist als Liefertag erlaubt (UserAbo::allowedDeliveryDays), Tage 29-31 liefern in kuerzeren Monaten am letzten Tag. Eine Stelle AboHelper::dateForDayInMonth klammert; setNextDate, Erstausfuehrung, Admin-Termin und Pause rechnen darueber, der Folgemonat immer aus dem Liefertag (31.01 -> 28.02 -> 31.03). Liefertag-Aenderung gilt fuer den laufenden Zyklus und nur nach vorn: ist der Tag im Referenzmonat vorbei, wird abgelehnt, der Monat verschiebt sich nie (Rueckfrage R1). Admin-Filter "naechste Ausfuehrung" als Datumsbereich. Prognose-Kacheln bekommen die Kachel Monatsende, Team-Abos rechnen bis Monatsende. A2: Sperrfristen Default 0, Setting 0 ist ausdruecklich 0 (fiel bisher auf den Default zurueck). Bedingung Kalendertage <= Sperre, zentral in AboHelper::isWithinLock: am Ausfuehrungstag ab 0:00 Uhr fixiert, Vortag bis 23:59 Uhr frei, fuer Liefertag, Produkte, Pause und Kuendigung (R2). Texte mit _zero-Varianten ueber AboHelper::lockMessage. Sprachdateien de/en/es/fr, neuer AboDeliveryDayTest, bestehende Tests angepasst, Plan-Status mit Deploy-Schritt (Settings auf 0). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
171 lines
No EOL
11 KiB
PHP
171 lines
No EOL
11 KiB
PHP
@extends('layouts.layout-2')
|
|
|
|
@section('content')
|
|
|
|
|
|
<h4 class="font-weight-bold py-2 mb-2">
|
|
{{ __('Abos') }}
|
|
</h4>
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<div class="form-row align-items-end">
|
|
<div class="col-6 col-md-3 col-lg-2 mb-2">
|
|
<label class="form-label" for="filter_status">{{ __('tables.status') }}</label>
|
|
<select class="custom-select" name="filter_status" id="filter_status">
|
|
<option value="">{{ __('tables.all') }}</option>
|
|
@foreach ($filter_statuses as $id => $name)
|
|
<option value="{{ $id }}" @if((string) get_user_attr('filter_status') === (string) $id) selected @endif>{{ $name }}</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
<div class="col-6 col-md-3 col-lg-2 mb-2">
|
|
<label class="form-label" for="filter_state">{{ __('abo.filter_state') }}</label>
|
|
<select class="custom-select" name="filter_state" id="filter_state">
|
|
<option value="">{{ __('tables.all') }}</option>
|
|
<option value="paused" @if(get_user_attr('filter_state') === 'paused') selected @endif>{{ __('abo.state_paused') }}</option>
|
|
<option value="payment_failed" @if(get_user_attr('filter_state') === 'payment_failed') selected @endif>{{ __('abo.state_payment_failed') }}</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-6 col-md-3 col-lg-2 mb-2">
|
|
<label class="form-label" for="filter_active">{{ __('tables.active') }}</label>
|
|
<select class="custom-select" name="filter_active" id="filter_active">
|
|
<option value="">{{ __('tables.all') }}</option>
|
|
<option value="1" @if((string) get_user_attr('filter_active') === '1') selected @endif>{{ __('tables.active') }}</option>
|
|
<option value="0" @if((string) get_user_attr('filter_active') === '0') selected @endif>{{ __('tables.inactive') }}</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-6 col-md-3 col-lg-2 mb-2">
|
|
<label class="form-label" for="filter_is_for">{{ __('tables.is_for') }}</label>
|
|
<select class="custom-select" name="filter_is_for" id="filter_is_for">
|
|
<option value="">{{ __('tables.all') }}</option>
|
|
<option value="me" @if(get_user_attr('filter_is_for') === 'me') selected @endif>{{ __('tables.adviser') }}</option>
|
|
<option value="ot" @if(get_user_attr('filter_is_for') === 'ot') selected @endif>{{ __('tables.customer') }}</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-6 col-md-3 col-lg-2 mb-2">
|
|
<label class="form-label" for="filter_payment">{{ __('tables.payment') }}</label>
|
|
<select class="custom-select" name="filter_payment" id="filter_payment">
|
|
<option value="">{{ __('tables.all') }}</option>
|
|
<option value="cc" @if(get_user_attr('filter_payment') === 'cc') selected @endif>{{ __('payment.credit_card') }}</option>
|
|
<option value="wlt" @if(get_user_attr('filter_payment') === 'wlt') selected @endif>{{ __('payment.paypal') }}</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="form-row align-items-end">
|
|
<div class="col-12 col-md-6 col-lg-4 mb-2">
|
|
<label class="form-label">{{ __('tables.start_date') }}</label>
|
|
<div class="d-flex border rounded p-1" style="gap: 6px;">
|
|
<select class="custom-select" name="filter_start_month" id="filter_start_month" aria-label="{{ __('tables.month') }}">
|
|
<option value="">{{ __('tables.month') }} ({{ __('tables.all') }})</option>
|
|
@foreach ($filter_months as $num => $name)
|
|
<option value="{{ $num }}" @if((string) get_user_attr('filter_start_month') === (string) $num) selected @endif>{{ $name }}</option>
|
|
@endforeach
|
|
</select>
|
|
<select class="custom-select" name="filter_start_year" id="filter_start_year" aria-label="{{ __('tables.year') }}" style="max-width: 130px;">
|
|
<option value="">{{ __('tables.year') }} ({{ __('tables.all') }})</option>
|
|
@foreach ($filter_years as $year)
|
|
<option value="{{ $year }}" @if((string) get_user_attr('filter_start_year') === (string) $year) selected @endif>{{ $year }}</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="col-12 col-md-6 col-lg-4 mb-2">
|
|
<label class="form-label">{{ __('tables.next_date') }}</label>
|
|
<div class="d-flex border rounded p-1" style="gap: 6px;">
|
|
<input type="date" class="form-control" name="filter_next_from" id="filter_next_from" value="{{ get_user_attr('filter_next_from') }}" aria-label="{{ __('abo.filter_next_from') }}" placeholder="{{ __('abo.filter_next_from') }}">
|
|
<input type="date" class="form-control" name="filter_next_to" id="filter_next_to" value="{{ get_user_attr('filter_next_to') }}" aria-label="{{ __('abo.filter_next_to') }}" placeholder="{{ __('abo.filter_next_to') }}">
|
|
</div>
|
|
</div>
|
|
<div class="col-12 col-sm-6 col-md-3 col-lg-3 mb-2">
|
|
<label class="form-label" for="filter_member_id">{{ __('tables.adviser') }}</label>
|
|
<select class="selectpicker" data-style="btn-default" name="filter_member_id" id="filter_member_id" data-live-search="true" title="{{ __('tables.all') }}">
|
|
<option value="">{{ __('tables.all') }}</option>
|
|
@foreach ($filter_members as $member)
|
|
<option value="{{ $member->id }}" @if(get_user_attr('filter_member_id') == $member->id) selected @endif>{{ $member->first_name }} {{ $member->last_name }} | {{ $member->email }}</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
<div class="col-12 col-lg-auto mb-2 d-flex align-items-end">
|
|
<a href="{{ route('admin_abos') }}?reset=filter" title="{{ __('Reset Filter') }}" class="btn icon-btn btn-sm btn-outline-dark">
|
|
<span class="fa fa-sync"></span>
|
|
</a>
|
|
<span class="ml-2">{{ __('Reset Filter') }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="card-datatable table-responsive">
|
|
<table class="datatable-abos table table-striped table-bordered" id="datatable-abos">
|
|
<thead>
|
|
<tr>
|
|
<th>#</th>
|
|
<th>{{__('tables.start_date')}}</th>
|
|
<th>{{__('tables.next_date')}}</th>
|
|
<th>{{__('tables.abo_delivery_day')}}</th>
|
|
<th>{{__('tables.status')}}</th>
|
|
<th>{{__('tables.active')}}</th>
|
|
<th>{{__('tables.is_for')}}</th>
|
|
<th>{{__('First name')}}</th>
|
|
<th>{{__('Last name')}}</th>
|
|
<th>{{__('E-Mail')}}</th>
|
|
<th>{{__('tables.exc')}}</th>
|
|
<th>{{__('tables.amount')}}</th>
|
|
<th>{{__('tables.payment')}}</th>
|
|
<th>{{__('tables.adviser')}}</th>
|
|
<th>{{__('PayOneID')}}</th>
|
|
|
|
</tr>
|
|
</thead>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
$( document ).ready(function() {
|
|
var oTable = $('#datatable-abos').DataTable({
|
|
"processing": true,
|
|
"serverSide": true,
|
|
ajax: {
|
|
url: '{!! route( 'admin_abos_datatable') !!}',
|
|
data: function(d) {
|
|
d.filter_member_id = $('select[name=filter_member_id]').val();
|
|
d.filter_status = $('select[name=filter_status]').val();
|
|
d.filter_state = $('select[name=filter_state]').val();
|
|
d.filter_active = $('select[name=filter_active]').val();
|
|
d.filter_is_for = $('select[name=filter_is_for]').val();
|
|
d.filter_payment = $('select[name=filter_payment]').val();
|
|
d.filter_start_month = $('select[name=filter_start_month]').val();
|
|
d.filter_start_year = $('select[name=filter_start_year]').val();
|
|
d.filter_next_from = $('input[name=filter_next_from]').val();
|
|
d.filter_next_to = $('input[name=filter_next_to]').val();
|
|
}
|
|
},
|
|
"order": [[0, "desc" ]],
|
|
"columns": [
|
|
{ data: 'id', searchable: false },
|
|
{ data: 'start_date', name: 'start_date', searchable: false },
|
|
{ data: 'next_date', name: 'next_date', searchable: false },
|
|
{ data: 'abo_interval', name: 'abo_interval', searchable: false },
|
|
{ data: 'status', name: 'status', searchable: false },
|
|
{ data: 'active', name: 'active', searchable: false },
|
|
{ data: 'is_for', name: 'is_for', searchable: false },
|
|
{ data: 'shopping_user.billing_firstname', name: 'shopping_user.billing_firstname' },
|
|
{ data: 'shopping_user.billing_lastname', name: 'shopping_user.billing_lastname' },
|
|
{ data: 'shopping_user.billing_email', name: 'shopping_user.billing_email' },
|
|
{ data: 'count', name: 'count', searchable: false },
|
|
{ data: 'amount', name: 'amount', searchable: false },
|
|
{ data: 'payment', name: 'payment', searchable: false, orderable: false },
|
|
{ data: 'member', name: 'member', searchable: false, orderable: false },
|
|
{ data: 'payone_userid', name: 'payone_userid', searchable: true },
|
|
|
|
],
|
|
"bLengthChange": false,
|
|
"iDisplayLength": 100,
|
|
"language": {
|
|
"url": "/js/datatables-{{ \App::getLocale() }}.json"
|
|
}
|
|
});
|
|
$('#filter_start_month, #filter_start_year, #filter_next_from, #filter_next_to, #filter_status, #filter_state, #filter_active, #filter_is_for, #filter_payment, #filter_member_id').on('change', function(){
|
|
oTable.draw();
|
|
});
|
|
});
|
|
</script>
|
|
@endsection |