HEX
Server: LiteSpeed
System: Linux s1049.use1.mysecurecloudhost.com 4.18.0-477.27.2.lve.el8.x86_64 #1 SMP Wed Oct 11 12:32:56 UTC 2023 x86_64
User: xedaptot (3356)
PHP: 8.3.31
Disabled: NONE
Upload Files
File: /home/xedaptot/be.naniguide.com/app/Http/Controllers/Refactor/Admin/CustomerController.php
<?php

namespace App\Http\Controllers\Refactor\Admin;

use App\Http\Controllers\Controller;
use App\Jobs\RefreshCacheableJob;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
use App\Model\Customer;
use App\Model\Plan;
use App\Model\Language;
use App\Model\Role;
use App\Model\User;
use App\Model\Contact;
use App\Model\Country;

class CustomerController extends Controller
{
    public function index(Request $request)
    {
        if (Gate::denies('read', new Customer())) {
            return $this->notAuthorized();
        }

        $admin = $request->user()->admin;
        $allCustomers = $admin->getAllCustomers();

        $stats = [
            'total' => (clone $allCustomers)->count(),
            'active' => (clone $allCustomers)->where('customers.status', 'active')->count(),
            'inactive' => (clone $allCustomers)->where('customers.status', 'inactive')->count(),
            'new_this_month' => (clone $allCustomers)->where('customers.created_at', '>=', now()->startOfMonth())->count(),
        ];

        return view('refactor.pages.admin.customers.index', compact('stats'));
    }

    public function listing(Request $request)
    {
        if (Gate::denies('read', new Customer())) {
            return response('Unauthorized', 403);
        }

        $admin = $request->user()->admin;
        $query = $admin->getAllCustomers();

        // Search — join users table (name/email are on users, not customers)
        if ($keyword = $request->keyword) {
            $query = $query->leftJoin('users', 'users.customer_id', '=', 'customers.id')
                ->distinct();

            foreach (explode(' ', trim($keyword)) as $word) {
                $query = $query->where(function ($q) use ($word) {
                    $q->where('users.first_name', 'like', "%{$word}%")
                      ->orWhere('users.last_name', 'like', "%{$word}%")
                      ->orWhere('users.email', 'like', "%{$word}%")
                      ->orWhere('customers.name', 'like', "%{$word}%");
                });
            }
        }

        // Status filter
        if ($request->status && $request->status !== 'all') {
            $query = $query->where('customers.status', $request->status);
        }

        // Sort
        $sortBy = $request->sort_by ?? 'customers.created_at';
        $sortDir = $request->sort_direction ?? 'desc';
        $query = $query->orderBy($sortBy, $sortDir);

        $customers = $query->paginate($request->per_page ?? 15);

        return view('refactor.pages.admin.customers._list', compact('customers'));
    }

    public function create(Request $request)
    {
        if (Gate::denies('create', new Customer())) {
            return $this->notAuthorized();
        }

        $customer = Customer::newCustomer();
        $roles = Role::active()->get();

        return view('refactor.pages.admin.customers.create', compact('customer', 'roles'));
    }

    public function store(Request $request)
    {
        if (Gate::denies('create', new Customer())) {
            return $this->notAuthorized();
        }

        list($validator, $customer, $user) = app(\App\Services\AccountManagement\AccountProvisioningService::class)->createCustomer(
            $request->user()->admin,
            $request->name,
            $request->timezone,
            $request->language_id,
            $request->email,
            $request->password,
            $request->password_confirmation,
            $request->first_name,
            $request->last_name,
            $request->image,
            $request->role_uid
        );

        if (!$validator->errors()->isEmpty()) {
            return redirect()->back()
                ->withErrors($validator)
                ->withInput();
        }

        return redirect()->route('refactor.admin.customers.index')
            ->with('success', trans('refactor/admin_customers.flash.created'));
    }

    public function edit(Request $request, $uid)
    {
        $customer = Customer::findByUid($uid);

        if (Gate::denies('update', $customer)) {
            return $this->notAuthorized();
        }

        return view('refactor.pages.admin.customers.edit', compact('customer'));
    }

