20-02-2026
This commit is contained in:
parent
a8b395e20d
commit
a00c42e770
252 changed files with 28785 additions and 8907 deletions
692
resources/views/admin/user/cleanup/index.blade.php
Normal file
692
resources/views/admin/user/cleanup/index.blade.php
Normal file
|
|
@ -0,0 +1,692 @@
|
|||
@extends('layouts.layout-2')
|
||||
|
||||
@push('head')
|
||||
<style>
|
||||
/* Bootstrap-select Dropdown im Modal */
|
||||
.bootstrap-select .dropdown-menu {
|
||||
z-index: 10060 !important;
|
||||
}
|
||||
</style>
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
<h4 class="font-weight-bold py-2 mb-2">
|
||||
<i class="ion ion-ios-people"></i> {{ __('navigation.user_cleanup') }}
|
||||
</h4>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col">
|
||||
<div class="alert alert-info">
|
||||
<strong>Info:</strong> Diese Übersicht zeigt alle deaktivierten und gelöschten User.
|
||||
Deaktivierte User können ihre Downline behalten oder an den Sponsor übertragen haben.
|
||||
Gelöschte User haben alle Daten an den Sponsor übertragen.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="nav-tabs-top mb-4">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="{{ route('admin_user_cleanup') }}">
|
||||
<i class="ion ion-ios-people"></i> Deaktivierte/Gelöschte User
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route('admin_user_cleanup_logs') }}">
|
||||
<i class="ion ion-md-git-network"></i> Downline-Übertragungen
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route('admin_user_cleanup_shopping_logs') }}">
|
||||
<i class="ion ion-md-cart"></i> Kunden-Übertragungen
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-datatable table-responsive">
|
||||
<table class="datatables-cleanup table table-striped table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>{{ __('tables.firstname') }}</th>
|
||||
<th>{{ __('tables.lastname') }}</th>
|
||||
<th>{{ __('E-Mail') }}</th>
|
||||
<th>M-Account</th>
|
||||
<th>Status</th>
|
||||
<th>Gelöscht am</th>
|
||||
<th>Account bis</th>
|
||||
<th>Sponsor</th>
|
||||
<th>Pre-Sponsor</th>
|
||||
<th>Downline</th>
|
||||
<th>Kunden</th>
|
||||
<th> #</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal User Historie -->
|
||||
<div class="modal fade" id="modal-user-history" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-xl" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">
|
||||
<i class="fa fa-history"></i> User Historie & Details
|
||||
</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>
|
||||
</div>
|
||||
<div class="modal-body" id="history-content" style="max-height: 75vh; overflow-y: auto;">
|
||||
<div class="text-center py-5">
|
||||
<i class="fa fa-spinner fa-spin fa-3x"></i>
|
||||
<p class="mt-3">Lade Daten...</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ __('close') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal Restore User -->
|
||||
<div class="modal fade" id="modal-restore-user">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">User wiederherstellen</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<input type="hidden" id="restore-user-id">
|
||||
<div class="form-group">
|
||||
<label>E-Mail:</label>
|
||||
<input type="text" class="form-control" id="restore-user-email" readonly>
|
||||
</div>
|
||||
<div class="alert alert-warning">
|
||||
<strong>Hinweis:</strong> Dies führt den Artisan-Befehl <code>user:restore</code> aus.
|
||||
Bitte in den Logs überprüfen ob die Wiederherstellung erfolgreich war.
|
||||
</div>
|
||||
<div class="alert alert-info">
|
||||
<strong>Was wird wiederhergestellt:</strong>
|
||||
<ul class="mb-0">
|
||||
<li>User wird reaktiviert (active=true)</li>
|
||||
<li>Sponsor wird aus pre_sponsor wiederhergestellt</li>
|
||||
<li>Downline-Struktur wird wiederhergestellt</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ __('close') }}</button>
|
||||
<button type="button" class="btn btn-success" id="btn-restore-user">
|
||||
<i class="fa fa-undo"></i> User wiederherstellen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('.datatables-cleanup').dataTable({
|
||||
"processing": true,
|
||||
"serverSide": true,
|
||||
"ajax": '{!! route('admin_user_cleanup_datatable') !!}',
|
||||
"order": [[0, "desc"]],
|
||||
"columns": [
|
||||
{ data: 'user_id', name: 'id' },
|
||||
{ data: 'first_name', name: 'account.first_name' },
|
||||
{ data: 'last_name', name: 'account.last_name' },
|
||||
{ data: 'email', name: 'email' },
|
||||
{ data: 'm_account', name: 'account.m_account' },
|
||||
{ data: 'status', name: 'status' },
|
||||
{ data: 'deleted_at', name: 'pre_deleted_at', orderable: true },
|
||||
{ data: 'payment_account', name: 'payment_account' },
|
||||
{ data: 'm_sponsor', name: 'm_sponsor', orderable: false },
|
||||
{ data: 'pre_sponsor', name: 'pre_sponsor', orderable: false },
|
||||
{ data: 'childs_count', name: 'childs_count', orderable: false, searchable: false },
|
||||
{ data: 'shopping_users_count', name: 'shopping_users_count', orderable: false, searchable: false },
|
||||
{ data: 'action', orderable: false, searchable: false }
|
||||
],
|
||||
"bLengthChange": false,
|
||||
"iDisplayLength": 50,
|
||||
"language": {
|
||||
"url": "/js/datatables-{{ \App::getLocale() }}.json"
|
||||
}
|
||||
});
|
||||
|
||||
// Modal Cleanup beim Schließen
|
||||
$('#modal-user-history').on('hidden.bs.modal', function() {
|
||||
// Zerstöre selectpicker Instanz wenn vorhanden
|
||||
if ($('#select-new-sponsor').length && $('#select-new-sponsor').hasClass('selectpicker')) {
|
||||
$('#select-new-sponsor').selectpicker('destroy');
|
||||
}
|
||||
currentUserId = null;
|
||||
});
|
||||
|
||||
// Modal Historie Handler
|
||||
$(document).on('click', '.btn-user-history', function() {
|
||||
var userId = $(this).data('id');
|
||||
var userEmail = $(this).data('email');
|
||||
|
||||
$('#modal-user-history').modal('show');
|
||||
$('#history-content').html('<div class="text-center py-5"><i class="fa fa-spinner fa-spin fa-3x"></i><p class="mt-3">Lade Daten...</p></div>');
|
||||
|
||||
$.ajax({
|
||||
url: '{{ route('admin_user_cleanup_history', ['userId' => ':userId']) }}'.replace(':userId', userId),
|
||||
type: 'GET',
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
renderHistory(response);
|
||||
} else {
|
||||
$('#history-content').html('<div class="alert alert-danger">Fehler: ' + response.message + '</div>');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
$('#history-content').html('<div class="alert alert-danger">Fehler beim Laden der Daten: ' + xhr.responseText + '</div>');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var currentUserId = null;
|
||||
|
||||
function renderHistory(data) {
|
||||
currentUserId = data.user.id;
|
||||
var html = '';
|
||||
|
||||
// User Info
|
||||
html += '<div class="card mb-3">';
|
||||
html += '<div class="card-header"><h5><i class="fa fa-user"></i> User Informationen</h5></div>';
|
||||
html += '<div class="card-body">';
|
||||
html += '<div class="row">';
|
||||
html += '<div class="col-md-6"><strong>Name:</strong> ' + data.user.name + '</div>';
|
||||
html += '<div class="col-md-6"><strong>E-Mail:</strong> ' + data.user.email + '</div>';
|
||||
html += '<div class="col-md-6"><strong>M-Account:</strong> ' + data.user.m_account + '</div>';
|
||||
html += '<div class="col-md-6"><strong>Status:</strong> ';
|
||||
if (data.user.deleted) {
|
||||
html += '<span class="badge badge-danger">Gelöscht am ' + data.user.deleted_at + '</span>';
|
||||
} else if (data.user.active) {
|
||||
html += '<span class="badge badge-success">Aktiv</span>';
|
||||
} else {
|
||||
html += '<span class="badge badge-warning">Deaktiviert</span>';
|
||||
}
|
||||
html += '</div>';
|
||||
html += '</div></div></div>';
|
||||
|
||||
// Sponsor Neu-Zuweisen
|
||||
// Die zu übertragenden Werte kommen IMMER aus den Logs (bereits übertragene, die neu zugewiesen werden sollen)
|
||||
var childrenCount = data.cleanup_logs ? data.cleanup_logs.length : 0;
|
||||
var customersCount = data.shopping_logs ? data.shopping_logs.length : 0;
|
||||
|
||||
html += '<div class="card mb-3 border-warning">';
|
||||
html += '<div class="card-header bg-warning"><h5><i class="fa fa-exchange-alt"></i> Sponsor manuell neu zuweisen</h5></div>';
|
||||
html += '<div class="card-body">';
|
||||
html += '<div class="alert alert-warning">';
|
||||
html += '<strong>⚠️ Achtung:</strong> Diese Funktion ermöglicht die manuelle Korrektur eines falsch zugewiesenen Sponsors. ';
|
||||
html += 'Alle Änderungen werden vollständig geloggt und können bei Bedarf rückgängig gemacht werden.';
|
||||
html += '</div>';
|
||||
|
||||
// Bereits übertragene Zuordnungen anzeigen (aus Logs)
|
||||
html += '<div class="alert alert-info mb-3">';
|
||||
html += '<strong>📊 Bereits übertragene Zuordnungen (können neu zugewiesen werden):</strong><br>';
|
||||
html += '<div class="row mt-2">';
|
||||
html += '<div class="col-6">';
|
||||
html += '<i class="fa fa-users"></i> <strong>Downline:</strong> ';
|
||||
if (childrenCount > 0) {
|
||||
html += '<span class="badge badge-warning">' + childrenCount + ' bereits übertragen</span>';
|
||||
} else {
|
||||
html += '<span class="text-muted">Keine Übertragungen</span>';
|
||||
}
|
||||
html += '</div>';
|
||||
html += '<div class="col-6">';
|
||||
html += '<i class="fa fa-shopping-cart"></i> <strong>Kunden:</strong> ';
|
||||
if (customersCount > 0) {
|
||||
html += '<span class="badge badge-warning">' + customersCount + ' bereits übertragen</span>';
|
||||
} else {
|
||||
html += '<span class="text-muted">Keine Übertragungen</span>';
|
||||
}
|
||||
html += '</div>';
|
||||
html += '</div>';
|
||||
html += '</div>';
|
||||
|
||||
html += '<div class="form-group">';
|
||||
html += '<label for="select-new-sponsor"><strong>Neuer Sponsor auswählen:</strong></label>';
|
||||
html += '<select id="select-new-sponsor" class="selectpicker" data-style="btn-light" data-live-search="true" data-size="8" style="width: 100%;">';
|
||||
html += '<option value="">Bitte auswählen...</option>';
|
||||
html += '</select>';
|
||||
html += '<small class="form-text text-muted">Suche nach Name, E-Mail oder M-Account</small>';
|
||||
html += '</div>';
|
||||
|
||||
html += '<hr>';
|
||||
html += '<h6 class="mb-3">Was soll mit übertragen werden?</h6>';
|
||||
|
||||
html += '<div class="form-group">';
|
||||
html += '<div class="custom-control custom-checkbox">';
|
||||
html += '<input type="checkbox" class="custom-control-input" id="transfer-downline" ' + (childrenCount > 0 ? 'checked' : 'disabled') + '>';
|
||||
html += '<label class="custom-control-label" for="transfer-downline">';
|
||||
html += '<strong>Downline neu zuweisen</strong> ';
|
||||
if (childrenCount > 0) {
|
||||
html += '<span class="badge badge-primary">' + childrenCount + '</span>';
|
||||
} else {
|
||||
html += '<span class="text-muted">(keine Übertragungen vorhanden)</span>';
|
||||
}
|
||||
html += '</label>';
|
||||
html += '</div>';
|
||||
html += '<small class="form-text text-muted">Die bereits übertragenen Downline-Mitglieder werden dem neuen Sponsor zugewiesen</small>';
|
||||
html += '</div>';
|
||||
|
||||
html += '<div class="form-group">';
|
||||
html += '<div class="custom-control custom-checkbox">';
|
||||
html += '<input type="checkbox" class="custom-control-input" id="transfer-customers" ' + (customersCount > 0 ? 'checked' : 'disabled') + '>';
|
||||
html += '<label class="custom-control-label" for="transfer-customers">';
|
||||
html += '<strong>Shopping-Kunden neu zuweisen</strong> ';
|
||||
if (customersCount > 0) {
|
||||
html += '<span class="badge badge-primary">' + customersCount + '</span>';
|
||||
} else {
|
||||
html += '<span class="text-muted">(keine Übertragungen vorhanden)</span>';
|
||||
}
|
||||
html += '</label>';
|
||||
html += '</div>';
|
||||
html += '<small class="form-text text-muted">Die bereits übertragenen Shopping-Kunden werden dem neuen Berater zugewiesen</small>';
|
||||
html += '</div>';
|
||||
|
||||
html += '<button type="button" class="btn btn-warning btn-block btn-lg" id="btn-reassign-sponsor">';
|
||||
html += '<i class="fa fa-exchange-alt"></i> Sponsor jetzt neu zuweisen';
|
||||
html += '</button>';
|
||||
|
||||
html += '</div></div>';
|
||||
|
||||
// Downline Position
|
||||
html += '<div class="card mb-3">';
|
||||
html += '<div class="card-header">';
|
||||
html += '<h5 class="mb-0"><i class="fa fa-sitemap"></i> Position in der Downline</h5>';
|
||||
html += '</div>';
|
||||
html += '<div class="card-body">';
|
||||
|
||||
// Sponsor-Info
|
||||
html += '<div class="row mb-3">';
|
||||
html += '<div class="col-md-6">';
|
||||
html += '<strong>Aktueller Sponsor:</strong><br>';
|
||||
if (data.sponsor) {
|
||||
html += '<span class="badge badge-' + (data.sponsor.active ? 'success' : 'warning') + '">' + data.sponsor.name + '</span> ';
|
||||
html += '<small class="text-muted">(' + data.sponsor.email + ')</small>';
|
||||
} else {
|
||||
html += '<em class="text-muted">Nicht vorhanden</em>';
|
||||
}
|
||||
html += '</div>';
|
||||
|
||||
if (data.pre_sponsor) {
|
||||
html += '<div class="col-md-6">';
|
||||
html += '<strong>Vorheriger Sponsor (Pre-Sponsor):</strong><br>';
|
||||
html += '<span class="badge badge-info">' + data.pre_sponsor.name + '</span> ';
|
||||
html += '<small class="text-muted">(' + data.pre_sponsor.email + ')</small>';
|
||||
html += '</div>';
|
||||
}
|
||||
html += '</div>';
|
||||
|
||||
html += '<hr>';
|
||||
|
||||
// Downline mit Badge
|
||||
html += '<div class="mb-2">';
|
||||
html += '<strong>Direkte Downline:</strong> ';
|
||||
if (data.children.length > 0) {
|
||||
html += '<span class="badge badge-primary">' + data.children.length + ' Mitglieder</span>';
|
||||
} else {
|
||||
html += '<span class="badge badge-secondary">0 Mitglieder</span>';
|
||||
}
|
||||
html += '</div>';
|
||||
if (data.children.length > 0) {
|
||||
html += '<table class="table table-sm mt-2">';
|
||||
html += '<thead><tr><th>Name</th><th>E-Mail</th><th>Status</th></tr></thead><tbody>';
|
||||
data.children.forEach(function(child) {
|
||||
html += '<tr>';
|
||||
html += '<td>' + child.name + '</td>';
|
||||
html += '<td>' + child.email + '</td>';
|
||||
html += '<td>';
|
||||
if (child.deleted) {
|
||||
html += '<span class="badge badge-danger">Gelöscht</span>';
|
||||
} else if (child.active) {
|
||||
html += '<span class="badge badge-success">Aktiv</span>';
|
||||
} else {
|
||||
html += '<span class="badge badge-warning">Inaktiv</span>';
|
||||
}
|
||||
if (child.is_pre_sponsor) {
|
||||
html += ' <span class="badge badge-info">Pre-Sponsor</span>';
|
||||
}
|
||||
html += '</td></tr>';
|
||||
});
|
||||
html += '</tbody></table>';
|
||||
} else {
|
||||
html += '<p class="mt-2 mb-0"><em>Keine direkten Downline-Mitglieder</em></p>';
|
||||
}
|
||||
html += '</div></div></div>';
|
||||
|
||||
// Shopping Kunden
|
||||
html += '<div class="card mb-3">';
|
||||
html += '<div class="card-header">';
|
||||
html += '<h5 class="mb-0">';
|
||||
html += '<i class="fa fa-shopping-cart"></i> Shopping-Kunden ';
|
||||
if (data.shopping_users.length > 0) {
|
||||
html += '<span class="badge badge-primary">' + data.shopping_users.length + '</span>';
|
||||
} else {
|
||||
html += '<span class="badge badge-secondary">0</span>';
|
||||
}
|
||||
html += '</h5>';
|
||||
html += '</div>';
|
||||
html += '<div class="card-body">';
|
||||
if (data.shopping_users.length > 0) {
|
||||
html += '<table class="table table-sm">';
|
||||
html += '<thead><tr><th>Name</th><th>E-Mail</th><th>Stadt</th><th>Erstellt am</th></tr></thead><tbody>';
|
||||
data.shopping_users.forEach(function(customer) {
|
||||
html += '<tr>';
|
||||
html += '<td>' + customer.name + '</td>';
|
||||
html += '<td>' + customer.email + '</td>';
|
||||
html += '<td>' + customer.city + '</td>';
|
||||
html += '<td>' + customer.created_at + '</td>';
|
||||
html += '</tr>';
|
||||
});
|
||||
html += '</tbody></table>';
|
||||
} else {
|
||||
html += '<p class="mb-0"><em>Keine Shopping-Kunden vorhanden</em></p>';
|
||||
}
|
||||
html += '</div></div>';
|
||||
|
||||
// Cleanup Logs
|
||||
if (data.cleanup_logs.length > 0) {
|
||||
html += '<div class="card mb-3">';
|
||||
html += '<div class="card-header">';
|
||||
html += '<h5 class="mb-0">';
|
||||
html += '<i class="fa fa-exchange-alt"></i> Downline-Übertragungen (Protokoll) ';
|
||||
html += '<span class="badge badge-info">' + data.cleanup_logs.length + '</span>';
|
||||
html += '</h5>';
|
||||
html += '</div>';
|
||||
html += '<div class="card-body">';
|
||||
html += '<table class="table table-sm">';
|
||||
html += '<thead><tr><th>Betroffener User</th><th>Status</th><th>Von Sponsor</th><th>Zu Sponsor</th><th>Datum</th></tr></thead><tbody>';
|
||||
data.cleanup_logs.forEach(function(log) {
|
||||
html += '<tr>';
|
||||
html += '<td>' + (log.child_user ? log.child_user.name + '<br><small>' + log.child_user.email + '</small>' : 'N/A') + '</td>';
|
||||
html += '<td>';
|
||||
if (log.child_user) {
|
||||
if (log.child_user.deleted) {
|
||||
html += '<span class="badge badge-danger">Gelöscht</span>';
|
||||
} else if (log.child_user.active) {
|
||||
html += '<span class="badge badge-success">Aktiv</span>';
|
||||
} else {
|
||||
html += '<span class="badge badge-warning">Inaktiv</span>';
|
||||
}
|
||||
} else {
|
||||
html += 'N/A';
|
||||
}
|
||||
html += '</td>';
|
||||
html += '<td>' + (log.inactive_sponsor ? log.inactive_sponsor.name + '<br><small>' + log.inactive_sponsor.email + '</small>' : 'N/A') + '</td>';
|
||||
html += '<td>';
|
||||
|
||||
// Ursprünglicher Sponsor aus dem Log
|
||||
if (log.new_sponsor) {
|
||||
html += '<small class="text-muted">Damals:</small><br>';
|
||||
html += log.new_sponsor.name + '<br><small>' + log.new_sponsor.email + '</small>';
|
||||
|
||||
// Falls aktueller Sponsor anders ist
|
||||
if (log.current_sponsor) {
|
||||
html += '<hr class="my-1">';
|
||||
html += '<span class="badge badge-warning">Geändert!</span><br>';
|
||||
html += '<small class="text-success">Aktuell:</small><br>';
|
||||
html += '<strong>' + log.current_sponsor.name + '</strong><br>';
|
||||
html += '<small>' + log.current_sponsor.email + '</small>';
|
||||
}
|
||||
} else {
|
||||
html += 'N/A';
|
||||
}
|
||||
|
||||
html += '</td>';
|
||||
html += '<td>' + log.created_at + '</td>';
|
||||
html += '</tr>';
|
||||
});
|
||||
html += '</tbody></table></div></div>';
|
||||
}
|
||||
|
||||
// Shopping Logs
|
||||
if (data.shopping_logs.length > 0) {
|
||||
html += '<div class="card mb-3">';
|
||||
html += '<div class="card-header">';
|
||||
html += '<h5 class="mb-0">';
|
||||
html += '<i class="fa fa-users"></i> Kunden-Übertragungen (Protokoll) ';
|
||||
html += '<span class="badge badge-info">' + data.shopping_logs.length + '</span>';
|
||||
html += '</h5>';
|
||||
html += '</div>';
|
||||
html += '<div class="card-body">';
|
||||
html += '<table class="table table-sm">';
|
||||
html += '<thead><tr><th>Kunde</th><th>Neuer Berater</th><th>Datum</th></tr></thead><tbody>';
|
||||
data.shopping_logs.forEach(function(log) {
|
||||
html += '<tr>';
|
||||
html += '<td>' + log.customer_name + '<br><small>' + log.customer_email + '</small></td>';
|
||||
html += '<td>';
|
||||
|
||||
// Ursprünglicher Berater aus dem Log
|
||||
if (log.new_member) {
|
||||
html += '<small class="text-muted">Damals:</small><br>';
|
||||
html += log.new_member.name + '<br><small>' + log.new_member.email + '</small>';
|
||||
|
||||
// Falls aktueller Berater anders ist
|
||||
if (log.current_member) {
|
||||
html += '<hr class="my-1">';
|
||||
html += '<span class="badge badge-warning">Geändert!</span><br>';
|
||||
html += '<small class="text-success">Aktuell:</small><br>';
|
||||
html += '<strong>' + log.current_member.name + '</strong><br>';
|
||||
html += '<small>' + log.current_member.email + '</small>';
|
||||
}
|
||||
} else {
|
||||
html += 'N/A';
|
||||
}
|
||||
|
||||
html += '</td>';
|
||||
html += '<td>' + log.created_at + '</td>';
|
||||
html += '</tr>';
|
||||
});
|
||||
html += '</tbody></table></div></div>';
|
||||
}
|
||||
|
||||
$('#history-content').html(html);
|
||||
|
||||
// Lade Sponsoren und initialisiere selectpicker
|
||||
setTimeout(function() {
|
||||
var selectElement = $('#select-new-sponsor');
|
||||
|
||||
if (selectElement.length) {
|
||||
console.log('Lade Sponsoren für selectpicker...');
|
||||
|
||||
// Lade alle aktiven Sponsoren
|
||||
$.ajax({
|
||||
url: '{{ route('admin_user_cleanup_search_sponsors') }}',
|
||||
type: 'GET',
|
||||
data: {
|
||||
q: '', // Leere Suche = alle laden
|
||||
exclude_user_id: currentUserId,
|
||||
load_all: true
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.results && response.results.length > 0) {
|
||||
// Füge alle Sponsoren als Options hinzu
|
||||
response.results.forEach(function(sponsor) {
|
||||
selectElement.append(
|
||||
$('<option></option>')
|
||||
.val(sponsor.id)
|
||||
.text(sponsor.text)
|
||||
);
|
||||
});
|
||||
|
||||
// Initialisiere selectpicker
|
||||
selectElement.selectpicker('refresh');
|
||||
console.log('Selectpicker initialisiert mit ' + response.results.length + ' Sponsoren');
|
||||
} else {
|
||||
console.warn('Keine Sponsoren gefunden');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
console.error('Fehler beim Laden der Sponsoren:', xhr);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.error('Select Element nicht gefunden');
|
||||
}
|
||||
}, 200);
|
||||
|
||||
// Reassign Sponsor Handler
|
||||
$('#btn-reassign-sponsor').off('click').on('click', function() {
|
||||
var newSponsorId = $('#select-new-sponsor').val();
|
||||
var transferDownline = $('#transfer-downline').is(':checked');
|
||||
var transferCustomers = $('#transfer-customers').is(':checked');
|
||||
|
||||
if (!newSponsorId) {
|
||||
alert('Bitte wählen Sie einen neuen Sponsor aus!');
|
||||
return;
|
||||
}
|
||||
|
||||
var sponsorName = $('#select-new-sponsor option:selected').text() || 'ID: ' + newSponsorId;
|
||||
|
||||
var confirmMsg = '═══════════════════════════════════════\n';
|
||||
confirmMsg += 'SPONSOR NEU ZUWEISEN - BESTÄTIGUNG\n';
|
||||
confirmMsg += '═══════════════════════════════════════\n\n';
|
||||
confirmMsg += '👤 User:\n ' + data.user.name + '\n ' + data.user.email + '\n\n';
|
||||
confirmMsg += '➡️ Neuer Sponsor:\n ' + sponsorName + '\n\n';
|
||||
confirmMsg += '───────────────────────────────────────\n';
|
||||
confirmMsg += 'WAS WIRD NEU ZUGEWIESEN?\n';
|
||||
confirmMsg += '───────────────────────────────────────\n\n';
|
||||
|
||||
if (transferDownline && childrenCount > 0) {
|
||||
confirmMsg += '✅ Downline: ' + childrenCount + ' bereits übertragene Kinder\n';
|
||||
} else if (childrenCount > 0) {
|
||||
confirmMsg += '❌ Downline: ' + childrenCount + ' Kinder (NICHT neu zuweisen)\n';
|
||||
} else {
|
||||
confirmMsg += '⚪ Downline: Keine Übertragungen vorhanden\n';
|
||||
}
|
||||
|
||||
if (transferCustomers && customersCount > 0) {
|
||||
confirmMsg += '✅ Kunden: ' + customersCount + ' bereits übertragene Kunden\n';
|
||||
} else if (customersCount > 0) {
|
||||
confirmMsg += '❌ Kunden: ' + customersCount + ' Kunden (NICHT neu zuweisen)\n';
|
||||
} else {
|
||||
confirmMsg += '⚪ Kunden: Keine Übertragungen vorhanden\n';
|
||||
}
|
||||
|
||||
confirmMsg += '\n───────────────────────────────────────\n';
|
||||
confirmMsg += '📝 WICHTIG:\n';
|
||||
confirmMsg += ' • Alle Änderungen werden geloggt\n';
|
||||
confirmMsg += ' • Kann rückgängig gemacht werden\n';
|
||||
confirmMsg += ' • User wird dem neuen Sponsor zugewiesen\n\n';
|
||||
confirmMsg += '═══════════════════════════════════════\n\n';
|
||||
confirmMsg += 'Fortfahren?';
|
||||
|
||||
if (!confirm(confirmMsg)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var btn = $(this);
|
||||
btn.prop('disabled', true).html('<i class="fa fa-spinner fa-spin"></i> Wird neu zugewiesen...');
|
||||
|
||||
$.ajax({
|
||||
url: '{{ route('admin_user_cleanup_reassign_sponsor') }}',
|
||||
type: 'POST',
|
||||
data: {
|
||||
_token: '{{ csrf_token() }}',
|
||||
user_id: currentUserId,
|
||||
new_sponsor_id: newSponsorId,
|
||||
transfer_downline: transferDownline,
|
||||
transfer_customers: transferCustomers
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
var msg = '═══════════════════════════════════════\n';
|
||||
msg += '✅ ERFOLGREICH ABGESCHLOSSEN\n';
|
||||
msg += '═══════════════════════════════════════\n\n';
|
||||
msg += 'Der Sponsor wurde erfolgreich neu zugewiesen!\n\n';
|
||||
|
||||
if (response.logs && response.logs.length > 0) {
|
||||
msg += '───────────────────────────────────────\n';
|
||||
msg += '📋 Durchgeführte Änderungen:\n';
|
||||
msg += '───────────────────────────────────────\n\n';
|
||||
response.logs.forEach(function(log) {
|
||||
msg += '• ' + log + '\n';
|
||||
});
|
||||
msg += '\n';
|
||||
}
|
||||
|
||||
if (response.transferred) {
|
||||
msg += '───────────────────────────────────────\n';
|
||||
msg += '📊 Zusammenfassung:\n';
|
||||
msg += '───────────────────────────────────────\n\n';
|
||||
if (response.transferred.downline > 0) {
|
||||
msg += '✓ Downline übertragen\n';
|
||||
}
|
||||
if (response.transferred.customers > 0) {
|
||||
msg += '✓ Kunden übertragen\n';
|
||||
}
|
||||
msg += '✓ User neu zugewiesen\n\n';
|
||||
}
|
||||
|
||||
msg += '═══════════════════════════════════════';
|
||||
alert(msg);
|
||||
$('#modal-user-history').modal('hide');
|
||||
$('.datatables-cleanup').DataTable().ajax.reload();
|
||||
} else {
|
||||
alert('❌ FEHLER\n\n' + response.message);
|
||||
btn.prop('disabled', false).html('<i class="fa fa-exchange-alt"></i> Sponsor jetzt neu zuweisen');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
var errorMsg = 'Fehler beim Neu-Zuweisen';
|
||||
try {
|
||||
var response = JSON.parse(xhr.responseText);
|
||||
errorMsg += ': ' + response.message;
|
||||
} catch(e) {
|
||||
errorMsg += ': ' + xhr.responseText;
|
||||
}
|
||||
alert(errorMsg);
|
||||
btn.prop('disabled', false).html('<i class="fa fa-exchange-alt"></i> Sponsor jetzt neu zuweisen');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Modal Restore Handler
|
||||
$('#modal-restore-user').on('show.bs.modal', function(event) {
|
||||
var button = $(event.relatedTarget);
|
||||
$('#restore-user-id').val(button.data('id'));
|
||||
$('#restore-user-email').val(button.data('email'));
|
||||
});
|
||||
|
||||
$('#btn-restore-user').click(function() {
|
||||
var userId = $('#restore-user-id').val();
|
||||
var btn = $(this);
|
||||
|
||||
btn.prop('disabled', true).html('<i class="fa fa-spinner fa-spin"></i> Wird wiederhergestellt...');
|
||||
|
||||
$.ajax({
|
||||
url: '{{ route('admin_user_cleanup_restore') }}',
|
||||
type: 'POST',
|
||||
data: {
|
||||
_token: '{{ csrf_token() }}',
|
||||
user_id: userId
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
alert('User wurde erfolgreich wiederhergestellt!');
|
||||
$('#modal-restore-user').modal('hide');
|
||||
$('.datatables-cleanup').DataTable().ajax.reload();
|
||||
} else {
|
||||
alert('Fehler: ' + response.message);
|
||||
}
|
||||
btn.prop('disabled', false).html('<i class="fa fa-undo"></i> User wiederherstellen');
|
||||
},
|
||||
error: function(xhr) {
|
||||
alert('Fehler beim Wiederherstellen: ' + xhr.responseText);
|
||||
btn.prop('disabled', false).html('<i class="fa fa-undo"></i> User wiederherstellen');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
75
resources/views/admin/user/cleanup/logs.blade.php
Normal file
75
resources/views/admin/user/cleanup/logs.blade.php
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
@extends('layouts.layout-2')
|
||||
|
||||
@section('content')
|
||||
<h4 class="font-weight-bold py-2 mb-2">
|
||||
<i class="ion ion-md-git-network"></i> Downline-Übertragungen (User Cleanup Logs)
|
||||
</h4>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col">
|
||||
<div class="alert alert-info">
|
||||
<strong>Info:</strong> Diese Übersicht zeigt alle Downline-Übertragungen bei User-Deaktivierungen.
|
||||
Wenn ein User deaktiviert wird, werden seine Vertriebspartner-Kinder dem nächsten aktiven Sponsor zugewiesen.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="nav-tabs-top mb-4">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route('admin_user_cleanup') }}">
|
||||
<i class="ion ion-ios-people"></i> Deaktivierte/Gelöschte User
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="{{ route('admin_user_cleanup_logs') }}">
|
||||
<i class="ion ion-md-git-network"></i> Downline-Übertragungen
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route('admin_user_cleanup_shopping_logs') }}">
|
||||
<i class="ion ion-md-cart"></i> Kunden-Übertragungen
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-datatable table-responsive">
|
||||
<table class="datatables-logs table table-striped table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Inaktiver Sponsor</th>
|
||||
<th>Betroffenes Kind (Downline)</th>
|
||||
<th>Neuer Sponsor</th>
|
||||
<th>Übertragen am</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('.datatables-logs').dataTable({
|
||||
"processing": true,
|
||||
"serverSide": true,
|
||||
"ajax": '{!! route('admin_user_cleanup_logs_datatable') !!}',
|
||||
"order": [[0, "desc"]],
|
||||
"columns": [
|
||||
{ data: 'id', name: 'id' },
|
||||
{ data: 'inactive_sponsor', name: 'inactive_sponsor_id' },
|
||||
{ data: 'child_user', name: 'child_user_id' },
|
||||
{ data: 'new_sponsor', name: 'new_sponsor_id' },
|
||||
{ data: 'created_at', name: 'created_at' }
|
||||
],
|
||||
"bLengthChange": false,
|
||||
"iDisplayLength": 50,
|
||||
"language": {
|
||||
"url": "/js/datatables-{{ \App::getLocale() }}.json"
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
75
resources/views/admin/user/cleanup/shopping_logs.blade.php
Normal file
75
resources/views/admin/user/cleanup/shopping_logs.blade.php
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
@extends('layouts.layout-2')
|
||||
|
||||
@section('content')
|
||||
<h4 class="font-weight-bold py-2 mb-2">
|
||||
<i class="ion ion-md-cart"></i> Kunden-Übertragungen (Shopping User Member Logs)
|
||||
</h4>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col">
|
||||
<div class="alert alert-info">
|
||||
<strong>Info:</strong> Diese Übersicht zeigt alle Shopping-Kunden-Übertragungen bei User-Löschungen.
|
||||
Wenn ein User gelöscht wird, werden seine Shopping-Kunden dem neuen Sponsor übertragen.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="nav-tabs-top mb-4">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route('admin_user_cleanup') }}">
|
||||
<i class="ion ion-ios-people"></i> Deaktivierte/Gelöschte User
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route('admin_user_cleanup_logs') }}">
|
||||
<i class="ion ion-md-git-network"></i> Downline-Übertragungen
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="{{ route('admin_user_cleanup_shopping_logs') }}">
|
||||
<i class="ion ion-md-cart"></i> Kunden-Übertragungen
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-datatable table-responsive">
|
||||
<table class="datatables-shopping-logs table table-striped table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Vorheriger Berater</th>
|
||||
<th>Shopping-Kunde</th>
|
||||
<th>Neuer Berater</th>
|
||||
<th>Übertragen am</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('.datatables-shopping-logs').dataTable({
|
||||
"processing": true,
|
||||
"serverSide": true,
|
||||
"ajax": '{!! route('admin_user_cleanup_shopping_logs_datatable') !!}',
|
||||
"order": [[0, "desc"]],
|
||||
"columns": [
|
||||
{ data: 'id', name: 'id' },
|
||||
{ data: 'pre_member', name: 'pre_member_id' },
|
||||
{ data: 'shopping_user', name: 'shopping_user_id' },
|
||||
{ data: 'new_member', name: 'new_member_id' },
|
||||
{ data: 'created_at', name: 'created_at' }
|
||||
],
|
||||
"bLengthChange": false,
|
||||
"iDisplayLength": 50,
|
||||
"language": {
|
||||
"url": "/js/datatables-{{ \App::getLocale() }}.json"
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
Loading…
Add table
Add a link
Reference in a new issue