Kunden loeschen (Rueckmeldung "es wird nichts geloescht"): - DSGVO-geloeschte Eintraege blieben mit Name in den Listen stehen; Kunde 61009 wurde deshalb achtmal geloescht, bei Eintrag 45013 wurde die E-Mail danach ueber ein offenes Bearbeiten-Formular zurueckgeschrieben - neue Spalte shopping_users.gdpr_deleted_at (Bestand per Migration markiert) - Admin-Kundenliste blendet geloeschte Kunden aus (Filter: ausblenden / mit anzeigen / nur geloeschte), Berater-Kundenliste immer - Bearbeiten/Speichern im Admin und beim Berater gesperrt; ShoppingUser verweigert das Zurueckschreiben von E-Mail und Telefon - Modal und Erfolgsmeldung (de/en/es/fr) sagen klar, dass Name und Rechnungsadresse wegen der Aufbewahrungspflicht bleiben - gdpr:repair-customers [--execute] zieht protokollierte Loeschungen nach - DSGVO-Loeschung prueft Superadmin serverseitig; Berater duerfen eine Kunden-E-Mail nur beim eigenen Kunden nachtragen - setFakerMail setzt faker_mail bei geloeschten Eintraegen nicht zurueck Checkout: "Wie bist du auf uns aufmerksam geworden?" ist kein Pflichtfeld mehr und wird farbig hervorgehoben. Deploy: php artisan migrate && php artisan gdpr:repair-customers --execute Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
124 lines
5.7 KiB
PHP
124 lines
5.7 KiB
PHP
@extends('layouts.layout-2')
|
|
|
|
@section('content')
|
|
|
|
|
|
<h4 class="font-weight-bold py-2 mb-2">
|
|
{{ __('Kunden') }}
|
|
</h4>
|
|
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<div class="form-row align-items-center">
|
|
<div class="col-sm-7 mb-2">
|
|
<label class="form-label" for="filter_user_shop_id">Filter zugewiesener Berater</label>
|
|
<select class="selectpicker" data-style="btn-default" name="filter_member_id" id="filter_member_id" data-live-search="true">
|
|
<option value="">Filter aus</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-sm-3 mb-2">
|
|
<label class="form-label" for="filter_gdpr_deleted">DSGVO-gelöschte Kunden</label>
|
|
<select class="custom-select" name="filter_gdpr_deleted" id="filter_gdpr_deleted">
|
|
<option value="">ausblenden</option>
|
|
<option value="all" @if(get_user_attr('filter_gdpr_deleted') === 'all') selected @endif>mit anzeigen</option>
|
|
<option value="only" @if(get_user_attr('filter_gdpr_deleted') === 'only') selected @endif>nur gelöschte</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-2 col-sm-2 mb-2 mt-4">
|
|
<a href="{{ route('admin_customers') }}?reset=filter" data-toggle="tooltip" data-placement="top" title="Reset Filter" class="btn icon-btn btn-sm btn-outline-dark float-right">
|
|
<span class="fa fa-sync"></span>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
<div class="card-datatable table-responsive">
|
|
<div class="ml-4">
|
|
<!--<a href="{{ route('admin_lead_edit', ['new']) }}" class="btn btn-sm btn-primary">{{__('Neuen Berater erstellen')}}</a> -->
|
|
</div>
|
|
<table class="datatables-customers table table-striped table-bordered" id="datatables-customers">
|
|
<thead>
|
|
<tr>
|
|
<th>#</th>
|
|
<th>{{__('Nummer')}}</th>
|
|
<th>{{__('E-Mail')}}</th>
|
|
<th>{{__('ist Berater')}}</th>
|
|
<th>{{ __('Salutation') }}</th>
|
|
<th>{{ __('Company') }}</th>
|
|
<th>{{ __('First name') }}</th>
|
|
<th>{{__('Last name')}}</th>
|
|
<th>{{ __('Postcode') }}</th>
|
|
<th>{{ __('City') }}</th>
|
|
<th>{{ __('Country') }}</th>
|
|
<th>{{__('Käufe')}}</th>
|
|
<th>{{__('Newsletter')}}</th>
|
|
<th>{{__('zugewiesener Berater')}}</th>
|
|
<th>{{__('Datum')}}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
<div class="mt-4 ml-4">
|
|
<!-- <a href="{{ route('admin_lead_edit', ['new']) }}" class="btn btn-sm btn-primary">{{__('Neuen Berater erstellen')}}</a> -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
$( document ).ready(function() {
|
|
|
|
var oTable = $('#datatables-customers').DataTable({
|
|
"processing": true,
|
|
"serverSide": true,
|
|
ajax: {
|
|
url: '{!! route( 'admin_customer_datatable') !!}',
|
|
data: function(d) {
|
|
d.filter_member_id = $('select[name=filter_member_id]').val();
|
|
d.filter_customer_member = $('select[name=filter_customer_member]').val();
|
|
d.filter_gdpr_deleted = $('select[name=filter_gdpr_deleted]').val();
|
|
}
|
|
},
|
|
"order": [[0, "desc" ]],
|
|
"columns": [
|
|
{ data: 'id', searchable: false},
|
|
{ data: 'number', name: 'number'},
|
|
{ data: 'billing_email', name: 'billing_email' },
|
|
{ data: 'isMember', name: 'isMember' },
|
|
{ data: 'billing_salutation', name: 'billing_salutation' },
|
|
{ data: 'billing_company', name: 'billing_company' },
|
|
{ data: 'billing_firstname', name: 'billing_firstname' },
|
|
{ data: 'billing_lastname', name: 'billing_lastname' },
|
|
{ data: 'billing_zipcode', name: 'billing_zipcode' },
|
|
{ data: 'billing_city', name: 'billing_city' },
|
|
{ data: 'billing_country_id', name: 'billing_country_id' },
|
|
{ data: 'orders', name: 'orders' },
|
|
{ data: 'subscribed', name: 'subscribed' },
|
|
{ data: 'member_id', name: 'member_id', searchable: false, orderable: false },
|
|
{ data: 'created_at', name: 'created_at' },
|
|
],
|
|
"bLengthChange": false,
|
|
"iDisplayLength": 50,
|
|
"language": {
|
|
"url": "/js/datatables-{{ \App::getLocale() }}.json"
|
|
}
|
|
});
|
|
$('#filter_member_id').on('change', function(){
|
|
oTable.draw();
|
|
});
|
|
$('#filter_customer_member').on('change', function(){
|
|
oTable.draw();
|
|
});
|
|
$('#filter_gdpr_deleted').on('change', function(){
|
|
oTable.draw();
|
|
});
|
|
|
|
});
|
|
</script>
|
|
@endsection
|
|
|