    /**
     * Per-row refresh button on /admin/customers — does two different jobs of work
     * because two stale-source domains share the row:
     *
     *   1. CREDITS — `subscription_credit_state.remaining` mirrors the live file
     *      tracker `storage/app/quota/*`. Production sends decrement only the
     *      tracker; the DB row is the snapshot the UI reads. We sync it inline
     *      via `CreditsService::syncSnapshotFromTracker` (small: 1 file read +
     *      a few row UPDATEs) and return the fresh values so the JS can update
     *      the row's progress bar without a page reload.
     *
     *   2. CACHE — LocalCustomer manifest entries (SubscriberCount, EmailMetrics_*,
     *      etc.) are Laravel-cache blobs. Some of these compute over big tables
     *      and aren't safe to run inline (docs/cache §2 "no auto warm-on-miss").
     *      Dispatched as a fan-out via `RefreshCacheableJob::dispatchAll` so each
     *      entry is bounded independently.
     *
     * Response shape mirrors the customer-side `AccountController::refreshCredits`:
     * 200 + `{credits, last_synced_at}` lets `CreditRefresh.js` update credit
     * spans in place. The `cache_queued` flag tells the JS to also surface a
     * toast — "subscriber count refreshing, reload later".
     */
    public function refreshCache(Request $request, $uid)
    {
        $customer = Customer::findByUid($uid);

        if (Gate::denies('read', $customer)) {
            return $this->notAuthorized();
        }

        // Credits — inline DB-row sync (fast)
        $credits = [];
        $sub = $customer->getCurrentActiveSubscription();
        if ($sub !== null) {
            $credits = app(\App\Services\Plans\Credits\CreditsService::class)
                ->syncSnapshotFromTracker($sub);
        }

        // Cache — async fan-out (each manifest entry as its own job)
        RefreshCacheableJob::dispatchAll($customer->local());

        return response()->json([
            'credits'        => $credits,
            'last_synced_at' => now()->toIso8601String(),
            'cache_queued'   => true,
            'message'        => trans('refactor/credits.refresh_dispatched'),
        ]);
    }

    public function update(Request $request, $uid)
    {
        $customer = Customer::findByUid($uid);

        if (Gate::denies('update', $customer)) {
            return $this->notAuthorized();
        }

        $validator = $customer->updateCustomer(
            $request->name,
            $request->timezone,
            $request->language_id
        );

        if (is_object($validator) && method_exists($validator, 'fails') && $validator->fails()) {
            return redirect()->back()
                ->withErrors($validator)
                ->withInput();
        }

        // Refresh per-customer cache (subscriptions, credits) — listener: UpdateUserJob.
        event(new \App\Events\UserUpdated($customer));

        return redirect()->route('refactor.admin.customers.index')
            ->with('success', trans('refactor/admin_customers.flash.updated'));
    }

    public function select2(Request $request)
    {
        return response(Customer::select2($request))
            ->header('Content-Type', 'application/json');
    }

    public function enable(Request $request)
    {
        $uids = is_array($request->uids) ? $request->uids : explode(',', $request->uids);

        foreach ($uids as $uid) {
            $customer = Customer::findByUid($uid);
            if ($customer && Gate::allows('update', $customer)) {
                $customer->enable();
            }
        }

        return response()->json([
            'message' => trans('refactor/admin_customers.flash.enabled'),
        ]);
    }

    public function disable(Request $request)
    {
        $uids = is_array($request->uids) ? $request->uids : explode(',', $request->uids);

        foreach ($uids as $uid) {
            $customer = Customer::findByUid($uid);
            if ($customer && Gate::allows('update', $customer)) {
                $customer->disable();
            }
        }

        return response()->json([
            'message' => trans('refactor/admin_customers.flash.disabled'),
        ]);
    }

