Kunden loeschen: DSGVO-geloeschte Kunden ausblenden und sperren; Checkout-Herkunft freiwillig
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>
This commit is contained in:
parent
083d643220
commit
3d0864713b
19 changed files with 635 additions and 90 deletions
|
|
@ -1,6 +1,13 @@
|
|||
<div class="card">
|
||||
<!-- Info -->
|
||||
<div class="card-body pb-1">
|
||||
@if($shopping_user->isGdprDeleted())
|
||||
<div class="alert alert-secondary">
|
||||
<b>DSGVO-gelöscht am {{ $shopping_user->gdpr_deleted_at->format('d.m.Y H:i') }}.</b>
|
||||
Kontaktdaten wurden entfernt. Name und Rechnungsadresse bleiben wegen der gesetzlichen
|
||||
Aufbewahrungspflicht an den Bestellungen erhalten. Der Eintrag kann nicht mehr bearbeitet werden.
|
||||
</div>
|
||||
@endif
|
||||
@if($isAdmin)
|
||||
<div class="row">
|
||||
<div class="col-md-3 mb-3">
|
||||
|
|
@ -20,7 +27,9 @@
|
|||
{{$shopping_user->created_at->format("d.m.Y H:i")}}
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
@if(!$shopping_user->isGdprDeleted())
|
||||
<a class="btn btn-sm btn-secondary mt-2" href="{{route('admin_customer_edit', [$shopping_user->id])}}">{{ __('customer.edit_customer_data') }}</a>
|
||||
@endif
|
||||
<button type="button" class="btn btn-sm btn-danger mt-2" data-toggle="modal" data-target="#modals-customer-delete">{{ __('customer.delete_customer') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -44,7 +53,7 @@
|
|||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
|
||||
@if(!$shopping_user->is_like)
|
||||
@if(!$shopping_user->is_like && !$shopping_user->isGdprDeleted())
|
||||
<a class="btn btn-sm btn-secondary mt-2" href="{{route('user_customer_edit', [$shopping_user->id])}}">{{ __('customer.edit_customer_data') }}</a>
|
||||
@endif
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -49,7 +49,8 @@
|
|||
<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> @endif
|
||||
@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>
|
||||
|
|
@ -60,12 +61,24 @@
|
|||
</table>
|
||||
</div>
|
||||
|
||||
@if ($deletion['orders_count'] > 0)
|
||||
@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 personenbezogenen Daten werden unwiderruflich anonymisiert. Bei Einträgen mit Bestellung bleiben Name und
|
||||
Rechnungsadresse wegen der gesetzlichen Aufbewahrungspflichten erhalten; alle Kontaktdaten (E-Mail, Telefon,
|
||||
Notizen, Newsletter) sowie die Portal-Logins werden entfernt.
|
||||
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
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="form-row align-items-center">
|
||||
<div class="col-sm-10 mb-2">
|
||||
<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>
|
||||
|
|
@ -19,6 +19,14 @@
|
|||
@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>
|
||||
|
|
@ -73,6 +81,7 @@
|
|||
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" ]],
|
||||
|
|
@ -105,6 +114,9 @@
|
|||
$('#filter_customer_member').on('change', function(){
|
||||
oTable.draw();
|
||||
});
|
||||
$('#filter_gdpr_deleted').on('change', function(){
|
||||
oTable.draw();
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -111,6 +111,19 @@
|
|||
font-size: 0.8em;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.order-source-highlight {
|
||||
background: #f3f7f0;
|
||||
border: 1px solid #97b085;
|
||||
border-left: 4px solid #97b085;
|
||||
border-radius: 4px;
|
||||
padding: 12px 15px;
|
||||
}
|
||||
|
||||
.order-source-highlight label {
|
||||
font-weight: 600;
|
||||
color: #5f7a4e;
|
||||
}
|
||||
select.form-control:not([size]):not([multiple]) {
|
||||
height: 38px;
|
||||
color: #6f6f6f;
|
||||
|
|
@ -554,9 +567,10 @@
|
|||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col-md-12 col-sm-12">
|
||||
<div class="form-group {{($errors->has('customer_order_source_comment') ? 'error' : '')}}">
|
||||
<label class="mt-0 fs-14 fw-400" for="customer_order_source_comment">Wie bist du auf uns aufmerksam geworden? *</label>
|
||||
{!! Form::textarea('customer_order_source_comment', old('customer_order_source_comment'), ['class' => 'form-control '.($errors->has('customer_order_source_comment') ? 'error' : ''), 'id'=>'customer_order_source_comment', 'rows' => 3, 'maxlength' => 500, 'required' => 'required', 'placeholder' => 'Bitte konkret: z. B. Name der Person, die dich empfohlen hat, oder die genaue Messe/Veranstaltung']) !!}
|
||||
<div class="form-group order-source-highlight {{($errors->has('customer_order_source_comment') ? 'error' : '')}}">
|
||||
<label class="mt-0 fs-14" for="customer_order_source_comment"><i class="fa fa-heart"></i> Wie bist du auf uns aufmerksam geworden?</label>
|
||||
<span class="info-small mb-2" style="display: block;">Freiwillig – hilft uns aber sehr, dich der richtigen Person zuzuordnen.</span>
|
||||
{!! Form::textarea('customer_order_source_comment', old('customer_order_source_comment'), ['class' => 'form-control '.($errors->has('customer_order_source_comment') ? 'error' : ''), 'id'=>'customer_order_source_comment', 'rows' => 3, 'maxlength' => 500, 'placeholder' => 'z. B. Name der Person, die dich empfohlen hat, oder die genaue Messe/Veranstaltung']) !!}
|
||||
@if ($errors->has('customer_order_source_comment'))
|
||||
<label for="customer_order_source_comment" class="error text-danger small" style="display: block;">{{ $errors->first('customer_order_source_comment') }}</label>
|
||||
@endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue