Statistiken/Abo: Kundenfeedback 2026-07-24 komplett umgesetzt + Steuern: DATEV-Fixes 08+09/2025 (Sammel-Commit Branch-WIP)

Feedback-Umsetzung (dev/2026-07-22/feedback-analyse-2026-07-24.md, alle 10 Punkte):
- VIP-Statistik: eigener Berater ('ich', Linie 0) in Neue-Kundenabos- und beiden Top-10-Listen; Top-10-Umsatz sortiert nach abgerechneten Ist-Punkten + Abo-Anzahl-Spalte; Fußnote nicht-payline-wirksame Punkte (SalesVolumePoints::nonPaylinePoints)
- Führungskräfte-Liste: beide Sichten 'direkt' (an nächster FK abgeschnitten, additiv) und 'gesamt' (komplette Downline), Gesamt-Spalte nach Kundenzählweise
- Team-Abos: je Ebene 'abgerechnet (Monat)' und 'bis zum 25. erwartet'; Payline-Karte mit Teamabo-/Kundenabo-Zählern
- Incentive-Live-Ranking: Qualifizierte zuerst nummeriert (fixt auch isWinner rank<=max_winners)
- Porto: Netto-/Brutto-Kennzeichnung (Berater netto, Endkunden inkl. MwSt., portal_view-Flag; auch CRM-/Shop-Warenkorb + Checkout), Yard::shipping_tax-Fix
- Struktur-Ansicht: Abo-Badges 'A' (eigenes Abo) und '(n)' (Kundenabos) je Teampartner, gebatcht
- Abo-Löschung: Softdelete setzt active=0 (UserAbo deleting-Hook) + Bereinigungs-Migration für gelöschte-aber-aktive Abos
- Doku: technische Analyse + Kundinnen-Feedback-Dokument unter dev/2026-07-22/
- Tests: IncentiveRankingTest, TeamStructureAboBadgesTest, YardShippingTaxTest (neu); BackofficeStatisticsListsTest, TeamAboOverviewTest, PaylineForecastServiceTest, AboAdminDeleteTest, AboOneTimeViewTest erweitert

Außerdem enthalten (Branch-WIP vor dem Feedback): DATEV-Abgleich-Fixes 08+09/2025, USt-ID-Live-Validierung sowie restliche unkommittete Stände (u. a. Abo-Pause-Sprachkeys).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Kevin 2026-07-24 13:51:16 +00:00
parent 657d4bd5b7
commit ac3bd6e8ea
136 changed files with 7610 additions and 2688 deletions

View file