    public function delete(Request $request)
    {
        $uids = is_array($request->uids) ? $request->uids : explode(',', $request->uids);

        foreach ($uids as $uid) {
            $customer = Customer::findByUid($uid);
            if ($customer && Gate::allows('delete', $customer)) {
                $customer->deleteAccount();
            }
        }

        return response()->json([
            'message' => trans('refactor/admin_customers.flash.deleted'),
        ]);
    }

    public function loginAs(Request $request, $uid)
    {
        $customer = Customer::findByUid($uid);

        if (!$customer) {
            return redirect()->back()->with('error', 'Customer not found');
        }

        // Find first user of this customer
        $user = $customer->users()->first();
        if (!$user) {
            return redirect()->back()->with('error', 'No user found for this customer');
        }

        // Save admin user ID in session to allow login-back
        $request->session()->put('orig_admin_user_id', $request->user()->id);

        \Auth::login($user);

        return redirect()->route('refactor.dashboard');
    }

    public function loginBack(Request $request)
    {
        $adminUserId = $request->session()->get('orig_admin_user_id');

        if ($adminUserId) {
            $user = \App\Model\User::find($adminUserId);
            if ($user && $user->admin) {
                \Auth::login($user);
                $request->session()->forget('orig_admin_user_id');
                return redirect()->route('refactor.admin.dashboard');
            }
        }

        return redirect('/');
    }

    public function subscriptions(Request $request, $uid)
    {
        $customer = Customer::findByUid($uid);

        if (Gate::denies('read', $customer)) {
            return $this->notAuthorized();
        }

        $subscriptions = $customer->subscriptions()
            ->orderBy('created_at', 'desc')
            ->paginate(10);

        return view('refactor.pages.admin.customers.subscriptions', compact('customer', 'subscriptions'));
    }

    public function growthChart(Request $request)
    {
        $admin = $request->user()->admin;
        $data = [];
        $columns = [];

        for ($i = 5; $i >= 0; $i--) {
            $date = now()->subMonths($i);
            $columns[] = $date->format('m/Y');
            $data[] = Customer::customersCountByTime(
                $date->startOfMonth(),
                $date->endOfMonth(),
                $admin
            );
        }

        return response()->json([
            'columns' => $columns,
            'data' => $data,
        ]);
    }

    public function assignPlan(Request $request, $uid)
    {
        $customer = Customer::findByUid($uid);

        if (Gate::denies('assignPlan', $customer)) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }

        if ($request->isMethod('post')) {
            $plan = Plan::findByUid($request->plan_uid);
            app(\App\Services\Subscription\SubscriptionManagementService::class)
                ->assignPlan($customer, $plan);

            return response()->json([
                'message' => trans('refactor/admin_customers.flash.plan_assigned'),
            ]);
        }

        // GET — return plans list for popup
        $plans = Plan::where('status', 'active')->get();
        $currentSub = $customer->getCurrentActiveSubscription();

