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>
123 lines
No EOL
8.3 KiB
PHP
123 lines
No EOL
8.3 KiB
PHP
@extends('layouts.layout-2')
|
||
|
||
@section('content')
|
||
|
||
<h4 class="font-weight-bold py-2 mb-2">
|
||
<a href="{{route('admin_customers')}}" class="btn btn-sm btn-default float-right">{{ __('back') }}</a>
|
||
{{ __('customer.customer_details') }}
|
||
</h4>
|
||
@include('admin.customer._detail')
|
||
<a href="{{route('admin_customers')}}" class="btn btn-sm btn-default mt-2 float-right">{{ __('back') }}</a>
|
||
|
||
{{-- Kunden löschen: ein Modal für beide Wege (dev/_tickets/2026-09-08.md, Ticket #2) --}}
|
||
@php($canGdprDelete = Auth::user()->isSuperAdmin())
|
||
<div class="modal fade" id="modals-customer-delete">
|
||
<div class="modal-dialog modal-lg">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title">{{ __('customer.delete_customer') }}</h5>
|
||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
@if ($deletion['is_member'])
|
||
<div class="alert alert-warning mb-0">{{ __('msg.gdpr_error_customer_is_member') }}</div>
|
||
@else
|
||
<p>
|
||
Der Kunde ist <b>{{ $deletion['rows']->count() }}-mal</b> angelegt
|
||
@if ($deletion['email'])
|
||
(E-Mail <b>{{ $deletion['email'] }}</b>, Kundennummer {{ $shopping_user->number ?: '-' }}).
|
||
@else
|
||
(Kundennummer {{ $shopping_user->number ?: '-' }}; keine gültige E-Mail zur Duplikat-Suche).
|
||
@endif
|
||
Alle folgenden Einträge werden gemeinsam behandelt:
|
||
</p>
|
||
<div class="table-responsive">
|
||
<table class="table table-sm table-bordered" id="customer-delete-rows">
|
||
<thead>
|
||
<tr>
|
||
<th>ID</th>
|
||
<th>Kd-Nr.</th>
|
||
<th>Name</th>
|
||
<th>Berater</th>
|
||
<th>Bestellungen</th>
|
||
<th>Angelegt</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
@foreach ($deletion['rows'] as $row)
|
||
<tr class="{{ $row->id === $shopping_user->id ? 'font-weight-bold' : '' }}">
|
||
<td>{{ $row->id }}</td>
|
||
<td>{{ $row->number ?: '-' }}</td>
|
||
<td>{{ trim($row->billing_firstname.' '.$row->billing_lastname) }}
|
||
@if ($row->deleted_at) <span class="badge badge-secondary">gelöscht</span>
|
||
@elseif ($row->isGdprDeleted()) <span class="badge badge-secondary">DSGVO-gelöscht</span> @endif
|
||
</td>
|
||
<td>{{ $row->member->email ?? '-' }}</td>
|
||
<td>{{ $deletion['orders_by_row'][$row->id] ?? 0 }}</td>
|
||
<td>{{ $row->created_at ? $row->created_at->format('d.m.Y') : '-' }}</td>
|
||
</tr>
|
||
@endforeach
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
@if ($deletion['all_gdpr_deleted'])
|
||
<div class="alert alert-success mb-0">
|
||
Der Kunde wurde bereits am <b>{{ $deletion['gdpr_deleted_at']->format('d.m.Y H:i') }}</b> DSGVO-gelöscht.
|
||
Alle Kontaktdaten (E-Mail, Telefon, Notizen, Newsletter) und Portal-Logins sind entfernt. Name und
|
||
Rechnungsadresse bleiben wegen der gesetzlichen Aufbewahrungspflicht an den Bestellungen erhalten.
|
||
Die Einträge sind in der Kundenliste ausgeblendet (Filter „DSGVO-gelöschte Kunden“) und gegen
|
||
Bearbeiten gesperrt.
|
||
</div>
|
||
@elseif ($deletion['orders_count'] > 0)
|
||
<div class="alert alert-warning">
|
||
Der Kunde hat schon <b>{{ $deletion['orders_count'] }} Bestellung(en)</b>. Es ist nur <b>DSGVO löschen</b> möglich:
|
||
Alle Kontaktdaten (E-Mail, Telefon, Notizen, Newsletter) sowie die Portal-Logins werden unwiderruflich entfernt.
|
||
<b>Name und Rechnungsadresse bleiben</b> bei Einträgen mit Bestellung wegen der gesetzlichen
|
||
Aufbewahrungspflicht erhalten. Die Einträge werden danach in der Kundenliste ausgeblendet und gegen
|
||
Bearbeiten gesperrt.
|
||
@if ($deletion['gdpr_deleted_rows'] > 0)
|
||
<br>{{ $deletion['gdpr_deleted_rows'] }} von {{ $deletion['rows']->count() }} Einträgen sind bereits gelöscht.
|
||
@endif
|
||
@if ($deletion['active_abos'] > 0)
|
||
<br><b>{{ __('msg.gdpr_error_active_abo') }}</b>
|
||
@endif
|
||
</div>
|
||
@if ($canGdprDelete)
|
||
<form action="{{ route('admin_customer_gdpr_delete', [$shopping_user->id]) }}" method="post" id="form-customer-gdpr-delete">
|
||
@csrf
|
||
<label class="custom-control custom-checkbox mb-3">
|
||
<input type="checkbox" class="custom-control-input" name="gdpr_delete_customer" value="1">
|
||
<span class="custom-control-label">DSGVO-Löschung unwiderruflich ausführen?</span>
|
||
</label>
|
||
<button type="submit" class="btn btn-danger" {{ $deletion['active_abos'] > 0 ? 'disabled' : '' }}>{{ __('msg.gdpr_delete_customer_button') }}</button>
|
||
</form>
|
||
@else
|
||
<p class="text-muted mb-0">Die DSGVO-Löschung kann nur von einem Superadmin ausgeführt werden.</p>
|
||
@endif
|
||
@elseif ($deletion['active_abos'] > 0)
|
||
<div class="alert alert-warning mb-0">{{ __('msg.gdpr_error_active_abo') }}</div>
|
||
@else
|
||
<div class="alert alert-info">
|
||
Der Kunde hat <b>keine Bestellungen</b> und kann <b>komplett gelöscht</b> werden: Alle oben aufgeführten Einträge
|
||
werden vollständig anonymisiert und entfernt, inklusive Portal-Login und inaktiver Abos.
|
||
</div>
|
||
<form action="{{ route('admin_customer_delete', [$shopping_user->id]) }}" method="post" id="form-customer-delete">
|
||
@csrf
|
||
<label class="custom-control custom-checkbox mb-3">
|
||
<input type="checkbox" class="custom-control-input" name="delete_customer" value="1">
|
||
<span class="custom-control-label">Kunden mit allen {{ $deletion['rows']->count() }} Einträgen unwiderruflich löschen?</span>
|
||
</label>
|
||
<button type="submit" class="btn btn-danger">{{ __('msg.gdpr_purge_customer_button') }}</button>
|
||
</form>
|
||
@endif
|
||
@endif
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ __('close') }}</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
@endsection |