@ -117,6 +117,7 @@ class AboController extends Controller
if (isset($data['action'])) {
if ($data['action'] === 'abo_update_settings') {
$user_abo = UserAbo::findOrFail($data['id']);
$data['view'] = 'admin';
$this->aboRepository->setModel($user_abo);
$this->aboRepository->update($data);
@ -274,7 +275,7 @@ class AboController extends Controller
->orderColumn('status', 'status $1')
->orderColumn('active', 'active $1')
->orderColumn('is_for', 'is_for $1')
->orderColumn('count', 'count $1')
->orderColumn('count', '(select count(*) from user_abo_orders where user_abo_orders.user_abo_id = user_abos.id and user_abo_orders.status >= 2) $1')
->orderColumn('amount', 'amount $1')
->orderColumn('payone_userid', 'payone_userid $1')
->rawColumns(['id', 'status', 'active', 'is_for', 'member'])

View file

@ -2,21 +2,23 @@
namespace App\Http\Controllers;
use Auth;
use Carbon;
use Request;
use App\User;
use Validator;
use App\Exceptions\GdprDeletionException;
use App\Mail\UserRestoreEmail;
use App\Models\UserAccount;
use App\Repositories\UserRepository;
use App\Services\GdprDeletionService;
use App\Services\HTMLHelper;
use App\Services\SysLog;
use App\Services\UserUtil;
use App\Models\UserAccount;
use App\Services\HTMLHelper;
use App\Models\PaymentMethod;
use App\Repositories\UserRepository;
use App\User;
use Auth;
use Carbon;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Mail;
use Util;
use Illuminate\View\View;
use Request;
class AdminUserController extends Controller
{
@ -29,33 +31,35 @@ class AdminUserController extends Controller
}
/**
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
* @return Factory|View
*/
public function index()
{
$data = [
//'values' => User::where('admin', 0)->get(),
'values' => User::where('confirmation_code_remider', '!=', 2)->get(),
// 'values' => User::where('admin', 0)->get(),
'values' => User::where('confirmation_code_remider', '!=', 2)->get(),
];
return view('admin.user.index', $data);
}
public function edit($user_id)
{
$user = User::findOrFail($user_id);
if (!$user->account) {
$user->account = new UserAccount();
if (! $user->account) {
$user->account = new UserAccount;
}
$data = [
'user' => $user,
];
return view('admin.user.edit', $data);
}
/**
* @param Request $request
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View
* @param Request $request
* @return Factory|RedirectResponse|Redirector|View
*/
public function store()
{
@ -73,7 +77,7 @@ class AdminUserController extends Controller
SysLog::action('save-admin', 'admin_user', 3)
->setUserId(Auth::user()->id)
->setModel($user->id, User::class)
->setMessage('Set user admin value: ' . HTMLHelper::getLabel($user->admin))
->setMessage('Set user admin value: '.HTMLHelper::getLabel($user->admin))
->save();
}
@ -81,10 +85,10 @@ class AdminUserController extends Controller
$data['confirmed'] = isset($data['confirmed']) ? true : false;
$user->confirmed = $data['confirmed'];
if ($data['confirmed']) {
if (!isset($data['confirmation_date']) || $data['confirmation_date'] == "") {
if (! isset($data['confirmation_date']) || $data['confirmation_date'] == '') {
$user->confirmation_date = now();
} else {
$user->confirmation_date = \Carbon::parse(str_replace("- ", "", $data['confirmation_date']));
$user->confirmation_date = Carbon::parse(str_replace('- ', '', $data['confirmation_date']));
}
} else {
$user->confirmation_date = null;
@ -92,7 +96,7 @@ class AdminUserController extends Controller
SysLog::action('save-confirmed', 'admin_user', 3)
->setUserId(Auth::user()->id)
->setModel($user->id, User::class)
->setMessage('Set user confirmed value: ' . $user->confirmed . " to date: " . $data['confirmation_date'])
->setMessage('Set user confirmed value: '.$user->confirmed.' to date: '.$data['confirmation_date'])
->save();
}
@ -103,10 +107,10 @@ class AdminUserController extends Controller
$user->wizard = 20;
}
if ($data['active']) {
if (!isset($data['active_date']) || $data['active_date'] == "") {
if (! isset($data['active_date']) || $data['active_date'] == '') {
$user->active_date = now();
} else {
$user->active_date = \Carbon::parse(str_replace("- ", "", $data['active_date']));
$user->active_date = Carbon::parse(str_replace('- ', '', $data['active_date']));
}
} else {
$user->active_date = null;
@ -114,7 +118,7 @@ class AdminUserController extends Controller
SysLog::action('save-active', 'admin_user', 3)
->setUserId(Auth::user()->id)
->setModel($user->id, User::class)
->setMessage('Set user active value: ' . $user->active . " to date: " . $data['active_date'])
->setMessage('Set user active value: '.$user->active.' to date: '.$data['active_date'])
->save();
}
@ -122,14 +126,15 @@ class AdminUserController extends Controller
$restore_account = isset($data['restore_account']) ? true : false;
$restore_childs = isset($data['restore_childs']) ? true : false;
$restore_send_email = isset($data['restore_send_email']) ? true : false;
if (isset($data['payment_account']) || $data['payment_account'] != "") {
if (isset($data['payment_account']) || $data['payment_account'] != '') {
$error = UserUtil::checkEmailExists($user);
if ($error) {
\Session()->flash('alert-error', $error);
return redirect()->back()->withInput()->withErrors(['error' => $error]);
}
$payment_account = \Carbon::parse(str_replace("- ", "", $data['payment_account']));
$payment_account = Carbon::parse(str_replace('- ', '', $data['payment_account']));
if ($restore_account) {
UserUtil::restoreUser($user, $payment_account);
if ($restore_childs) {
@ -137,24 +142,24 @@ class AdminUserController extends Controller
}
if ($restore_send_email) {
$user = User::with('account')->findOrFail($data['id']);
Mail::to($user->email)->send(new \App\Mail\UserRestoreEmail($user));
Mail::to($user->email)->send(new UserRestoreEmail($user));
}
}
}
SysLog::action('save-restore', 'admin_user', 3)
->setUserId(Auth::user()->id)
->setModel($user->id, User::class)
->setMessage('Set user restore_account value: ' . $user->restore_account . " and restore_childs value: " . $user->restore_childs)
->setMessage('Set user restore_account value: '.$user->restore_account.' and restore_childs value: '.$user->restore_childs)
->save();
}
if (isset($data['save-account'])) {
$old = $user->getPaymentAccountDateFormat(true);
if (!isset($data['payment_account']) || $data['payment_account'] == "") {
if (! isset($data['payment_account']) || $data['payment_account'] == '') {
$user->payment_account = null;
} else {
$user->wizard = 100;
$payment_account = \Carbon::parse(str_replace("- ", "", $data['payment_account']));
$payment_account = Carbon::parse(str_replace('- ', '', $data['payment_account']));
$user->payment_account = $payment_account;
if ($payment_account > Carbon::now()) {
if ($user->active === 0) {
@ -168,26 +173,26 @@ class AdminUserController extends Controller
}
}
}
//th.schifferegger@gmail.com
// th.schifferegger@gmail.com
SysLog::action('save-account', 'admin_user', 3)
->setUserId(Auth::user()->id)
->setModel($user->id, User::class)
->setMessage('Set user payment_account from date: ' . $old . " to date: " . $data['payment_account'])
->setMessage('Set user payment_account from date: '.$old.' to date: '.$data['payment_account'])
->save();
}
if (isset($data['save-shop'])) {
$old = $user->getPaymentShopDateFormat(true);
if (!isset($data['payment_shop']) || $data['payment_shop'] == "") {
if (! isset($data['payment_shop']) || $data['payment_shop'] == '') {
$user->payment_shop = null;
} else {
$user->wizard = 100;
$user->payment_shop = \Carbon::parse(str_replace("- ", "", $data['payment_shop']));
$user->payment_shop = Carbon::parse(str_replace('- ', '', $data['payment_shop']));
}
SysLog::action('save-shop', 'admin_user', 3)
->setUserId(Auth::user()->id)
->setModel($user->id, User::class)
->setMessage('Set user payment_shop from date: ' . $old . " to date: " . $data['payment_shop'])
->setMessage('Set user payment_shop from date: '.$old.' to date: '.$data['payment_shop'])
->save();
}
@ -196,7 +201,7 @@ class AdminUserController extends Controller
SysLog::action('save-test_mode', 'admin_user', 3)
->setUserId(Auth::user()->id)
->setModel($user->id, User::class)
->setMessage('Set user test_mode value: ' . $user->test_mode)
->setMessage('Set user test_mode value: '.$user->test_mode)
->save();
}
@ -205,13 +210,14 @@ class AdminUserController extends Controller
SysLog::action('save-payment_methods', 'admin_user', 3)
->setUserId(Auth::user()->id)
->setModel($user->id, User::class)
->setMessage('Set user payment_methods value: ' . $user->getPaymentMethodsShort())
->setMessage('Set user payment_methods value: '.$user->getPaymentMethodsShort())
->save();
}
$user->save();
\Session()->flash('alert-save', true);
return redirect('/admin/users');
}
@ -228,15 +234,24 @@ class AdminUserController extends Controller
$this->userRepo->deleteUser($user, true);
\Session()->flash('alert-success', __('msg.contact_delete'));
}
if (isset($data['gdpr_delete_user'])) {
try {
app(GdprDeletionService::class)->deleteUser($user, Auth::id());
\Session()->flash('alert-success', __('msg.gdpr_delete_success'));
} catch (GdprDeletionException $e) {
\Session()->flash('alert-danger', $e->getMessage());
}
}
return redirect('/admin/users');
}
public function userLoginAs($userId)
{
if (Auth::user()->isSuperAdmin()) {
$user = User::find($userId);
Auth::login($user);
return redirect('/home');
}
}
@ -253,7 +268,7 @@ class AdminUserController extends Controller
})
->with('account')
->select('users.*')
->where('users.admin', "<", 5);
->where('users.admin', '<', 5);
return \DataTables::eloquent($query)
->addColumn('first_name', function (User $user) {
@ -261,89 +276,101 @@ class AdminUserController extends Controller
})
->addColumn('email', function (User $user) {
if ($user->pre_deleted_at) {
return '<span class="badge badge-pill badge-danger">' . $user->email . '</span>';
return '<span class="badge badge-pill badge-danger">'.$user->email.'</span>';
}
return $user->email;
})
->addColumn('last_name', function (User $user) {
return $user->account ? $user->account->last_name : '';
})
->addColumn('id', function (User $user) {
return '<a href="' . route('admin_lead_edit', [$user->id]) . '" class="btn icon-btn btn-sm btn-primary"><span class="fa fa-edit"></span></a>';
return '<a href="'.route('admin_lead_edit', [$user->id]).'" class="btn icon-btn btn-sm btn-primary"><span class="fa fa-edit"></span></a>';
})
->addColumn('admin', function (User $user) {
return '<a href="#" data-toggle="modal" data-target="#modals-admin" data-id="' . $user->id . '" data-email="' . $user->email . '" data-admin="' . $user->admin . '">' . HTMLHelper::getRoleLabel($user->admin) . '</a>';
return '<a href="#" data-toggle="modal" data-target="#modals-admin" data-id="'.$user->id.'" data-email="'.$user->email.'" data-admin="'.$user->admin.'">'.HTMLHelper::getRoleLabel($user->admin).'</a>';
})
->addColumn('confirmed', function (User $user) {
$date = $user->getConfirmationDateFormat();
$link = '<a href="#" data-toggle="modal" data-target="#modals-confirmed" data-id="' . $user->id . '" data-email="' . $user->email . '" data-confirmed="' . $user->confirmed . '" data-confirmation_date="' . $date . '">';
return $user->confirmed ? $link . '<span class="badge badge-pill badge-success"><i class="fa fa-check"></i> ' . $date . '</span></a>' : $link . '<span class="badge badge-pill badge-danger"><i class="fa fa-times"></i></span></a>';
$link = '<a href="#" data-toggle="modal" data-target="#modals-confirmed" data-id="'.$user->id.'" data-email="'.$user->email.'" data-confirmed="'.$user->confirmed.'" data-confirmation_date="'.$date.'">';
return $user->confirmed ? $link.'<span class="badge badge-pill badge-success"><i class="fa fa-check"></i> '.$date.'</span></a>' : $link.'<span class="badge badge-pill badge-danger"><i class="fa fa-times"></i></span></a>';
})
->addColumn('active', function (User $user) {
if ($user->trashed()) {
$date = Carbon::parse(now())->addDays(10)->format('d.m.Y H:i');
$email = str_replace("delete-", "", $user->email);
$link = '<a href="#" data-toggle="modal" data-target="#modals-restore" data-id="' . $user->id . '" data-email="' . $email . '" data-active="' . $user->active . '" data-payment_account="' . $date . '">';
return $link . '<span class="badge badge-pill badge-info"><i class="fa fa-undo"></i> Account reaktivieren</span></a>';
$email = str_replace('delete-', '', $user->email);
$link = '<a href="#" data-toggle="modal" data-target="#modals-restore" data-id="'.$user->id.'" data-email="'.$email.'" data-active="'.$user->active.'" data-payment_account="'.$date.'">';
return $link.'<span class="badge badge-pill badge-info"><i class="fa fa-undo"></i> Account reaktivieren</span></a>';
}
$date = $user->getActiveDateFormat();
$link = '<a href="#" data-toggle="modal" data-target="#modals-active" data-id="' . $user->id . '" data-email="' . $user->email . '" data-active="' . $user->active . '" data-active_date="' . $date . '">';
return $user->active ? $link . '<span class="badge badge-pill badge-success"><i class="fa fa-check"></i> ' . $date . '</span></a>' : $link . '<span class="badge badge-pill badge-danger"><i class="fa fa-times"></i></span></a>';
$link = '<a href="#" data-toggle="modal" data-target="#modals-active" data-id="'.$user->id.'" data-email="'.$user->email.'" data-active="'.$user->active.'" data-active_date="'.$date.'">';
return $user->active ? $link.'<span class="badge badge-pill badge-success"><i class="fa fa-check"></i> '.$date.'</span></a>' : $link.'<span class="badge badge-pill badge-danger"><i class="fa fa-times"></i></span></a>';
})
->addColumn('account', function (User $user) {
$date = $user->getPaymentAccountDateFormat();
$link = '<a href="#" data-toggle="modal" data-target="#modals-account" data-id="' . $user->id . '" data-email="' . $user->email . '" data-payment_account="' . $date . '">';
$link = '<a href="#" data-toggle="modal" data-target="#modals-account" data-id="'.$user->id.'" data-email="'.$user->email.'" data-payment_account="'.$date.'">';
if ($user->payment_account) {
if ($user->isActiveAccount()) {
return $link . '<span class="badge badge-pill badge-success"><i class="fa fa-check"></i> ' . $date . '</span></a>';
return $link.'<span class="badge badge-pill badge-success"><i class="fa fa-check"></i> '.$date.'</span></a>';
}
return $link . '<span class="badge badge-pill badge-warning"><i class="fa fa-ban"></i> ' . $date . '</span></a>';
return $link.'<span class="badge badge-pill badge-warning"><i class="fa fa-ban"></i> '.$date.'</span></a>';
}
return $link . '<span class="badge badge-pill badge-danger"><i class="fa fa-times"></i></span></a>';
return $link.'<span class="badge badge-pill badge-danger"><i class="fa fa-times"></i></span></a>';
})
->addColumn('shop', function (User $user) {
$date = $user->getPaymentShopDateFormat();
$link = '<a href="#" data-toggle="modal" data-target="#modals-shop" data-id="' . $user->id . '" data-email="' . $user->email . '" data-payment_shop="' . $date . '">';
$link = '<a href="#" data-toggle="modal" data-target="#modals-shop" data-id="'.$user->id.'" data-email="'.$user->email.'" data-payment_shop="'.$date.'">';
if ($user->payment_shop) {
if ($user->isActiveShop()) {
return $link . '<span class="badge badge-pill badge-success"><i class="fa fa-check"></i> ' . $date . '</span></a>';
return $link.'<span class="badge badge-pill badge-success"><i class="fa fa-check"></i> '.$date.'</span></a>';
}
return $link . '<span class="badge badge-pill badge-warning"><i class="fa fa-ban"></i> ' . $date . '</span></a>';
return $link.'<span class="badge badge-pill badge-warning"><i class="fa fa-ban"></i> '.$date.'</span></a>';
}
return $link . '<span class="badge badge-pill badge-danger"><i class="fa fa-times"></i></span></a>';
return $link.'<span class="badge badge-pill badge-danger"><i class="fa fa-times"></i></span></a>';
})
->addColumn('shop_domain', function (User $user) {
return $user->shop ? '<a href="' . $user->shop->getSubdomain(false) . '" target="_blank">' . $user->shop->getSubdomain(false) . '</a>' : '';
return $user->shop ? '<a href="'.$user->shop->getSubdomain(false).'" target="_blank">'.$user->shop->getSubdomain(false).'</a>' : '';
})
->addColumn('since', function (User $user) {
if ($user->shop) {
if ($user->shop->active) {
return $user->shop->getActiveDateFormatSmall();
}
return $user->shop->getActiveDateFormatSmall();
}
return "-";
return '-';
})
->addColumn('country', function (User $user) {
return ($user->account && $user->account->country) ? $user->account->country->de : '';
})
->addColumn('my_payment_methods', function (User $user) {
$payment_methods = json_encode($user->payment_methods);
$link = '<a href="#" data-toggle="modal" data-target="#modals-payment_methods" data-id="' . $user->id . '" data-email="' . $user->email . '" data-payment_methods="' . htmlspecialchars($payment_methods) . '">';
if (!$user->payment_methods) {
return $link . '<span class="badge badge-pill badge-danger"><i class="fa fa-times"></i></span></a>';
$link = '<a href="#" data-toggle="modal" data-target="#modals-payment_methods" data-id="'.$user->id.'" data-email="'.$user->email.'" data-payment_methods="'.htmlspecialchars($payment_methods).'">';
if (! $user->payment_methods) {
return $link.'<span class="badge badge-pill badge-danger"><i class="fa fa-times"></i></span></a>';
}
return $link . '<span class="badge badge-pill badge-success"><i class="fa fa-check"></i> ' . $user->getPaymentMethodsShort() . '</span></a>';
return $link.'<span class="badge badge-pill badge-success"><i class="fa fa-check"></i> '.$user->getPaymentMethodsShort().'</span></a>';
})
->addColumn('action_login', function (User $user) {
return '<a href="' . route('admin_user_login_as', [$user->id]) . '" class="btn icon-btn btn-sm btn-warning" onclick="return confirm(\'' . __('Login as User?') . '\');"><span class="fa fa-sign-in-alt"></span></a>';
return '<a href="'.route('admin_user_login_as', [$user->id]).'" class="btn icon-btn btn-sm btn-warning" onclick="return confirm(\''.__('Login as User?').'\');"><span class="fa fa-sign-in-alt"></span></a>';
})
->addColumn('action_delete', function (User $user) {
return '<a class="btn icon-btn btn-sm btn-danger" href="#" data-toggle="modal" data-target="#modals-user-delete" data-id="' . $user->id . '" data-email="' . $user->email . '"><span class="fa fa-trash"></span></a>';
return '<a class="btn icon-btn btn-sm btn-danger" href="#" data-toggle="modal" data-target="#modals-user-delete" data-id="'.$user->id.'" data-email="'.$user->email.'"><span class="fa fa-trash"></span></a>';
})
->addColumn('test_mode', function (User $user) {
$link = '<a href="#" data-toggle="modal" data-target="#modals-test_mode" data-id="' . $user->id . '" data-email="' . $user->email . '" data-test_mode="' . $user->test_mode . '">';
return $user->test_mode ? $link . '<span class="badge badge-pill badge-success"><i class="fa fa-check"></i></span></a>' : $link . '<span class="badge badge-pill badge-danger"><i class="fa fa-times"></i></span></a>';
$link = '<a href="#" data-toggle="modal" data-target="#modals-test_mode" data-id="'.$user->id.'" data-email="'.$user->email.'" data-test_mode="'.$user->test_mode.'">';
return $user->test_mode ? $link.'<span class="badge badge-pill badge-success"><i class="fa fa-check"></i></span></a>' : $link.'<span class="badge badge-pill badge-danger"><i class="fa fa-times"></i></span></a>';
})
->orderColumn('id', 'id $1')
->orderColumn('email', 'email $1')

View file

@ -1,116 +0,0 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Session;
use \SoapClient;
class KasController extends Controller
{
// Logindaten
private $kas_user = 'w017f6e4'; // KAS-Logon
private $kas_pass = 'Medxiz-funteb-7dubdi'; // KAS-Passwort
private $session_lifetime = 600; // Gültigkeit des Tokens in Sek. bis zur neuen Authentifizierung
private $session_update_lifetime = 'Y'; // bei N läuft die Session nach <$session_lifetime> Sekunden ab, bei Y verlängert sich die Session mit jeder Benutzung
private $CredentialToken = false;
private $kas_flood_delay = 2;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->login();
}
public function action($func, $para = array()){
$this->checkSession($func);
try
{
$Params = array(); // Parameter für die API-Funktion
$SoapRequest = new SoapClient('https://kasapi.kasserver.com/soap/wsdl/KasApi.wsdl', [
'cache_wsdl' => WSDL_CACHE_NONE,
'exceptions' => false
]);
$req = $SoapRequest->KasApi(json_encode(array(
'KasUser' => $this->kas_user, // KAS-User
'KasAuthType' => 'session', // Auth per Sessiontoken
'KasAuthData' => $this->CredentialToken, // Auth-Token
'KasRequestType' => $func, // API-Funktion
'KasRequestParams' => $para // Parameter an die API-Funktion
)));
Session::put('flood_protection.'.$func, time() + $this->kas_flood_delay + 0.2);
if(is_array($req) && isset($req['Response']['ReturnString']) && $req['Response']['ReturnString'] == "TRUE"){
return $req['Response']['ReturnInfo'];
}
return $req;
}
// Fehler abfangen und ausgeben
catch (\SoapFault $fault)
{
trigger_error(" Fehlernummer: {$fault->faultcode},
Fehlermeldung: {$fault->faultstring},
Verursacher: {$fault->faultactor},
Details: {$fault->detail}", E_USER_ERROR);
}
}
private function login(){
$this->checkSession('auth');
try
{
$SoapLogon = new SoapClient('https://kasapi.kasserver.com/soap/wsdl/KasAuth.wsdl', [
'cache_wsdl' => WSDL_CACHE_NONE,
'exceptions' => false
]);
$this->CredentialToken = $SoapLogon->KasAuth(json_encode(array(
'KasUser' => $this->kas_user,
'KasAuthType' => 'plain',
'KasPassword' => $this->kas_pass,
'SessionLifeTime' => $this->session_lifetime,
'SessionUpdateLifeTime' => $this->session_update_lifetime
)));
Session::put('flood_protection.auth', time() + $this->kas_flood_delay + 0.2);
}
// Fehler abfangen und ausgeben
catch (\SoapFault $fault)
{
trigger_error("Fehlernummer: {$fault->faultcode},
Fehlermeldung: {$fault->faultstring},
Verursacher: {$fault->faultactor},
Details: {$fault->detail}", E_USER_ERROR);
}
}
private function checkSession($func)
{
$name = 'flood_protection.'.$func;
if(Session::exists($name)){
$time_to_wait = (float)Session::get($name) - time();
Session::forget($name);
}else {
$time_to_wait = 0;
}
if ( $time_to_wait >= 0 ) {
usleep( intval( $time_to_wait*1000000 ) );
}
}
}

View file

@ -11,7 +11,9 @@ use App\Models\ShoppingOrder;
use App\Models\ShoppingOrderItem;
use App\Models\ShoppingUser;
use App\Services\CustomerPriority;
use App\Services\Shop;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use Yard;
@ -28,7 +30,7 @@ class ShoppingUserController extends Controller
/**
* @param Request $request
* wp_order_numbers[1234, 1234]
* @return \Illuminate\Http\JsonResponse
* @return JsonResponse
*/
public function status(Request $request)
{
@ -74,7 +76,7 @@ class ShoppingUserController extends Controller
/**
* @param Request $request
* wp_order_number [1234]
* @return \Illuminate\Http\JsonResponse
* @return JsonResponse
*/
public function cancel(Request $request)
{
@ -126,7 +128,7 @@ class ShoppingUserController extends Controller
/**
* @param Request $request
* wp_order_number [1234]
* @return \Illuminate\Http\JsonResponse
* @return JsonResponse
*/
public function open(Request $request)
{
@ -178,7 +180,7 @@ class ShoppingUserController extends Controller
/**
* @param Request $request
* wp_order_numbers [1234, 1234]
* @return \Illuminate\Http\JsonResponse
* @return JsonResponse
*/
public function show(Request $request)
{
@ -229,7 +231,7 @@ class ShoppingUserController extends Controller
}
/**
* @return \Illuminate\Http\JsonResponse
* @return JsonResponse
*/
public function store(Request $request)
{
@ -258,7 +260,7 @@ class ShoppingUserController extends Controller
// Kundenhoheit prüfen
$priority = CustomerPriority::checkOne($shopping_user, true, false, true);
\App\Services\Shop::newUserOrder($shopping_user->number);
Shop::newUserOrder($shopping_user->number);
// exists //like //update
$user = $this->prepareForShow($shopping_user);
@ -277,7 +279,7 @@ class ShoppingUserController extends Controller
}
/**
* @return \Illuminate\Http\JsonResponse
* @return JsonResponse
*/
public function update(Request $request)
{
@ -297,7 +299,7 @@ class ShoppingUserController extends Controller
// Kundenhoheit prüfen
$priority = CustomerPriority::checkChangeOne($shopping_user, $data, true);
$updated = $shopping_user->fill($data)->save();
\App\Services\Shop::newUserOrder($shopping_user->number);
Shop::newUserOrder($shopping_user->number);
if ($updated) {
$user = $this->prepareForShow($shopping_user);
@ -610,6 +612,12 @@ class ShoppingUserController extends Controller
$ShippingCountry = ShippingCountry::whereCountryId($shopping_user->shipping_country_id)->first();
if ($ShippingCountry) {
Yard::instance('shopping')->setUserPriceInfos([
'shipping_free' => $ShippingCountry->shipping?->free ?? false,
'user_tax_free' => false,
'user_reverse_charge' => false,
'user_country_id' => $shopping_user->billing_country_id,
]);
Yard::instance('shopping')->setShippingCountryWithPrice($ShippingCountry->id);
}
$shopping_order = $this->makeShoppingOrder($shopping_user, $wp_invoice_path, $api_notice);

View file

@ -2,14 +2,17 @@
namespace App\Http\Controllers;
use App\Exceptions\GdprDeletionException;
use App\Models\ShoppingUser;
use App\Repositories\CustomerRepository;
use App\Services\CustomerPriority;
use App\Services\GdprDeletionService;
use App\Services\HTMLHelper;
use App\Services\Shop;
use Auth;
use Request;
use Validator;
class CustomerController extends Controller
{
protected $customerRepository;
@ -17,6 +20,7 @@ class CustomerController extends Controller
public function __construct(CustomerRepository $customerRepository)
{
$this->middleware('admin');
$this->middleware('superadmin')->only('gdprDelete');
$this->customerRepository = $customerRepository;
}
@ -25,16 +29,17 @@ class CustomerController extends Controller
if (Request::get('reset') === 'filter') {
set_user_attr('filter_member_id', null);
set_user_attr('filter_customer_member', null);
return redirect(route('admin_customers'));
}
$filter_members = ShoppingUser::join('users', 'member_id', '=', 'users.id')->groupBy('member_id')->join('user_accounts', 'account_id', '=', 'user_accounts.id')->select('users.id', 'users.email', 'user_accounts.first_name', 'user_accounts.last_name')->get(); //->pluck('email', 'id')->unique()->toArray();
$filter_members = ShoppingUser::join('users', 'member_id', '=', 'users.id')->groupBy('member_id')->join('user_accounts', 'account_id', '=', 'user_accounts.id')->select('users.id', 'users.email', 'user_accounts.first_name', 'user_accounts.last_name')->get(); // ->pluck('email', 'id')->unique()->toArray();
$data = [
'filter_members' => $filter_members,
];
return view('admin.customer.index', $data);
}
public function detail($id)
{
$shopping_user = ShoppingUser::findOrFail($id);
@ -43,6 +48,7 @@ class CustomerController extends Controller
'isAdmin' => true,
'isView' => 'customer',
];
return view('admin.customer.detail', $data);
}
@ -50,20 +56,44 @@ class CustomerController extends Controller
{
$shopping_user = ShoppingUser::findOrFail($id);
$result = $this->customerRepository->deleteCustomer($shopping_user);
if (!$result) {
if (! $result) {
return back()->with('alert-error', 'Kunde hat Bestellungen. Löschen nicht möglich.');
} else {
\Session()->flash('alert-success', 'Kunde wurde gelöscht');
return redirect(route('admin_customers'));
}
return redirect(route('admin_customers'));
}
public function gdprDelete($id)
{
$shopping_user = ShoppingUser::withTrashed()->findOrFail($id);
if (! Request::get('gdpr_delete_customer')) {
\Session()->flash('alert-danger', __('msg.gdpr_confirm_checkbox_missing'));
return redirect(route('admin_customer_detail', [$shopping_user->id]));
}
try {
app(GdprDeletionService::class)->deleteShoppingUser($shopping_user, Auth::id());
\Session()->flash('alert-success', __('msg.gdpr_delete_customer_success'));
} catch (GdprDeletionException $e) {
\Session()->flash('alert-danger', $e->getMessage());
return redirect(route('admin_customer_detail', [$shopping_user->id]));
}
return redirect(route('admin_customers'));
}
public function edit($id)
{
if ($id === "new") {
$shopping_user = new ShoppingUser();
$shopping_user->id = "new";
if ($id === 'new') {
$shopping_user = new ShoppingUser;
$shopping_user->id = 'new';
} else {
$shopping_user = ShoppingUser::findOrFail($id);
}
@ -72,6 +102,7 @@ class CustomerController extends Controller
'isAdmin' => true,
'isView' => 'customer',
];
return view('admin.customer.edit', $data);
}
@ -80,23 +111,25 @@ class CustomerController extends Controller
$data = Request::all();
if ($data['action'] === 'shopping-user-change-member') {
if (!isset($data['change_member_key']) || $data['change_member_key'] !== config('mivita.edit_data_pass')) {
if (! isset($data['change_member_key']) || $data['change_member_key'] !== config('mivita.edit_data_pass')) {
$data = [
'change_member_error' => "Das Passwort ist falsch.",
'change_member_error' => 'Das Passwort ist falsch.',
'shopping_user' => ShoppingUser::find($id),
'isAdmin' => true,
'isView' => 'customer',
];
return view('admin.customer.detail', $data);
}
//change
// change
$shopping_user = ShoppingUser::findOrFail($data['id']);
CustomerPriority::newMemberForCustomer($shopping_user, $data['change_member_id'], $data['customer_set_member_for']);
\Session()->flash('alert-save', true);
return redirect(route('admin_customer_detail', [$shopping_user->id]));
}
if ($data['action'] === 'shopping-user-store') {
$rules = array(
$rules = [
'billing_salutation' => 'required',
'billing_firstname' => 'required',
'billing_lastname' => 'required',
@ -104,10 +137,10 @@ class CustomerController extends Controller
'billing_address' => 'required',
'billing_zipcode' => 'required',
'billing_city' => 'required',
'billing_country_id' => 'required'
);
'billing_country_id' => 'required',
];
if (!Request::get('same_as_billing')) {
if (! Request::get('same_as_billing')) {
$rules = array_merge($rules, [
'shipping_firstname' => 'required',
'shipping_lastname' => 'required',
@ -115,7 +148,7 @@ class CustomerController extends Controller
'shipping_zipcode' => 'required',
'shipping_city' => 'required',
'shipping_salutation' => 'required',
'shipping_country_id' => 'required'
'shipping_country_id' => 'required',
]);
}
$validator = Validator::make(Request::all(), $rules);
@ -128,7 +161,7 @@ class CustomerController extends Controller
$data['language'] = isset($data['language']) ? $data['language'] : \App::getLocale();
$data['has_buyed'] = isset($data['has_buyed']) ? true : false;
$data['subscribed'] = isset($data['subscribed']) ? true : false;
//subscribed can only true when has_buyed ist active
// subscribed can only true when has_buyed ist active
$data['subscribed'] = $data['has_buyed'] ? $data['subscribed'] : false;
/* if($shopping_user->auth_user_id > 0){
@ -140,21 +173,23 @@ class CustomerController extends Controller
CustomerPriority::checkChangeOne($shopping_user, $data, true);
$shopping_user->fill($data);
$shopping_user->save();
\App\Services\Shop::newUserOrder($shopping_user->number);
Shop::newUserOrder($shopping_user->number);
\Session()->flash('alert-save', true);
}
return redirect(route('admin_customer_detail', [$shopping_user->id]));
}
public function getCustomers()
{
$query = ShoppingUser::select('shopping_users.*')->where('auth_user_id', '=', NULL);
$query = ShoppingUser::select('shopping_users.*')->where('auth_user_id', '=', null);
set_user_attr('filter_member_id', Request::get('filter_member_id'));
if (Request::get('filter_member_id') != "") {
if (Request::get('filter_member_id') != '') {
$query->where('member_id', '=', Request::get('filter_member_id'));
}
/* set_user_attr('filter_customer_member', Request::get('filter_customer_member'));
if(Request::get('filter_customer_member') != ""){
if(Request::get('filter_customer_member') === 'customers'){
@ -166,10 +201,10 @@ class CustomerController extends Controller
}*/
return \DataTables::eloquent($query)
->addColumn('id', function (ShoppingUser $ShoppingUser) {
return '<a href="' . route('admin_customer_detail', [$ShoppingUser->id]) . '" class="btn icon-btn btn-sm btn-primary"><span class="fa fa-edit"></span></a>';
return '<a href="'.route('admin_customer_detail', [$ShoppingUser->id]).'" class="btn icon-btn btn-sm btn-primary"><span class="fa fa-edit"></span></a>';
})
->addColumn('billing_email', function (ShoppingUser $ShoppingUser) {
return $ShoppingUser->faker_mail ? "-" : $ShoppingUser->billing_email;
return $ShoppingUser->faker_mail ? '-' : $ShoppingUser->billing_email;
})
->addColumn('billing_salutation', function (ShoppingUser $ShoppingUser) {
return HTMLHelper::getSalutationLang($ShoppingUser->billing_salutation);
@ -178,19 +213,19 @@ class CustomerController extends Controller
return $ShoppingUser->billing_country ? $ShoppingUser->billing_country->getLocated() : '';
})
->addColumn('isMember', function (ShoppingUser $ShoppingUser) {
return get_active_badge($ShoppingUser->auth_user_id) . ($ShoppingUser->mode === 'dev' ? ' <span class="badge badge-warning">dev</span>' : '');
return get_active_badge($ShoppingUser->auth_user_id).($ShoppingUser->mode === 'dev' ? ' <span class="badge badge-warning">dev</span>' : '');
})
->addColumn('member_id', function (ShoppingUser $ShoppingUser) {
if ($ShoppingUser->is_like) {
return '<button type="button" class="btn btn-xs btn-outline-info" data-toggle="modal" data-target="#modals-load-content"
data-id="' . $ShoppingUser->id . '"
data-id="'.$ShoppingUser->id.'"
data-action="shopping-user-is-like-member"
data-back="' . route('admin_customers') . '"
data-back="'.route('admin_customers').'"
data-modal="modal-xl"
data-route="' . route('modal_load') . '"><span class="fa fa-edit"></span> Berater zuordnen</button>';
data-route="'.route('modal_load').'"><span class="fa fa-edit"></span> Berater zuordnen</button>';
}
if ($ShoppingUser->member) {
return '<a href="' . route('admin_lead_edit', [$ShoppingUser->member_id]) . '">' . $ShoppingUser->member->getFullName() . '</a>';
return '<a href="'.route('admin_lead_edit', [$ShoppingUser->member_id]).'">'.$ShoppingUser->member->getFullName().'</a>';
}
return '';
@ -202,8 +237,8 @@ class CustomerController extends Controller
return get_active_badge($ShoppingUser->subscribed);
})
->filterColumn('billing_email', function ($query, $keyword) {
if ($keyword != "") {
$query->where('billing_email', 'LIKE', '%' . $keyword . '%');
if ($keyword != '') {
$query->where('billing_email', 'LIKE', '%'.$keyword.'%');
}
})
->orderColumn('id', 'id $1')

View file

@ -2,7 +2,11 @@
namespace App\Http\Controllers;
use App\Models\DcFile;
use App\Models\File;
use App\Models\ShoppingOrder;
use App\Models\UserCredit;
use App\Models\UserInvoice;
use App\Repositories\CreditRepository;
use Auth;
use Response;
@ -78,7 +82,7 @@ class FileController extends Controller
}
}*/
if ($from === 'invoice') {
$shopping_order = \App\Models\ShoppingOrder::findOrFail($id);
$shopping_order = ShoppingOrder::findOrFail($id);
if ($shopping_order->user_invoice) {
$this->isPermissionShoppingOrder($shopping_order);
$user_invoice = $shopping_order->user_invoice;
@ -95,7 +99,7 @@ class FileController extends Controller
}
if ($from === 'delivery') {
$shopping_order = \App\Models\ShoppingOrder::findOrFail($id);
$shopping_order = ShoppingOrder::findOrFail($id);
if ($shopping_order->user_invoice) {
$this->isPermissionShoppingOrder($shopping_order);
$user_invoice = $shopping_order->user_invoice;
@ -121,12 +125,12 @@ class FileController extends Controller
}
if ($from === 'cancellation') {
$shopping_order = \App\Models\ShoppingOrder::findOrFail($id);
$shopping_order = ShoppingOrder::findOrFail($id);
$this->isPermissionShoppingOrder($shopping_order);
// Stornorechnung finden: cancellation=true UND cancellation_id=null
// (Die Original-Rechnung hat auch cancellation=true, aber MIT cancellation_id)
$cancellation_invoice = \App\Models\UserInvoice::where('shopping_order_id', $shopping_order->id)
$cancellation_invoice = UserInvoice::where('shopping_order_id', $shopping_order->id)
->where('cancellation', true)
->whereNull('cancellation_id')
->first();
@ -147,7 +151,7 @@ class FileController extends Controller
}
if ($from === 'credit') {
$user_credit = \App\Models\UserCredit::findOrFail($id);
$user_credit = UserCredit::findOrFail($id);
$this->isPermissionUserCredit($user_credit);
$disk = $user_credit->disk;
// Lokalisierte Version wenn angegeben
@ -161,7 +165,7 @@ class FileController extends Controller
}
if ($from === 'credit_detail') {
$user_credit = \App\Models\UserCredit::findOrFail($id);
$user_credit = UserCredit::findOrFail($id);
$this->isPermissionUserCredit($user_credit);
return $this->create_credit_detail($user_credit, $do);
@ -175,14 +179,14 @@ class FileController extends Controller
if ($from === 'dc_file') {
// $this->isPermissionAuth();
$dc_file = \App\Models\DcFile::findOrFail($id);
$dc_file = DcFile::findOrFail($id);
$filename = $dc_file->filename;
$disk = 'public';
$path = $dc_file->getFile();
}
if ($from === 'dc_thumb') {
// $this->isPermissionAuth();
$dc_file = \App\Models\DcFile::findOrFail($id);
$dc_file = DcFile::findOrFail($id);
$filename = $dc_file->filename;
$disk = 'public';
$path = $dc_file->getThumb();
@ -190,14 +194,14 @@ class FileController extends Controller
if ($from === 'dc_big') {
// $this->isPermissionAuth();
$dc_file = \App\Models\DcFile::findOrFail($id);
$dc_file = DcFile::findOrFail($id);
$filename = $dc_file->filename;
$disk = 'public';
$path = $dc_file->getBig();
}
if ($from === 'user') {
$file = \App\Models\File::findOrFail($id);
$file = File::findOrFail($id);
$filename = $file->filename;
$disk = 'user';
$path = $file->dir.$file->filename;
@ -244,6 +248,7 @@ class FileController extends Controller
private function create_credit_detail(UserCredit $user_credit, $do)
{
abort_if($user_credit->user === null, 404, 'User zur Gutschrift nicht gefunden.');
$credit_repo = new CreditRepository($user_credit->user);

View file

@ -7,15 +7,15 @@ use App\Models\Incentive;
use App\Models\IncentiveParticipant;
use App\Models\ShoppingPayment;
use App\Models\UserAbo;
use App\Models\UserBusiness;
use App\Services\Abo\PaylineForecastService;
use App\Services\Abo\TeamAboOverviewService;
use App\Services\AboHelper;
use App\Services\Backoffice\BackofficeDashboardService;
use App\Services\BusinessPlan\TreeCalcBot;
use App\Services\BusinessPlan\LiveCommissionService;
use App\User;
use Carbon\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\View\View;
use Request;
use Util;
@ -38,11 +38,11 @@ class HomeController extends Controller
return redirect('home');
}
public function newsArchive(): \Illuminate\View\View
public function newsArchive(): View
{
return view('dashboard.news_archive', [
'currentNews' => \App\Models\DashboardNews::getActiveNews(),
'archiveNews' => \App\Models\DashboardNews::getArchiveNews(),
'currentNews' => DashboardNews::getActiveNews(),
'archiveNews' => DashboardNews::getArchiveNews(),
]);
}
@ -111,10 +111,18 @@ class HomeController extends Controller
private function buildMonthlyStats(User $user): array
{
$month = max(1, min(12, (int) Request::get('stats_month', now()->month)));
$year = (int) Request::get('stats_year', now()->year);
$year = max(2020, min((int) now()->year + 1, (int) Request::get('stats_year', now()->year)));
$salesVolume = $user->getUserSalesVolume($month, $year, 'first');
[$paylinePoints, $paylineIsLive] = $this->teamPaylinePoints($user, $month, $year);
$customerPoints = $salesVolume ? (float) $salesVolume->getPointsKPSum() : 0.0;
// Payline-Prognose (B10) nur für den laufenden Monat — Basis ist der heutige
// Stand aus Kundenumsatz + Payline-Punkten.
$isCurrentMonth = $month === (int) now()->month && $year === (int) now()->year;
$paylineForecast = $isCurrentMonth
? app(PaylineForecastService::class)->forecastDays($user, $customerPoints + (float) $paylinePoints)
: null;
$firstlineIds = User::where('m_sponsor', $user->id)
->whereColumn('id', '!=', 'm_sponsor')
@ -130,9 +138,11 @@ class HomeController extends Controller
[
'month' => $month,
'year' => $year,
'customer_points' => $salesVolume ? (float) $salesVolume->getPointsKPSum() : 0.0,
'customer_points' => $customerPoints,
'team_payline_points' => $paylinePoints,
'payline_is_live' => $paylineIsLive,
'payline_forecast' => $paylineForecast,
'commission' => app(LiveCommissionService::class)->commission($user, $month, $year),
'direct_new_partners' => $dashboardService->newPartnersCount($firstlineIds, $month, $year),
],
$teamOverview->teamKpis($user, $month, $year),
@ -141,45 +151,16 @@ class HomeController extends Controller
}
/**
* Team-Payline-Punkte: aus dem UserBusiness-Snapshot (abgeschlossene Monate) oder
* – für den laufenden Monat – einmalig live berechnet und für Folge-Aufrufe gecacht.
* Team-Payline-Punkte: aus dem gemeinsamen Live-Lauf ({@see LiveCommissionService}),
* der auch die Provision und die Payline-Tiefe liefert — ein Baum-Lauf für alles.
*
* @return array{0: float, 1: bool} [Punkte, istLive]
*/
private function teamPaylinePoints(User $user, int $month, int $year): array
{
$userBusiness = UserBusiness::where('user_id', $user->id)
->where('month', $month)
->where('year', $year)
->first();
$snapshot = app(LiveCommissionService::class)->snapshot($user, $month, $year);
if ($userBusiness) {
return [(float) ($userBusiness->payline_points ?? 0), false];
}
$points = Cache::remember(
"home_payline_{$user->id}_{$month}_{$year}",
now()->addHours(6),
fn (): float => $this->calculatePaylineLive($user, $month, $year)
);
return [(float) $points, true];
}
private function calculatePaylineLive(User $user, int $month, int $year): float
{
try {
$treeCalcBot = new TreeCalcBot($month, $year, 'member');
$treeCalcBot->initBusinesslUserDetail($user);
if ($treeCalcBot->business_user) {
return (float) ($treeCalcBot->business_user->payline_points ?? 0);
}
} catch (\Throwable $e) {
\Log::warning("Live-Berechnung Payline-Punkte fehlgeschlagen für User {$user->id}: ".$e->getMessage());
}
return 0.0;
return [$snapshot['payline_points'], $snapshot['is_live']];
}
public function loadingModal()

View file

@ -2,6 +2,7 @@
namespace App\Http\Controllers;
use App\Models\Country;
use App\Models\Homeparty;
use App\Models\HomepartyUser;
use App\Models\Product;
@ -11,10 +12,12 @@ use App\Models\UserAbo;
use App\Models\UserCredit;
use App\Models\UserLevel;
use App\Models\UserSalesVolume;
use App\Services\Abo\TeamAboOverviewService;
use App\Services\AboHelper;
use App\Services\BusinessPlan\TreeCalcBot;
use App\Services\BusinessPlan\TreeCalcBotOptimized;
use App\Services\DhlModalService;
use App\Services\DhlProductResolver;
use App\User;
use Request;
@ -141,7 +144,7 @@ class ModalController extends Controller
}
if ($data['action'] === 'team-abo-member-show') {
$summary = app(\App\Services\Abo\TeamAboOverviewService::class)
$summary = app(TeamAboOverviewService::class)
->memberAboSummary(\Auth::user(), (int) $data['id']);
if ($summary) {
$ret = view('user.team.modal_member_abos', compact('summary', 'data'))->render();
@ -174,7 +177,7 @@ class ModalController extends Controller
$ret = view('admin.payment.modal_add_credit', compact('value', 'data'))->render();
}
if ($data['action'] === 'user-credit-status') {
$UserCredit = UserCredit::find($data['id']); // current user form order
$UserCredit = UserCredit::findOrFail($data['id']); // current user form order
$ret = view('admin.payment.modal_credit_status', compact('UserCredit', 'data'))->render();
}
if ($data['action'] === 'abo_update_settings') {
@ -279,12 +282,12 @@ class ModalController extends Controller
'order' => null,
'orderWeight' => 1.0,
'shippingAddress' => null,
'availableCountries' => \App\Models\Country::where('active', 1)->get(),
'availableCountries' => Country::where('active', 1)->get(),
'productCodes' => [
'V01PAK' => 'DHL Paket (National)',
'V53WPAK' => 'DHL Paket International',
],
'productSuggestions' => (new \App\Services\DhlProductResolver)->getProductSuggestionsByCountry(),
'productSuggestions' => (new DhlProductResolver)->getProductSuggestionsByCountry(),
'selectedProductCode' => 'V01PAK',
'errors' => ['Fehler beim Laden der Daten: '.$e->getMessage()],
'warnings' => [],

View file

@ -57,8 +57,12 @@ class AboController extends Controller
}
$shopping_user = ShoppingUser::findOrFail($user->shopping_user_id);
// Gekündigte/beendete Abos (Status 4/5) zählen nicht mehr als "mein Abo" —
// nach einer Kündigung muss das Portal wieder die Neuanlage anbieten (Ein-Abo-Regel, A2).
$user_abo = UserAbo::where('email', $shopping_user->billing_email)
->where('status', '>=', 1)
->whereNotIn('status', AboHelper::ENDED_STATUSES)
->orderByDesc('id')
->first();
if (! $user_abo) {
@ -110,6 +114,7 @@ class AboController extends Controller
if ($data['action'] === 'abo_update_settings') {
$user_abo = UserAbo::findOrFail($data['id']);
$this->checkPortalPermission($user_abo);
$data['view'] = 'portal';
$aboRepository = new AboRepository;
$aboRepository->setModel($user_abo);
$aboRepository->update($data);
@ -243,6 +248,7 @@ class AboController extends Controller
'summary' => $summary,
'add_only_mode' => $isAddOnlyMode,
'change_locked' => $changeLocked,
'portal_view' => true,
])->render();
$html_comp = view('user.order.comp_product', array_merge($data, [
'cart_instance' => AboOrderCart::INSTANCE,
@ -250,6 +256,7 @@ class AboController extends Controller
]))->render();
$html_summary = view('admin.abo._order_combined_summary', [
'summary' => $summary,
'portal_view' => true,
])->render();
$amount = $user_abo->getFormattedAmount();
@ -409,9 +416,11 @@ class AboController extends Controller
'only_show_products' => false,
'add_only_mode' => $isAddOnlyMode,
'change_locked' => $changeLocked,
'portal_view' => true,
])->render(),
'html_summary' => view('admin.abo._order_combined_summary', [
'summary' => $summary,
'portal_view' => true,
])->render(),
'html_comp' => view('user.order.comp_product', [
'comp_products' => [],

View file

@ -11,7 +11,6 @@ use App\Services\SyS\CleanHTMLProductDescription;
use App\Services\SyS\Correction;
use App\Services\SyS\Cronjobs;
use App\Services\SyS\Customers;
use App\Services\SyS\DomainSSL;
use App\Services\SyS\Import;
use App\Services\SyS\ImportDbipCountry;
use App\Services\SyS\PayoneCallbackTestbench;
@ -57,9 +56,6 @@ class SysController extends Controller
case 'cronjobs':
return Cronjobs::show();
break;
case 'domainssl':
return DomainSSL::show();
break;
case 'shopping_orders':
return ShoppingOrders::show();
break;
@ -115,9 +111,6 @@ class SysController extends Controller
case 'cronjobs':
return Cronjobs::store();
break;
case 'domainssl':
return DomainSSL::store();
break;
case 'shopping_orders':
return ShoppingOrders::store();
break;

View file

@ -158,7 +158,13 @@ class AboController extends Controller
if (isset($data['action'])) {
if ($data['action'] === 'abo_update_settings') {
// Body-id kann von der Route abweichen: Berechtigungen erneut auf dem
// tatsächlich bearbeiteten Abo prüfen. Die Sicht kommt ausschließlich aus
// der (bereits geprüften) Route, nie aus dem Formular — sonst ließen sich
// per view=admin sämtliche Selfservice-Regeln umgehen.
$user_abo = UserAbo::findOrFail($data['id']);
$this->checkPermissions($view, $user_abo);
$data['view'] = $view;
$this->aboRepository->setModel($user_abo);
$this->aboRepository->update($data);

View file

@ -6,6 +6,7 @@ use App\Http\Controllers\Controller;
use App\Services\Backoffice\BackofficeDashboardService;
use App\Services\Backoffice\BackofficeDrilldownService;
use App\Services\Backoffice\PersonalStatisticsService;
use App\Services\BusinessPlan\LiveCommissionService;
use App\Services\HTMLHelper;
use Illuminate\Http\Request;
use Illuminate\View\View;
@ -47,6 +48,7 @@ class BackofficeStatisticsController extends Controller
'filterYears' => HTMLHelper::getYearRange(2022),
'statistics' => $statistics,
'performance' => $performance,
'commission' => app(LiveCommissionService::class)->commission($request->user(), $selectedMonth, $selectedYear),
]);
}
@ -76,11 +78,12 @@ class BackofficeStatisticsController extends Controller
[$selectedMonth, $selectedYear] = $this->selectedPeriod($request);
$line = (int) $request->get('line', 1);
$metric = (string) $request->get('metric', 'consultants');
$onlyNew = $request->boolean('only_new');
return view('user.backoffice.statistics.details', [
'selectedMonth' => $selectedMonth,
'selectedYear' => $selectedYear,
'details' => $this->drilldownService->details($request->user(), $line, $metric, $selectedMonth, $selectedYear),
'details' => $this->drilldownService->details($request->user(), $line, $metric, $selectedMonth, $selectedYear, $onlyNew),
]);
}
@ -93,10 +96,12 @@ class BackofficeStatisticsController extends Controller
[$selectedMonth, $selectedYear] = $this->selectedPeriod($request);
$line = (int) $request->get('line', 1);
$metric = (string) $request->get('metric', 'consultants');
$details = $this->drilldownService->details($request->user(), $line, $metric, $selectedMonth, $selectedYear);
$onlyNew = $request->boolean('only_new');
$details = $this->drilldownService->details($request->user(), $line, $metric, $selectedMonth, $selectedYear, $onlyNew);
$filename = sprintf(
'backoffice-statistik-%s-linie-%s-%02d-%d.csv',
'backoffice-statistik-%s%s-linie-%s-%02d-%d.csv',
$metric,
$details['only_new'] ? '-neu' : '',
$line === 0 ? 'alle' : $line,
$selectedMonth,
$selectedYear
@ -156,7 +161,7 @@ class BackofficeStatisticsController extends Controller
private function selectedPeriod(Request $request): array
{
$selectedMonth = max(1, min(12, (int) $request->get('month', session(self::SESSION_MONTH_KEY, now()->month))));
$selectedYear = (int) $request->get('year', session(self::SESSION_YEAR_KEY, now()->year));
$selectedYear = max(2020, min((int) now()->year + 1, (int) $request->get('year', session(self::SESSION_YEAR_KEY, now()->year))));
session([
self::SESSION_MONTH_KEY => $selectedMonth,
@ -232,6 +237,10 @@ class BackofficeStatisticsController extends Controller
return ['Name', 'E-Mail', 'Karriere-Level', 'Eigenpunkte', 'Shop-Punkte', 'Abo-Punkte', 'Sonstige Punkte', 'Kundenpunkte', 'Gesamtpunkte'];
}
if ($metric === 'new_partners') {
return ['Name', 'E-Mail', 'Karriere-Level', 'Sponsor', 'Kundenpunkte', 'Aktiv seit', 'Account gueltig bis'];
}
return ['Name', 'E-Mail', 'Karriere-Level', 'Aktiv seit', 'Account gueltig bis', 'Account Status'];
}
@ -280,6 +289,18 @@ class BackofficeStatisticsController extends Controller
];
}
if ($metric === 'new_partners') {
return [
$row['name'] ?? '',
$row['email'] ?? '',
$row['career_level'] ?? '',
$row['sponsor'] ?? '',
$row['customer_points'] ?? 0,
$row['active_date'] ?? '',
$row['payment_account'] ?? '',
];
}
return [
$row['name'] ?? '',
$row['email'] ?? '',
@ -311,6 +332,10 @@ class BackofficeStatisticsController extends Controller
return ['Summe', $summary['count'].' Eintraege', '', $summary['own_points'], $summary['customer_single_order_points'], $summary['customer_abo_points'], $summary['customer_other_points'], $summary['external_points'], $summary['total_points']];
}
if ($metric === 'new_partners') {
return ['Summe', $summary['count'].' Eintraege', '', '', $summary['customer_points'], '', '', ''];
}
return ['Summe', $summary['count'].' Eintraege', '', '', '', ''];
}
}

View file

@ -4,9 +4,14 @@ namespace App\Http\Controllers\User;
use App\Exports\UserTeamExport;
use App\Http\Controllers\Controller;
use App\Models\UserAbo;
use App\Models\UserBusiness;
use App\Models\UserLevel;
use App\Models\UserSalesVolume;
use App\Services\Abo\PaylineForecastService;
use App\Services\Abo\TeamAboOverviewService;
use App\Services\AboHelper;
use App\Services\AboOrderCart;
use App\Services\BusinessPlan\ExportBot;
use App\Services\BusinessPlan\TreeCalcBot;
use App\Services\BusinessPlan\TreeCalcBotOptimized;
@ -16,6 +21,7 @@ use App\Services\LevelReportService;
use App\Services\NextLevelBadgeHelper;
use App\Services\TranslationHelper;
use App\User;
use Illuminate\Http\RedirectResponse;
use Maatwebsite\Excel\Facades\Excel;
use Request;
@ -318,6 +324,9 @@ class TeamController extends Controller
})
->addColumn('is_qual_kp', function ($teamUser) {
$user = User::find($teamUser->user_id);
if ($user === null) {
return '-';
}
return TreeHelperOptimized::generateQualKPBadgeForUser($user, $this->month, $this->year);
})
@ -652,7 +661,7 @@ class TeamController extends Controller
$currentLevel = $user->user_level;
// Lade alle aktiven User Level, sortiert nach Position
$userLevels = \App\Models\UserLevel::where('active', true)
$userLevels = UserLevel::where('active', true)
->orderBy('pos', 'asc')
->get();
@ -706,7 +715,7 @@ class TeamController extends Controller
* Konsolidierte Team-Abo-Übersicht: Abos im Team nach Ebenen/Linien gruppiert,
* inkl. Eigen-Abos, Kundenabos und neuer Abos im gewählten Monat.
*/
public function showAbos(\App\Services\Abo\TeamAboOverviewService $overviewService)
public function showAbos(TeamAboOverviewService $overviewService, PaylineForecastService $paylineService)
{
$user = User::find(\Auth::user()->id);
$now = now();
@ -725,6 +734,7 @@ class TeamController extends Controller
'growthChart' => $this->buildGrowthChart($growth),
'growthYear' => $growthYear,
'filterYears' => HTMLHelper::getYearRange(2022),
'paylineAboTurnover' => $paylineService->aboTurnover($user, (int) $now->month, (int) $now->year),
];
return view('user.team.abos', $data);
@ -767,7 +777,7 @@ class TeamController extends Controller
* (`user_abos_team_show`) eingeflossen. Diese Route bleibt für Bookmarks/Altlinks
* bestehen und leitet dauerhaft dorthin weiter.
*/
public function showTeamCustomerAbos(): \Illuminate\Http\RedirectResponse
public function showTeamCustomerAbos(): RedirectResponse
{
return redirect()->route('user_abos_team_show');
}
@ -778,7 +788,7 @@ class TeamController extends Controller
public function detailAbo($id)
{
$user = User::find(\Auth::user()->id);
$user_abo = \App\Models\UserAbo::findOrFail($id);
$user_abo = UserAbo::findOrFail($id);
// Prüfe ob das Abo zu einem Team-Mitglied gehört (effizient via Sponsor-Kette)
if (! AboHelper::isUserInTeam($user->id, $user_abo->user_id)) {
@ -786,9 +796,9 @@ class TeamController extends Controller
}
// Lade Abo-Details (ähnlich wie AboController)
\App\Services\AboOrderCart::initYard($user_abo);
$customer_detail = \App\Services\AboOrderCart::getCustomerDetail();
\App\Services\AboOrderCart::makeOrderYard($user_abo);
AboOrderCart::initYard($user_abo);
$customer_detail = AboOrderCart::getCustomerDetail();
AboOrderCart::makeOrderYard($user_abo);
$data = [
'user_abo' => $user_abo,
@ -1071,7 +1081,7 @@ class TeamController extends Controller
{
$levels = [0 => 'Alle Level'];
$userLevels = \App\Models\UserLevel::orderBy('pos')->get(['id', 'name']);
$userLevels = UserLevel::orderBy('pos')->get(['id', 'name']);
foreach ($userLevels as $level) {
$levels[$level->id] = $level->name;
}

View file

@ -1,22 +1,21 @@
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Api\KasController;
use App\Models\UserShop;
use App\Models\UserShopOnSite;
use App\Repositories\UserRepository;
use App\Services\Slim;
use Auth;
use Cviebrock\EloquentSluggable\Services\SlugService;
use Request;
use Response;
use Validator;
class UserShopController extends Controller
{
protected $db;
protected $userRepo;
public function __construct(UserRepository $userRepo)
@ -28,9 +27,9 @@ class UserShopController extends Controller
public function index()
{
$user = Auth::user();
if ($user->shop && !$user->shop->set_defaults) {
if ($user->shop && ! $user->shop->set_defaults) {
if ($user->account) {
$user->shop->title = $user->account->first_name . " " . $user->account->last_name;
$user->shop->title = $user->account->first_name.' '.$user->account->last_name;
}
if ($user->account) {
$user->shop->contact = $this->generate_contact($user);
@ -45,6 +44,7 @@ class UserShopController extends Controller
$data = [
'user' => $user,
];
return view('user.shop', $data);
}
@ -56,6 +56,7 @@ class UserShopController extends Controller
'localizations' => array_keys(config('localization.supportedLocales')),
];
return view('user.shop.translate', $data);
}
@ -64,13 +65,14 @@ class UserShopController extends Controller
$user = Auth::user();
$data = Request::all();
if (!$user->shop) {
if (! $user->shop) {
abort(404);
}
foreach ($data['trans'] as $lang => $val) {
$this->storeTranslations($user->shop, $lang, $val);
}
\Session()->flash('alert-save', true);
return redirect(route('user_shop_translate'));
}
@ -79,7 +81,7 @@ class UserShopController extends Controller
$user = Auth::user();
$data = Request::all();
if (!$user->shop) {
if (! $user->shop) {
abort(404);
}
$user->shop->title = $data['title'];
@ -100,34 +102,35 @@ class UserShopController extends Controller
$user_shop->accessibility = trim(preg_replace('/\s*\n+/', "\n", $data['accessibility']));
$user_shop->about = trim(preg_replace('/\s+/', ' ', $data['about']));
$user_shop->save();
return;
}
$trans = $user_shop->trans;
$trans[$lang]['contact'] = trim(preg_replace('/\s*\n+/', "\n", $data['contact']));
$trans[$lang]['accessibility'] = trim(preg_replace('/\s*\n+/', "\n", $data['accessibility']));
$trans[$lang]['about'] = trim(preg_replace('/\s+/', ' ', $data['about']));
$trans[$lang]['about'] = trim(preg_replace('/\s+/', ' ', $data['about']));
$user_shop->trans = $trans;
$user_shop->save();
return;
}
private function generate_contact($user)
{
$ret = "";
$ret = '';
$sep = "\n";
$ret = $user->account->street != "" ? $user->account->street : __('shop.your_street_number');
$ret .= " • ";
$ret .= $user->account->postal_code != "" ? $user->account->postal_code . " " : __('shop.your_zip_code');
$ret .= $user->account->city != "" ? $user->account->city : __('shop.your_city');
$ret = $user->account->street != '' ? $user->account->street : __('shop.your_street_number');
$ret .= ' • ';
$ret .= $user->account->postal_code != '' ? $user->account->postal_code.' ' : __('shop.your_zip_code');
$ret .= $user->account->city != '' ? $user->account->city : __('shop.your_city');
$ret .= $sep;
$pre = $user->account->pre_phone_id != "" ? $user->account->pre_phone->phone . " " : "";
$ret .= __('shop.phone') . ": " . ($user->account->phone != "" ? $pre . $user->account->phone : __('shop.your_phone_number'));
$pre = $user->account->pre_phone_id != '' ? $user->account->pre_phone->phone.' ' : '';
$ret .= __('shop.phone').': '.($user->account->phone != '' ? $pre.$user->account->phone : __('shop.your_phone_number'));
$ret .= $sep;
$pre = $user->account->pre_mobil_id != "" ? $user->account->pre_mobil->phone . " " : "";
$ret .= __('shop.mobil') . ": " . ($user->account->mobil != "" ? $pre . $user->account->mobil : __('shop.your_mobile_number'));
$pre = $user->account->pre_mobil_id != '' ? $user->account->pre_mobil->phone.' ' : '';
$ret .= __('shop.mobil').': '.($user->account->mobil != '' ? $pre.$user->account->mobil : __('shop.your_mobile_number'));
$ret .= $sep;
$ret .= $user->email;
@ -142,31 +145,32 @@ class UserShopController extends Controller
$user = Auth::user();
if (!$user->shop) {
if (! $user->shop) {
abort(404);
}
try {
$image = \App\Services\Slim::getImages('images')[0];
$image = Slim::getImages('images')[0];
if (isset($image['output']['data'])) {
// Base64 of the image
$data = $image['output']['data'];
$file_ex = array('image/jpeg' => 'jpg', 'image/png' => 'png');
$file_ex = ['image/jpeg' => 'jpg', 'image/png' => 'png'];
if (!isset($file_ex[$image['output']['type']])) {
if (! isset($file_ex[$image['output']['type']])) {
\Session()->flash('alert-danger', 'File is not jpg or png!');
return redirect(route('user_shop'));
}
$ext = $file_ex[$image['output']['type']];
// Original file name
$name = $image['output']['name'];
$name = \App\Services\Slim::sanitizeFileName($name);
$name = uniqid() . '_' . $name;
$name = Slim::sanitizeFileName($name);
$name = uniqid().'_'.$name;
$data = \Storage::disk('public')->put(
'images/shop/' . $name,
'images/shop/'.$name,
$data
);
@ -177,15 +181,16 @@ class UserShopController extends Controller
$user->shop->size = $image['input']['size'];
$user->shop->save();
\Session()->flash('alert-success', __('msg.file_uploaded'));
return redirect(route('user_shop'));
}
\Session()->flash('alert-danger', __('msg.file_empty'));
return redirect(route('user_shop'));
} catch (\Exception $e) {
\Session()->flash('alert-danger', "Error: " . $e);
\Session()->flash('alert-danger', 'Error: '.$e);
return redirect(route('user_shop'));
}
}
@ -195,12 +200,12 @@ class UserShopController extends Controller
$user = Auth::user();
if (!$user->shop) {
if (! $user->shop) {
abort(404);
}
if ($user->shop->filename) {
$file = 'images/shop/' . $user->shop->filename;
$file = 'images/shop/'.$user->shop->filename;
\Storage::disk('public')->delete($file);
$user->shop->filename = null;
@ -211,9 +216,11 @@ class UserShopController extends Controller
$user->shop->save();
\Session()->flash('alert-success', __('msg.file_deleted'));
return redirect(route('user_shop'));
}
\Session()->flash('alert-danger', __('msg.file_not_found'));
return redirect(route('user_shop'));
}
@ -223,32 +230,33 @@ class UserShopController extends Controller
$user = Auth::user();
$user_shop_id = Request::get('user_shop_id');
if (!$user->shop || $user->shop->id != $user_shop_id) {
if (! $user->shop || $user->shop->id != $user_shop_id) {
abort(404);
}
try {
$image = \App\Services\Slim::getImages('images')[0];
$image = Slim::getImages('images')[0];
if (isset($image['output']['data'])) {
// Base64 of the image
$data = $image['output']['data'];
$file_ex = array('image/jpeg' => 'jpg', 'image/png' => 'png');
$file_ex = ['image/jpeg' => 'jpg', 'image/png' => 'png'];
if (!isset($file_ex[$image['output']['type']])) {
if (! isset($file_ex[$image['output']['type']])) {
\Session()->flash('alert-danger', 'File is not jpg or png!');
return redirect(route('user_shop'));
}
$ext = $file_ex[$image['output']['type']];
// Original file name
$name = $image['output']['name'];
$name = \App\Services\Slim::sanitizeFileName($name);
$name = uniqid() . '_' . $name;
$name = Slim::sanitizeFileName($name);
$name = uniqid().'_'.$name;
$data = \Storage::disk('public')->put(
'images/user_shop/' . $user->shop->id . '/' . $name,
'images/user_shop/'.$user->shop->id.'/'.$name,
$data
);
@ -258,16 +266,19 @@ class UserShopController extends Controller
'original_name' => $image['output']['name'],
'ext' => $ext,
'mine' => $image['output']['type'],
'size' => $image['input']['size']
'size' => $image['input']['size'],
]);
\Session()->flash('alert-success', __('msg.file_uploaded'));
return redirect(route('user_shop'));
}
\Session()->flash('alert-danger', __('msg.file_empty'));
return redirect(route('user_shop'));
} catch (\Exception $e) {
\Session()->flash('alert-danger', "Error: " . $e);
\Session()->flash('alert-danger', 'Error: '.$e);
return redirect(route('user_shop'));
}
}
@ -276,74 +287,78 @@ class UserShopController extends Controller
{
$user = Auth::user();
if (!$user->shop || $user->shop->id != $user_shop_id) {
if (! $user->shop || $user->shop->id != $user_shop_id) {
abort(404);
}
$image = UserShopOnSite::findOrFail($image_id);
if ($image->user_shop_id == $user_shop_id) {
$file = 'images/user_shop/' . $user_shop_id . '/' . $image->filename;
$file = 'images/user_shop/'.$user_shop_id.'/'.$image->filename;
\Storage::disk('public')->delete($file);
$image->delete();
\Session()->flash('alert-success', __('msg.file_deleted'));
return redirect(route('user_shop'));
}
\Session()->flash('alert-danger', __('msg.file_not_found'));
return redirect(route('user_shop'));
}
public function userShopRegisterForm()
{
if (Request::get('shop_submit') == 'check') {
$rules = array(
$rules = [
'user_shop_name' => ' required|alpha_dash|unique:user_shops,name|min:4|max:20|full_word_check',
);
];
Validator::extend('full_word_check', function ($attribute, $value, $parameters, $validator) {
if (in_array($value, config('profanity.full_word_check'))) {
return false;
}
return true;
});
$validator = Validator::make(Request::all(), $rules);
if ($validator->fails()) {
\Session()->flash('shop-name-error', 'error');
return redirect()->back()->withErrors($validator)->withInput(Request::all());
}
\Session()->flash('shop-name-error', 'check');
if (Request::get('user_shop_id')) {
return back()->withInput(Request::all());
}
return redirect(route('user_shop'))->withInput(Request::all());
}
if (Request::get('shop_submit') == 'action') {
$rules = array(
$rules = [
'user_shop_name' => ' required|alpha_dash|unique:user_shops,name|min:4|max:20|full_word_check',
'user_shop_active' => 'accepted',
);
];
Validator::extend('full_word_check', function ($attribute, $value, $parameters, $validator) {
if (in_array($value, config('profanity.full_word_check'))) {
return false;
}
return true;
});
$validator = Validator::make(Request::all(), $rules);
if ($validator->fails()) {
\Session()->flash('shop-name-error', 'error');
return redirect()->back()->withErrors($validator)->withInput(Request::all());
}
\Session()->flash('shop-name-error', 'check');
//all is right - save
// all is right - save
$user = Auth::user();
$data = Request::all();
$slug = SlugService::createSlug(UserShop::class, 'slug', $data['user_shop_name']);
@ -367,93 +382,51 @@ class UserShopController extends Controller
);
}
\Session()->flash('alert-save', true);
return redirect(route('user_shop'));
/*$ret = $this->userShopRegisterSubDomain($user_shop->slug);
if($ret['success'] === true){
\Session()->flash('alert-save', true);
}else{
$user_shop->forceDelete();
\Session()->flash('alert-error', $ret['error']);
}
return redirect(route('user_shop'));*/
}
}
public function userShopRegisterSubDomain($slug)
{
$kas = new KasController();
$domain = 'mivita.care';
//check if exisist
$subdomains = $kas->action('get_subdomains');
foreach ($subdomains as $subdomain) {
if (!isset($subdomain['subdomain_name'])) {
continue;
}
$sub = str_replace("." . $domain, '', $subdomain['subdomain_name']);
if ($sub == $slug) {
return ['success' => false, 'error' => __('shop.error_subdomain_exists')];
}
}
//add
$full_subdomain_name = $slug . "." . $domain;
$pra = array(
'subdomain_name' => $slug,
'domain_name' => $domain,
'subdomain_path' => '/mein.mivita.care/public/',
'php_version' => config('app.php_version'),
//'ssl_proxy' => 'Y',
//'redirect_status' => 0
);
$add_subdomain = $kas->action('add_subdomain', $pra);
if ($add_subdomain == $full_subdomain_name) {
return ['success' => true];
}
return ['success' => false, 'error' => $add_subdomain];
}
/**
* @return string to ajax
*/
public function checkUserShopName()
{
$rules = array(
$rules = [
'user_shop_name' => ' required|alpha_dash|unique:user_shops,name|min:4|max:20|full_word_check',
);
];
Validator::extend('full_word_check', function ($attribute, $value, $parameters, $validator) {
if (in_array($value, config('profanity.full_word_check'))) {
return false;
}
return true;
});
$validator = Validator::make(Request::all(), $rules);
if ($validator->fails()) {
//$messages = $validator->messages();
return Response::json(array(
// $messages = $validator->messages();
return Response::json([
'success' => false,
'errors' => $validator->getMessageBag()->toArray()
'errors' => $validator->getMessageBag()->toArray(),
));
]);
}
$slug = SlugService::createSlug(UserShop::class, 'slug', Request::get('user_shop_name'));
return Response::json(array(
return Response::json([
'success' => true,
'preview_user_shop_name' => "https://" . $slug . "." . config('app.domain') . config('app.tld_care'),
));
'preview_user_shop_name' => 'https://'.$slug.'.'.config('app.domain').config('app.tld_care'),
]);
}
public function editName()
{
$user = Auth::user();
$user_shop = $user->shop;
if (!$user_shop) {
if (! $user_shop) {
abort(404);
}
$user_shop_domain = $user_shop->getSubdomain(false);
@ -462,6 +435,7 @@ class UserShopController extends Controller
'user_shop_id' => $user_shop->id,
'user_shop_domain' => $user_shop_domain,
];
return view('user.shop_edit_name', $data);
}
}

View file

@ -9,11 +9,43 @@ use App\Models\Product;
use App\Models\ProductCategory;
use App\Services\LocaleGuard;
use App\Services\Shop;
use App\Services\UserService;
use App\Services\Util;
use Request;
class SiteController extends Controller
{
/**
* Templates, die eigene Controller mit eigenen View-Daten haben und daher
* nicht über die Catch-all-Route ({site}/{subsite?}) gerendert werden dürfen.
*
* @var array<int, string>
*/
private const PROTECTED_TEMPLATES = [
'checkout',
'checkout-error',
'checkout-final',
'checkout-is-final',
'card',
'kontakt',
'contact-final',
'registrierung',
'registrierung_finish',
'widerruf',
'widerruf-final',
'produkte-show',
'produkte-item',
'versandkosten',
'zahlungsarten',
];
private function isRenderableTemplate(string $template): bool
{
return ! str_starts_with($template, '_')
&& ! in_array($template, self::PROTECTED_TEMPLATES, true)
&& view()->exists('web.templates.'.$template);
}
public function index()
{
$this->setIPInfo();
@ -83,7 +115,7 @@ class SiteController extends Controller
// ist default
// sprache
if (array_key_exists($country, \App\Services\UserService::getTransChange())) {
if (array_key_exists($country, UserService::getTransChange())) {
\Session::put('user_init_country', $country);
\Session::put('locale', $country);
\App::setLocale($country);
@ -177,13 +209,13 @@ class SiteController extends Controller
'yard_instance' => 'webshop',
];
if ($subsite) {
if (! view()->exists('web.templates.'.$subsite)) {
if (! $this->isRenderableTemplate($subsite)) {
abort(404);
}
return view('web.templates.'.$subsite, $data);
}
if (! view()->exists('web.templates.'.$site)) {
if (! $this->isRenderableTemplate($site)) {
abort(404);
}