        return view('refactor.pages.admin.customers._assign_plan', compact('customer', 'plans', 'currentSub'));
    }

    public function contact(Request $request, $uid)
    {
        $customer = Customer::findByUid($uid);

        if (Gate::denies('update', $customer)) {
            return $this->notAuthorized();
        }

        $contact = $customer->contact ?? new Contact();
        $countries = Country::getSelectOptions();

        return view('refactor.pages.admin.customers.contact', compact('customer', 'contact', 'countries'));
    }

    public function contactUpdate(Request $request, $uid)
    {
        $customer = Customer::findByUid($uid);

        if (Gate::denies('update', $customer)) {
            return $this->notAuthorized();
        }

        $validator = \Validator::make($request->all(), Contact::$rules);

        if ($validator->fails()) {
            return redirect()->back()
                ->withErrors($validator)
                ->withInput();
        }

        $contact = $customer->contact ?? new Contact();
        $contact->fill($request->only([
            'first_name', 'last_name', 'company', 'phone', 'email',
            'zip', 'state', 'city', 'address_1', 'address_2',
            'country_id', 'url', 'tax_number', 'billing_address',
        ]));
        $contact->save();

        if (!$customer->contact_id) {
            $customer->contact_id = $contact->id;
            $customer->save();
        }

        return redirect()->route('refactor.admin.customers.contact', $customer->uid)
            ->with('success', trans('refactor/admin_customers.flash.contact_updated'));
    }

    public function oneClickLogin(Request $request, $uid)
    {
        $customer = Customer::findByUid($uid);

        if (!$customer) {
            return response('Customer not found', 404);
        }

        // If user_uid is provided, use that specific user; otherwise use first user
        if ($request->user_uid) {
            $user = User::findByUid($request->user_uid);
        } else {
            $user = $customer->users()->first();
        }

        if (!$user) {
            return response('User not found', 404);
        }

        $url = $user->generateOneClickLoginUrl();

        return view('refactor.pages.admin.customers._one_click_login', compact('url'));
    }

    public function users(Request $request, $uid)
    {
        $customer = Customer::findByUid($uid);

        if (Gate::denies('read', $customer)) {
            return $this->notAuthorized();
        }

        return view('refactor.pages.admin.customers.users', compact('customer'));
    }

    public function usersListing(Request $request, $uid)
    {
        $customer = Customer::findByUid($uid);

        if (Gate::denies('read', $customer)) {
            return response('Unauthorized', 403);
        }

        $query = $customer->users();

        // Search
        if ($keyword = $request->keyword) {
            $query = $query->where(function ($q) use ($keyword) {
                $q->where('users.first_name', 'like', "%{$keyword}%")
                  ->orWhere('users.last_name', 'like', "%{$keyword}%")
                  ->orWhere('users.email', 'like', "%{$keyword}%");
            });
        }

        // Status filter
        if ($request->status && $request->status !== 'all') {
            if ($request->status === 'active') {
                $query = $query->where('users.activated', true);
            } elseif ($request->status === 'inactive') {
                $query = $query->where('users.activated', false);
            }
        }

        $query = $query->orderBy('users.created_at', 'desc');
        $users = $query->paginate($request->per_page ?? 15);

        return view('refactor.pages.admin.customers._users_list', compact('customer', 'users'));
    }

    public function userCreate(Request $request, $uid)
    {
        $customer = Customer::findByUid($uid);

        if (Gate::denies('update', $customer)) {
            return $this->notAuthorized();
        }

        $user = new User();
        $roles = Role::active()->get();

        return view('refactor.pages.admin.customers.user_form', compact('customer', 'user', 'roles'));
    }

    public function userStore(Request $request, $uid)
    {
        $customer = Customer::findByUid($uid);

        if (Gate::denies('update', $customer)) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }

        $validator = \Validator::make($request->all(), [
            'email' => 'required|email|unique:users,email',
            'password' => 'required|min:6|confirmed',
            'first_name' => 'nullable|string|max:255',
            'last_name' => 'nullable|string|max:255',
        ]);

        if ($validator->fails()) {
            if ($request->ajax()) {
                return response()->json(['errors' => $validator->errors()], 422);
            }
            return redirect()->back()
                ->withErrors($validator)
                ->withInput();
        }

        $user = new User();
        $user->email = $request->email;
        $user->first_name = $request->first_name;
        $user->last_name = $request->last_name;
        $user->password = bcrypt($request->password);
        $user->customer_id = $customer->id;
        $user->activated = true;
        $user->save();

        if ($request->role_uid) {
            $role = Role::findByUid($request->role_uid);
            if ($role) {
                $user->setRole($role);
            }
        }

        // Handle image upload
        if ($request->hasFile('image')) {
            $user->uploadProfileImage($request->file('image'));
        }

        if ($request->ajax()) {
            return response()->json([
                'message' => trans('refactor/admin_customers.flash.user_created'),
            ]);
        }

        return redirect()->route('refactor.admin.customers.users', $customer->uid)
            ->with('success', trans('refactor/admin_customers.flash.user_created'));
    }

    public function userEdit(Request $request, $uid, $user_uid)
    {
        $customer = Customer::findByUid($uid);

        if (Gate::denies('update', $customer)) {
            return $this->notAuthorized();
        }

        $user = User::findByUid($user_uid);
        $roles = Role::active()->get();

        return view('refactor.pages.admin.customers.user_form', compact('customer', 'user', 'roles'));
    }

    public function userUpdate(Request $request, $uid, $user_uid)
    {
        $customer = Customer::findByUid($uid);

        if (Gate::denies('update', $customer)) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }

        $user = User::findByUid($user_uid);

        $rules = [
            'email' => 'required|email|unique:users,email,' . $user->id,
            'first_name' => 'nullable|string|max:255',
            'last_name' => 'nullable|string|max:255',
        ];

        if ($request->password) {
            $rules['password'] = 'min:6|confirmed';
        }

        $validator = \Validator::make($request->all(), $rules);

        if ($validator->fails()) {
            if ($request->ajax()) {
                return response()->json(['errors' => $validator->errors()], 422);
            }
            return redirect()->back()
                ->withErrors($validator)
                ->withInput();
        }

        $user->email = $request->email;
        $user->first_name = $request->first_name;
        $user->last_name = $request->last_name;

        if ($request->password) {
            $user->password = bcrypt($request->password);
        }

        $user->save();

        if ($request->role_uid) {
            $role = Role::findByUid($request->role_uid);
            if ($role) {
                $user->setRole($role);
            }
        } else {
            // Remove current role if any
            $currentRole = $user->getRole();
            if ($currentRole) {
                $user->roles()->detach($currentRole);
            }
        }

        // Handle image upload
        if ($request->hasFile('image')) {
            $user->uploadProfileImage($request->file('image'));
        }

        if ($request->ajax()) {
            return response()->json([
                'message' => trans('refactor/admin_customers.flash.user_updated'),
            ]);
        }

        return redirect()->route('refactor.admin.customers.users', $customer->uid)
            ->with('success', trans('refactor/admin_customers.flash.user_updated'));
    }

    public function usersEnable(Request $request, $uid)
    {
        $customer = Customer::findByUid($uid);

        if (Gate::denies('update', $customer)) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }

        $uids = is_array($request->uids) ? $request->uids : explode(',', $request->uids);

        foreach ($uids as $userUid) {
            $user = User::findByUid($userUid);
            if ($user && $user->customer_id == $customer->id) {
                $user->enable();
            }
        }

        return response()->json([
            'message' => trans('refactor/admin_customers.flash.users_enabled'),
        ]);
    }

    public function usersDisable(Request $request, $uid)
    {
        $customer = Customer::findByUid($uid);

        if (Gate::denies('update', $customer)) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }

        $uids = is_array($request->uids) ? $request->uids : explode(',', $request->uids);

        foreach ($uids as $userUid) {
            $user = User::findByUid($userUid);
            if ($user && $user->customer_id == $customer->id) {
                $user->disable();
            }
        }

        return response()->json([
            'message' => trans('refactor/admin_customers.flash.users_disabled'),
        ]);
    }

    public function usersDelete(Request $request, $uid)
    {
        $customer = Customer::findByUid($uid);

        if (Gate::denies('update', $customer)) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }

        $uids = is_array($request->uids) ? $request->uids : explode(',', $request->uids);

        foreach ($uids as $userUid) {
            $user = User::findByUid($userUid);
            if ($user && $user->customer_id == $customer->id) {
                $user->deleteAndCleanup();
            }
        }

        return response()->json([
            'message' => trans('refactor/admin_customers.flash.users_deleted'),
        ]);
    }

    public function userLoginAs(Request $request, $uid, $user_uid)
    {
        $customer = Customer::findByUid($uid);

        if (!$customer) {
            return redirect()->back()->with('error', 'Customer not found');
        }

        $user = User::findByUid($user_uid);

        if (!$user || $user->customer_id != $customer->id) {
            return redirect()->back()->with('error', 'User not found');
        }

        // Save admin user ID in session to allow login-back
        $request->session()->put('orig_admin_user_id', $request->user()->id);

        \Auth::login($user);

        return redirect()->route('refactor.dashboard');
    }
}