diff --git a/app/Http/Controllers/admin/CustomerController.php b/app/Http/Controllers/admin/CustomerController.php index bcf549d..33d7876 100644 --- a/app/Http/Controllers/admin/CustomerController.php +++ b/app/Http/Controllers/admin/CustomerController.php @@ -27,6 +27,7 @@ use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Validator; use Illuminate\Support\Str; +use Yajra\DataTables\Facades\DataTables; class CustomerController extends Controller @@ -120,7 +121,7 @@ class CustomerController extends Controller return redirect()->route('customer.index')->withErrors('No data found for this user'); } - $title = "#" . $customer->id . " " . $customer->firstname . " " . $customer->lastname; + $title = "#" . $customer->id . " " . $customer->fullname; return view("administrator.pages.customer.info", compact('customer', 'title', 'userid')); } @@ -156,7 +157,7 @@ class CustomerController extends Controller return redirect()->route('customer.index')->withErrors('No data found for this user'); } - $title = "#" . $customer->id . " " . $customer->firstname . " " . $customer->lastname; + $title = "#" . $customer->id . " " . $customer->fullname; return view("administrator.pages.customer.profile", compact('customer', 'title', 'userid')); } @@ -174,7 +175,7 @@ class CustomerController extends Controller //validate data after validate userid $request->validate([ - 'firstname' => 'required', + 'fullname' => 'required', 'email' => 'required' ]); //find user @@ -307,7 +308,7 @@ class CustomerController extends Controller break; } - $title = "#" . $customer->id . " " . $customer->firstname . " " . $customer->lastname; + $title = "#" . $customer->id . " " . $customer->fullname; return view( 'administrator.pages.customer.product', compact( @@ -428,7 +429,7 @@ class CustomerController extends Controller ['customer'] ); - $title = "#" . $customer->id . " " . $customer->firstname . " " . $customer->lastname; + $title = "#" . $customer->id . " " . $customer->fullname; return view('administrator.pages.customer.domain', compact('userid', 'title', 'domains')); } @@ -461,7 +462,7 @@ class CustomerController extends Controller ); - $title = "#" . $customer->id . " " . $customer->firstname . " " . $customer->lastname; + $title = "#" . $customer->id . " " . $customer->fullname; return view('administrator.pages.customer.invoice', compact('userid', 'title', 'invoices')); } @@ -490,7 +491,7 @@ class CustomerController extends Controller ] ); - $title = "#" . $customer->id . " " . $customer->firstname . " " . $customer->lastname; + $title = "#" . $customer->id . " " . $customer->fullname; return view('administrator.pages.customer.transaction', compact('userid', 'title', 'transactions')); } @@ -517,7 +518,7 @@ class CustomerController extends Controller ] ); - $title = "#" . $customer->id . " " . $customer->firstname . " " . $customer->lastname; + $title = "#" . $customer->id . " " . $customer->fullname; if (isset($request->email_id)) { $template = $this->mailRepository->find($request->get('email_id')); @@ -550,7 +551,7 @@ class CustomerController extends Controller 'page' => $request->get('page') ?? 1 ], ['customer']); - $title = "#" . $customer->id . " " . $customer->firstname . " " . $customer->lastname; + $title = "#" . $customer->id . " " . $customer->fullname; return view('administrator.pages.customer.log', compact('userid', 'title', 'logs')); } @@ -726,4 +727,24 @@ class CustomerController extends Controller Auth::guard('users')->logout(); return redirect()->route('customer.index'); } + + public function datatable(Request $request) + { + $query = $this->customerRepository->filter( + $request->all(), + [], + ['hosting', 'vps', 'domain'], + ['*'], + true + ); + + return DataTables::eloquent($query) + ->addColumn( + 'action', + function ($d) { + return view('administrator.pages.customer.datatable.action', ['row' => $d])->render(); + } + ) + ->make(true); + } } diff --git a/app/Http/Controllers/frontend/CartController.php b/app/Http/Controllers/frontend/CartController.php deleted file mode 100644 index 5a7747a..0000000 --- a/app/Http/Controllers/frontend/CartController.php +++ /dev/null @@ -1,713 +0,0 @@ -cart(customer()?->id); - $title = "Giỏ hàng"; - - return view("frontend.cart.index", compact('cartItems', 'title')); - } - - public function addCart(Request $request) - { - $userId = customer()?->id; - - if (!$userId) { - return back()->with('error', 'Bạn cần đăng nhập để thêm sản phẩm vào giỏ hàng.'); - } - - // Get request data - $productId = $request->product_id; - $typeId = $request->type_id; // Can be null for new Product system - $months = $request->input('months'); - $billingCycle = $request->input('billing_cycle'); // New: billing cycle - $productPrice = $request->input('product_price'); // Price from form - - // Validate basic input - if (!$productId) { - return back()->with('error', 'Sản phẩm không hợp lệ.'); - } - - try { - // Check if this is new Product system or legacy (Hosting/VPS) - $product = Product::find($productId); - - if ($product) { - // NEW FLOW: Using Product table - $pricingId = null; - $finalPrice = $productPrice; - - // Find the pricing based on billing_cycle - if ($billingCycle) { - $pricing = ProductPricings::where('product_id', $productId) - ->where('billing_cycle', $billingCycle) - ->where('is_active', 1) - ->first(); - - if ($pricing) { - $pricingId = $pricing->id; - $finalPrice = $pricing->price_sale ?: $pricing->price; - } - } - - // Add to cart - CartModel::updateOrCreate( - ['customer_id' => $userId], - [ - 'product_id' => $productId, - 'type_product' => null, // New system doesn't use type_product - 'months' => $months, - 'billing_cycle' => $billingCycle, - 'product_pricing_id' => $pricingId, - 'price' => $finalPrice, - 'quantity' => 1, - ] - ); - - return redirect()->route('cart.index')->with('success', 'Sản phẩm đã được thêm vào giỏ hàng!'); - } else { - // LEGACY FLOW: Using old Hosting/VPS system - if (!$typeId || !$months) { - return back()->with('error', 'Dữ liệu không hợp lệ.'); - } - - CartModel::updateOrCreate( - ['customer_id' => $userId], - [ - 'product_id' => $productId, - 'type_product' => $typeId, - 'months' => $months, - 'price' => $productPrice, - ] - ); - - return redirect()->route('cart.index')->with('success', 'Sản phẩm đã được thêm vào giỏ hàng!'); - } - } catch (\Exception $e) { - Log::error('Cart add error: ' . $e->getMessage(), [ - 'user_id' => $userId, - 'product_id' => $productId, - 'type_id' => $typeId, - 'billing_cycle' => $billingCycle ?? null, - 'trace' => $e->getTraceAsString() - ]); - return back()->with('error', 'Có lỗi xảy ra khi thêm sản phẩm vào giỏ hàng.'); - } - } - - public function store(Request $request, Cart $cart) - { - $validator = null; - $allOrderItem = []; - if ($request->vps) { - $validator = Validator::make( - $request->all(), - [ - 'vps.*.os_id' => 'required', - 'vps.*.os_version_id' => 'required', - 'vps.*.time_buy' => 'required', - 'vps.*.hostname' => 'required' - ], - [ - 'vps.*.os_id' => [ - 'required' => 'Vui lòng chọn hệ điều hành cần cài đặt!' - ], - 'vps.*.os_version_id' => [ - 'required' => 'Vui lòng chọn version cần cài đặt!' - ], - 'vps.*.hostname' => [ - 'required' => 'Vui lòng nhập hostname!' - ] - ] - ); - - foreach ($request->vps as $_key => $_item) { - $product = $cart->getItem(customer()?->id, $_key); - if ($product) { - $allOrderItem[] = [ - 'data' => $_item, - 'product' => $product - ]; - } - } - } - if ($request->hosting) { - $validator = Validator::make( - $request->all(), - [ - 'hosting.*.time_buy' => 'required', - 'hosting.*.domain' => 'required' - ], - [ - 'hosting.*.domain' => [ - 'required' => 'Vui lòng nhập tên miền để kích hoạt Hosting!' - ], - 'hosting.*.time_buy' => [ - 'required' => 'Vui lòng chọn thời gian thanh toán!' - ], - ] - ); - $regexFilterDomain = '/(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]/m'; - - foreach ($request->hosting as $_key => $_item) { - $filter = filter_var( - $request->hosting[$_key]['domain'], - FILTER_VALIDATE_REGEXP, - [ - 'options' => [ - 'regexp' => $regexFilterDomain - ] - ] - ); - - if ($filter === false) { - return back()->with($request->except(['_token']))->withErrors("Tên miền không hợp lệ"); - } - } - foreach ($request->hosting as $_key => $_item) { - $product = $cart->getItem(customer()?->id, $_key); - if ($product) { - $allOrderItem[] = [ - 'data' => $_item, - 'product' => $product - ]; - } - } - } - - if ($validator && $validator->fails()) { - return back()->with($request->except(['_token']))->withErrors($validator); - } - - - if (!count($allOrderItem)) { - return back()->with($request->except('_token'))->withErrors("Yêu cầu không hợp lệ"); - } - - $relid_data = []; - - foreach ($allOrderItem as $key => $item) { - $relid_code = Helper::generateUniqueCode(); - $product = null; - $relid_data[$key]['code'] = $relid_code; - $relid_data[$key]['data'] = [ - 'customer_id' => customer()?->id, - 'status' => 3 - ]; - - switch ($item['product']['product_type']) { - case 3: - $product = Hosting::find($item['product']['product']); - $relid_data[$key]['data']['name'] = $item['data']['domain']; - $relid_data[$key]['type'] = 3; - break; - case 4: - $product = VPS::find($item['product']['product']); - $relid_data[$key]['data']['hostname'] = $item['data']['hostname']; - $relid_data[$key]['data']['os_id'] = $item['data']['os_version_id']; - $relid_data[$key]['type'] = 4; - break; - } - - $subMessage = ""; - - $billing = 0; - - switch ($item['data']['time_buy']) { - case 1: - $billing = 2; - $subMessage = " ( " . Carbon::today()->format('d/m/Y') . " - " . Carbon::today()->addMonths(1)->format('d/m/Y') . " )"; - $relid_data[$key]['data']['next_due_date'] = Carbon::today()->addMonths(1)->timestamp; - $relid_data[$key]['data']['next_invoice'] = Carbon::today()->addMonths(1)->timestamp; - break; - case 3: - $billing = 3; - $subMessage = " ( " . Carbon::today()->format('d/m/Y') . " - " . Carbon::today()->addMonths(3)->format('d/m/Y') . " )"; - $relid_data[$key]['data']['next_due_date'] = Carbon::today()->addMonths(3)->timestamp; - $relid_data[$key]['data']['next_invoice'] = Carbon::today()->addMonths(3)->timestamp; - break; - case 6: - $billing = 4; - $subMessage = " ( " . Carbon::today()->format('d/m/Y') . " - " . Carbon::today()->addMonths(6)->format('d/m/Y') . " )"; - $relid_data[$key]['data']['next_due_date'] = Carbon::today()->addMonths(6)->timestamp; - $relid_data[$key]['data']['next_invoice'] = Carbon::today()->addMonths(6)->timestamp; - break; - case 12: - $billing = 5; - $subMessage = " ( " . Carbon::today()->format('d/m/Y') . " - " . Carbon::today()->addMonths(12)->format('d/m/Y') . " )"; - $relid_data[$key]['data']['next_due_date'] = Carbon::today()->addMonths(12)->timestamp; - $relid_data[$key]['data']['next_invoice'] = Carbon::today()->addMonths(12)->timestamp; - break; - } - $totalAddon = 0; - - $message = $product->name; - - - $product_item[] = [ - 'customer_id' => customer()?->id, - 'type_id' => $item['product']['product_type'], - 'product_id' => $item['product']['product'], - 'description' => $message . $subMessage, - 'amount' => $item['product']['price'] * $item['data']['time_buy'], - 'billing' => $billing, - 'invoice_type' => 1, - 'tax' => 1, - 'parent_id' => 0, - 'code' => $relid_code, - 'due_date' => Carbon::today()->hour(23)->minute(59)->second(59)->timestamp, - ]; - - if (isset($item['data']['addon'])) { - foreach ($item['data']['addon'] as $_key => $_sub) { - $productAddon = Addon::where('name', 'like', "%$_key%")->first(); - $message = "Addon " . $productAddon->name; - if ($_sub['value']) { - $totalAddon += $_sub['price'] * $_sub['value'] * $item['data']['time_buy']; - $product_item[$key]['addon'][] = [ - 'customer_id' => customer()?->id, - 'type_id' => $productAddon->type_id, - 'product_id' => $productAddon->id, - 'description' => $message . $subMessage, - 'amount' => $_sub['price'] * $_sub['value'] * $item['data']['time_buy'], - 'billing' => $billing, - 'invoice_type' => 1, - 'tax' => 1, - 'due_date' => Carbon::today()->hour(23)->minute(59)->second(59)->timestamp, - ]; - } - } - } - - $relid_data[$key]['data']['first_payment'] = $item['product']['price'] * $item['data']['time_buy'] + $totalAddon; - $relid_data[$key]['data']['next_payment'] = $item['product']['price'] * $item['data']['time_buy'] + $totalAddon; - } - - $allOrderItemWithAddon = array_map(function ($item) { - $codeCheckAddon = Helper::generateUniqueCode(); - $item['addon_code'] = $codeCheckAddon; - return $item; - }, $product_item); - - $addonArray = []; - - foreach ($allOrderItemWithAddon as $item) { - if (isset($item['addon'])) { - foreach ($item['addon'] as $_Sub) { - $_Sub['parent'] = $item['addon_code']; - $addonArray[] = $_Sub; - } - } - } - - $allOrderItemWithAddon = array_map(function ($item) { - if (isset($item['addon'])) { - unset($item['addon']); - } - return $item; - }, array_merge($addonArray, $allOrderItemWithAddon)); - - $total = array_sum(array_map(function ($item) { - return $item['amount']; - }, $allOrderItemWithAddon)); - - $discount = 0; - - $discount_value = 0; - - if (session('coupon')) { - $discount = session('coupon')['coupon_id']; - switch (session('coupon')['coupon_type']) { - case 1: - $discount_value = (int) ((session('coupon')['coupon_value'] / 100) * $total); - $total -= $discount_value; - break; - case 2: - $discount_value = (int) session('coupon')['coupon_value']; - $total -= $discount_value; - break; - } - } - - try { - DB::beginTransaction(); - $invoice_data = [ - 'date' => Carbon::today()->timestamp, - 'due_date' => Carbon::today()->hour(23)->minute(59)->second(59)->timestamp, - 'sub_total' => $total, - 'tax' => $total * (10 / 100), - 'total' => $total + ($total * (10 / 100)), - 'payment_id' => 1, - 'customer_id' => customer()?->id, - 'status' => 0 - ]; - $invoice_id = Invoice::insertGetId($invoice_data); - - $allOrderItemWithAddon = array_map(function ($array) use ($invoice_id) { - $array['invoice_id'] = $invoice_id; - return $array; - }, $allOrderItemWithAddon); - - $order_item = [ - 'order_num' => Helper::generateUniqueCode(), - 'customer_id' => customer()?->id, - 'date' => Carbon::today()->timestamp, - 'invoice_id' => $invoice_id, - 'discount_id' => $discount, - 'discount_value' => $discount_value, - 'amount' => $total + ($total * (10 / 100)), - 'payment_id' => 1, - 'user_id' => 0, - 'status' => 0, - 'client_ip' => $request->getClientIp() - ]; - - $order = Order::insertGetId($order_item); - - $relid_data = array_map(function ($array) use ($order) { - $array['data']['order_id'] = $order; - return $array; - }, $relid_data); - - $relid = []; - //insert + get id for item auto created by module - foreach ($relid_data as $item) { - $code = $item['code']; - - switch ($item['type']) { - case 3: - $relid_id = ModuleHosting::insertGetId($item['data']); - $relid[$code] = $relid_id; - break; - case 4: - $relid_id = ModuleVmware::insertGetId($item['data']); - $relid[$code] = $relid_id; - break; - } - - } - - $allInvoiceItem = array_map(function ($array) use ($relid) { - if (isset($array['code']) && array_key_exists($array['code'], $relid)) { - $array['relid'] = $relid[$array['code']]; - - } else { - $array['relid'] = 0; - } - unset($array['code']); - - return $array; - - }, $allOrderItemWithAddon); - - $productNoAddon = array_values(array_filter($allInvoiceItem, function ($item) { - if (isset($item['addon_code'])) { - return $item; - } - })); - $productAddon = array_values(array_filter($allInvoiceItem, function ($item) { - if (!isset($item['addon_code'])) { - return $item; - } - })); - - $allProduct = []; - - foreach ($productNoAddon as $item) { - foreach ($productAddon as $_sub) { - if ($item['addon_code'] === $_sub['parent']) { - $_Sub['parent_id'] = $item['relid']; - - $_sub['parent_id'] = $item['relid']; - unset($_sub['parent']); - $allProduct[] = $_sub; - } - } - if (isset($item['addon_code'])) { - unset($item['addon_code']); - } - $allProduct[] = $item; - } - - InvoiceItem::insert($allProduct); - - $last_id = InvoiceItem::latest('id')->limit(count($allProduct))->select('id')->get()->toArray(); - - $Order__order_item = array_map(function ($array) use ($order) { - return [ - 'order_id' => $order, - 'InvoiceItem_id' => $array['id'] - ]; - }, $last_id); - - DB::table('order__order_item')->insert($Order__order_item); - - - - Log::create([ - 'agent' => $request->userAgent(), - 'client_ip' => $request->getClientIp(), - 'username' => "System", - 'description' => customer()?->firstname . " created new Order with Order id: " . $order, - 'customer_id' => customer()?->id - ]); - if (session('coupon')) { - Discount::find(session('coupon')['coupon_id'])->increment('use', 1); - } - DB::commit(); - - } catch (Exception $exception) { - DB::rollBack(); - return back()->with($request->except(['_token']))->withErrors($exception->getMessage()); - } - session()->forget('cart'); - session()->forget('coupon'); - return redirect()->route('invoice.show', ['invoice_id' => $invoice_id])->with('sucess', 'Đặt hàng thành công'); - } - - - - - public function destroy(Request $request, Cart $cart) - { - $validator = Validator::make( - $request->all(), - [ - 'cart_id' => 'required' - ], - [ - 'cart_id' => [ - 'required' => 'Yêu cầu không hợp lệ' - ] - ] - ); - if ($validator->fails()) { - return back()->withErrors($validator); - } - - $status = $cart->removeCartItem(customer()?->id, $request->cart_id); - - if ($status) { - return back()->with('success', 'Xoá thông tin đơn hàng thành công'); - } - return back()->withErrors('Yêu cầu không hợp lệ'); - } - - public function applyCoupon(Request $request) - { - $validator = Validator::make( - $request->all(), - [ - 'promotion_code' => 'required' - ], - [ - 'promotion_code' => [ - 'required' => 'Mã giảm giá không được để trống' - ] - ] - ); - if ($validator->fails()) { - return redirect() - ->route('cart') - ->with($request->except(['_token'])) - ->withErrors($validator); - } - $Coupon = Discount::where('code', $request->promotion_code)->first(); - if (!$Coupon) { - return redirect() - ->route('cart') - ->with($request->except(['_token'])) - ->withErrors("Mã giảm giá không hợp lệ"); - } - if ($Coupon->status === 0) { - return redirect() - ->route('cart') - ->with($request->except(['_token'])) - ->withErrors("Mã giảm giá không hợp lệ"); - } - if ($Coupon->end < Carbon::today()->timestamp) { - return redirect() - ->route('cart') - ->with($request->except(['_token'])) - ->withErrors("Mã giảm giá đã hết hạn sử dụng"); - } - if ($Coupon->start > Carbon::today()->timestamp) { - return redirect() - ->route('cart') - ->with($request->except(['_token'])) - ->withErrors("Mã giảm giá không hợp lệ"); - } - if ($Coupon->use === $Coupon->count) { - return redirect() - ->route('cart') - ->with($request->except(['_token'])) - ->withErrors("Mã giảm giá đã đạt giới hạn số lượng cho phép"); - } - $couponAdded = [ - 'coupon_value' => $Coupon->discount, - 'coupon_type' => $Coupon->type, - 'coupon_code' => $Coupon->code, - 'coupon_id' => $Coupon->id - ]; - session()->put('coupon', $couponAdded); - return redirect() - ->route('cart') - ->with($request->except(['_token'])) - ->with('success', 'Áp dụng mã giảm thành công!'); - } - - public function addon(Request $request) - { - $validator = Validator::make($request->all(), [ - 'product' => 'required|not__in:0' - ], ['product.required' => 'Yêu cầu không hợp lệ']); - - if ($validator->fails()) { - return response()->json(['error' => true, 'message' => $validator]); - } - - $count = 0; - $sumAddon = 0; - $addOn = []; - $billing = 0; - if ($request->addon) { - $i = 0; - foreach ($request->addon as $key => $item) { - if ($item['quantity'] != 0) { - $product = Addon::where('name', 'like', "%$key%")->first(); - $addOn[$i] = [ - 'customer_id' => customer()?->id, - 'type_id' => 1, - 'due_date' => Carbon::today()->hour(23)->minute(59)->second(59)->timestamp, - 'product_id' => $product->id, - 'parent_id' => $request->product, - 'relid' => 0, - 'invoice_type' => "1", - 'billing' => $request->billing, - 'amount' => $item['price'] * $item['quantity'], - 'tax' => 1, - ]; - $message = "Addon " . strtoupper($key); - switch ($request->billing) { - case 2: - $billing = 1; - $message .= " ( " . Carbon::today()->format('d/m/Y') . " - " . Carbon::today()->addMonths(1)->format('d/m/Y') . " )"; - break; - case 3: - $billing = 3; - $message .= " ( " . Carbon::today()->format('d/m/Y') . " - " . Carbon::today()->addMonths(3)->format('d/m/Y') . " )"; - break; - case 4: - $billing = 6; - $message .= " ( " . Carbon::today()->format('d/m/Y') . " - " . Carbon::today()->addMonths(6)->format('d/m/Y') . " )"; - - break; - case 5: - $billing = 12; - $message .= " ( " . Carbon::today()->format('d/m/Y') . " - " . Carbon::today()->addMonths(12)->format('d/m/Y') . " )"; - break; - } - $addOn[$i]['description'] = $message; - } - if ($item['quantity'] == 0) { - ++$count; - } - $sumAddon += $item['price'] * $item['quantity']; - $i++; - } - } - - $sumAddon *= $billing; - - if ($count === 3) { - return response()->json(['error' => true, 'message' => 'Vui lòng chọn một addon để nâng cấp cấu hình!']); - } - - $product = ModuleVmware::with('Order')->find($request->product); - - if (!$product) { - return response()->json(['error' => true, 'message' => 'Yêu cầu không hợp lệ']); - } - - $invoice_data = [ - 'date' => Carbon::today()->timestamp, - 'due_date' => Carbon::today()->hour(23)->minute(59)->second(59)->timestamp, - 'sub_total' => $sumAddon, - 'tax' => $sumAddon * (10 / 100), - 'total' => $sumAddon + ($sumAddon * (10 / 100)), - 'payment_id' => 1, - 'customer_id' => customer()?->id, - 'status' => 0 - ]; - - try { - DB::beginTransaction(); - $invoice = Invoice::insertGetId($invoice_data); - - - - $order = [ - 'order_num' => Helper::generateUniqueCode(), - 'customer_id' => customer()?->id, - 'date' => Carbon::today()->timestamp, - 'invoice_id' => $invoice, - 'discount_id' => 0, - 'discount_value' => 0, - 'amount' => $sumAddon + ($sumAddon * (10 / 100)), - 'payment_id' => 1, - 'user_id' => 0, - 'status' => 0, - 'client_ip' => $request->getClientIp() - ]; - $order_id = Order::insertGetId($order); - $AddonItem = array_map(function ($item) use ($invoice) { - $item['invoice_id'] = $invoice; - return $item; - }, $addOn); - - InvoiceItem::insert($AddonItem); - - $Order_item = InvoiceItem::select('id')->latest('id')->limit(count($AddonItem))->get(); - - foreach ($Order_item as $item) { - DB::table('order__order_item')->insert([ - 'InvoiceItem_id' => $item->id, - 'order_id' => $order_id - ]); - } - DB::commit(); - } catch (Exception $exception) { - DB::rollBack(); - return response()->json(['error' => true, 'message' => $exception->getMessage()]); - } - return response()->json(['error' => false, 'message' => 'Order thành công. Vui lòng thanh toán để tiến hành nâng cấp!']); - } -} diff --git a/app/Http/Controllers/frontend/CustomerLogController.php b/app/Http/Controllers/frontend/CustomerLogController.php deleted file mode 100644 index d93088d..0000000 --- a/app/Http/Controllers/frontend/CustomerLogController.php +++ /dev/null @@ -1,19 +0,0 @@ -id())->paginate(15); - - return view('frontend.logs',compact('title','logs')); - } -} diff --git a/app/Http/Controllers/frontend/DomainController.php b/app/Http/Controllers/frontend/DomainController.php deleted file mode 100644 index e935209..0000000 --- a/app/Http/Controllers/frontend/DomainController.php +++ /dev/null @@ -1,15 +0,0 @@ -invoiceRepository->findWithRelationships($order_num, [ - 'order', - 'invoiceItem.addons', - 'invoiceItem.os.osGroup', - 'customer' - ]); - - // Log để debug - if (!$invoice) { - Log::warning('Invoice not found', [ - 'invoice_id' => $invoice_id, - 'order_num' => $order_num, - 'user_id' => customer()?->id ?? 'guest' - ]); - } else { - // Kiểm tra quyền truy cập - chỉ cho phép customer xem invoice của chính mình - $currentCustomer = customer(); - if ($currentCustomer && $invoice->customer_id !== $currentCustomer->id) { - Log::warning('Unauthorized invoice access attempt', [ - 'invoice_id' => $invoice->id, - 'order_num' => $order_num, - 'customer_id' => $currentCustomer->id, - 'invoice_customer_id' => $invoice->customer_id - ]); - - abort(403, 'Bạn không có quyền xem hóa đơn này.'); - } - } - - return view("frontend.invoice.show", compact('title', 'order_num', 'invoice')); - } - - public function show_bk(Request $request) - { - $validator = Validator::make( - $request->all(), - [ - 'invoice_id' => 'required|not__in:0|numeric' - ], - [ - 'invoice_id' => [ - 'required' => 'Yêu cầu không hợp lệ' - ] - ] - ); - if ($validator->fails()) { - return back()->withErrors($validator); - } - $invoice = Invoice::with('InvoiceItem', 'Payment', 'Customer', 'Order')->find($request->invoice_id); - - if (!$invoice) { - return back()->withErrors('Yêu cầu không hợp lệ'); - } - $title = "Chi tiết hoá đơn #" . $invoice->id; - - return view("frontend.invoice.view", compact('title', 'invoice')); - } - - - public function store( - Request $request, - $order_id, - $order_num, - InvoiceService $invoiceService, - Discord $discord, - vCenter $vCenter - ) { - $order = $this->orderRepository->findWithRelationships($order_id, [ - 'orderItems.addons', - 'orderItems.os.osGroup', - 'customer', - 'orderItems.ipAddress.host.oneDatastore', - 'orderItems.ipAddress.host.datacenter.vCenter' - ]); - - if (!$order) { - return redirect()->route('home')->with('error', 'Không tìm thấy đơn hàng.'); - } - - $user = customer(); - - if ($user->credit < (int) $order->amount) { - return redirect()->route('recharge.index')->with('error', 'Tài khoản không đủ số dư để thanh toán.'); - } - - DB::beginTransaction(); - - try { - $invoice = Invoice::where('order_id', $order_id)->firstOrFail(); - - // Cập nhật trạng thái đơn hàng thành "Processing" thay vì "Paid" - $order->update(['status' => OrderStatus::PROCESSING->value]); - - DB::commit(); - - // ✅ Gửi thông báo Discord về việc bắt đầu xử lý - $discord->SendJobRunInfo( - 'Order Payment Processing', - 'processing', - [ - 'order_id' => $order->id, - 'order_num' => $order->order_num, - 'customer_email' => $user->email, - 'amount' => $order->amount, - 'has_addons' => $order->orderItems->some(function($item) { - return $item->addons->isNotEmpty(); - }) - ] - ); - - // ✅ Dispatch job để xử lý thanh toán và tạo VM - \App\Jobs\VirtualMachine\ProcessOrderPaymentJob::dispatch($order) - ->delay(now()->addSeconds(5)); - - return redirect()->route('invoice.index', $order->id) - ->with('success', 'Đơn hàng đang được xử lý. Hệ thống sẽ khởi tạo máy ảo và trừ tiền khi hoàn thành. Bạn sẽ nhận được email thông báo kết quả.'); - - } catch (\Throwable $e) { - DB::rollBack(); - Log::error('Lỗi xử lý đơn hàng: ' . $e->getMessage()); - - $discord->SendErrorMessage([ - 'error' => $e->getMessage(), - 'order_id' => $order_id, - 'order_num' => $order_num, - 'customer_email' => $user->email - ], 'InvoiceController - Order Processing Error'); - - return back()->with('error', 'Có lỗi xảy ra: ' . $e->getMessage()); - } - } - -} diff --git a/app/Http/Controllers/frontend/MainController.php b/app/Http/Controllers/frontend/MainController.php deleted file mode 100644 index 9763506..0000000 --- a/app/Http/Controllers/frontend/MainController.php +++ /dev/null @@ -1,168 +0,0 @@ -moduleDomainRepository->filter( - [ - 'customer_id' => auth('users')->id(), - 'status' => 0 - ] - ); - - $invocie_unpaid = $this->invoiceRepository->filter( - [ - 'customer_id' => auth('users')->id(), - 'status' => 0 - ] - ); - - $ticket = $this->ticketRepository->filter( - [ - 'customer' => auth('users')->id() - ] - )->unique('ticket_num'); - - $discount = $this->discountRepository->filter( - [ - 'status' => 'active', - 'end' => [ - 'key' => 'end', - 'condition' => '>', - 'value' => Carbon::now()->timestamp - ] - ] - ); - - $posts = $this->postRepository->filter([ - 'published' => 1, - 'limit' => 4 - ]); - - $vmware = $this->vmwareRepository->filter([ - 'customer_id' => auth('users')->id(), - 'status' => 1 - ]); - $hosting = $this->moduleHostingRepository->filter([ - 'customer_id' => auth('users')->id(), - 'status' => 1 - ]); - - $title = "Khu vực khách hàng"; - return view('frontend.home', compact( - 'domain', - 'discount', - 'invocie_unpaid', - 'ticket', - 'title', - 'posts', - 'vmware', - 'hosting' - )); - } - - public function index_new() - { - $title = "Khu vực khách hàng"; - $domain = $this->moduleDomainRepository->filter( - [ - 'customer_id' => auth('users')->id(), - 'status' => 0 - ] - ); - - $invocie_unpaid = $this->invoiceRepository->filter( - [ - 'customer_id' => auth('users')->id(), - 'status' => 0 - ] - ); - - $ticket = $this->ticketRepository->filter( - [ - 'customer' => auth('users')->id() - ] - )->unique('ticket_num'); - - $discount = $this->discountRepository->filter( - [ - 'status' => 'active', - 'end' => [ - 'key' => 'end', - 'condition' => '>', - 'value' => Carbon::now()->timestamp - ] - ] - ); - - $posts = $this->postRepository->filter([ - 'published' => 1, - 'limit' => 4 - ]); - - $vmware = $this->vmwareRepository->filter([ - 'customer_id' => auth('users')->id(), - 'status' => 1 - ]); - - - $hosting = $this->moduleHostingRepository->filter([ - 'customer_id' => auth('users')->id(), - 'status' => 1 - ]); - - return view( - "frontend.home.index", - [ - 'title' => $title, - 'breadcrumbs' => $this->crums->add(__('Dashboard'))->add(__('Khu vực khách hàng')), - 'domain' => $domain, - 'discount' => $discount, - 'invocie_unpaid' => $invocie_unpaid, - 'ticket' => $ticket, - 'posts' => $posts, - 'vmware' => $vmware, - 'hosting' => $hosting - ] - ); - } -} diff --git a/app/Http/Controllers/frontend/ManagerService.php b/app/Http/Controllers/frontend/ManagerService.php deleted file mode 100644 index ef54fb0..0000000 --- a/app/Http/Controllers/frontend/ManagerService.php +++ /dev/null @@ -1,259 +0,0 @@ - $title, - 'breadcrumbs' => $this->crums->add(__('Dashboard'), route('home'))->add(__('Dịch vụ của tôi')), - ]); - } - - public function show(Request $request) - { - - $validator = Validator::make($request->all(), - [ - 'type' => 'required', - 'product' => 'required' - ], - [ - 'type' => [ - 'required' => 'Yêu cầu không hợp lệ' - ], - 'product' => [ - 'required' => 'Yêu cầu không hợp lệ' - ] - ] - ); - if ($validator->fails()) { - return back()->withErrors($validator); - } - - $product = null; - $information = null; - $addon = []; - $view = ""; - switch ($request->type) { - case 3: - $product = ModuleHosting::with('Server')->find($request->product); - $information = InvoiceItem::where('relid', $product->id) - ->where('type_id', 3) - ->where('invoice_type', 1) - ->first() - ->GetItemProduct(); - $view = "frontend.service.hosting"; - break; - case 4: - $product = ModuleVmware::with('IpAddress.Host')->find($request->product); - $information = InvoiceItem::where('relid', $product->id) - ->where('type_id', 4) - ->where('invoice_type', 1) - ->first() - ->GetItemProduct(); - $AllOn = InvoiceItem::whereHas('OrderItem', function ($query) { - $query->where('status', 1); - }) - ->where('parent_id', $product->id) - ->where('type_id', 1) - ->get(); - - foreach ($AllOn as $item) { - - $itemData = $item->GetItemProduct(); - - $price = 0; - - switch ($item->billing) { - case 2: - $price = $item->amount / 1; - break; - case 3: - $price = $item->amount / 3; - break; - case 4: - $price = $item->amount / 6; - break; - case 5: - $price = $item->amount / 12; - break; - } - if (array_key_exists(strtolower($itemData->name), $addon)) { - $addon[strtolower($itemData->name)] += $price / $itemData->price; - } else { - $addon[strtolower($itemData->name)] = $price / $itemData->price; - } - } - - - $view = "frontend.service.vmware"; - break; - } - - if (!$product) { - return back()->withErrors("Không tìm thấy thông tin dữ liệu"); - } - - $title = "Thông tin chi tiết dịch vụ"; - - return view($view, compact('title', 'product', 'information', 'addon')); - } - - public function reinstall(Request $request) - { - - $validator = Validator::make($request->all(), [ - 'userid' => 'numeric|required', - 'type' => 'numeric|required', - 'product' => 'numeric|required', - 'action' => 'required' - ]); - - if ($validator->fails()) { - return back()->withErrors($validator); - } - - $product = ModuleVmware::find($request->product); - - if (!$product) { - return back()->withErrors("Không tìm thấy thông tin dịch vụ"); - } - $product->update([ - 'status' => 3 - ]); - $jobs = new RemoveVirtualMachine($product->id); - - dispatch($jobs)->delay(now()->addSeconds(5)); - - return back()->with('success', 'The system has received the information. Please wait a second'); - } - - public function action(Request $request) - { - $validator = Validator::make($request->all(), [ - 'product' => 'numeric|required', - 'userid' => 'numeric|required', - 'action' => 'required' - ]); - - if ($validator->fails()) { - return response()->json(['error' => true, 'message' => $validator]); - } - - $jobs = new VMJobs($request->product, $request->action); - - $this->dispatch($jobs); - - } - - public function snapshot(Request $request) - { - $validator = Validator::make($request->all(), - [ - 'product' => 'numeric|required|not__in:0', - 'userid' => 'numeric|required|not__in:0', - 'action' => 'required' - ], - [ - 'product' => [ - 'required' => 'Yêu cầu không hợp lệ' - ], - 'userid' => [ - 'required' => 'Yêu cầu không hợp lệ' - ], - 'action' => [ - 'required' => 'Yêu cầu không hợp lệ' - ], - ] - ); - if ($validator->fails()) { - return response()->json(['error' => true, 'message' => $validator->getMessageBag()]); - } - - - $jobs = null; - - switch ($request->action) { - case "Create": - $SnapshotLimited = ModuleSnapshotLimit::where('customer_id', $request->userid)->first(); - - if ($SnapshotLimited->used == $SnapshotLimited->limit) { - return response()->json([ - 'error' => true, - 'message' => "Đã đạt giới hạn số lượng Snapshot. Vui lòng liên hệ quản trị viên để nâng cấp!" - ]); - } - $jobs = new CreateSnapshot($request->product); - break; - case "Revert": - $validator = Validator::make($request->all(), - [ - 'snap' => 'numeric|required|not__in:0', - ], - [ - 'snap' => [ - 'required' => 'Yêu cầu không hợp lệ' - ] - ] - ); - if ($validator->fails()) { - return response()->json(['error' => true, 'message' => $validator->getMessageBag()]); - } - $jobs = new RevertSnapshot($request->product, $request->snap); - break; - case "Remove": - $validator = Validator::make($request->all(), - [ - 'snap' => 'numeric|required|not__in:0', - ], - [ - 'snap' => [ - 'required' => 'Yêu cầu không hợp lệ' - ] - ] - ); - if ($validator->fails()) { - return response()->json(['error' => true, 'message' => $validator->getMessageBag()]); - } - $jobs = new RemoveSnapshot($request->product, $request->snap); - break; - } - $this->dispatch($jobs); - - } - - public function console(Request $request) - { - $validator = Validator::make($request->all(), [ - 'product' => 'required|not__in:0' - ], ['product.required' => 'Yêu cầu không hợp lệ']); - - if ($validator->fails()) { - return back()->withErrors($validator); - } - $product = ModuleVmware::find($request->product); - if (!$product) { - return back()->withErrors('Yêu cầu không hợp lệ'); - } - $title = "Console for #" . $product->name; - return view('frontend.service.console', compact('product', 'title')); - } -} diff --git a/app/Http/Controllers/frontend/Order/OrderController.php b/app/Http/Controllers/frontend/Order/OrderController.php deleted file mode 100644 index 2705a46..0000000 --- a/app/Http/Controllers/frontend/Order/OrderController.php +++ /dev/null @@ -1,156 +0,0 @@ -orderRepository->findWithRelationships($order_id, ['orderItems.addons.addonItems', 'orderItems.os.osGroup', 'customer']); - if (!$orders || $orders->customer_id !== customer()?->id) { - - return redirect()->route('client.order.index') - ->with('error', 'Đơn hàng không thuộc về bạn. Vui lòng kiểm tra lại!'); - } - - return view('frontend.order.payment', compact('orders')); - } - - - - public function destroy(Request $request, $order_id) - { - $order_num = $request->input('order_num'); - - $order = $this->orderRepository->findWithRelationships($order_id, [ - 'orderItems.addons', - 'orderItems.os.osGroup', - 'customer' - ]); - - if ( - !$order || - $order->customer_id !== customer()?->id || - $order->order_num !== $order_num - ) { - return redirect()->route('home') - ->with('error', 'Không tìm thấy đơn hàng hợp lệ để xoá!'); - } - - DB::beginTransaction(); - - try { - foreach ($order->orderItems as $item) { - $item->addons()->delete(); - } - - $order->orderItems()->delete(); - - $order->delete(); - - DB::commit(); - - return redirect()->route('home') - ->with('success', 'Đơn hàng đã được huỷ thành công.'); - } catch (\Exception $e) { - DB::rollBack(); - - return redirect()->route('home') - ->with('error', 'Đã có lỗi xảy ra khi huỷ đơn hàng. Vui lòng thử lại.'); - } - } - - - - public function store(OrderRequest $request, InvoiceService $invoiceService) - { - $data = $request->validated(); - - $orderNum = generate_order_number(); - - $order = Order::create([ - 'order_num' => $orderNum, - 'customer_id' => customer()?->id, - 'date' => now()->timestamp, - 'discount_id' => 0, - 'discount_value' => null, - 'amount' => $data['totalPrice'], - 'note' => null, - 'client_ip' => request()->ip(), - 'status' => 1, - ]); - - $orderItemId = OrderItem::create([ - 'order_id' => $order->id, - 'product_id' => $data['product_id'], - 'os_id' => $data['os_id'], - 'server_name' => $data['server_name'], - 'months' => $data['months'], - 'quantity' => 1, - 'price' => $data['totalPrice'], - 'product_type' => $data['product_type'], - ]); - - if (isset($data['addons']) && is_array($data['addons'])) { - foreach ($data['addons'] as $addonId => $addonData) { - if (isset($addonData['qty'], $addonData['price']) && intval($addonData['qty']) > 0) { - $qty = intval($addonData['qty']); - $unitPrice = intval($addonData['price']); - $totalPrice = $qty * $unitPrice; - - OrderAddon::create([ - 'order_item_id' => $orderItemId->id, - 'addon_id' => $addonId, - 'qty' => $qty, - 'price' => $totalPrice, - ]); - } - } - } - - $__order = $this->orderRepository->findWithRelationships($order->id, [ - 'orderItems.addons', - 'orderItems.os.osGroup', - 'customer' - ]); - - $invoice = $invoiceService->createInvoice($__order); - - if (!empty($data['cart_id'])) { - Cart::where('id', $data['cart_id'])->delete(); - } - - - - return redirect()->route('client.order.payment', ['order_id' => $order]) - ->with('success', 'Đặt đơn thành công'); - } - -} diff --git a/app/Http/Controllers/frontend/PostController.php b/app/Http/Controllers/frontend/PostController.php deleted file mode 100644 index 025f9f6..0000000 --- a/app/Http/Controllers/frontend/PostController.php +++ /dev/null @@ -1,22 +0,0 @@ -first(); - if (! $post) - { - return redirect()->route('home')->withErrors('Yêu cầu không hợp lệ'); - } - $title = $post->name; - return view('frontend.post',compact('post','title')); - } -} diff --git a/app/Http/Controllers/frontend/RechargeController.php b/app/Http/Controllers/frontend/RechargeController.php deleted file mode 100644 index 47a38ba..0000000 --- a/app/Http/Controllers/frontend/RechargeController.php +++ /dev/null @@ -1,129 +0,0 @@ -vnpayService = $vnPayService; - } - - public function index() - { - $title = 'Yêu cầu nạp tiền vào tài khoản'; - - $payment = Payment::whereNot('id', 1)->select('id', 'name')->get(); - $breadcrumbs = $this->crums->add(__('Dashboard'), route('home'))->add(__('Nạp tiền')); - return view('frontend.payment.index', compact('title', 'payment', 'breadcrumbs')); - } - - public function paymentProcess(RechargeRequest $request) - { - $data = $request->validated(); - - $auth = customer(); - if (!$auth) { - return redirect()->route('auth.index')->withErrors('Vui lòng đăng nhập'); - } - - // Chuẩn bị dữ liệu cho VNPAY - $paymentData = [ - 'amount' => $data['total_amount'], - 'language' => 'vn', - ]; - $paymentUrl = $this->vnpayService->createPaymentUrl($paymentData); - return redirect($paymentUrl); - } - - public function paymentReturn(Request $request) - { - $result = $this->vnpayService->verifyPayment($request->all()); - $data = $result['data'] ?? []; - - if (!empty($data) && ($data['vnp_TransactionStatus'] ?? '') === '00') { - $amount = ($data['vnp_Amount'] ?? 0) / 100; - $customerId = customer()->id; - - // Lưu vào bảng transaction - Transaction::create([ - 'trans' => $data['vnp_TxnRef'] ?? 'unknown', - 'amount' => $amount, - 'customer_id' => $customerId, - ]); - - // Cộng vào credit của Customer - $customer = Customer::find($customerId); - if ($customer) { - $customer->increment('credit', $amount); - $customer->increment('total', $amount); - } - dispatch(new GetPaymentMessage($customerId, $amount)) - ->delay(now()->addSeconds(10)); - - return redirect()->route('recharge.index')->with('success', 'Thanh toán thành công, tài khoản đã được cộng tiền!'); - } - - return redirect()->route('recharge.index')->withErrors('Thanh toán thất bại hoặc bị hủy.'); - } - - public function show(Request $request) - { - $amount = (int)$request->amount; - - if ($amount < 200000) { - return back()->withErrors('Yêu cầu không hợp lệ!'); - } - - Cookie::queue(Cookie::forget('start_checking')); - $memo = "NapTienUser" . customer()->id; - - $payment = Payment::find($request->payment); - - - if ($payment->type == 1 && !session()->has('start_checking')) { - \session()->put('start_checking', true); - - $time = Carbon::now()->addMinutes(5)->timestamp; - - dispatch(new GetTransactionPayment($memo, $time, customer()->id))->delay(now()->addSeconds(30)); - } - - $qr = "https://img.vietqr.io/image/$payment->bankCode-$payment->accountNo-qr_only.png?amount=$amount&addInfo=$memo&accountName=$payment->bankName"; - - $title = "Kiểm tra thanh toán"; - $breadcrumbs = $this->crums->add(__('Dashboard'), route('home'))->add(__('Nạp tiền'), route('recharge.index'))->add(__('Kiểm tra thanh toán')); - return view('frontend.payment.view', compact('title', 'qr', 'amount', 'payment', 'memo', 'breadcrumbs')); - } - - public function HistoryRecharge() - { - $title = 'Lịch sử giao dịch'; - $breadcrumbs = $this->crums->add(__('Dashboard'), route('home'))->add(__('Lịch sử giao dịch')); - return view('frontend.transaction', compact('title', 'breadcrumbs')); - } - - public function CallbackResponse(Request $request) - { - \session()->forget('start_checking'); - - return redirect()->route('home'); - } -} diff --git a/app/Http/Controllers/frontend/ServiceController.php b/app/Http/Controllers/frontend/ServiceController.php deleted file mode 100644 index fc046f0..0000000 --- a/app/Http/Controllers/frontend/ServiceController.php +++ /dev/null @@ -1,1483 +0,0 @@ -invoiceRepository->findWithRelationships($invoice_ordernum, [ - 'order', - 'invoiceItem.addons', - 'invoiceItem.os.osGroup', - 'customer' - ]); - - if (!$invoice) { - return redirect()->route('service.index')->with('error', 'Không tìm thấy dịch vụ.'); - } - - if ($invoice->customer_id !== customer()->id) { - return redirect()->route('service.index')->with('error', 'Bạn không có quyền truy cập dịch vụ này.'); - } - - $vmInfo = null; - if ($invoice->vm_id) { - $vmInfo = $this->getVMInfoFromVCenter($invoice, $vCenterService); - $this->dispatchVMInfoUpdateJob($invoice); - } - $title = "Chi tiết dịch vụ #" . $invoice->id; - return view('frontend.service.show', [ - 'title' => $title, - 'invoice' => $invoice, - 'vmInfo' => $vmInfo, - 'breadcrumbs' => $this->crums->add(__('Dashboard'))->add('Dịch vụ #' . $invoice->id), - ]); - } catch (\Exception $e) { - Log::error('Error in ServiceController@show: ' . $e->getMessage()); - return redirect()->route('service.index')->with('error', 'Có lỗi xảy ra khi tải thông tin dịch vụ.'); - } - } - - /** - * Lấy thông tin VM từ vCenter API - OPTIMIZED WITH CACHING - */ - private function getVMInfoFromVCenter($invoice, $vCenterService) - { - $cacheKey = "vm_info_{$invoice->vm_id}"; - $cacheDuration = 300; // 5 minutes - - if (Cache::has($cacheKey)) { - return Cache::get($cacheKey); - } - - try { - $orderItem = $invoice->invoiceItem->first(); - if (!$orderItem) { - Log::warning('Không tìm thấy order item cho invoice', ['invoice_id' => $invoice->id]); - $defaultInfo = $this->getDefaultVMInfo($invoice); - Cache::put($cacheKey, $defaultInfo, $cacheDuration); - return $defaultInfo; - } - - $product = $orderItem->getProductAttribute(); - if (!$product) { - Log::warning('Không tìm thấy product cho order item', ['order_item_id' => $orderItem->id]); - $defaultInfo = $this->getDefaultVMInfo($invoice); - Cache::put($cacheKey, $defaultInfo, $cacheDuration); - return $defaultInfo; - } - - $host = $product->host; - $datacenter = $host?->datacenter; - $vcenter = $datacenter?->vcenter; - - if (!$vcenter) { - $defaultInfo = $this->getDefaultVMInfo($invoice); - Cache::put($cacheKey, $defaultInfo, $cacheDuration); - return $defaultInfo; - } - - $loginSuccess = false; - try { - $loginSuccess = $vCenterService->loginServer($vcenter); - } catch (\Exception $e) { - Log::warning('vCenter login failed', ['vm_id' => $invoice->vm_id, 'error' => $e->getMessage()]); - } - - if (!$loginSuccess) { - $defaultInfo = $this->getDefaultVMInfo($invoice); - Cache::put($cacheKey, $defaultInfo, $cacheDuration); - return $defaultInfo; - } - - $vmDetail = null; - $ipInfo = null; - - try { - // Set timeout for API calls - $vmDetail = $vCenterService->GetDetailVirtualMachine($invoice->vm_id); - $ipInfo = $vCenterService->GetIPAddressVirtualMachine($invoice->vm_id); - } catch (\Exception $e) { - Log::warning('vCenter API calls failed', ['vm_id' => $invoice->vm_id, 'error' => $e->getMessage()]); - $defaultInfo = $this->getDefaultVMInfo($invoice); - Cache::put($cacheKey, $defaultInfo, $cacheDuration); - return $defaultInfo; - } - - if ($vmDetail['error'] === false) { - $vmData = $vmDetail['data']; - - // Lấy thông tin IP - $ipAddress = 'N/A'; - if ($ipInfo['error'] === false && !empty($ipInfo['data']['ip_address'])) { - $ipAddress = $ipInfo['data']['ip_address'] ?? 'N/A'; - } elseif ($ipInfo['error'] === false && isset($ipInfo['data']['value']['ip_address'])) { - // Fallback for nested structure - $ipAddress = $ipInfo['data']['value']['ip_address'] ?? 'N/A'; - } - - // Tính toán thông tin phần cứng - $cpuCount = $vmData['cpu']['count'] ?? 1; - $memoryMB = $vmData['memory']['size_MiB'] ?? 1024; - $memoryGB = round($memoryMB / 1024, 1); - - $diskSizeGB = 0; - if (isset($vmData['disks']) && is_array($vmData['disks'])) { - foreach ($vmData['disks'] as $disk) { - $diskSizeGB += round(($disk['value']['capacity'] ?? 0) / (1024 * 1024 * 1024), 1); - } - } - - $vmInfo = [ - 'vm_id' => $invoice->vm_id, - 'status' => $vmData['power_state'], - 'ip_address' => $ipAddress, - 'hostname' => $orderItem->server_name ?? 'Unknown', - 'os' => $orderItem->os->osGroup->name ?? 'Unknown', - 'cpu' => $cpuCount . ' cores', - 'ram' => $memoryGB . ' GB', - 'disk' => $diskSizeGB . ' GB', - 'uptime' => 'N/A', - 'last_updated' => now()->format('Y-m-d H:i:s'), - 'vm_name' => $vmData['name'] ?? 'Unknown', - 'vm_folder' => $vmData['folder'] ?? 'Unknown', - 'vm_resource_pool' => $vmData['resource_pool'] ?? 'Unknown', - 'vm_datastore' => $vmData['datastore'] ?? 'Unknown', - 'vm_network' => $vmData['nics'][0]['backing']['network'] ?? 'Unknown', - 'vm_mac' => $vmData['nics'][0]['mac_address'] ?? 'N/A', - 'vm_guest_id' => $vmData['guest_ID'] ?? 'Unknown', - 'vm_version' => $vmData['version'] ?? 'Unknown', - 'vm_hardware_version' => $vmData['hardware']['version'] ?? 'Unknown', - ]; - - // Cache the successful result - Cache::put($cacheKey, $vmInfo, $cacheDuration); - return $vmInfo; - } else { - $defaultInfo = $this->getDefaultVMInfo($invoice); - Cache::put($cacheKey, $defaultInfo, $cacheDuration); - return $defaultInfo; - } - } catch (\Exception $e) { - Log::error('Error in getVMInfoFromVCenter', ['vm_id' => $invoice->vm_id, 'error' => $e->getMessage()]); - $defaultInfo = $this->getDefaultVMInfo($invoice); - Cache::put($cacheKey, $defaultInfo, $cacheDuration); - return $defaultInfo; - } - } - - /** - * Lấy thông tin VM mặc định khi không thể kết nối vCenter - */ - private function getDefaultVMInfo($invoice) - { - $orderItem = $invoice->invoiceItem->first(); - return [ - 'vm_id' => $invoice->vm_id, - 'status' => 'unknown', - 'ip_address' => 'N/A', - 'hostname' => $orderItem->server_name ?? 'Unknown', - 'os' => $orderItem->os->osGroup->name ?? 'Unknown', - 'cpu' => 'N/A', - 'ram' => 'N/A', - 'disk' => 'N/A', - 'uptime' => 'N/A', - 'last_updated' => now()->format('Y-m-d H:i:s'), - 'vm_name' => 'Unknown', - 'vm_folder' => 'Unknown', - 'vm_resource_pool' => 'Unknown', - 'vm_datastore' => 'Unknown', - 'vm_network' => 'Unknown', - 'vm_mac' => 'N/A', - 'vm_guest_id' => 'Unknown', - 'vm_version' => 'Unknown', - 'vm_hardware_version' => 'Unknown', - ]; - } - - /** - * Action để bật/tắt VM (placeholder - chưa implement) - */ - public function toggleVM(Request $request, $invoice_ordernum) - { - try { - $invoice = Invoice::where('order_num', $invoice_ordernum)->first(); - - // Kiểm tra quyền truy cập - if ($invoice->customer_id !== customer()->id) { - return response()->json(['error' => true, 'message' => 'Bạn không có quyền thực hiện thao tác này.']); - } - - $action = $request->input('action'); - - $response = [ - 'success' => true, - 'message' => "Đã thực hiện thao tác: {$action}", - 'vm_id' => $invoice->vm_id, - 'action' => $action - ]; - - // Clear cache when VM state changes - if ($invoice->vm_id) { - Cache::forget("vm_info_{$invoice->vm_id}"); - } - - return response()->json($response); - } catch (\Exception $e) { - // Log::error('Error in ServiceController@toggleVM: ' . $e->getMessage()); - return response()->json(['error' => true, 'message' => 'Có lỗi xảy ra khi thực hiện thao tác. ' . $e->getMessage()]); - } - } - - /** - * Lấy thông tin VM từ vCenter (placeholder - chưa implement) - */ - public function getVMInfo($invoice_id) - { - try { - $invoice = Invoice::findOrFail($invoice_id); - - // Kiểm tra quyền truy cập - if ($invoice->customer_id !== customer()->id) { - return response()->json(['error' => true, 'message' => 'Bạn không có quyền truy cập thông tin này.']); - } - - if (!$invoice->vm_id) { - return response()->json(['error' => true, 'message' => 'Dịch vụ này chưa có VM ID.']); - } - - // TODO: Implement vCenter API calls here - // Hiện tại chỉ trả về data mẫu - $vmInfo = [ - 'vm_id' => $invoice->vm_id, - 'status' => 'running', - 'ip_address' => '192.168.1.100', - 'hostname' => $invoice->invoiceItem->first()->server_name ?? 'Unknown', - 'os' => $invoice->invoiceItem->first()->os->osGroup->name ?? 'Unknown', - 'cpu' => '2 cores', - 'ram' => '4 GB', - 'disk' => '50 GB', - 'uptime' => '2 days, 5 hours', - 'last_updated' => now()->format('Y-m-d H:i:s') - ]; - - return redirect()->back()->with('success', 'Lấy thông tin VM thành công'); - } catch (\Exception $e) { - // Log::error('Error in ServiceController@getVMInfo: ' . $e->getMessage()); - return response()->json(['error' => true, 'message' => 'Có lỗi xảy ra khi lấy thông tin VM.']); - } - } - - /** - * Dispatch background job to update VM info - */ - private function dispatchVMInfoUpdateJob($invoice): void - { - try { - // Check if cache is stale (older than 2 minutes) - $cacheKey = "vm_info_{$invoice->vm_id}"; - $cachedData = Cache::get($cacheKey); - - if ( - !$cachedData || - (isset($cachedData['last_updated']) && - now()->diffInMinutes($cachedData['last_updated']) > 2) - ) { - - // Dispatch background job to update VM info - \App\Jobs\VirtualMachine\Sync\UpdateVMInfoJob::dispatch($invoice->id, $invoice->vm_id) - ->delay(now()->addSeconds(5)) - ->onQueue('vm-updates'); - } - } catch (\Exception $e) { - Log::warning('Failed to dispatch VM info update job', [ - 'vm_id' => $invoice->vm_id, - 'error' => $e->getMessage() - ]); - } - } - - - public function vmConsole(Request $request, $invoice_ordernum) - { - $cacheKey = 'vm_console_invoice_' . $invoice_ordernum; - $data = cache()->remember($cacheKey, 300, function () use ($invoice_ordernum) { - $invoice = Invoice::where('order_num', $invoice_ordernum)->first(); - if (!$invoice) - return null; - $order = Order::find($invoice->order_id); - if (!$order) - return null; - $product = ModuleVmware::where('order_id', $order->id)->first(); - if (!$product) - return null; - $title = "VM Console - " . $product->name; - return compact('product', 'title', 'invoice'); - }); - if (!$data) { - abort(404, 'Không tìm thấy thông tin VM Console'); - } - return view('frontend.service.console', $data); - } - - public function createSnapshots(SnapShotRequest $request) - { - try { - $user = customer(); - if (!$user) { - return redirect()->back()->with('error', 'Chưa đăng nhập.'); - } - - $data = $request->validated(); - $productId = $data['product_id']; - - $product = ModuleVmware::with('ipAddress.host.datacenter.vCenter') - ->where('vmware_id', $productId) - ->where('customer_id', $user->id) - ->first(); - - if (!$product) { - return redirect()->back()->with('error', "Không tìm thấy VPS hoặc bạn không có quyền."); - } - - if ($product->status != 1) { - return redirect()->back()->with('error', 'Chỉ tạo snapshot cho VM đang hoạt động.'); - } - - $limit = ModuleSnapshotLimit::where('customer_id', $user->id)->first(); - if ($limit) { - $count = ModuleSnapshot::where('customer_id', $user->id) - ->where('module_vmware_id', $product->id) - ->count(); - - if ($count >= $limit->limit) { - return redirect()->back()->with( - 'error', - "Đã đạt giới hạn snapshot ({$limit->limit})." - ); - } - } - - $snapshot = ModuleSnapshot::create([ - 'name' => 'snapshot-' . now()->format('Ymd-His'), - 'customer_id' => $user->id, - 'module_vmware_id' => $product->id, - 'status' => 'pending', - 'created_by' => $user->id, - ]); - - \App\Jobs\VirtualMachine\Snapshot\CreateSnapshot::dispatch( - $snapshot->id - )->delay(now()->addSeconds(3)); - - return redirect()->back()->with( - 'success', - 'Đã gửi yêu cầu tạo snapshot. Hệ thống sẽ xử lý trong nền.' - ); - } catch (\Throwable $e) { - Log::error('Lỗi khi tạo snapshot', [ - 'product_id' => $request->product_id ?? null, - 'user_id' => $user->id ?? null, - 'error' => $e->getMessage(), - ]); - - return redirect()->back()->with( - 'error', - 'Lỗi hệ thống khi tạo snapshot.' - ); - } - } - - public function getSnapshots(Request $request) - { - $user = customer(); - if (!$user) { - return response()->json([ - 'error' => true, - 'message' => __('Chưa đăng nhập') - ], 401); - } - - $validator = Validator::make($request->all(), [ - 'product_id' => 'required|string|max:255', - ]); - - if ($validator->fails()) { - return response()->json([ - 'error' => true, - 'message' => __('Dữ liệu không hợp lệ'), - 'errors' => $validator->errors() - ], 422); - } - - $product = $this->findVmwareProduct( - $this->sanitizeInput($request->product_id), - $user->id - ); - - if (!$product) { - return response()->json([ - 'error' => true, - 'message' => __('Không tìm thấy VPS') - ], 404); - } - - $snapshots = ModuleSnapshot::query() - ->where('customer_id', $user->id) - ->where('module_vmware_id', $product->id) - ->orderByDesc('created_at') - ->get([ - 'id', - 'name', - 'status', - 'snapshot_ref', - 'error_message', - 'created_at', - ]); - - return response()->json([ - 'error' => false, - 'message' => __('Lấy danh sách snapshot thành công'), - 'data' => [ - 'vm_name' => e($product->name), - 'vm_id' => $product->vmware_id, - 'snapshots' => $snapshots, - 'total_count' => $snapshots->count(), - 'last_updated' => now()->format('Y-m-d H:i:s'), - ] - ]); - } - - - /** - * Reset VM password (Windows/Linux) via vCenter helpers - */ - public function resetVMPassword(Request $request) - { - $user = customer(); - if (!$user) { - return response()->json(['error' => true, 'message' => __('Chưa đăng nhập. Vui lòng đăng nhập để sử dụng tính năng này.')], 401); - } - - $validated = Validator::make($request->all(), [ - 'product_id' => 'required|string|max:255', - 'new_password' => 'required|string|min:8|max:128', - 'old_password' => 'required|string|min:8|max:128', - ]); - if ($validated->fails()) { - return response()->json(['error' => true, 'message' => __('Dữ liệu không hợp lệ'), 'errors' => $validated->errors()], 422); - } - - $productId = $this->sanitizeInput($request->product_id); - $newPassword = (string) $request->new_password; - $oldPassword = (string) $request->old_password; - - // load & ownership check nhanh (không cần toàn bộ nặng nề vì Job sẽ retry) - $product = ModuleVmware::where('vmware_id', $productId) - ->where('customer_id', $user->id) - ->first(); - if (!$product) { - return response()->json(['error' => true, 'message' => __('Không tìm thấy VPS hoặc bạn không có quyền truy cập')], 404); - } - - // Dispatch job với delay 5s - ResetVmPasswordJob::dispatch( - productId: $productId, - newPassword: $newPassword, - oldPassword: $oldPassword, - userId: $user->id, - email: $user->email - )->delay(now()->addSeconds(5)); - - // trả accepted để UI biết đang xử lý nền - return redirect()->back()->with('success', 'Đã gửi yêu cầu tạo đặt lại mật khẩu. Quá trình sẽ mất 3-5 phút, vui lòng chờ đợi.'); - } - - - - - /** - * Change Remote Desktop port (Windows only) - */ - public function changeRemotePort(Request $request) - { - $user = customer(); - if (!$user) { - return response()->json(['error' => true, 'message' => __('Chưa đăng nhập. Vui lòng đăng nhập để sử dụng tính năng này.')], 401); - } - - $validated = Validator::make($request->all(), [ - 'product_id' => 'required|string|max:255', - 'new_port' => 'required|string|min:4|max:128', - 'password' => 'required|string|min:4|max:128', - ]); - if ($validated->fails()) { - return response()->json(['error' => true, 'message' => __('Dữ liệu không hợp lệ'), 'errors' => $validated->errors()], 422); - } - - $productId = $this->sanitizeInput($request->product_id); - $newPort = (string) $request->new_port; - - // load & ownership check nhanh (không cần toàn bộ nặng nề vì Job sẽ retry) - $product = ModuleVmware::where('vmware_id', $productId) - ->where('customer_id', $user->id) - ->first(); - if (!$product) { - return response()->json(['error' => true, 'message' => __('Không tìm thấy VPS hoặc bạn không có quyền truy cập')], 404); - } - - // Dispatch job với delay 5s - ChangeRemotePortJob::dispatch( - productId: $productId, - newPort: $newPort, - password: (string) $request->password, - userId: $user->id, - email: $user->email - )->delay(now()->addSeconds(5)); - - // trả accepted để UI biết đang xử lý nền - return redirect()->back()->with('success', 'Đã gửi yêu cầu thay đổi cổng Remote Desktop. Quá trình sẽ mất 3-5 phút, vui lòng chờ đợi.'); - } - - /** - * Change public IP for VM (request-based), logs request. - */ - public function changeIP(Request $request) - { - try { - $user = customer(); - if (!$user) { - return response()->json([ - 'error' => true, - 'message' => __('Chưa đăng nhập. Vui lòng đăng nhập để sử dụng tính năng này.'), - ], 401); - } - - $validated = FacadesValidator::make($request->all(), [ - 'product_id' => 'required|string|max:255', - 'ip' => ['required', 'string', 'regex:/^(?:(?:[0-9]{1,3}\.){3}[0-9]{1,3})$/'], - ]); - - if ($validated->fails()) { - return response()->json([ - 'error' => true, - 'message' => __('Dữ liệu không hợp lệ'), - 'errors' => $validated->errors(), - ], 422); - } - - $productId = $this->sanitizeInput($request->product_id); - $desiredIp = $this->sanitizeInput($request->ip); - - // Persist an audit log entry for ops to handle allocation if needed - Log::info('Khách yêu cầu đổi IP', [ - 'user_id' => $user->id, - 'product_vmware_id' => $productId, - 'desired_ip' => $desiredIp, - ]); - - // Here you could enqueue a Job to validate/assign IP from pool - // For now, return accepted message - return response()->json([ - 'error' => false, - 'message' => __('Yêu cầu đổi IP đã được ghi nhận, chúng tôi sẽ xử lý trong thời gian sớm nhất.'), - ]); - } catch (\Exception $e) { - Log::error('Lỗi changeIP', [ - 'user_id' => customer()?->id, - 'error' => $e->getMessage(), - ]); - return response()->json([ - 'error' => true, - 'message' => __('Có lỗi xảy ra khi đổi IP'), - ], 500); - } - } - - - - /** - * Secure remove snapshot using session authentication - NO BEARER TOKEN - */ - public function removeSnapshot(Request $request) - { - try { - $user = customer(); - if (!$user) { - return response()->json([ - 'error' => true, - 'message' => 'Chưa đăng nhập. Vui lòng đăng nhập để sử dụng tính năng này.' - ], 401); - } - - $validator = Validator::make($request->all(), [ - 'product_id' => 'required|string', - 'snapshot_name' => 'required|string', - ]); - - if ($validator->fails()) { - return response()->json([ - 'error' => true, - 'message' => 'Dữ liệu không hợp lệ', - 'errors' => $validator->errors() - ], 422); - } - - $productId = $request->product_id; - $snapshotName = $request->snapshot_name; - $userId = $user->id; - - // Tìm VPS - $product = ModuleVmware::with('ipAddress.host.datacenter.vCenter') - ->where('vmware_id', $productId) - ->where('customer_id', $userId) - ->first(); - - if (!$product) { - return response()->json([ - 'error' => true, - 'message' => "Không tìm thấy VPS #{$productId} hoặc bạn không có quyền truy cập" - ], 404); - } - - // Tìm snapshot trong database - $snapshot = ModuleSnapshot::where('customer_id', $userId) - ->where('module_vmware_id', $product->id) - ->where('name', $snapshotName) - ->first(); - - if (!$snapshot) { - return response()->json([ - 'error' => true, - 'message' => "Không tìm thấy snapshot '{$snapshotName}' hoặc bạn không có quyền truy cập" - ], 404); - } - - // Kiểm tra trạng thái VPS - if ($product->status != 1) { - return response()->json([ - 'error' => true, - 'message' => 'Chỉ có thể xóa snapshot cho máy ảo đang hoạt động' - ], 400); - } - - // Dispatch job để xóa snapshot trong background - \App\Jobs\VirtualMachine\Snapshot\RemoveSnapshot::dispatch($product->id, $snapshot->id) - ->delay(now()->addSeconds(5)) - ->onQueue('snapshots'); - - return response()->json([ - 'error' => false, - 'message' => 'Đã gửi yêu cầu xóa snapshot. Quá trình sẽ mất 1-2 phút, vui lòng chờ đợi.' - ]); - } catch (\Exception $e) { - Log::error('❌ Lỗi khi xóa snapshot', [ - 'product_id' => $request->product_id ?? 'not_provided', - 'snapshot_name' => $request->snapshot_name ?? 'not_provided', - 'user_id' => $user->id ?? 'guest', - 'error' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine() - ]); - - return response()->json([ - 'error' => true, - 'message' => 'Lỗi hệ thống khi xóa snapshot: ' . $e->getMessage() - ], 500); - } - } - - /** - * Secure revert snapshot using session authentication - NO BEARER TOKEN - */ - public function revertSnapshot(Request $request) - { - try { - $user = customer(); - if (!$user) { - return response()->json([ - 'error' => true, - 'message' => 'Chưa đăng nhập. Vui lòng đăng nhập để sử dụng tính năng này.' - ], 401); - } - - $validator = Validator::make($request->all(), [ - 'product_id' => 'required|string', - 'snapshot_name' => 'required|string', - ]); - - if ($validator->fails()) { - return response()->json([ - 'error' => true, - 'message' => 'Dữ liệu không hợp lệ', - 'errors' => $validator->errors() - ], 422); - } - - $productId = $request->product_id; - $snapshotName = $request->snapshot_name; - $userId = $user->id; - - // Tìm VPS - $product = ModuleVmware::with('ipAddress.host.datacenter.vCenter') - ->where('vmware_id', $productId) - ->where('customer_id', $userId) - ->first(); - - if (!$product) { - return response()->json([ - 'error' => true, - 'message' => "Không tìm thấy VPS #{$productId} hoặc bạn không có quyền truy cập" - ], 404); - } - - // Tìm snapshot trong database - $snapshot = ModuleSnapshot::where('customer_id', $userId) - ->where('module_vmware_id', $product->id) - ->where('name', $snapshotName) - ->first(); - - if (!$snapshot) { - return response()->json([ - 'error' => true, - 'message' => "Không tìm thấy snapshot '{$snapshotName}' hoặc bạn không có quyền truy cập" - ], 404); - } - - // Kiểm tra trạng thái VPS - if ($product->status != 1) { - return response()->json([ - 'error' => true, - 'message' => 'Chỉ có thể khôi phục snapshot cho máy ảo đang hoạt động' - ], 400); - } - - // Dispatch job để khôi phục snapshot trong background - \App\Jobs\VirtualMachine\Snapshot\RevertSnapshot::dispatch($product->id, $snapshot->id) - ->delay(now()->addSeconds(5)) - ->onQueue('snapshots'); - - return response()->json([ - 'error' => false, - 'message' => 'Đã gửi yêu cầu khôi phục snapshot. Quá trình sẽ mất 2-3 phút, vui lòng chờ đợi.' - ]); - } catch (\Exception $e) { - Log::error('❌ Lỗi khi khôi phục snapshot', [ - 'product_id' => $request->product_id ?? 'not_provided', - 'snapshot_name' => $request->snapshot_name ?? 'not_provided', - 'user_id' => $user->id ?? 'guest', - 'error' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine() - ]); - - return response()->json([ - 'error' => true, - 'message' => 'Lỗi hệ thống khi khôi phục snapshot: ' . $e->getMessage() - ], 500); - } - } - - /** - * Secure start VM using session authentication - NO BEARER TOKEN - */ - /** - * Secure start VM using session authentication - NO BEARER TOKEN - */ - public function startVM(Request $request) - { - try { - $user = customer(); - if (!$user) { - return response()->json([ - 'error' => true, - 'message' => __('Chưa đăng nhập. Vui lòng đăng nhập để sử dụng tính năng này.') - ], 401); - } - - $validator = Validator::make($request->all(), [ - 'product_id' => 'required|string|max:255', - ]); - if ($validator->fails()) { - return response()->json([ - 'error' => true, - 'message' => __('Dữ liệu không hợp lệ'), - 'errors' => $validator->errors() - ], 422); - } - - $productId = $request->product_id; - $userId = $user->id; - - $product = ModuleVmware::where('vmware_id', $productId) - ->where('customer_id', $userId) - ->first(); - if (!$product) { - return response()->json([ - 'error' => true, - 'message' => __('Không tìm thấy VPS hoặc bạn không có quyền truy cập') - ], 404); - } - - // Dispatch Job - \App\Jobs\VirtualMachine\Power\StartVmJob::dispatch($product->id, $userId); - - return response()->json([ - 'error' => false, - 'message' => __('Yêu cầu khởi động máy ảo đã được gửi. Vui lòng chờ trong giây lát.') - ]); - - } catch (\Exception $e) { - Log::error('Lỗi khi khởi động máy ảo', [ - 'user_id' => $user->id ?? 'guest', - 'product_id' => $request->product_id ?? 'not_provided', - 'error' => $e->getMessage() - ]); - return response()->json([ - 'error' => true, - 'message' => __('Có lỗi xảy ra khi khởi động máy ảo') - ], 500); - } - } - - /** - * Secure stop VM using session authentication - NO BEARER TOKEN - */ - public function stopVM(Request $request) - { - try { - $user = customer(); - if (!$user) { - return response()->json([ - 'error' => true, - 'message' => __('Chưa đăng nhập. Vui lòng đăng nhập để sử dụng tính năng này.') - ], 401); - } - - $validator = Validator::make($request->all(), [ - 'product_id' => 'required|string|max:255', - ]); - if ($validator->fails()) { - return response()->json([ - 'error' => true, - 'message' => __('Dữ liệu không hợp lệ'), - 'errors' => $validator->errors() - ], 422); - } - - $productId = htmlspecialchars(strip_tags(trim($request->product_id)), ENT_QUOTES, 'UTF-8'); - $userId = $user->id; - - $product = ModuleVmware::where('vmware_id', $productId) - ->where('customer_id', $userId) - ->first(); - if (!$product) { - return response()->json([ - 'error' => true, - 'message' => __('Không tìm thấy VPS hoặc bạn không có quyền truy cập') - ], 404); - } - - // Dispatch Job - \App\Jobs\VirtualMachine\Power\StopVmJob::dispatch($product->id, $userId); - - return response()->json([ - 'error' => false, - 'message' => __('Yêu cầu tắt máy ảo đã được gửi. Vui lòng chờ trong giây lát.') - ]); - - } catch (\Exception $e) { - Log::error('Lỗi khi tắt máy ảo', [ - 'user_id' => $user->id ?? 'guest', - 'product_id' => $request->product_id ?? 'not_provided', - 'error' => $e->getMessage() - ]); - return response()->json([ - 'error' => true, - 'message' => __('Có lỗi xảy ra khi tắt máy ảo') - ], 500); - } - } - - /** - * Secure reboot VM using session authentication - NO BEARER TOKEN - */ - public function rebootVM(Request $request) - { - try { - $user = customer(); - if (!$user) { - return response()->json([ - 'error' => true, - 'message' => __('Chưa đăng nhập. Vui lòng đăng nhập để sử dụng tính năng này.') - ], 401); - } - - $validator = Validator::make($request->all(), [ - 'product_id' => 'required|string|max:255', - ]); - if ($validator->fails()) { - return response()->json([ - 'error' => true, - 'message' => __('Dữ liệu không hợp lệ'), - 'errors' => $validator->errors() - ], 422); - } - - $productId = htmlspecialchars(strip_tags(trim($request->product_id)), ENT_QUOTES, 'UTF-8'); - $userId = $user->id; - - $product = ModuleVmware::where('vmware_id', $productId) - ->where('customer_id', $userId) - ->first(); - if (!$product) { - return response()->json([ - 'error' => true, - 'message' => __('Không tìm thấy VPS hoặc bạn không có quyền truy cập') - ], 404); - } - - // Dispatch Job - \App\Jobs\VirtualMachine\Power\RebootVmJob::dispatch($product->id, $userId); - - return response()->json([ - 'error' => false, - 'message' => __('Yêu cầu khởi động lại máy ảo đã được gửi. Vui lòng chờ trong giây lát.') - ]); - - } catch (\Exception $e) { - Log::error('Lỗi khi reboot VM', [ - 'user_id' => $user->id ?? 'guest', - 'product_id' => $request->product_id ?? 'not_provided', - 'error' => $e->getMessage() - ]); - return response()->json([ - 'error' => true, - 'message' => __('Có lỗi xảy ra khi khởi động lại máy ảo') - ], 500); - } - } - - - public function reinstallVM(Request $request, vCenter $vCenterService) - { - try { - $user = customer(); - if (!$user) { - Log::warning('User not logged in for reinstallVM'); - return response()->json([ - 'error' => true, - 'message' => __('Chưa đăng nhập. Vui lòng đăng nhập để sử dụng tính năng này.') - ], 401); - } - - $validator = Validator::make($request->all(), [ - 'invoice_id' => 'required|integer', - ]); - - if ($validator->fails()) { - Log::warning('Validation failed for reinstallVM', [ - 'errors' => $validator->errors()->toArray() - ]); - return response()->json([ - 'error' => true, - 'message' => __('Dữ liệu không hợp lệ'), - 'errors' => $validator->errors() - ], 422); - } - - $invoice = Invoice::find($request->invoice_id); - if (!$invoice) { - return response()->json([ - 'error' => true, - 'message' => __('Không tìm thấy hóa đơn') - ], 404); - } - - // Debug: Log product lookup - $invoiceItem = $invoice->invoiceItem->first(); - $productId = $invoiceItem?->getProductAttribute()?->id; - $vmware = $productId; - $osId = $request->os_id; - $userId = $user->id; - - // Tìm product và kiểm tra quyền sở hữu - $vm = ModuleVmware::where('vmware_id', $vmware->vmware_id) - ->where('customer_id', $userId) - ->first(); - - Log::info('VM lookup result', [ - 'vm_found' => $vm ? 'yes' : 'no', - 'vm_data' => $vm ? $vm->toArray() : null - ]); - if (!$vm) { - return response()->json([ - 'error' => true, - 'message' => __('Không tìm thấy VPS hoặc bạn không có quyền truy cập') - ], 404); - } - - // Kiểm tra OS có tồn tại và hợp lệ không - $os = Os::find($osId); - if (!$os) { - return response()->json([ - 'error' => true, - 'message' => __('Hệ điều hành không tồn tại') - ], 404); - } - - // Kiểm tra OS có được phép cho VPS này không - $allowedOs = $vm->operatingSystems()->where('os.id', $osId)->first(); - if (!$allowedOs) { - return response()->json([ - 'error' => true, - 'message' => __('Hệ điều hành này không được phép cho VPS này') - ], 403); - } - - $result = $vCenterService->DeleteVirtualMachine($vm->vmware_id); - if (is_array($result) && isset($result['error']) && $result['error'] === false) { - // Cập nhật OS trong database - $vm->update([ - 'os_id' => $osId - ]); - - Cache::forget('vm_info_' . $vm->vmware_id); - return response()->json([ - 'error' => false, - 'message' => __('Yêu cầu cài lại máy ảo đã được gửi thành công. Quá trình sẽ mất 5-10 phút.') - ]); - } else { - $msg = is_array($result) && isset($result['data']) ? $result['data'] : __('Không thể cài lại máy ảo'); - Log::warning('vCenter call failed', [ - 'result' => $result, - 'message' => $msg - ]); - return response()->json([ - 'error' => true, - 'message' => $msg - ], 500); - } - } catch (\Exception $e) { - Log::error('Lỗi khi cài lại máy ảo', [ - 'user_id' => $user->id ?? 'guest', - 'product_id' => $request->product_id ?? 'not_provided', - 'os_id' => $request->os_id ?? 'not_provided', - 'error' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine() - ]); - return response()->json([ - 'error' => true, - 'message' => __('Có lỗi xảy ra khi cài lại máy ảo') - ], 500); - } - } - - /** - * Sanitize input data - */ - private function sanitizeInput($input): string - { - return htmlspecialchars(strip_tags(trim($input)), ENT_QUOTES, 'UTF-8'); - } - - /** - * Sanitize output data - */ - private function sanitizeOutput($output): string - { - return htmlspecialchars($output, ENT_QUOTES, 'UTF-8'); - } - - /** - * Kiểm tra cache có hết hạn chưa - */ - private function isCacheExpired($cachedData): bool - { - if (!isset($cachedData['last_updated'])) { - return true; - } - - $lastUpdated = \Carbon\Carbon::parse($cachedData['last_updated']); - return now()->diffInMinutes($lastUpdated) > 2; // Cache 2 phút - } - - /** - * Tìm VPS với eager loading - */ - private function findVmwareProduct($productId, $userId) - { - return ModuleVmware::with(['ipAddress.host.datacenter.vCenter']) - ->where('vmware_id', $productId) - ->where('customer_id', $userId) - ->first(); - } - - /** - * Validate vCenter configuration - */ - private function validateVcenterConfiguration($product) - { - if (!$product->ipAddress?->host?->datacenter?->vCenter) { - return null; - } - - return $product->ipAddress->host->datacenter->vCenter; - } - - /** - * Lấy snapshot từ vCenter - */ - private function fetchSnapshotsFromVCenter($serviceVCenter, $product, $vcenter) - { - try { - // Login to vCenter - if (!$serviceVCenter->loginServer($vcenter)) { - return false; - } - - // Kiểm tra method tồn tại - if (!method_exists($serviceVCenter, 'getSnapShot')) { - Log::error('getSnapShot method không tồn tại trong ServiceVCenter'); - return false; - } - - $result = $serviceVCenter->getSnapShot($product); - - // Retry logic - if ($result === "Login_Again") { - if ($serviceVCenter->loginServer($vcenter)) { - $result = $serviceVCenter->getSnapShot($product); - } else { - return false; - } - } - - // Validate result - if (is_string($result) || (isset($result['error']) && $result['error'])) { - return false; - } - - return $result['data'] ?? []; - } catch (\Exception $e) { - Log::error('Lỗi khi lấy snapshot từ vCenter', [ - 'product_id' => $product->id, - 'error' => $e->getMessage() - ]); - return false; - } - } - - /** - * Lấy snapshot từ database - */ - private function getDatabaseSnapshots($userId, $productId) - { - return ModuleSnapshot::where('customer_id', $userId) - ->where('module_vmware_id', $productId) - ->get() - ->keyBy('name'); - } - - /** - * Xử lý và sanitize snapshot data - */ - private function processSnapshotsData($snapshots, $dbSnapshots): array - { - $processed = []; - - if (!is_array($snapshots)) { - return $processed; - } - - foreach ($snapshots as $snapshot) { - $snapshotName = $this->sanitizeOutput($snapshot['name'] ?? $snapshot['Name'] ?? 'Unknown'); - $dbSnapshot = $dbSnapshots->get($snapshotName); - - $processed[] = [ - 'name' => $snapshotName, - 'description' => $this->sanitizeOutput($snapshot['description'] ?? $snapshot['Description'] ?? ''), - 'created' => $this->sanitizeOutput($snapshot['created'] ?? $snapshot['Created'] ?? ''), - 'power_state' => $this->sanitizeOutput($snapshot['power_state'] ?? $snapshot['PowerState'] ?? ''), - 'size_mb' => (int) ($snapshot['size_mb'] ?? $snapshot['SizeMB'] ?? 0), - 'size_gb' => (float) ($snapshot['size_gb'] ?? $snapshot['SizeGB'] ?? 0), - 'is_current' => (bool) ($snapshot['is_current'] ?? $snapshot['IsCurrent'] ?? false), - 'is_replay_supported' => (bool) ($snapshot['is_replay_supported'] ?? $snapshot['IsReplaySupported'] ?? false), - 'in_database' => $dbSnapshot ? true : false, - 'db_created_at' => $dbSnapshot ? $dbSnapshot->created_at->format('d/m/Y H:i:s') : null - ]; - } - - return $processed; - } - - /** - * Calculate renewal price (AJAX) - */ - public function renewPrice(Request $request) - { - try { - $user = customer(); - if (!$user) { - return response()->json(['error' => true, 'message' => __('Vui lòng đăng nhập.')], 401); - } - - $vmware_id = $this->sanitizeInput($request->product_id); - $plan = $request->input('plan'); - $months = $plan === 'other' ? (int) $request->input('months') : (int) $plan; - - if ($months < 1) - $months = 1; - - $vm = ModuleVmware::where('vmware_id', $vmware_id) - ->where('customer_id', $user->id) - ->first(); - - if (!$vm) { - return response()->json(['error' => true, 'message' => __('Không tìm thấy dịch vụ.')], 404); - } - - $order = Order::find($vm->order_id); - if (!$order) { - return response()->json(['error' => true, 'message' => __('Không tìm thấy đơn hàng gốc.')], 404); - } - - // Find OrderItem in order__order_item - // Rule: product_type = 4 (VPS) or 3 (Hosting) - // Ideally we match the product_id too, but ModuleVmware may not store original product_id directly except via relation? - // ModuleVmware has no 'product_id' column in the schema we saw, but it has 'order_id'. - // Let's assume we look for the item that created this VM. - // Since we are in ServiceController for VM, we look for Type 4 (VPS). - - $orderItem = \App\Models\OrderItem::where('order_id', $order->id) - ->where('product_type', 4) // VPS - ->first(); - - if (!$orderItem) { - // Fallback or error - return response()->json(['error' => true, 'message' => __('Không tìm thấy thông tin sản phẩm trong đơn hàng.')], 404); - } - - // Get Product Price - $product = null; - if ($orderItem->product_type == 4) { - $product = \App\Models\VPS::find($orderItem->product_id); - } elseif ($orderItem->product_type == 3) { - $product = \App\Models\Hosting::find($orderItem->product_id); - } - - if (!$product) { - return response()->json(['error' => true, 'message' => __('Sản phẩm không còn tồn tại.')], 404); - } - - // Priority: Price Sale -> Price - $base_unit_price = (float) ($product->price_sale > 0 ? $product->price_sale : $product->price); - - // Calculate Addons Price - // Look into order__order_addons via OrderItem relationship - $addons_unit_price = 0; - if ($orderItem->addons && $orderItem->addons->count() > 0) { - foreach ($orderItem->addons as $addonPivot) { - // $addonPivot is OrderAddon model - // We need current price of the addon? User said "lấy giá đã lưu" (take stored price) - // BUT for renewal, usually we take CURRENT price of the addon or the STORED price? - // User said: "lấy sản order hiện tại kèm các addon nếu có lấy giá đã lưu * với số tháng" - // "giá đã lưu" implies the price stored in the order/product table? - // But then user said: "nếu product có price_sale thì ưu tiên lấy price_sale còn lại thì lấy price". - // This implies looking at the ACTUAL Product table for the base Item. - - // For Addons: "kèm các addon nếu có". - // Let's look at the Addon model (Current Price). - if ($addonPivot->addonItems) { - $addons_unit_price += (float) ($addonPivot->addonItems->price); - } - } - } - - $total_unit_price = $base_unit_price + $addons_unit_price; - $total = $total_unit_price * $months; - - return response()->json([ - 'error' => false, - 'data' => [ - 'unit_price' => $total_unit_price, - 'months' => $months, - 'total' => $total - ] - ]); - - } catch (\Exception $e) { - Log::error("Error calculating renew price: " . $e->getMessage()); - return response()->json(['error' => true, 'message' => $e->getMessage()], 500); - } - } - - /** - * Renew VPS Service - */ - public function renew(Request $request) - { - try { - $user = customer(); - if (!$user) { - return redirect()->route('user.login')->with('error', __('Vui lòng đăng nhập.')); - } - - // 1. Validate Input - $validator = FacadesValidator::make($request->all(), [ - 'product_id' => 'required|string', - 'plan' => 'required', - 'months' => 'nullable|integer|min:2|max:60' - ]); - - if ($validator->fails()) { - return redirect()->back()->withErrors($validator)->withInput()->with('error', __('Dữ liệu không hợp lệ.')); - } - - $vmware_id = $this->sanitizeInput($request->product_id); - $plan = $request->input('plan'); - $months = $plan === 'other' ? (int) $request->input('months') : (int) $plan; - - if ($months < 2) { - return redirect()->back()->with('error', __('Thời hạn gia hạn tối thiểu là 2 tháng.')); - } - - // 2. Find Service & Verify Ownership - $vm = ModuleVmware::where('vmware_id', $vmware_id) - ->where('customer_id', $user->id) - ->first(); - - if (!$vm) { - return redirect()->back()->with('error', __('Không tìm thấy dịch vụ hoặc bạn không có quyền truy cập.')); - } - - // 3. Calculate Price based on Original Order -> OrderItem - $order = Order::find($vm->order_id); - if (!$order) { - return redirect()->back()->with('error', __('Không tìm thấy đơn hàng gốc của dịch vụ này.')); - } - - $orderItem = \App\Models\OrderItem::where('order_id', $order->id) - ->where('product_type', 4) // VPS - ->first(); - - if (!$orderItem) { - return redirect()->back()->with('error', __('Không tìm thấy thông tin sản phẩm trong đơn hàng.')); - } - - // Get Product Price - $product = null; - if ($orderItem->product_type == 4) { - $product = \App\Models\VPS::find($orderItem->product_id); - } elseif ($orderItem->product_type == 3) { - $product = \App\Models\Hosting::find($orderItem->product_id); - } - - if (!$product) { - return redirect()->back()->with('error', __('Sản phẩm không còn tồn tại.')); - } - - // Priority: Price Sale -> Price - $base_unit_price = (float) ($product->price_sale > 0 ? $product->price_sale : $product->price); - - // Calculate Addons Price - $addons_unit_price = 0; - if ($orderItem->addons && $orderItem->addons->count() > 0) { - foreach ($orderItem->addons as $addonPivot) { - if ($addonPivot->addonItems) { - $addons_unit_price += (float) ($addonPivot->addonItems->price); - } - } - } - - $total_unit_price = $base_unit_price + $addons_unit_price; - $total_cost = $total_unit_price * $months; - - // 4. Check Balance - if ($user->credit < $total_cost) { - return redirect()->back()->with('error', __('Số dư tài khoản không đủ để gia hạn (Cần: :amount). Vui lòng nạp thêm tiền.', ['amount' => number_format($total_cost) . ' VNĐ'])); - } - - // 5. Process Renewal - DB::beginTransaction(); - try { - // Deduct Credit - $user->decrement('credit', $total_cost); - - // Create Renewal Invoice (Paid) - $newInvoice = Invoice::create([ - 'customer_id' => $user->id, - 'status' => 1, // Paid - 'date' => now()->timestamp, // Using timestamp as per schema - 'due_date' => now()->timestamp, - 'total' => $total_cost, - // 'payment_method' => 'credit_balance', // Schema doesn't have this, maybe note? - 'note' => "Gia hạn dịch vụ VPS #{$vm->name} ({$months} tháng)" - ]); - - // Update VM Expiry - $current_due = $vm->next_due_date ? \Carbon\Carbon::parse($vm->next_due_date) : now(); - $new_due_date = $current_due->copy()->addMonths($months); - - $vm->update([ - 'next_due_date' => $new_due_date, - 'status' => 1, - ]); - - // TODO: Update OrderItem duration/dates if needed? Or just create new invoice record? - // The prompt was about "gia hạn thêm sản phẩm" (add renewal product?), but generally it just extends the service. - - DB::commit(); - - // Clear cache - Cache::forget("vm_info_{$vm->vmware_id}"); - - return redirect()->back()->with('success', __('Gia hạn dịch vụ thành công! Hạn sử dụng mới: :date', ['date' => $new_due_date->format('d/m/Y')])); - - } catch (\Exception $e) { - DB::rollBack(); - throw $e; - } - - } catch (\Exception $e) { - Log::error("Error renewing VM: " . $e->getMessage()); - return redirect()->back()->with('error', __('Có lỗi xảy ra khi gia hạn dịch vụ. Vui lòng thử lại sau.')); - } - } -} diff --git a/app/Http/Controllers/frontend/ServiceController_renew.php b/app/Http/Controllers/frontend/ServiceController_renew.php deleted file mode 100644 index 89ca262..0000000 --- a/app/Http/Controllers/frontend/ServiceController_renew.php +++ /dev/null @@ -1,158 +0,0 @@ - - /** - * Renew VPS Service - */ - public function renew(Request $request) - { - try { - $user = customer(); - if (!$user) { - return redirect()->route('user.login')->with('error', __('Vui lòng đăng nhập.')); - } - - // 1. Validate Input - $validator = FacadesValidator::make($request->all(), [ - 'product_id' => 'required|string', - 'plan' => 'required', - 'months' => 'nullable|integer|min:2|max:60' - ]); - - if ($validator->fails()) { - return redirect()->back()->withErrors($validator)->withInput()->with('error', __('Dữ liệu không hợp lệ.')); - } - - $vmware_id = $this->sanitizeInput($request->product_id); - $plan = $request->input('plan'); - $months = $plan === 'other' ? (int)$request->input('months') : (int)$plan; - - if ($months < 2) { - return redirect()->back()->with('error', __('Thời hạn gia hạn tối thiểu là 2 tháng.')); - } - - // 2. Find Service & Verify Ownership - $vm = ModuleVmware::where('vmware_id', $vmware_id) - ->where('customer_id', $user->id) - ->first(); - - if (!$vm) { - return redirect()->back()->with('error', __('Không tìm thấy dịch vụ hoặc bạn không có quyền truy cập.')); - } - - // 3. Calculate Price based on Original Order/InvoiceItem - // Strategy: Find the InvoiceItem from the Order associated with this VM. - // If multiple items, try to match type VPS (4). - - $order = Order::find($vm->order_id); - if (!$order) { - // Fallback if order missing (rare) - // Try finding by invoice_id if stored on VM? ModuleVmware has next_invoice but not current_invoice. - return redirect()->back()->with('error', __('Không tìm thấy đơn hàng gốc của dịch vụ này.')); - } - - // Find InvoiceItem - // Order has relationship to Invoice (order->invoice) - // Or Order has orderItems (which are InvoiceItems) - $invoiceItem = null; - if ($order->invoice) { - // Try finding item in the invoice related to this order - // Note: The modal uses $invoice->invoiceItem->first(). We should try to be specific. - // We don't have a direct link from ModuleVmware to InvoiceItem. - // But ModuleVmware links to Order, which links to items. - // Let's take the first item of type 4 (VPS) from the order's invoice. - $invoiceItem = $order->invoice->invoiceItem->where('type_id', 4)->first(); - if (!$invoiceItem) { - $invoiceItem = $order->invoice->invoiceItem->first(); - } - } - - if (!$invoiceItem) { - // Extreme fallback or failure - return redirect()->back()->with('error', __('Không tìm thấy thông tin giá của dịch vụ.')); - } - - // Calculate Unit Price (Monthly) - // 'amount' in InvoiceItem is total price for 'months' duration. - $billing_months = $invoiceItem->months > 0 ? $invoiceItem->months : 1; - if ($invoiceItem->amount <= 0) { - // If amount is 0 (free?), unit price is 0. - $base_unit_price = 0; - } else { - $base_unit_price = $invoiceItem->amount / $billing_months; - } - - // Calculate Addons Unit Price - $addons_unit_price = 0; - if ($invoiceItem->addons && $invoiceItem->addons->count() > 0) { - foreach ($invoiceItem->addons as $addonPivot) { - // Try to find price. Assuming Addon model has current price. - // Ideally we should use the price stored in pivot if available, but pivot structure is unknown. - // We'll use the Addon catalog price as fallback or primary if pivot doesn't store it. - // $addonPivot->addonItems returns the Addon model. - if ($addonPivot->addonItems) { - $addons_unit_price += $addonPivot->addonItems->price; - } - } - } - - $total_unit_price = $base_unit_price + $addons_unit_price; - $total_cost = $total_unit_price * $months; - - // 4. Check Balance - if ($user->credit < $total_cost) { - return redirect()->back()->with('error', __('Số dư tài khoản không đủ để gia hạn (Cần: :amount). Vui lòng nạp thêm tiền.', ['amount' => number_format($total_cost) . ' VNĐ'])); - } - - // 5. Process Renewal - DB::beginTransaction(); - try { - // Deduct Credit - $user->decrement('credit', $total_cost); - - // Create Renewal Invoice (Paid) - Optional but good for history - $newInvoice = Invoice::create([ - 'customer_id' => $user->id, - 'status' => 1, // Paid - 'date' => now(), - 'due_date' => now(), - 'total' => $total_cost, - 'payment_method' => 'credit_balance', // or similar - 'description' => "Gia hạn dịch vụ VPS #{$vm->name} ({$months} tháng)" - ]); - - // Update VM Expiry - // If current expiry is in the past, renew from NOW? Or from expiry? - // Usually from expiry if it's recent grace period. If long expired, maybe from now. - // Let's simply add to next_due_date. - - $current_due = $vm->next_due_date ? \Carbon\Carbon::parse($vm->next_due_date) : now(); - if ($current_due->isPast()) { - // If expired, maybe we should start from today? - // Or just extend the gap. User usually pays for the gap. - // Let's extend from current_due to maintain billing cycle. - } - $new_due_date = $current_due->copy()->addMonths($months); - - $vm->update([ - 'next_due_date' => $new_due_date, - 'status' => 1, // Ensure active if it was suspended - ]); - - // Log or Notify (Optional) - - DB::commit(); - - // Clear cache - Cache::forget("vm_info_{$vm->vmware_id}"); - - return redirect()->back()->with('success', __('Gia hạn dịch vụ thành công! Hạn sử dụng mới: :date', ['date' => $new_due_date->format('d/m/Y')])); - - } catch (\Exception $e) { - DB::rollBack(); - throw $e; - } - - } catch (\Exception $e) { - Log::error("Error renewing VM: " . $e->getMessage()); - return redirect()->back()->with('error', __('Có lỗi xảy ra khi gia hạn dịch vụ. Vui lòng thử lại sau.')); - } - } diff --git a/app/Http/Controllers/frontend/ShopController.php b/app/Http/Controllers/frontend/ShopController.php deleted file mode 100644 index 1d4ee01..0000000 --- a/app/Http/Controllers/frontend/ShopController.php +++ /dev/null @@ -1,161 +0,0 @@ - function ($query) { - $query->where('status', 1); // Only active groups - }]) - ->whereNotIn('id', [1, 2]) - ->where('status', 1) // Only active types - ->latest('id') - ->get(); - - // Handle product filtering - if ($request->type && $request->group) { - $product = $this->getProductsByTypeAndGroup($request->type, $request->group); - $group = $this->getGroupsByType($request->type); - - return view('frontend.shop', compact('title', 'type', 'group', 'product')); - } - - if ($request->type) { - $group = $this->getGroupsByType($request->type); - return view('frontend.shop', compact('title', 'type', 'group')); - } - - return view('frontend.shop', compact('title', 'type')); - } - - /** - * Add product to cart with validation - */ - public function store(AddToCartRequest $request, Cart $cart) - { - $product = $this->findProduct($request->type_id, $request->product_id); - - if (!$product) { - return back()->with('error', 'Sản phẩm không tồn tại!'); - } - - $cart->addToCart($request->user('users')->id, $request->product_price, $product); - - return redirect()->back()->with('success', 'Thêm vào giỏ hàng thành công!'); - } - - /** - * Display products by category slug (ProductCategories) - */ - public function show(Request $request, string $slug) - { - // Find category by slug - $category = ProductCategories::with(['parent', 'children']) - ->where('slug', $slug) - ->where('is_active', 1) - ->first(); - - if (!$category) { - abort(404, 'Danh mục sản phẩm không tồn tại'); - } - - // Get products with pagination and pricing - $products = $category->products() - ->with([ - 'pricings' => function ($query) { - $query->where('is_active', 1)->orderBy('price'); - }, - 'osVersions.osGroup', - 'controlPanels' - ]) - ->where('is_active', 1) - ->orderBy('created_at', 'desc') - ->paginate(12); - - return view('frontend.service.index', [ - 'category' => $category, - 'products' => $products, - 'breadcrumbs' => $this->crums->add(__('Dashboard'))->add('Sản phẩm thuộc ' . $category->name), - ]); - } - - /** - * Get products by type and group - */ - private function getProductsByTypeAndGroup(int $typeId, int $groupId) - { - return match ($typeId) { - 3 => Hosting::where('group_id', $groupId) - ->where('status', 1) - ->with(['group', 'type']) - ->get(), - 4 => VPS::where('group_id', $groupId) - ->where('status', 1) - ->with(['group', 'type', 'operatingSystems.osGroup']) - ->get(), - default => collect() - }; - } - - /** - * Get groups by type - */ - private function getGroupsByType(int $typeId) - { - return Group::with('type') - ->where('type_id', $typeId) - ->where('status', 1) - ->get(); - } - - /** - * Find product by type and ID - */ - private function findProduct(int $typeId, int $productId) - { - return match ($typeId) { - 3 => Hosting::where('id', $productId) - ->where('status', 1) - ->first(), - 4 => VPS::where('id', $productId) - ->where('status', 1) - ->first(), - default => null - }; - } -} diff --git a/app/Http/Controllers/frontend/TicketController.php b/app/Http/Controllers/frontend/TicketController.php deleted file mode 100644 index 683f973..0000000 --- a/app/Http/Controllers/frontend/TicketController.php +++ /dev/null @@ -1,212 +0,0 @@ -crums->add(__('Dashboard'), route('home'))->add(__('Yêu cầu hỗ trợ')); - return view("frontend.ticket.ticket", compact('title', 'breadcrumbs')); - } - - public function create() - { - $title = "Gửi yêu cầu hỗ trợ"; - $ticket = true; - $breadcrumbs = $this->crums->add(__('Dashboard'), route('home'))->add(__('DS Yêu cầu hỗ trợ'), route('ticket'))->add(__('Gửi yêu cầu hỗ trợ')); - $itemProduct = \App\Models\InvoiceItem::whereHas('invoice', function ($query) { - $query->where('customer_id', customer()->id); - }) - ->where('invoice_type', 1) - ->get(); - return view("frontend.ticket.add", compact('title', 'itemProduct', 'ticket', 'breadcrumbs')); - } - - public function store(Request $request, Upload $upload) - { - $validator = Validator::make( - $request->all(), - [ - 'full_name' => 'required', - 'email' => 'required', - 'subject' => 'required', - 'room' => 'required', - 'description' => 'required', - ], - [ - 'full_name' => [ - 'required' => 'Yêu cầu không hợp lệ' - ], - 'email' => [ - 'required' => 'Yêu cầu không hợp lệ' - ], - 'subject' => [ - 'required' => 'Tiêu đề không được để trống' - ], - 'room' => [ - 'required' => 'Vui lòng chọn phòng ban cần hỗ trợ' - ], - 'description' => [ - 'required' => 'Vui lòng nhập nội dung cần hỗ trợ' - ] - ] - ); - if ($validator->fails()) { - return back()->withInput()->withErrors($validator); - } - if ($request->fileTicket) { - $data = $upload->ImageUpload($request->fileTicket); - - if ($data['error']) { - return back()->withInput()->withErrors($data['message']); - } - } - $type = !empty($request->product) ? explode("|", $request->product) : []; - - try { - DB::beginTransaction(); - $dataJson = [ - 'product' => count($type) ? $type[1] : "", - 'product_type' => count($type) ? $type[0] : "", - 'file' => isset($data) ? $data['data'] : "" - ]; - $ticket = Ticket::create([ - 'subject' => $request->subject, - 'ticket_num' => random_int(1000000, 99999999), - 'description' => $request->description, - 'customer_id' => $request->user('users')->id, - 'data' => json_encode($dataJson), - 'room' => $request->room, - 'status' => 1 - ]); - DB::commit(); - // Dispatch job to send Telegram notification - $customer = \App\Models\Customer::find($ticket->customer_id); - \App\Jobs\Ticket\TicketJobs::dispatch($ticket, $customer); - } catch (\Exception $exception) { - DB::rollBack(); - return back()->withInput()->withErrors($exception->getMessage()); - } - return redirect()->route('ticket')->with('success', 'Gửi yêu cầu hỗ trợ thành công!'); - } - - public function show(Request $request) - { - $validator = Validator::make( - $request->all(), - [ - 'ticket_num' => 'required' - ], - [ - 'ticket_num' => [ - 'required' => 'Yêu cầu không hợp lệ' - ] - ] - ); - if ($validator->fails()) { - return back()->withErrors($validator); - } - $ticket = Ticket::with([ - 'Reply' => function ($query) { - $query->latest('id'); - }, - 'Reply.User', - 'Customer' - ])->where('ticket_num', $request->ticket_num)->latest('id')->get(); - - $title = "Ticket #" . $request->ticket_num; - - return view("frontend.ticket.view", compact('title', 'ticket')); - } - - public function ReplyStore(Request $request, Upload $upload) - { - $validator = Validator::make( - $request->all(), - [ - 'ticket_num' => 'required', - 'description' => 'required', - ], - [ - 'ticket_num' => [ - 'required' => 'Yêu cầu không hợp lệ' - ], - 'description' => [ - 'required' => 'Vui lòng nhập nội dung cần hỗ trợ' - ] - ] - ); - if ($validator->fails()) { - return back()->withInput()->withErrors($validator); - } - $ticket = Ticket::where('ticket_num', $request->ticket_num)->first(); - - if (!$ticket) { - return back()->withInput()->withErrors('Yêu cầu không hợp lệ'); - } - - if ($request->fileTicket) { - $data = $upload->ImageUpload($request->fileTicket); - - if ($data['error']) { - return back()->withInput()->withErrors($data['message']); - } - } - try { - DB::beginTransaction(); - $dataJson = json_decode($ticket->data, true); - $dataJson['file'] = isset($data) ? $data['data'] : ""; - Ticket::create([ - 'subject' => $ticket->subject, - 'ticket_num' => $ticket->ticket_num, - 'description' => $request->description, - 'customer_id' => $ticket->customer_id, - 'data' => json_encode($dataJson), - 'room' => $ticket->room, - 'status' => 1 - ]); - DB::commit(); - } catch (\Exception $exception) { - DB::rollBack(); - return back()->withInput()->withErrors($exception->getMessage()); - } - return back()->with('success', 'Trả lời yêu cầu hỗ trợ thành công!'); - } - - public function ClosedTicket(Request $request) - { - $validator = Validator::make( - $request->all(), - [ - 'ticket_num' => 'required' - ], - [ - 'ticket_num' => [ - 'required' => 'Yêu cầu không hợp lệ' - ] - ] - ); - if ($validator->fails()) { - return back()->withInput()->withErrors($validator); - } - try { - DB::beginTransaction(); - Ticket::where('ticket_num', $request->ticket_num)->update(['status' => 0]); - DB::commit(); - } catch (\Exception $exception) { - DB::rollBack(); - return back()->withInput()->withErrors($exception->getMessage()); - } - return redirect()->route('ticket')->with('success', 'Yêu cầu xử lý thành công!'); - } -} diff --git a/app/Http/Controllers/frontend/UserController.php b/app/Http/Controllers/frontend/UserController.php deleted file mode 100644 index 4ac8578..0000000 --- a/app/Http/Controllers/frontend/UserController.php +++ /dev/null @@ -1,408 +0,0 @@ -validate( - [ - 'email' => 'required', - 'password' => 'required' - ], - [ - 'email' => [ - 'required' => 'Vui lòng nhập Email' - ], - 'password' => [ - 'required' => 'Vui lòng nhập Mật Khẩu' - ] - ] - ); - $customer = Customer::where('email', $request->email); - - if (!$customer) { - return back()->withInput()->withErrors('Địa chỉ email không tồn tại'); - } - - if ( - auth('users')->attempt( - ['email' => $request->email, 'password' => $request->password], - $request->remember - ) - ) { - - if (auth('users')->user()->status == 2) { - - auth('users')->logout(); - - return back()->withInput()->withErrors('Vui lòng kích hoạt tài khoản để tiếp tục sử dụng dịch vụ.'); - } - if (auth('users')->user()->status == 0) { - - auth('users')->logout(); - - return back()->withInput()->withErrors('Tài khoản bị khoá, Vui lòng liên hệ admin để được hỗ trợ.'); - } - - $request->session()->regenerate(); - - $token = \auth('users')->user()->createToken('access_token', ['*'], Carbon::now()->addDay())->plainTextToken; - - Cookie::queue('aut_accessToken', $token, 24 * 60); - - $this->customerLogRepository->create([ - 'customer_id' => auth('users')->id(), - 'client_ip' => $request->getClientIp(), - 'agent' => $request->userAgent(), - 'action' => 'Đăng nhập' - ]); - - if (Cookie::has('prev_url') && Cookie::get('prev_url') !== route('home')) { - Cookie::queue(Cookie::forget('prev_url')); - return redirect(Cookie::get('prev_url')); - } - - return redirect()->route('home')->with('success', 'Đăng nhập tài khoản thành công!'); - } - return back()->withInput()->withErrors('Thông tin đăng nhập không chính xác!'); - } - - public function Logout() - { - $this->customerLogRepository->create([ - 'customer_id' => auth('users')->id(), - 'client_ip' => \request()->getClientIp(), - 'agent' => \request()->userAgent(), - 'action' => 'Đăng xuất' - ]); - - Cookie::queue(Cookie::forget('aut_accessToken')); - - auth('users')->user()->tokens()->delete(); - - auth('users')->logout(); - - return redirect()->route('user.login')->with('success', 'Đăng xuất tài khoản thành công!'); - } - - public function Information() - { - $title = "Thông tin tài khoản"; - $customer = auth('users')->user(); - - return view("frontend.user.account", compact('title', 'customer')); - } - - public function StoreInformation(UserStoreInformation $request) - { - $validated = $request->validated(); - - try { - DB::beginTransaction(); - - $user = user(); - $dataToUpdate = collect($validated)->except(['_token', '_method', 'email'])->toArray(); - $path = 'uploads/customers/' . $user->id . '/documents'; - - $fileFields = ['front_cccd', 'back_cccd', 'avatar']; - - foreach ($fileFields as $field) { - if ($request->hasFile($field)) { - $file = $request->file($field); - $filename = $field . '_' . $user->id . '_' . time() . '.' . $file->getClientOriginalExtension(); - - foreach (Storage::disk('public')->files($path) as $existingFile) { - if (Str::startsWith(basename($existingFile), $field . '_')) { - Storage::disk('public')->delete($existingFile); - } - } - - $file->storeAs($path, $filename, 'public'); - $dataToUpdate[$field] = $path . '/' . $filename; - } - } - - Customer::find($user->id)->update($dataToUpdate); - - DB::commit(); - return back()->with('success', 'Cập nhật thông tin tài khoản thành công'); - } catch (Exception $exception) { - DB::rollBack(); - return back()->withInput()->withErrors(['update_error' => $exception->getMessage()]); - } - } - - - public function updateNotification(Request $request) - { - $user = auth('users')->user(); - - $request->validate([ - 'email_marketing' => 'boolean', - 'receive_deposit' => 'boolean', - ]); - - $user->update([ - 'email_marketing' => $request->input('email_marketing', false), - 'receive_deposit' => $request->input('receive_deposit', false), - ]); - - return response()->json(['success' => true]); - } - - - public function Email() - { - $title = "Lịch sử Email"; - return view("frontend.email", compact('title')); - } - - public function ViewEmail(Request $request) - { - $validator = Validator::make( - $request->all(), - [ - 'id' => 'required|numeric|not__in:0' - ], - [ - 'id' => [ - 'required' => 'Vui lòng chọn Email' - ] - ] - ); - if ($validator->fails()) { - return back()->withErrors($validator); - } - $template = Mail::find($request->id); - if ($template) { - $title = $template->subject; - return view("emails.render", compact('title', 'template')); - } - return back()->withErrors("Yêu cầu không hợp lệ"); - } - - public function ChangePassword() - { - $title = "Thay đổi mật khẩu"; - $breadcrumbs = $this->crums->add(__('Dashboard'), route('home'))->add(__('Bảo mật tài khoản')); - return view("frontend.user.password", compact('title', 'breadcrumbs')); - } - - public function StoreChangePassword(Request $request) - { - $validator = Validator::make( - $request->all(), - [ - "password" => 'required', - "new_password" => 'required', - 'confirm_password' => 'required' - ], - [ - "password" => [ - 'required' => 'Vui lòng nhập mật khẩu!' - ], - "new_password" => [ - 'required' => 'Vui lòng nhập mật khẩu mới' - ], - 'confirm_password' => [ - 'required' => 'Vui lòng nhập lại mật khẩu mới' - ] - ] - ); - if ($validator->fails()) { - return back()->withInput()->withErrors($validator); - } - - if (!Hash::check($request->password, $request->user('users')->password)) { - return back()->withInput()->withErrors("Mật khẩu cũ không chính xác"); - } - - if ($request->new_password !== $request->confirm_password) { - return back()->withInput()->withErrors("Nhập lại mật khẩu mới không chính xác"); - } - try { - DB::beginTransaction(); - Customer::find($request->user('users')->id)->update([ - 'password' => Hash::make($request->new_password) - ]); - DB::commit(); - } catch (Exception $exception) { - DB::rollBack(); - return back()->withInput()->withErrors($exception->getMessage()); - } - - return back()->with('success', 'Thay đổi mật khẩu thành công!'); - } - - public function Register() - { - return view("frontend.register", [ - 'title' => 'Đăng ký tài khoản' - ]); - } - - public function RegisterStore(UserRegisterRequest $request) - { - try { - $validator = $request->validated(); - DB::beginTransaction(); - $code = Helper::generateUniqueCode(); - $id = Customer::insertGetId([ - 'firstname' => $validator['firstname'], - 'lastname' => $validator['lastname'], - 'email' => $validator['email'], - 'phone' => $validator['phone'], - 'avatar' => '/images/avatar.png', - 'email_hash' => $code, - 'status' => 2, - 'password' => Hash::make($validator['password']), - 'created_at' => Carbon::now(), - 'updated_at' => Carbon::now(), - ]); - - $jobs = new CustomerRegister(1, $code, $validator['email'], $id); - dispatch($jobs)->delay(now()->addSeconds(10)); - - DB::commit(); - - } catch (Exception $exception) { - DB::rollBack(); - return back()->withInput()->withErrors($exception->getMessage()); - } - return redirect()->route('user.login')->with('success', 'Đăng ký thành công. Vui lòng kiểm tra xác thực Email!'); - } - - public function Verify(Request $request) - { - $validator = Validator::make( - $request->all(), - [ - 'verify' => 'required', - ], - ['verify.required' => 'Yêu cầu không hợp lệ'] - ); - if ($validator->fails()) { - return redirect()->route('user.login')->withErrors($validator); - } - $code = base64_decode(SignRSA::DecryptFunc($request->verify)); - - $customer = Customer::where('email_hash', 'LIKE', "%$code%")->first(); - - if (!$customer) { - return redirect()->route('user.login')->withErrors('Yêu cầu không hợp lệ'); - } - - if ($customer->status == 1 || $customer->status == 0) { - return redirect()->route('user.login')->withErrors('Yêu cầu không hợp lệ'); - } - - try { - DB::beginTransaction(); - $customer->update([ - 'status' => 1, - 'email_verify' => Carbon::now() - ]); - ModuleSnapshotLimit::create([ - 'customer_id' => $customer->id, - 'limit' => 1, - 'used' => 0 - ]); - DB::commit(); - } catch (Exception $exception) { - DB::rollBack(); - return redirect()->route('user.login')->withErrors($exception->getMessage()); - } - return redirect()->route('user.login')->with('success', 'Kích hoạt tài khoản thành công'); - } - - public function Reset() - { - $title = "Quên mật khẩu"; - - return view("frontend.reset", compact('title')); - } - - public function ResetStore(Request $request) - { - - $request->validate( - [ - 'email' => 'required|email' - ], - [ - 'email' => [ - 'required' => 'Vui lòng nhập địa chỉ email!', - 'email' => 'Định dạng email không hợp lệ' - ] - ] - ); - - $user = Customer::where('email', $request->email)->first(); - if (!$user) { - return back()->withErrors('Không tìm thấy thông tin người dùng'); - } - - $password = Str::random(10); - - try { - DB::beginTransaction(); - $user->update([ - 'password' => Hash::make($password) - ]); - - $data = [ - 'company_name' => setting('setting.company'), - 'company_logo' => setting('setting.logo'), - 'password' => $password, - ]; - - $jobs = new PasswordRecoverJob($data, $user); - - dispatch($jobs)->delay(now()->addSeconds(10)); - DB::commit(); - } catch (Exception $exception) { - DB::rollBack(); - return back()->withErrors($exception->getMessage()); - } - return redirect()->route('user.login')->with('success', "Thiết lập đặt lại mật khẩu thành công. Vui lòng kiểm tra email và thực hiện xác thực theo hướng dẫn."); - - } -} diff --git a/app/Http/Controllers/frontend/Whois/WhoisController.php b/app/Http/Controllers/frontend/Whois/WhoisController.php deleted file mode 100644 index 2fa64e1..0000000 --- a/app/Http/Controllers/frontend/Whois/WhoisController.php +++ /dev/null @@ -1,88 +0,0 @@ -whoisService = $whoisService; - } - - public function index() - { - return view('frontend.whois.index'); - } - - /** - * Get domain whois information - * - * @param WhoisRequest $request - * @return JsonResponse - */ - public function getDomainInfo(WhoisRequest $request): JsonResponse - { - try { - $domain = $request->validated()['domain']; - $data = $this->whoisService->getDomainInfo($domain); - - return response()->json([ - 'success' => true, - 'message' => __('Domain information retrieved successfully.'), - 'data' => $data - ], 200); - - } catch (Exception $e) { - return response()->json([ - 'success' => false, - 'message' => __('Failed to retrieve domain information.'), - 'errors' => [ - 'domain' => [$e->getMessage()] - ] - ], 400); - } - } - - /** - * Check if domain is available - * - * @param WhoisRequest $request - * @return JsonResponse - */ - public function checkAvailability(WhoisRequest $request): JsonResponse - { - try { - $domain = $request->validated()['domain']; - $isAvailable = $this->whoisService->isDomainAvailable($domain); - $status = $this->whoisService->getDomainStatus($domain); - - return response()->json([ - 'success' => true, - 'message' => __('Domain availability checked successfully.'), - 'data' => [ - 'domain' => $domain, - 'available' => $isAvailable, - 'status' => $status - ] - ], 200); - - } catch (Exception $e) { - return response()->json([ - 'success' => false, - 'message' => __('Failed to check domain availability.'), - 'errors' => [ - 'domain' => [$e->getMessage()] - ] - ], 400); - } - } -} diff --git a/app/Http/Requests/CreateCustomerRequest.php b/app/Http/Requests/CreateCustomerRequest.php index 281c25a..74b8df7 100644 --- a/app/Http/Requests/CreateCustomerRequest.php +++ b/app/Http/Requests/CreateCustomerRequest.php @@ -22,8 +22,7 @@ class CreateCustomerRequest extends FormRequest public function rules(): array { return [ - 'firstname' => 'required', - 'lastname' => 'required', + 'fullname' => 'required', 'email' => 'required|email', 'password' => 'required', 'company' => 'nullable', diff --git a/app/Models/Customer.php b/app/Models/Customer.php index 1b77cd6..b18b149 100644 --- a/app/Models/Customer.php +++ b/app/Models/Customer.php @@ -54,8 +54,6 @@ class Customer extends Authenticatable * Appends for API */ protected $appends = [ - 'first_name', - 'last_name', 'point', 'gender_label', ]; diff --git a/app/Repositories/Customer/CustomerCachedRepository.php b/app/Repositories/Customer/CustomerCachedRepository.php index fec6716..53c90e1 100644 --- a/app/Repositories/Customer/CustomerCachedRepository.php +++ b/app/Repositories/Customer/CustomerCachedRepository.php @@ -16,19 +16,32 @@ class CustomerCachedRepository extends BaseCachedRepository implements CustomerR { return $this->customerRepository->getModel(); } - public function filter(array $data = [], array $relationships = [], array $withCount = [], array $select = ['*']) - { + public function filter( + array $data = [], + array $relationships = [], + array $withCount = [], + array $select = ['*'], + bool $returnQuery = false + ) { + if ( + $returnQuery || + !empty($data['paginate']) + ) { + return $this->customerRepository + ->filter($data, $relationships, $withCount, $select, $returnQuery); + } + $cacheKey = $this->getCacheKey(md5(json_encode([ - 'filterItem' => [ - 'data' => $data, - 'relationships' => $relationships, - 'select' => $select, - 'withCount' => $withCount - ] + 'filter' => compact('data', 'relationships', 'withCount', 'select') ]))); - return Cache::remember($cacheKey, $this->cacheTime, function () use ($data, $relationships, $select, $withCount) { - return $this->customerRepository->filter($data, $relationships, $withCount, $select); - }); + + return Cache::remember( + $cacheKey, + $this->cacheTime, + fn() => + $this->customerRepository + ->filter($data, $relationships, $withCount, $select, $returnQuery) + ); } public function findWithRelationships(int $id = 0, array $relationships = [], array $withCount = [], array $withSum = []) { diff --git a/app/Repositories/Customer/CustomerRepository.php b/app/Repositories/Customer/CustomerRepository.php index 5f4c0ba..3d0e8e7 100644 --- a/app/Repositories/Customer/CustomerRepository.php +++ b/app/Repositories/Customer/CustomerRepository.php @@ -11,14 +11,18 @@ class CustomerRepository extends BaseRepository implements CustomerRepositoryInt { return Customer::class; } - public function filter(array $data = [], array $relationships = [], array $withCount = [], array $select = ['*']) - { + public function filter( + array $data = [], + array $relationships = [], + array $withCount = [], + array $select = ['*'], + bool $returnQuery = false + ) { $model = $this->model->with($relationships)->select($select); if (isset($data['name']) && ! empty($data['name'])) { $model = $model->where(function ($query) use ($data) { $name = trim($data['name']); - $query->where("firstname", "LIKE", "%$name%"); - $query->orWhere("lastname", "LIKE", "%$name%"); + $query->where("fullname", "LIKE", "%$name%"); $query->orWhere("company", "LIKE", "%$name%"); }); } @@ -59,6 +63,9 @@ class CustomerRepository extends BaseRepository implements CustomerRepositoryInt if (count($withCount) > 0) { $model = $model->withCount($withCount); } + if ($returnQuery) { + return $model; + } if (isset($data['page'])) { return $model->paginate(15); } diff --git a/app/Repositories/Customer/CustomerRepositoryInterface.php b/app/Repositories/Customer/CustomerRepositoryInterface.php index 6926635..83631d2 100644 --- a/app/Repositories/Customer/CustomerRepositoryInterface.php +++ b/app/Repositories/Customer/CustomerRepositoryInterface.php @@ -6,7 +6,13 @@ use App\Repositories\BaseRepositoryInterface; interface CustomerRepositoryInterface extends BaseRepositoryInterface { - public function filter(array $data = [],array $relationships = [],array $withCount = [],array $select = ['*']); + public function filter( + array $data = [], + array $relationships = [], + array $withCount = [], + array $select = ['*'], + bool $returnQuery = false + ); public function findWithRelationships(int $id = 0, array $relationships = [],array $withCount = [], array $withSum = []); public function findBy(string $key = '',string $value = ''); } \ No newline at end of file diff --git a/config/cors.php b/config/cors.php index 0966399..d8e09b8 100644 --- a/config/cors.php +++ b/config/cors.php @@ -19,7 +19,7 @@ return [ 'allowed_methods' => ['*'], - 'allowed_origins' => ['*', 'http://localhost:5173'], + 'allowed_origins' => ['*', 'http://localhost:5173', 'http://localhost:3000', 'http://localhost:3001'], 'allowed_origins_patterns' => [], diff --git a/database/migrations/2026_02_16_153732_create_cache_table.php b/database/migrations/2026_02_16_153732_create_cache_table.php new file mode 100644 index 0000000..b9c106b --- /dev/null +++ b/database/migrations/2026_02_16_153732_create_cache_table.php @@ -0,0 +1,35 @@ +string('key')->primary(); + $table->mediumText('value'); + $table->integer('expiration'); + }); + + Schema::create('cache_locks', function (Blueprint $table) { + $table->string('key')->primary(); + $table->string('owner'); + $table->integer('expiration'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('cache'); + Schema::dropIfExists('cache_locks'); + } +}; diff --git a/resources/views/administrator/pages/customer/add.blade.php b/resources/views/administrator/pages/customer/add.blade.php index 3a2851d..00a4a20 100644 --- a/resources/views/administrator/pages/customer/add.blade.php +++ b/resources/views/administrator/pages/customer/add.blade.php @@ -7,20 +7,12 @@
- {{--First name--}} + {{--Fullname--}}
- +
- -
-
- {{--Last name--}} -
- -
- +
{{--Company--}} diff --git a/resources/views/administrator/pages/customer/datatable/action.blade.php b/resources/views/administrator/pages/customer/datatable/action.blade.php new file mode 100644 index 0000000..e69de29 diff --git a/resources/views/administrator/pages/customer/index.blade.php b/resources/views/administrator/pages/customer/index.blade.php index e7e00ca..6b7fa3b 100644 --- a/resources/views/administrator/pages/customer/index.blade.php +++ b/resources/views/administrator/pages/customer/index.blade.php @@ -1,111 +1,38 @@ -@extends("administrator.layout.master") -@section("content") - @if(auth()->guard('admins')->user()->can("manager customer")) -
-
-
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
- - -
-
-
- {{ $customers->count() }} Records Found -
+@section('breadcrumb') + @php + $breadcrumbItems = [ + ['label' => 'Customers', 'active' => true], + ]; + @endphp + +@endsection -
- - - - - - - - - - - - - - - @if($customers->count()) - @foreach($customers->all() as $item) - - - - - - - - - - - @endforeach - @endif - -
- - First NameLast NameCompanyEmail AddressServicesCreatedStatus
- - - $item->id]) }}" - title="View Profile"> {{ $item->firstname }} - - {{ $item->lastname }} - - {{ $item->company }} - - {{ $item->email }} - - {!! Helpers::get_count_service($item) !!} - - @time($item->created_at) - - {!! $item->getStatus() !!} -
+@section('content') + @if (auth()->guard('admins')->user()->can('manager customer')) +
+
+
+
+ +
- -
@else
Access Denied - You are not assigned to any Customer @@ -113,3 +40,9 @@
@endif @endsection + +@push('plugin-scripts') + @foreach (config('assets.datatable.js') as $datatable) + + @endforeach +@endpush \ No newline at end of file diff --git a/resources/views/administrator/pages/customer/info.blade.php b/resources/views/administrator/pages/customer/info.blade.php index 5c07928..3b884b4 100644 --- a/resources/views/administrator/pages/customer/info.blade.php +++ b/resources/views/administrator/pages/customer/info.blade.php @@ -17,13 +17,8 @@ - - - - - - - + + diff --git a/resources/views/administrator/pages/customer/profile.blade.php b/resources/views/administrator/pages/customer/profile.blade.php index 0b6af28..096817c 100644 --- a/resources/views/administrator/pages/customer/profile.blade.php +++ b/resources/views/administrator/pages/customer/profile.blade.php @@ -11,20 +11,12 @@
- {{--First name--}} + {{--Fullname--}}
- +
- -
-
- {{--Last name--}} -
- -
- +
{{--Company--}} diff --git a/resources/views/errors/404.blade.php b/resources/views/errors/404.blade.php index 38062fe..980779c 100644 --- a/resources/views/errors/404.blade.php +++ b/resources/views/errors/404.blade.php @@ -1,5 +1,4 @@ -{{-- resources/views/errors/404.blade.php --}} -@extends('frontend.layouts.master') {{-- hoặc layout livewire chính của bạn --}} +@extends('administrator.layout.master') @section('content')

404

diff --git a/resources/views/frontend/auth/login.blade.php b/resources/views/frontend/auth/login.blade.php deleted file mode 100644 index 246cc05..0000000 --- a/resources/views/frontend/auth/login.blade.php +++ /dev/null @@ -1,67 +0,0 @@ -@php - $setting = \App\Models\Setting::where('key', 'setting')->first(); - $data = json_decode($setting->value); -@endphp - -
- -

Đăng nhập

-

Vui lòng tạo tài khoản để quản lý, đăng ký dịch vụ

- -
- @csrf - - -
- - -

-
- - -
- -
- - - - - - - - -
-
- - - Đăng nhập - -
- -

- Chưa có tài khoản? - - Đăng ký - -

- -

- Quên mật khẩu? -

-
- -
diff --git a/resources/views/frontend/auth/main.blade.php b/resources/views/frontend/auth/main.blade.php deleted file mode 100644 index eccac95..0000000 --- a/resources/views/frontend/auth/main.blade.php +++ /dev/null @@ -1,193 +0,0 @@ - - - - - - - - Đăng ký & đăng nhập - - - - - - - @livewireStyles - - - - - -
- - - -
-
- -
- @include('frontend.auth.login') - @include('frontend.auth.register') -
- - -
-
-
-
-
-
-
- - - - @stack('viewScripts') - - - @include('alerts') - @livewireScripts - @fluxScripts - - - diff --git a/resources/views/frontend/auth/register.blade.php b/resources/views/frontend/auth/register.blade.php deleted file mode 100644 index 1be811b..0000000 --- a/resources/views/frontend/auth/register.blade.php +++ /dev/null @@ -1,192 +0,0 @@ -
- -

Tạo tài khoản mới

-

Vui lòng tạo tài khoản để quản lý, đăng ký dịch vụ

- -
- @csrf - - -
- - - {{ __('Họ') }} - - - - - - {{ __('Tên') }} - - -
- - -
- - - {{ __('Email') }} - - - - - - - {{ __('Số điện thoại') }} - - - -
- - -
- - - Mật khẩu - - - - - - - - - - -
-
- -
-

-

-
-
- - - - Xác nhận mật khẩu - - - - - - - - - - - - Mật khẩu không khớp - - - Mật khẩu trùng khớp - - - Vui lòng xác nhận mật khẩu - - -
- - - - Tạo tài khoản - - - -

- Đã có tài khoản? - - Đăng nhập - -

- -
diff --git a/resources/views/frontend/cart.blade.php b/resources/views/frontend/cart.blade.php deleted file mode 100644 index 1e67fa7..0000000 --- a/resources/views/frontend/cart.blade.php +++ /dev/null @@ -1,457 +0,0 @@ -@extends("frontend.main") -@section("content") - @php $total = 0 @endphp -
- @if(! empty( $cart) ) -
-
- @csrf - @if(count($cart)) -
- @foreach($cart as $key => $item) - @if($item['product_type'] == 4) - -
-
-
-
-

{{ $item['product']->name }}

-
-
- - - -
-
-
- -
- -
- -
-
-
- -
-
-
-
Chọn hệ điều hành
- -
- - - @if($item['os_group']->count()) - @foreach($item['os_group']->all() as $_item) -
- - -
- {{ $_item->name }} - - {{ $_item->name }} - -
-
- -
- -
-
- @endforeach - @endif -
-
-
Dịch vụ bổ sung
-
- @if($item['addon']->count()) - @foreach($item['addon']->all() as $_item) -
-
-
- -
-
- - - - - -
-
-
- @endforeach - @endif -
- -
-
- @else - -
-
-
- -
-

{{ $item['product']->name }}

-
- -
- - - -
-
-
- -
- -
- -
-
- -
- -
- -
-
-
-
- @endif - @endforeach -
- @endif - -
-
-
-
- Thông tin đơn hàng -
- @foreach($cart as $key => $item) - @if(! is_null(session('vps')) && $item['product_type'] === 4 ) - @foreach(session('vps')[$key]['addon'] as $_key => $_add) - @if($_add['value']) - @php($total += $_add['value'] * $_add['price'] * session('vps')[$key]['time_buy']) - @endif - @endforeach - @endif -
-
- {{ $item['product']->name }} - - @switch($item['product_type']) - @case(3) - x {{ (! is_null(session('hosting')) ? session('hosting')[$key]['time_buy'] : null) ?? - ((! is_null(old('hosting')) ? old('hosting')[$key]['time_buy'] : null ) ?? 12) - }} Tháng - @break - @case(4) - x {{ (! is_null(session('vps')) ? session('vps')[$key]['time_buy'] : null) ?? - ((! is_null(old('vps')) ? old('vps')[$key]['time_buy'] : null ) ?? 1) - }} Tháng - @break - @endswitch - -
-
- - @switch($item['product_type']) - @case(3) - - {{ number_format(($item['price'] * ((! is_null(session('hosting')) ? session('hosting')[$key]['time_buy'] : null) ?? - ((! is_null(old('hosting')) ? old('hosting')[$key]['time_buy'] : null ) ?? 12))),0,'.',',') }} - đ - @php($total += $item['price']* ((! is_null(session('hosting')) ? session('hosting')[$key]['time_buy'] : null) ?? - ((! is_null(old('hosting')) ? old('hosting')[$key]['time_buy'] : null ) ?? 12))) - @break - @case(4) - - {{ number_format($item['price'] * ((! is_null(session('vps')) ? session('vps')[$key]['time_buy'] : null) ?? - ((! is_null(old('vps')) ? old('vps')[$key]['time_buy'] : null ) ?? 1)),0,'.',',') }} - đ - @php($total += $item['price']* ((! is_null(session('vps')) ? session('vps')[$key]['time_buy'] : null) ?? - ((! is_null(old('vps')) ? old('vps')[$key]['time_buy'] : null ) ?? 1))) - @break - @endswitch - -
-
-
Dịch vụ bổ sung
- - @if($item['product_type'] === 4) - @if(! is_null(session('vps'))) - @foreach(session('vps')[$key]['addon'] as $_key => $_add) - @if($_add['value']) -
-
{{ strtoupper($_key) }}
-
-
- - - {{ number_format($_add['value'] * $_add['price'],0,'.','.') }} đ - -
-
X {{$_add['value']}}
-
-
- @endif - @endforeach - @endif - @endif -
-
- @endforeach - @if(session('coupon')) -
- - Giảm giá - - - @switch(session('coupon')['coupon_type']) - @case(1) - - {{ number_format((session('coupon')['coupon_value'] / 100 ) * $total,0,'.',',') }} - - đ - @php($total -= (session('coupon')['coupon_value'] / 100 ) * $total) - @break - @case(2) - - {{ number_format(session('coupon')['coupon_value'],0,'.',',') }} - - đ - @php($total -= session('coupon')['coupon_value']) - @break - @endswitch - -
- @endif - @if($total < 0) - @php($total = 0) - @endif -
- - Tổng tiền (chưa VAT) - - - - {{ number_format($total,0,'.',',') }} - - đ - -
-
- - VAT - - - - {{ number_format($total * (10/100),0,'.',',') }} - @php($total += $total * (10/100) ) - - đ - -
-
- - Thành tiền - - - - {{ number_format($total,0,'.',',') }} - - đ - -
-
- @if(! session('coupon')) -
-
- Bạn có mã giảm giá? -
-
-
- @csrf -
- - -
- -
-
- -
-
- @endif - -
- @else -
- -
- @endif -
-@endsection -@if(! empty($cart)) - @push('viewScripts') - - @endpush -@endif diff --git a/resources/views/frontend/cart/index.blade.php b/resources/views/frontend/cart/index.blade.php deleted file mode 100644 index 46ff248..0000000 --- a/resources/views/frontend/cart/index.blade.php +++ /dev/null @@ -1,165 +0,0 @@ -@extends('frontend.layouts.master') - -@push('viewStyles') - - -@endpush - -@section('content') -
- @csrf -
- @if ($cartItems && count($cartItems) > 0) - @php $total = 0; @endphp - - -
-

Cấu hình tùy chọn và tiếp tục thanh toán

-
- -
- -
- @foreach ($cartItems as $index => $item) - @php - $product = $item['product']; - $total += $item['price']; - $addons = $item['addon'] ?? []; - $osGroups = $item['os_group'] ?? []; - @endphp - - - - - @include('frontend.cart.partials.domain-input') - - - @include('frontend.cart.partials.product-details', [ - 'product' => $product, - 'item' => $item - ]) - - - @if ($item['product_type'] == 4 && isset($item['os_group']) && count($item['os_group']) > 0) - @include('frontend.cart.partials.os-select', [ - 'item' => $item, - 'index' => $index - ]) - @endif - @endforeach -
- - -
- - - - - - -
- - Đặt hàng - -
-
-
- @else - @include('frontend.cart.partials.empty-cart') - @endif -
- -@endsection - -@push('viewScripts') - - -@endpush - diff --git a/resources/views/frontend/cart/partials/domain-input.blade.php b/resources/views/frontend/cart/partials/domain-input.blade.php deleted file mode 100644 index 3673e55..0000000 --- a/resources/views/frontend/cart/partials/domain-input.blade.php +++ /dev/null @@ -1,45 +0,0 @@ -
-

{{ __('Domain') }}

- - - - - - -
\ No newline at end of file diff --git a/resources/views/frontend/cart/partials/empty-cart.blade.php b/resources/views/frontend/cart/partials/empty-cart.blade.php deleted file mode 100644 index 08fc37e..0000000 --- a/resources/views/frontend/cart/partials/empty-cart.blade.php +++ /dev/null @@ -1,34 +0,0 @@ -
- - - - - -
\ No newline at end of file diff --git a/resources/views/frontend/cart/partials/os-select.blade.php b/resources/views/frontend/cart/partials/os-select.blade.php deleted file mode 100644 index 678a15d..0000000 --- a/resources/views/frontend/cart/partials/os-select.blade.php +++ /dev/null @@ -1,99 +0,0 @@ -
-

{{ __('Hệ điều hành') }}

- - - - - - - - -
-
-
{{ __('Thông tin hệ điều hành') }}
- -
-

- {{ __('Bạn đã chọn hệ điều hành. Hệ điều hành sẽ được cài đặt tự động khi máy chủ được tạo.') }} -

-
- - -
diff --git a/resources/views/frontend/cart/partials/product-details.blade.php b/resources/views/frontend/cart/partials/product-details.blade.php deleted file mode 100644 index a4f9b45..0000000 --- a/resources/views/frontend/cart/partials/product-details.blade.php +++ /dev/null @@ -1,70 +0,0 @@ -
- - - - - - - - -
\ No newline at end of file diff --git a/resources/views/frontend/cart/partials/skeleton-loader.blade.php b/resources/views/frontend/cart/partials/skeleton-loader.blade.php deleted file mode 100644 index 5e0329a..0000000 --- a/resources/views/frontend/cart/partials/skeleton-loader.blade.php +++ /dev/null @@ -1,28 +0,0 @@ -@props(['type' => 'default', 'lines' => 3, 'height' => 'h-4']) - -@php - $skeletonTypes = [ - 'text' => 'h-4 bg-gray-200 rounded', - 'title' => 'h-6 bg-gray-200 rounded', - 'button' => 'h-10 bg-gray-200 rounded-lg', - 'input' => 'h-12 bg-gray-200 rounded-lg', - 'card' => 'h-32 bg-gray-200 rounded-lg', - 'avatar' => 'w-8 h-8 bg-gray-200 rounded-full', - 'icon' => 'w-5 h-5 bg-gray-200 rounded', - 'image' => 'w-8 h-8 bg-gray-200 rounded object-cover', - ]; - - $skeletonClass = $skeletonTypes[$type] ?? $skeletonTypes['text']; -@endphp - -
- @if ($type === 'card') -
- @elseif ($type === 'avatar' || $type === 'icon' || $type === 'image') -
- @else - @for ($i = 0; $i < $lines; $i++) -
- @endfor - @endif -
\ No newline at end of file diff --git a/resources/views/frontend/cart/partials/vps-features.blade.php b/resources/views/frontend/cart/partials/vps-features.blade.php deleted file mode 100644 index 397c851..0000000 --- a/resources/views/frontend/cart/partials/vps-features.blade.php +++ /dev/null @@ -1,49 +0,0 @@ -@php - $features = [ - 'cpu' => ['icon' => 'cpu.svg', 'label' => 'CPU', 'unit' => 'vCore'], - 'ram' => ['icon' => 'ram.svg', 'label' => 'RAM', 'unit' => 'GB'], - 'disk' => ['icon' => 'storage.svg', 'label' => 'Disk', 'unit' => 'GB'], - 'gpu' => ['icon' => 'video.svg', 'label' => 'GPU', 'unit' => 'GB'], - 'ip' => ['icon' => 'network.svg', 'label' => 'IP Public', 'unit' => 'IP'], - 'bandwidth' => ['icon' => 'bandwidth.svg', 'label' => 'Băng thông', 'unit' => 'GB'] - ]; -@endphp - -
- - - - - -
\ No newline at end of file diff --git a/resources/views/frontend/domain.blade.php b/resources/views/frontend/domain.blade.php deleted file mode 100644 index b63de7e..0000000 --- a/resources/views/frontend/domain.blade.php +++ /dev/null @@ -1,10 +0,0 @@ -@extends("frontend.main") -@section("content") -
-
- -
-
-@endsection diff --git a/resources/views/frontend/email.blade.php b/resources/views/frontend/email.blade.php deleted file mode 100644 index 1a7294d..0000000 --- a/resources/views/frontend/email.blade.php +++ /dev/null @@ -1,5 +0,0 @@ -@extends("frontend.main") -@section("content") - @livewire('customer-email-history') - @livewireScripts -@endsection diff --git a/resources/views/frontend/footer.blade.php b/resources/views/frontend/footer.blade.php deleted file mode 100644 index 5db13ec..0000000 --- a/resources/views/frontend/footer.blade.php +++ /dev/null @@ -1,7 +0,0 @@ -
-
-

- Copyright © 2024 {{ setting('company') }}. All Rights Reserved. -

-
-
diff --git a/resources/views/frontend/head.blade.php b/resources/views/frontend/head.blade.php deleted file mode 100644 index c9c40ac..0000000 --- a/resources/views/frontend/head.blade.php +++ /dev/null @@ -1,19 +0,0 @@ - - - - {{ $title }} - - - - - - - - @stack('stylesLivewire') - @stack('viewStyles') - - diff --git a/resources/views/frontend/home.blade.php b/resources/views/frontend/home.blade.php deleted file mode 100644 index 84ef49a..0000000 --- a/resources/views/frontend/home.blade.php +++ /dev/null @@ -1,271 +0,0 @@ -@extends("frontend.main") -@section("content") -
-
-
-
-
- Dịch vụ của tôi -
-
-
Dịch vụ
-
{{count($vmware) + count($hosting)}}
-
-
-
-
-
-
-
-
- Dịch vụ của tôi -
-
-
Tên miền
-
{{count($domain)}}
-
-
-
-
-
-
-
-
- Dịch vụ của tôi -
-
-
Hoá đơn
-
{{count($invocie_unpaid)}}
-
-
-
-
-
-
-
-
- Dịch vụ của tôi -
-
-
Hỗ trợ
-
{{count($ticket)}}
-
-
-
-
-
-
-
-
-

Thống kê dịch vụ

-
-
First Name{{ $customer->firstname }}
Last Name{{ $customer->lastname }}Fullname{{ $customer->fullname }}
Company
- - - - - - - - - - - - - - - - - - - -
Dịch vụSố Lượng
- VPS - VPS{{ count($vmware) }} - Chi tiết -
- Hosting - Hosting{{ count($hosting) }} - Chi tiết -
-
-
-
-
-
-

Thông tin cơ bản

-
- - - - - - - - - - - - - - - -
- Số dư tài khoản - - {{ number_format(auth('users')->user()->credit,0,',','.') }} đ -
- Tổng tiền đã chi - - {{ number_format(((int)auth('users')->user()->total - (int)auth('users')->user()->credit),0,',','.') }} đ -
- Tổng tiền đã nạp - - {{ number_format((int)auth('users')->user()->total ,0,',','.') }} đ -
-
-
-
-
-
-
-
-

Mã giảm giá

- @if($discount->count()) - - @else - - @endif -
-
-
-
-

Thông báo

-
-
- @foreach($posts->all() as $item) -
-
P
-
- - {{ $item->name }} - -
-
{{ \Carbon\Carbon::parse($item->created_at)->diffForHumans() }}
-
-
- -
- @endforeach -
-
-
-
-
-@endsection -@push('viewStyles') - - - -@endpush -@push('viewScripts') - - - -@endpush diff --git a/resources/views/frontend/home/card/service.blade.php b/resources/views/frontend/home/card/service.blade.php deleted file mode 100644 index 3dee51b..0000000 --- a/resources/views/frontend/home/card/service.blade.php +++ /dev/null @@ -1,74 +0,0 @@ -@php - $serviceCards = [ - [ - 'icon' => 'box', - 'iconColor' => 'text-green-400', - 'badgeColor' => 'bg-green-400', - 'title' => __('Services'), - 'value' => count($vmware ?? []) + count($hosting ?? []), - 'label' => __('Services'), - 'tooltip' => __('Services') - ], - [ - 'icon' => 'credit-card', - 'iconColor' => 'text-primary', - 'badgeColor' => 'bg-primary', - 'title' => __('Balance'), - 'value' => number_format(auth('users')->user()->credit, 0, ',', '.') . ' đ', - 'label' => __('Balance'), - 'tooltip' => __('Balance') - ], - [ - 'icon' => 'file-text', - 'iconColor' => 'text-blue-600', - 'badgeColor' => 'bg-blue-600', - 'title' => __('Invoices'), - 'value' => count($invocie_unpaid ?? []), - 'label' => __('Invoices'), - 'tooltip' => __('Invoices') - ], - [ - 'icon' => 'help-circle', - 'iconColor' => 'text-red-600', - 'badgeColor' => 'bg-red-600', - 'title' => __('Support'), - 'value' => count($ticket ?? []), - 'label' => __('Support'), - 'tooltip' => __('Support') - ], - [ - 'icon' => 'globe', - 'iconColor' => 'text-purple-600', - 'badgeColor' => 'bg-purple-600', - 'title' => __('Domains'), - 'value' => count($domain ?? []), - 'label' => __('Domains'), - 'tooltip' => __('Domains') - ] - ]; -@endphp - -
- @foreach($serviceCards as $index => $card) - - @endforeach -
- -@push('scripts') - -@endpush diff --git a/resources/views/frontend/home/index.blade.php b/resources/views/frontend/home/index.blade.php deleted file mode 100644 index a8db9a1..0000000 --- a/resources/views/frontend/home/index.blade.php +++ /dev/null @@ -1,173 +0,0 @@ -@extends('frontend.layouts.master') - -@section('content') -
- -
- @include('frontend.home.card.service') -
- - - -
- -
- -
-
- -

Thông tin cá nhân

-
-
- -
-
    -
  • - Họ và tên: - {{ customer()?->firstname . ' ' . customer()?->lastname }} -
  • -
  • - Email: {{ customer()?->email }} - @if (customer()?->email_hash) - - Đã xác thực - - @else - - Chưa xác thực - - @endif -
  • -
  • - Điện thoại: - - {{ customer()?->phone }} - - - - -
  • -
  • - Đặc quyền: Cơ bản -
  • - -
-
- -
- -
- -
-
- -

Thống kế Credits và Points

-
-
- -
-
-
- Credit - Số dư - {{ format_price(customer()?->credit) }} -
-
- Credit - Đã chi - {{ format_price((int) customer()?->total - (int) customer()?->credit) }} -
-
- Credit - Đã nạp - {{ format_price((int) customer()?->total) }} -
-
- Credit - Points - {{ format_point(0) }} -
-
- Credit - Tổng tích điểm - {{ format_point(0) }} -
-
- Credit - Hạng - Cơ bản -
-
-
- -
-
- -
- -
-
- -

Hướng dẫn

-
-
- -
- -
-
-
-
-@endsection - -@push('viewScripts') - -@endpush diff --git a/resources/views/frontend/invoice/index.blade.php b/resources/views/frontend/invoice/index.blade.php deleted file mode 100644 index afd6709..0000000 --- a/resources/views/frontend/invoice/index.blade.php +++ /dev/null @@ -1,4 +0,0 @@ -@extends("frontend.layouts.master") -@section("content") - @livewire('invoice') -@endsection diff --git a/resources/views/frontend/invoice/show.blade.php b/resources/views/frontend/invoice/show.blade.php deleted file mode 100644 index d94783d..0000000 --- a/resources/views/frontend/invoice/show.blade.php +++ /dev/null @@ -1,262 +0,0 @@ -@extends('frontend.layouts.master') - -@section('content') - @if(!$invoice) -
-
-
-
- - - -
-

{{ __('Invoice not found') }}

-

{{ __('The invoice you are looking for could not be found or you do not have permission to view it.') }}

- -
-
-
- @else -
-
- -
- -
-
-

Thông tin đơn hàng

- - Mã đơn: #{{ $invoice->order_num ?? 'N/A'}} - -
-
- - -
-
-
-

Thông tin đơn hàng

-
-
- Ngày đặt: - - @if ($invoice->date) - {{ date('d/m/Y H:i', strtotime($invoice->date)) }} - @else - N/A - @endif - -
-
- Trạng thái: - - @if ($invoice->status == 1) - Chờ - thanh toán - @elseif($invoice->status == 2) - Đã - thanh toán - @else - Khác - @endif - -
-
- Tên miền (Domain): - {{ $invoice->invoiceItem->first()->server_name ?? '' }} - -
-
-
-
-

Thông tin khách hàng

-
-
- Họ tên: - {{ $invoice->customer->firstname . ' ' . $invoice->customer->lastname }} -
-
- Số điện thoại: - {{ $invoice->customer->phone }} -
-
- Email: - {{ $invoice->customer->email }} -
-
-
-
-
- - -
-

Chi tiết sản phẩm

- -
- - - - - - - - - - @foreach ($invoice->invoiceItem as $item) - - - - - - - - @foreach ($item->addons as $addon) - - - - - - @endforeach - @endforeach - - - @php - $addonTotal = 0; - foreach ($invoice->invoiceItem as $item) { - foreach ($item->addons as $addon) { - $addonTotal += $addon->price * $item->months; - } - } - $productTotal = $invoice->total - $addonTotal; - @endphp - - - - - - - - - - - @if ($invoice->discount_value) - - - - - - @endif - - - - - - -
- Mô tả - - Số lượng - - Giá -
-
Sản phẩm - {{ $item->product->name ?? 'Không xác định' }} -
-
- Loại: - @if ($item->product_type == 1) - Shared Hosting - @elseif($item->product_type == 4) - VPS - @elseif($item->product_type == 3) - Dedicated Server - @else - Khác - @endif -
-
- Hệ điều hành: -
-
-
- {{ $item->os->osGroup->name }} -
-
{{ $item->os->osGroup->name }} - {{ $item->os->version }} -
-
-
- {{ $item->quantity }} - -

- {{ format_price($item->price) }} - /{{ $item->months }}tháng -

-
-
- - Addon - - {{ $addon->addonItems->name }} đơn giá: - ({{ format_price($addon->addonItems->price) }}) - / {{ $addon->addonItems->step . $addon->addonItems->prefix }} - -
-
- {{ $addon->qty }} / {{ $addon->addonItems->prefix }} - ({{ $item->months }} tháng) - - {{ number_format($addon->price * $item->months) }} VNĐ -
Giá trị sản phẩm - {{ number_format($productTotal) }} VNĐ -
Tổng addon - {{ number_format($addonTotal) }} VNĐ -
Giảm giá - -{{ number_format($invoice->discount_value) }} VNĐ -
Tổng cộng - {{ number_format($invoice->total) }} VNĐ -
-
-
-
- - - @if ($invoice->note) -
-

Ghi chú đơn hàng

-

{{ $invoice->note }}

-
- @endif - - -
-
-
- - - -
-
-

Bạn cần hỗ trợ?

-

Nếu bạn gặp bất kỳ vấn đề nào khi thanh toán, vui lòng liên hệ với - chúng tôi thông qua.
Hotline {{ setting('setting.tel') }} hoặc - thông qua Email {{ setting('setting.support') }}

-
-
-
-
-
- @endif -@endsection diff --git a/resources/views/frontend/invoice/view.blade.php b/resources/views/frontend/invoice/view.blade.php deleted file mode 100644 index a4c10ac..0000000 --- a/resources/views/frontend/invoice/view.blade.php +++ /dev/null @@ -1,163 +0,0 @@ -@php - use Carbon\Carbon; - use App\Http\Helpers\Helper; -@endphp - -@extends("frontend.main") -@section("content") -
-
-
-
-
Khách hàng
-
{{ $invoice->Customer->firstname . " " . $invoice->Customer->lastname }}
-
Điện thoại: {{ $invoice->Customer->phone }}
-
Email: {{ $invoice->Customer->email }}
-
Địa chỉ: {{ $invoice->Customer->address }}
-
-
-
Thông tin hoá đơn
-
Mã hoá đơn: #{{ $invoice->id }}
-
Ngày tạo: {{ Carbon::parse($invoice->date)->format("d/m/Y") }}
-
Hạn thanh toán: {{ Carbon::parse($invoice->due_date)->format("d/m/Y") }}
-
Tổng tiền: {{ number_format($invoice->total,0,',','.') }} đ
-
-
-
-
-
Chi tiết hoá đơn
- - - - - - - - - - - @if($invoice->InvoiceItem->count()) - @foreach($invoice->InvoiceItem->all() as $key => $item) - - - - - - - @endforeach - @php($discount = 0) - @if($invoice->Order) - - - - - @endif - - - - - - - - - - - - - @endif - -
#Dịch vụThời hạnSố tiền
{{ $key + 1 }} - {{ $item->description }} - - - {!! Helper::ViewBillingCycle($item->billing) !!} - - {{ number_format($item->amount * Helper::BillingFormat($item->billing),0,',','.') }} - đ -
- Giảm giá - - {{ number_format($invoice->Order->discount_value,0,',','.') }} đ - @php( $discount = $invoice->Order->discount_value) -
- Thành tiền (Chưa VAT) - - {{ number_format($invoice->InvoiceItem->sum('amount') * Helper::BillingFormat($item->billing) - $discount,0,',','.') }} - đ -
- VAT (10%) - - {{ number_format(($invoice->InvoiceItem->sum('amount') * Helper::BillingFormat($item->billing) - $discount) * (10/100),0,',','.') }} - đ -
- Tổng cộng - - {{ number_format($invoice->total,0,',','.') }} đ -
-
- -
-
-
Thông tin thanh toán
-
-
-
Trạng thái thanh toán:
-
-
- {!! Helper::ViewInvoiceStatus($invoice->status) !!} -
-
- @if($invoice->status === 1) -
-
-
Ngày thanh toán:
-
-
- {{ Carbon::parse($invoice->date_paid)->format('d/m/Y') }} -
-
- {{--
-
-
Phương thức thanh toán:
-
-
- {{ $invoice->Payment->name }} -
-
--}} - @endif - @if($invoice->status === 0) -
-
- -
- -
-
Tổng thanh toán:
-
-
-
{{ number_format($invoice->total,0,',','.') }} đ
-
-
- -
-
- @endif - -
-
- - @push('viewScripts') - - - @endpush - @push('viewStyles') - - @endpush -@endsection diff --git a/resources/views/frontend/layouts/head.blade.php b/resources/views/frontend/layouts/head.blade.php deleted file mode 100644 index f54cae3..0000000 --- a/resources/views/frontend/layouts/head.blade.php +++ /dev/null @@ -1,32 +0,0 @@ - - - - {{ $title ?? 'Thế Giới Số' }} - - - - - - - - - - - - - - - @stack('stylesLivewire') - @stack('viewStyles') - diff --git a/resources/views/frontend/layouts/master.blade.php b/resources/views/frontend/layouts/master.blade.php deleted file mode 100644 index ca4d76b..0000000 --- a/resources/views/frontend/layouts/master.blade.php +++ /dev/null @@ -1,37 +0,0 @@ - - -@include('frontend.layouts.head') - - - - -
- -
- @include('frontend.layouts.sidebar') -
-
-
- @include('frontend.layouts.topbar') - - @include('frontend.layouts.partials.bottom-topbar') -
- @yield('content') -
-
- - @include('frontend.layouts.partials.floating') - - @include('alerts') -
- @include('frontend.script') - - - diff --git a/resources/views/frontend/layouts/partials/account.blade.php b/resources/views/frontend/layouts/partials/account.blade.php deleted file mode 100644 index de65819..0000000 --- a/resources/views/frontend/layouts/partials/account.blade.php +++ /dev/null @@ -1,65 +0,0 @@ -
- - - - -
- -
-
diff --git a/resources/views/frontend/layouts/partials/bottom-topbar.blade.php b/resources/views/frontend/layouts/partials/bottom-topbar.blade.php deleted file mode 100644 index 8d74739..0000000 --- a/resources/views/frontend/layouts/partials/bottom-topbar.blade.php +++ /dev/null @@ -1,12 +0,0 @@ - diff --git a/resources/views/frontend/layouts/partials/breadcrumbs.blade.php b/resources/views/frontend/layouts/partials/breadcrumbs.blade.php deleted file mode 100644 index d75b846..0000000 --- a/resources/views/frontend/layouts/partials/breadcrumbs.blade.php +++ /dev/null @@ -1,43 +0,0 @@ -@if (isset($breadcrumbs) && !empty($breadcrumbs->getBreadcrumbs())) - -@endif diff --git a/resources/views/frontend/layouts/partials/floating.blade.php b/resources/views/frontend/layouts/partials/floating.blade.php deleted file mode 100644 index f5bc8a2..0000000 --- a/resources/views/frontend/layouts/partials/floating.blade.php +++ /dev/null @@ -1,9 +0,0 @@ -
- -
diff --git a/resources/views/frontend/layouts/partials/notification-script.blade.php b/resources/views/frontend/layouts/partials/notification-script.blade.php deleted file mode 100644 index 34576ae..0000000 --- a/resources/views/frontend/layouts/partials/notification-script.blade.php +++ /dev/null @@ -1,67 +0,0 @@ -@if(customer()) - -@endif diff --git a/resources/views/frontend/layouts/sidebar.blade.php b/resources/views/frontend/layouts/sidebar.blade.php deleted file mode 100644 index 6a12e1d..0000000 --- a/resources/views/frontend/layouts/sidebar.blade.php +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/resources/views/frontend/layouts/topbar.blade.php b/resources/views/frontend/layouts/topbar.blade.php deleted file mode 100644 index c922085..0000000 --- a/resources/views/frontend/layouts/topbar.blade.php +++ /dev/null @@ -1,92 +0,0 @@ -
- - -
- - - -
- -
diff --git a/resources/views/frontend/logs.blade.php b/resources/views/frontend/logs.blade.php deleted file mode 100644 index 77e7c3d..0000000 --- a/resources/views/frontend/logs.blade.php +++ /dev/null @@ -1,38 +0,0 @@ -@extends("frontend.main") -@section("content") -
-
- - - - - - - - - - - @foreach($logs->all() as $item) - - - - - - - @endforeach - -
Client IPHoạt độngUser AgentThời gian
- {{ $item->client_ip }} - - {{ $item->action }} - - {{ $item->agent }} - - {{ $item->created_at }} -
-
-
- {{ $logs->links() }} -
-
-@endsection diff --git a/resources/views/frontend/main.blade.php b/resources/views/frontend/main.blade.php deleted file mode 100644 index 9790b7b..0000000 --- a/resources/views/frontend/main.blade.php +++ /dev/null @@ -1,89 +0,0 @@ - - -@include("frontend.head") - - -
- -
- -
- @include("frontend.sidebar") -
-

{{ $title }}

- @yield("content") -
- @include("frontend.footer") -
-@include("frontend.script") - - - diff --git a/resources/views/frontend/order/index.blade.php b/resources/views/frontend/order/index.blade.php deleted file mode 100644 index b037cc4..0000000 --- a/resources/views/frontend/order/index.blade.php +++ /dev/null @@ -1,5 +0,0 @@ -@extends('frontend.layouts.master') - -@section('content') - @livewire('order.order-list') -@endsection diff --git a/resources/views/frontend/order/modal/confirm.blade.php b/resources/views/frontend/order/modal/confirm.blade.php deleted file mode 100644 index 7752d79..0000000 --- a/resources/views/frontend/order/modal/confirm.blade.php +++ /dev/null @@ -1,18 +0,0 @@ - -
-
- Xác nhận thanh toán - Bạn có chắc chắn muốn thanh toán đơn hàng này?
- Hành động này không thể hoàn tác và số dư sẽ trừ vào tài khoản!
-
- -
- -
- @csrf - - Xác nhận thanh toán -
-
-
-
diff --git a/resources/views/frontend/order/modal/destroy.blade.php b/resources/views/frontend/order/modal/destroy.blade.php deleted file mode 100644 index 3ae87fa..0000000 --- a/resources/views/frontend/order/modal/destroy.blade.php +++ /dev/null @@ -1,19 +0,0 @@ - -
-
- Xác nhận huỷ đơn hàng - Bạn có chắc chắn muốn huỷ đơn hàng này?
- Hành động này không thể hoàn tác và đơn hàng sẽ bị xoá khỏi hệ thống.
-
- -
- -
- @csrf - @method('DELETE') - - Xác nhận huỷ -
-
-
-
diff --git a/resources/views/frontend/order/payment.blade.php b/resources/views/frontend/order/payment.blade.php deleted file mode 100644 index 8a13a48..0000000 --- a/resources/views/frontend/order/payment.blade.php +++ /dev/null @@ -1,253 +0,0 @@ -@extends('frontend.layouts.master') - -@section('content') -
-
- -
- -
-
-

Thanh toán đơn hàng

- - Mã đơn: #{{ $orders->order_num }} - -
-
- - -
-
-
-

Thông tin đơn hàng

-
-
- Ngày đặt: - {{ date('d/m/Y H:i', $orders->date) }} -
-
- Trạng thái: - - @if ($orders->status == 0) - Chờ xử - lý - @elseif($orders->status == 1) - Đã kích - hoạt - @elseif($orders->status == 2) - Đã hủy - @elseif($orders->status == 3) - Đang xử - lý - @else - Khác - @endif - -
-
- Tên miền (Domain): - {{ $orders->orderItems[0]->server_name }} -
-
-
-
-

Thông tin khách hàng

-
-
- Họ tên: - {{ $orders->customer->firstname . ' ' . $orders->customer->lastname }} -
-
- Số điện thoại: - {{ $orders->customer->phone }} -
-
- Email: - {{ $orders->customer->email }} -
-
-
-
-
- - -
-

Chi tiết sản phẩm

- -
- - - - - - - - - - @foreach ($orders->orderItems as $item) - - - - - - - - @foreach ($item->addons as $addon) - - - - - - @endforeach - @endforeach - - - @php - $addonTotal = 0; - foreach ($orders->orderItems as $item) { - foreach ($item->addons as $addon) { - $addonTotal += $addon->price * $item->months; - } - } - $productTotal = $orders->amount - $addonTotal; - @endphp - - - - - - - - - - - @if ($orders->discount_value) - - - - - - @endif - - - - - - -
- Mô tả - - Số lượng - - Giá -
-
Sản phẩm - {{ $item->product->name ?? 'Không xác định' }} -
-
- Loại: - @if ($item->product_type == 1) - Shared Hosting - @elseif($item->product_type == 2) - VPS - @elseif($item->product_type == 3) - Dedicated Server - @else - Khác - @endif -
-
- Hệ điều hành: -
-
-
- {{ $item->os->osGroup->name }} -
-
{{ $item->os->osGroup->name }} - {{ $item->os->version }} -
-
-
- {{ $item->quantity }} - -

- {{ format_price($item->price) }} - /{{ $item->months }}tháng -

-
-
- - Addon - - {{ $addon->addonItems->name }} đơn giá: - ({{ format_price($addon->addonItems->price) }}) - / {{ $addon->addonItems->step . $addon->addonItems->prefix }} - -
-
- {{ $addon->qty }} / {{ $addon->addonItems->prefix }} - ({{ $item->months }} tháng) - - {{ number_format($addon->price * $item->months) }} VNĐ -
Giá trị sản phẩm - {{ number_format($productTotal) }} VNĐ -
Tổng addon - {{ number_format($addonTotal) }} VNĐ -
Giảm giá - -{{ number_format($orders->discount_value) }} VNĐ -
Tổng cộng - {{ number_format($orders->amount) }} VNĐ -
- @if ($orders->status == 1) -
- - Xác nhận - thanh toán - -
- @endif -
-
-
- - - @if ($orders->note) -
-

Ghi chú đơn hàng

-

{{ $orders->note }}

-
- @endif - - -
-
-
- - - -
-
-

Bạn cần hỗ trợ?

-

Nếu bạn gặp bất kỳ vấn đề nào khi thanh toán, vui lòng liên hệ với - chúng tôi thông qua.
Hotline {{ setting('setting.tel') }} - hoặc - thông qua Email {{ setting('setting.support') }}

-
-
-
-
-
- - @include('frontend.order.modal.destroy', [ - 'order_id' => $orders->id, - 'order_num' => $orders->order_num, - ]) - - @include('frontend.order.modal.confirm', [ - 'order_id' => $orders->id, - 'order_num' => $orders->order_num, - ]) -@endsection diff --git a/resources/views/frontend/payment/index.blade.php b/resources/views/frontend/payment/index.blade.php deleted file mode 100644 index 15ffb64..0000000 --- a/resources/views/frontend/payment/index.blade.php +++ /dev/null @@ -1,228 +0,0 @@ -@extends('frontend.layouts.master') -@section('content') -
- -
- -
-
-
-
- Avatar -
-
-

{{ customer()?->firstname . ' ' . customer()?->lastname }}

-

{{ customer()?->email }}

-
-
-
-
Số dư hiện tại
-
{{ number_format(customer()?->credit ?? 0, 0, ',', '.') }} đ
-
-
-
- -
- -
- - -
-

- - Chọn mệnh giá nhanh -

-
- @foreach ([200000, 300000, 400000, 500000, 1000000, 2000000] as $price) - - @endforeach -
- - -
- -
-
- - -
-
- -
- -
- VNĐ -
-
- -
-
- - -
-
- -
-

Lưu ý quan trọng

-

- Số tiền tối thiểu cho mỗi lần nạp là 200.000đ. - Giao dịch sẽ được xử lý trong vòng 5-10 phút. -

-
-
-
- - -
-

- - Chọn phương thức thanh toán -

- -
- -
-
- @csrf - - -
-
- - -
- -
-
-
- - -
-
- -
-

Bảo mật thông tin

-

- Thông tin thanh toán của bạn được mã hóa và bảo vệ an toàn. - Chúng tôi không lưu trữ thông tin thẻ tín dụng. -

-
-
-
-
- - -
-
- -
-

- - Tóm tắt giao dịch -

- - -
-
Số dư hiện tại
-
- {{ number_format(customer()?->credit ?? 0, 0, ',', '.') }} đ
-
- - -
-
Số tiền nạp
-
-
- - -
-
Số dư sau nạp
-
-
-
- - -
-
- -
- Số tiền tối thiểu: 200.000đ -
-
-
-
- - -
-
- -

Cần hỗ trợ?

-

Đội ngũ hỗ trợ 24/7 sẵn sàng giúp đỡ bạn

- - - Liên hệ hỗ trợ - -
-
-
-
-
-
-
-@endsection diff --git a/resources/views/frontend/payment/view.blade.php b/resources/views/frontend/payment/view.blade.php deleted file mode 100644 index c534f96..0000000 --- a/resources/views/frontend/payment/view.blade.php +++ /dev/null @@ -1,56 +0,0 @@ -@extends("frontend.layouts.master") - -@section("content") -
-
-
-
Thông tin thanh toán
-
-

- {{__('bankName')}}: {{ $payment->name }}

-

- {{__('accountName')}}: {{ $payment->bankName }}

-

- {{__('accountNumber')}}: {{ $payment->accountNo }}

-
- -
Chi tiết thanh toán
-
-

- Số tiền thanh toán: {{ number_format($amount,0,',','.') }} đ

-

- Nội dung thanh toán: {{ $memo }}

-
- - -
- -
-
Hoặc quét mã QR bên dưới để tự động điền nội dung - chuyển khoản
-
- QR Thanh Toán -
-
-
- -
-
- -
-
-@endsection diff --git a/resources/views/frontend/post.blade.php b/resources/views/frontend/post.blade.php deleted file mode 100644 index a855ff3..0000000 --- a/resources/views/frontend/post.blade.php +++ /dev/null @@ -1,8 +0,0 @@ -@extends("frontend.main") -@section("content") -
-
- {!! $post->content !!} -
-
-@endsection diff --git a/resources/views/frontend/reset.blade.php b/resources/views/frontend/reset.blade.php deleted file mode 100644 index a6b3944..0000000 --- a/resources/views/frontend/reset.blade.php +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - {{ $title }} - - - - - - - @livewireStyles - - - - - -
-
- - -
- Logo -

{{ $title }}

-
- @csrf -
- Vui lòng nhập email đã đăng ký, chúng tôi sẽ gửi đường dẫn khôi phục lại mật khẩu qua email này. -
-
- - -
-
- Tiếp - tục -
-
-
- -

- Chưa có tài khoản? - - Đăng ký - -

-

- Đã có tài - khoản -

-
-
- - - -
-
- - - - - @stack('viewScripts') - - @include('alerts') - @livewireScripts - - - diff --git a/resources/views/frontend/script.blade.php b/resources/views/frontend/script.blade.php deleted file mode 100644 index f8d3c92..0000000 --- a/resources/views/frontend/script.blade.php +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - -{{-- {!! setting('setting.script') !!} --}} - -@include('alerts') -@stack('scriptsLivewire') -@stack('viewScripts') - -@stack('consoleScripts') -@include('frontend.layouts.partials.notification-script') - diff --git a/resources/views/frontend/service.blade.php b/resources/views/frontend/service.blade.php deleted file mode 100644 index adee74c..0000000 --- a/resources/views/frontend/service.blade.php +++ /dev/null @@ -1,4 +0,0 @@ -@extends("frontend.layouts.master") -@section("content") - @livewire('my-service') -@endsection diff --git a/resources/views/frontend/service/console.blade.php b/resources/views/frontend/service/console.blade.php deleted file mode 100644 index 0367a42..0000000 --- a/resources/views/frontend/service/console.blade.php +++ /dev/null @@ -1,225 +0,0 @@ -@extends('frontend.layouts.master') - -@push('viewStyles') - - -@endpush - -@section('content') -
-
- -
-
-
- -
-
-
-
-

VM Console

-

{{ $product->name ?? 'Virtual Machine' }}

-
-
-
- - Đang kết nối... -
-
-
- - -
-
-
-

Đang kết nối với vCenter

-

Vui lòng chờ...

-
-
- - - -
-
-
-
-
- - - -
- - - -
-
-
-
-
-
-
- - - - - - - -@endsection diff --git a/resources/views/frontend/service/hosting.blade.php b/resources/views/frontend/service/hosting.blade.php deleted file mode 100644 index e116361..0000000 --- a/resources/views/frontend/service/hosting.blade.php +++ /dev/null @@ -1,127 +0,0 @@ -@extends("frontend.main") -@section("content") - @inject("Carbon",Illuminate\Support\Carbon::class) -
-
-
Thông tin cấu hình
-
-
-
- Server -
-
- {{ $product->Server->name }} -
-
-
-
- Tên miền -
-
- {{ $product->name }} -
-
-
-
- Username -
-
- {{ $product->username }} -
-
-
-
- Password -
-
- {{ $product->password ? SignRSA::DecryptFunc($product->password) : "" }} -
-
-
-
- Gói dịch vụ -
-
- {{ $information->name }} -
-
- -
-
-
-
Thông tin thanh toán
-
-
-
- Ngày đăng ký -
-
- {{ $Carbon::parse($product->created_at)->format('d/m/Y') }} -
-
-
-
- Thanh toán lần đầu -
-
- {{ number_format($product->first_payment,0,',','.') }} đ -
-
-
-
- Thanh toán định kỳ -
-
- {{ number_format($product->next_payment,0,',','.') }} đ -
-
-
-
- Hạn sử dụng -
-
- @if($Carbon::now()->diffInDays($Carbon::parse($product->next_due_date),false) > 0) - Còn {{$Carbon::now()->diffInDays($Carbon::parse($product->next_due_date),false)}} ngày - @else - Hết hạn - @endif - -
-
-
-
- Ngày hết hạn -
-
- {{ $Carbon::parse($product->next_due_date)->format('d/m/Y') }} -
-
-
-
-
-
-
-
-
Reset password
-
Gia hạn dịch vụ
-
-
-{{--
--}} -{{--
--}} -{{--
Reset password
--}} -{{--
Reset Password
--}} -{{--
--}} -{{--
--}} -
-
-
Plesk Logo
-
Truy cập vào Plesk Panel
-
-
-
- @include("form.renew") -@endsection diff --git a/resources/views/frontend/service/index.blade.php b/resources/views/frontend/service/index.blade.php deleted file mode 100644 index befd0af..0000000 --- a/resources/views/frontend/service/index.blade.php +++ /dev/null @@ -1,338 +0,0 @@ -@extends('frontend.layouts.master') - -@section('content') - @if (!empty($category)) - -
- @forelse ($products as $index => $item) -
- @csrf - - {{-- Remove type_id for new Product system --}} - @php - $defaultPricingForCart = - $item->pricings->firstWhere('billing_cycle', 'semi_annually') ?? $item->pricings->first(); - $cartPrice = $defaultPricingForCart - ? floatval($defaultPricingForCart->price_sale ?: $defaultPricingForCart->price) - : 0; - @endphp - - -
- - -
-

- {{ $item->name }} -

-
- - @php - // Get pricing for different billing cycles - // Note: If billing_cycle is 'onetime', treat it as monthly - $monthlyPricing = - $item->pricings->firstWhere('billing_cycle', 'monthly') ?? - $item->pricings->firstWhere('billing_cycle', 'onetime'); - $semiAnnuallyPricing = $item->pricings->firstWhere('billing_cycle', 'semi_annually'); - $annuallyPricing = $item->pricings->firstWhere('billing_cycle', 'annually'); - $bienniallyPricing = $item->pricings->firstWhere('billing_cycle', 'biennially'); - $trienniallyPricing = $item->pricings->firstWhere('billing_cycle', 'triennially'); - - // Use monthly or first available pricing for display - $displayPricing = $monthlyPricing ?? $item->pricings->first(); - $basePrice = $displayPricing - ? floatval($displayPricing->price_sale ?: $displayPricing->price) - : 0; - @endphp - -
- - -
-
- - ≈ - {{ $displayPricing ? format_price($displayPricing->price_sale ?: $displayPricing->price) : 'Liên hệ' }} - - @if ($displayPricing) - / tháng - @endif -
-
- - -
- -
- @php - // Default to semi_annually (6 months) if available, otherwise first available - $defaultPricing = $semiAnnuallyPricing ?? $item->pricings->first(); - $defaultPrice = $defaultPricing - ? floatval($defaultPricing->price_sale ?: $defaultPricing->price) - : 0; - $defaultMonths = match ($defaultPricing?->billing_cycle) { - 'semi_annually' => 6, - 'annually' => 12, - 'biennially' => 24, - 'triennially' => 36, - default => 1, - }; - @endphp - - -
- - - -
- -
-
    - - @if ($item->cpu) -
  • -
    - -
    -
    - CPU: - {{ $item->cpu }} vCore -
    -
  • - @endif - - - @if ($item->ram) -
  • -
    - -
    -
    - RAM: - {{ $item->ram }} GB -
    -
  • - @endif - - - @if ($item->disk) -
  • -
    - -
    -
    - SSD: - {{ $item->disk }} GB -
    -
  • - @endif - - - @if ($item->gpu) -
  • -
    - -
    -
    - GPU: - {{ $item->gpu }} GB -
    -
  • - @endif - - - @if ($item->bandwidth) -
  • -
    - -
    -
    - Băng thông: - {{ $item->bandwidth }} MB -
    -
  • - @endif - - - @if ($item->osVersions && $item->osVersions->isNotEmpty()) -
  • -
    - -
    -
    - Hệ điều hành: - - {{ $item->osVersions->pluck('name')->unique()->implode(', ') }} - -
    -
  • - @endif -
-
- - - - Đăng ký ngay -
-
-
- @empty -
-
-
- -
-

Không có sản phẩm

-

Danh mục này hiện chưa có sản phẩm nào.

-
-
- {{ $products->links() }} - @endforelse -
- @else -
-
-
- -
-

Không tìm thấy

-

Danh mục này không tồn tại hoặc đã bị xóa.

- - Về trang chủ - -
-
- @endif -@endsection - -@push('viewStyles') - - -@endpush - -@push('viewScripts') - - -@endpush diff --git a/resources/views/frontend/service/list-snapshot.blade.php b/resources/views/frontend/service/list-snapshot.blade.php deleted file mode 100644 index f61e26e..0000000 --- a/resources/views/frontend/service/list-snapshot.blade.php +++ /dev/null @@ -1,82 +0,0 @@ -
-

- - - - - {{ __('Danh sách Snapshot') }} -

-
- {{ __('Đang tải snapshot...') }} -
- -
- {{ __('Không có snapshot nào.') }} -
-
diff --git a/resources/views/frontend/service/partials/change-ip-modal.blade.php b/resources/views/frontend/service/partials/change-ip-modal.blade.php deleted file mode 100644 index 8426877..0000000 --- a/resources/views/frontend/service/partials/change-ip-modal.blade.php +++ /dev/null @@ -1,30 +0,0 @@ -@props(['invoice']) - - -
-
- {{ __('Đổi địa chỉ IP') }} - {{ __('Nhập địa chỉ IP mới mà bạn muốn sử dụng.') }} -
- -
- @csrf - - - - {{ __('Địa chỉ IP mới') }} - - {{ __('Vui lòng nhập IPv4 hợp lệ. Yêu cầu sẽ được xử lý nếu khả dụng.') }} - - -
- - {{ __('Hủy') }} - - {{ __('Đồng ý') }} -
-
-
-
- - diff --git a/resources/views/frontend/service/partials/change-remote-port-modal.blade.php b/resources/views/frontend/service/partials/change-remote-port-modal.blade.php deleted file mode 100644 index 3bfe08c..0000000 --- a/resources/views/frontend/service/partials/change-remote-port-modal.blade.php +++ /dev/null @@ -1,37 +0,0 @@ -@props(['invoice']) - - -
-
- {{ __('Đổi Port Remote (RDP)') }} - {{ __('Nhập port RDP mới cho máy ảo Windows (mặc định 3389).') }} -
- -
- @csrf - - - - {{ __('Port mới') }} - - {{ __('Chỉ áp dụng cho Windows. Kết nối đến sẽ cần dùng port này.') }} - - - - {{ __('Mật khẩu') }} - - Vì lý do bảo mật, vui lòng xác thực mật khẩu VPS - - - -
- - {{ __('Hủy') }} - - - {{ __('Đồng ý') }} -
-
-
-
diff --git a/resources/views/frontend/service/partials/configuration-info.blade.php b/resources/views/frontend/service/partials/configuration-info.blade.php deleted file mode 100644 index f9e6acf..0000000 --- a/resources/views/frontend/service/partials/configuration-info.blade.php +++ /dev/null @@ -1,105 +0,0 @@ -{{-- Configuration Info Partial - Optimized with helper functions --}} -@php - $isWindows = Str::contains(Str::lower($vmInfo['os'] ?? ''), 'windows') || - Str::contains(Str::lower($invoice->invoiceItem->first()->os->osGroup->name ?? ''), 'windows'); - $vmIp = $vmInfo['ip_address'] ?? '103.42.56.177'; - $vmPort = $invoice->order->vmWare->first()->port ?? '3389'; - $vmUser = $isWindows ? 'administrator' : 'root'; - $osName = $invoice->invoiceItem->first()->os->osGroup->name ?? 'Unknown'; - $osVersion = $invoice->invoiceItem->first()->os->version ?? ''; - $vmCpu = $vmInfo['cpu'] ?? '3'; - $vmRam = $vmInfo['ram'] ?? '1 GB'; - $vmDisk = $vmInfo['disk'] ?? '25 GB'; - $addons = $invoice->invoiceItem->first()->addons; -@endphp - -
-

- {{ __('Thông tin cấu hình') }} -

-
- {{-- IP Address --}} -
- IP - {{ $vmIp }} -
- - {{-- Port --}} -
- Port - {{ $vmPort }} -
- - {{-- User --}} -
- User - {{ $vmUser }} -
- - {{-- Password --}} -
- Password -
- - - - -
-
- - {{-- Operating System --}} -
- OS - - {{ $osName }} {{ $osVersion }} - -
- - {{-- Specifications --}} -
- {{ __('Chi tiết') }} (CPU - RAM - DISK) - - {{ $vmCpu }} - {{ $vmRam }} - {{ $vmDisk }} - -
- - {{-- Addons --}} - @if ($addons->count() > 0) -
-
- {{ __('Addons') }} -
- - - {{ $addons->count() }} {{ __('addons') }} - - - @foreach ($addons as $addon) - - {{ $addon->addonItems->name }} - - {{ $addon->qty }} {{ $addon->addonItems->prefix }} - - {{ number_format($addon->price, 0, ',', '.') }} đ - - @endforeach - - -
-
-
- @endif -
-
\ No newline at end of file diff --git a/resources/views/frontend/service/partials/control-buttons/change-ip-button.blade.php b/resources/views/frontend/service/partials/control-buttons/change-ip-button.blade.php deleted file mode 100644 index 448ec56..0000000 --- a/resources/views/frontend/service/partials/control-buttons/change-ip-button.blade.php +++ /dev/null @@ -1,15 +0,0 @@ -{{-- Change IP Trigger --}} - -
-
-
- - - -
- {{ __('Đổi IP') }} -
-
-
- - diff --git a/resources/views/frontend/service/partials/control-buttons/console-button.blade.php b/resources/views/frontend/service/partials/control-buttons/console-button.blade.php deleted file mode 100644 index 02402da..0000000 --- a/resources/views/frontend/service/partials/control-buttons/console-button.blade.php +++ /dev/null @@ -1,12 +0,0 @@ -
-
-
- - - -
- {{ __('Mở Console') }} -
-
\ No newline at end of file diff --git a/resources/views/frontend/service/partials/control-buttons/reinstall-button.blade.php b/resources/views/frontend/service/partials/control-buttons/reinstall-button.blade.php deleted file mode 100644 index d3ab841..0000000 --- a/resources/views/frontend/service/partials/control-buttons/reinstall-button.blade.php +++ /dev/null @@ -1,15 +0,0 @@ - -
-
-
- - - - -
- {{ __('Cài lại') }} -
-
-
diff --git a/resources/views/frontend/service/partials/control-buttons/renewal-button.blade.php b/resources/views/frontend/service/partials/control-buttons/renewal-button.blade.php deleted file mode 100644 index 54f1050..0000000 --- a/resources/views/frontend/service/partials/control-buttons/renewal-button.blade.php +++ /dev/null @@ -1,14 +0,0 @@ -{{-- Renewal Button Trigger --}} - -
-
-
- - - -
- {{ __('Gia hạn') }} -
-
-
\ No newline at end of file diff --git a/resources/views/frontend/service/partials/control-buttons/reset-password-button.blade.php b/resources/views/frontend/service/partials/control-buttons/reset-password-button.blade.php deleted file mode 100644 index b99d471..0000000 --- a/resources/views/frontend/service/partials/control-buttons/reset-password-button.blade.php +++ /dev/null @@ -1,13 +0,0 @@ -{{-- Reset VM Password Trigger --}} - -
-
-
- - - -
- {{ __('Đặt lại mật khẩu') }} -
-
-
\ No newline at end of file diff --git a/resources/views/frontend/service/partials/control-buttons/reset-remote-button.blade.php b/resources/views/frontend/service/partials/control-buttons/reset-remote-button.blade.php deleted file mode 100644 index 01caee1..0000000 --- a/resources/views/frontend/service/partials/control-buttons/reset-remote-button.blade.php +++ /dev/null @@ -1,13 +0,0 @@ -{{-- Change Remote Port Trigger (Windows only) --}} - -
-
-
- - - -
- {{ __('Đổi Port Remote') }} -
-
-
\ No newline at end of file diff --git a/resources/views/frontend/service/partials/control-buttons/restart-button.blade.php b/resources/views/frontend/service/partials/control-buttons/restart-button.blade.php deleted file mode 100644 index 373d74e..0000000 --- a/resources/views/frontend/service/partials/control-buttons/restart-button.blade.php +++ /dev/null @@ -1,29 +0,0 @@ -{{-- Restart Button Component --}} -
- - -
diff --git a/resources/views/frontend/service/partials/control-buttons/snapshot-button.blade.php b/resources/views/frontend/service/partials/control-buttons/snapshot-button.blade.php deleted file mode 100644 index 9b6caf6..0000000 --- a/resources/views/frontend/service/partials/control-buttons/snapshot-button.blade.php +++ /dev/null @@ -1,15 +0,0 @@ - -
-
-
- - - - -
- {{ __('Tạo Snapshot') }} -
-
-
diff --git a/resources/views/frontend/service/partials/control-buttons/start-button.blade.php b/resources/views/frontend/service/partials/control-buttons/start-button.blade.php deleted file mode 100644 index 821407c..0000000 --- a/resources/views/frontend/service/partials/control-buttons/start-button.blade.php +++ /dev/null @@ -1,29 +0,0 @@ -{{-- Stop Button Component --}} -
- - -
diff --git a/resources/views/frontend/service/partials/control-buttons/stop-button.blade.php b/resources/views/frontend/service/partials/control-buttons/stop-button.blade.php deleted file mode 100644 index 171cbf5..0000000 --- a/resources/views/frontend/service/partials/control-buttons/stop-button.blade.php +++ /dev/null @@ -1,29 +0,0 @@ -{{-- Stop Button Component --}} -
- - -
diff --git a/resources/views/frontend/service/partials/control-notes.blade.php b/resources/views/frontend/service/partials/control-notes.blade.php deleted file mode 100644 index 90524e6..0000000 --- a/resources/views/frontend/service/partials/control-notes.blade.php +++ /dev/null @@ -1,17 +0,0 @@ -{{-- Control Notes Partial --}} -
-
-
- - - - {{ __('Lưu ý:') }} -
-
    -
  • • {{ __('Các thao tác có thể mất vài giây để hoàn thành') }}
  • -
  • • {{ __('VM sẽ được khởi động lại sau khi thay đổi cấu hình') }}
  • -
  • • {{ __('Vui lòng đợi thao tác hoàn thành trước khi thực hiện tiếp') }}
  • -
-
-
\ No newline at end of file diff --git a/resources/views/frontend/service/partials/no-vm-info.blade.php b/resources/views/frontend/service/partials/no-vm-info.blade.php deleted file mode 100644 index 1bb7edb..0000000 --- a/resources/views/frontend/service/partials/no-vm-info.blade.php +++ /dev/null @@ -1,22 +0,0 @@ -{{-- No VM Info Partial - Clean error state --}} -
-

- - - - - {{ __('Thông báo') }} -

- -
-
- - - - -
-

{{ __('Dịch vụ này chưa có thông tin VM hoặc đang trong quá trình khởi tạo.') }}

-
-
\ No newline at end of file diff --git a/resources/views/frontend/service/partials/renewal-modal.blade.php b/resources/views/frontend/service/partials/renewal-modal.blade.php deleted file mode 100644 index 86f720b..0000000 --- a/resources/views/frontend/service/partials/renewal-modal.blade.php +++ /dev/null @@ -1,157 +0,0 @@ -@props(['invoice']) - -@php - $initialPrice = (int) ($invoice->invoiceItem->first()?->getProductAttribute()?->price_sale ?? $invoice->invoiceItem->first()?->getProductAttribute()?->price ?? 0); -@endphp - - -
-
- {{ __('Gia hạn dịch vụ') }} - {{ __('Chọn thời hạn gia hạn hoặc nhập số tháng mong muốn (Tối thiểu 2 tháng).') }} - -
- -
- @csrf - - - - {{ __('Chọn thời hạn') }} - - {{-- {{ __('1 tháng') }} --}} - - {{ __('3 tháng') }} - {{ __('6 tháng') }} - {{ __('12 tháng') }} - {{ __('24 tháng') }} - {{ __('Khác...') }} - - - -
- - {{ __('Số tháng') }} - - {{ __('Nhập số tháng muốn gia hạn (tối thiểu 2, tối đa 60).') }} - -
- -
-
-
-
- -
- {{ __('Đơn giá / tháng') }} - -
-
-
- {{ __('Tổng thanh toán') }} - -
-
- {{ __('(Đã bao gồm VAT nếu có)') }} -
-
- -
- - {{ __('Hủy') }} - - - {{ __('Thanh toán gia hạn') }} - {{ __('Đang xử lý...') }} - -
-
-
-
- - diff --git a/resources/views/frontend/service/partials/reset-password-modal.blade.php b/resources/views/frontend/service/partials/reset-password-modal.blade.php deleted file mode 100644 index bff7276..0000000 --- a/resources/views/frontend/service/partials/reset-password-modal.blade.php +++ /dev/null @@ -1,39 +0,0 @@ -@props(['invoice', 'isWindows' => false]) - - -
-
- {{ __('Đặt lại mật khẩu VM') }} - - {{ __('Nhập mật khẩu mới cho máy ảo của bạn.') }} - -
- -
- @csrf - - - - {{ __('Mật khẩu cũ') }} - - - - {{ __('Mật khẩu mới') }} - - {{ $isWindows ? __('Tài khoản: administrator') : __('Tài khoản: root') }} - - - -
- - {{ __('Hủy') }} - - - {{ __('Đồng ý') }} -
-
-
-
diff --git a/resources/views/frontend/service/partials/service-header.blade.php b/resources/views/frontend/service/partials/service-header.blade.php deleted file mode 100644 index 54424c3..0000000 --- a/resources/views/frontend/service/partials/service-header.blade.php +++ /dev/null @@ -1,42 +0,0 @@ -{{-- Service Header Partial - Cached for performance --}} -@php - $serverName = $invoice->invoiceItem->first()->server_name ?? 'Cloud VPS'; - $vmStatus = $vmInfo['status'] ?? null; - $statusBg = match ($vmStatus) { - 'POWERED_ON' => 'bg-green-600', - 'POWERED_OFF' => 'bg-red-600', - default => 'bg-gray-600', - }; -@endphp - -
- {{ $invoice->invoiceItem->first()?->getProductAttribute()?->name }} -
- - - -
-

- {{ $serverName }} -

-

- {{ $serverName }} -

-
- -
- - -
- - @if ($vmStatus == 'POWERED_ON') - {{ __('RUNNING') }} - @elseif($vmStatus == 'POWERED_OFF') - {{ __('STOPPED') }} - @else - {{ __('UNKNOWN') }} - @endif - -
-
diff --git a/resources/views/frontend/service/partials/snapshots-modal.blade.php b/resources/views/frontend/service/partials/snapshots-modal.blade.php deleted file mode 100644 index 9110f60..0000000 --- a/resources/views/frontend/service/partials/snapshots-modal.blade.php +++ /dev/null @@ -1,96 +0,0 @@ -@props(['invoice']) - - -
-
-
- {{ __('Snapshot của máy ảo') }} - {{ __('Xem, tạo mới, khôi phục hoặc xóa snapshot.') }} -
- -
- -
- {{ __('Đang tải snapshot...') }} -
- - -
- {{ __('Không có snapshot nào.') }} -
-
-
- - {{ __('Tải lại') }} -
- @csrf - - {{ __('Tạo snapshot') }} -
-
- -
-
diff --git a/resources/views/frontend/service/partials/transaction-info.blade.php b/resources/views/frontend/service/partials/transaction-info.blade.php deleted file mode 100644 index 72e9b3c..0000000 --- a/resources/views/frontend/service/partials/transaction-info.blade.php +++ /dev/null @@ -1,100 +0,0 @@ -{{-- Transaction Info Partial - Optimized with date helpers --}} -@php - // Keep Carbon instances for calculations and formatted strings for display - $registrationCarbon = $invoice->date ? \Carbon\Carbon::parse($invoice->date) : null; - $dueCarbon = $invoice->due_date ? \Carbon\Carbon::parse($invoice->due_date) : null; - - $registrationDate = $registrationCarbon ? $registrationCarbon->format('d/m/Y') : 'N/A'; - $dueDate = $dueCarbon ? $dueCarbon->format('d/m/Y') : 'N/A'; - - $totalAmount = number_format($invoice->total ?? 0, 0, ',', '.'); - $isExpired = $invoice->status == 1; - - // Precompute days remaining (use 'N/A' when dates are missing) - $daysRemaining = $dueCarbon && $registrationCarbon ? $dueCarbon->diffInDays($registrationCarbon) : 'N/A'; -@endphp - -
-

- {{ __('Thông tin giao dịch') }} -

-
- {{-- Order Number --}} -
- {{ __('Mã đơn hàng') }} - - {{ $invoice->order_num }} - - -
- - {{-- Registration Date --}} -
- {{ __('Ngày đăng ký') }} - {{ $registrationDate }} -
- - {{-- Initial Payment --}} -
- {{ __('Thanh toán lần đầu') }} - {{ $totalAmount }} đ -
- - {{-- Recurring Payment Amount --}} -
- {{ __('Số tiền thanh toán định kỳ') }} - {{ $totalAmount }} đ -
- - {{-- Service Status --}} -
- {{ __('Hạn sử dụng') }} - - @if ($isExpired) - {{ __('Hết hạn') }} - @else - {{ __('Hoạt động') }} - @endif - -
- - {{-- Expiry Date --}} -
- {{ __('Ngày hết hạn') }} - {{ $dueDate }} -
- -
- {{ __('Số ngày còn lại') }} - {{ $daysRemaining }} Ngày -
- - - {{-- Auto Renewal Status --}} -
- {{ __('Trạng thái gia hạn tự động') }} - OFF -
- -
-
diff --git a/resources/views/frontend/service/partials/vm-control-panel.blade.php b/resources/views/frontend/service/partials/vm-control-panel.blade.php deleted file mode 100644 index 40b205c..0000000 --- a/resources/views/frontend/service/partials/vm-control-panel.blade.php +++ /dev/null @@ -1,68 +0,0 @@ -{{-- VM Control Panel Partial - Optimized with reusable components --}} -@php - $vmStatus = $vmInfo['status'] ?? null; - $isPoweredOn = $vmStatus == 'POWERED_ON'; - $isPoweredOff = $vmStatus == 'POWERED_OFF'; - $isWindows = - \Illuminate\Support\Str::contains(\Illuminate\Support\Str::lower($vmInfo['os'] ?? ''), 'windows') || - \Illuminate\Support\Str::contains( - \Illuminate\Support\Str::lower($invoice->invoiceItem->first()?->os?->osGroup?->name ?? ''), - 'windows', - ); -@endphp - -
-

- - - - - {{ __('Điều khiển VM') }} -

- - {{-- VM Control Grid --}} -
- {{-- Row 1: Basic Controls --}} - @include('frontend.service.partials.control-buttons.renewal-button') - {{-- Debug info removed - was causing htmlspecialchars error --}} - - @if ($isPoweredOff) - @include('frontend.service.partials.control-buttons.start-button') - @elseif ($isPoweredOn) - @include('frontend.service.partials.control-buttons.restart-button') - @if ($isWindows) - @include('frontend.service.partials.control-buttons.reset-remote-button') - @endif - @include('frontend.service.partials.control-buttons.stop-button') - @include('frontend.service.partials.control-buttons.console-button', ['invoice' => $invoice]) - @endif - - {{-- @include('frontend.service.partials.control-buttons.config-button') --}} - @include('frontend.service.partials.control-buttons.reinstall-button') - - @if ($isPoweredOn) - @include('frontend.service.partials.control-buttons.snapshot-button') - @include('frontend.service.partials.control-buttons.reset-password-button') - @include('frontend.service.partials.control-buttons.change-ip-button') - @endif -
- - {{-- Notes Section --}} - @include('frontend.service.partials.control-notes') - @livewire('v-p-s-reinstall-modal', [ - 'productId' => $invoice->invoiceItem->first()?->getProductAttribute()?->id, - 'invoiceId' => $invoice->id, - ]) - @if ($isPoweredOn) - @include('frontend.service.partials.snapshots-modal', ['invoice' => $invoice]) - @include('frontend.service.partials.reset-password-modal', [ - 'invoice' => $invoice, - 'isWindows' => $isWindows, - ]) - @include('frontend.service.partials.change-ip-modal', ['invoice' => $invoice]) - @include('frontend.service.partials.change-remote-port-modal', ['invoice' => $invoice]) - @include('frontend.service.partials.renewal-modal', ['invoice' => $invoice]) - @endif -
- diff --git a/resources/views/frontend/service/scripts/service.blade.php b/resources/views/frontend/service/scripts/service.blade.php deleted file mode 100644 index faecc8a..0000000 --- a/resources/views/frontend/service/scripts/service.blade.php +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/resources/views/frontend/service/show.blade.php b/resources/views/frontend/service/show.blade.php deleted file mode 100644 index b589edd..0000000 --- a/resources/views/frontend/service/show.blade.php +++ /dev/null @@ -1,74 +0,0 @@ -@extends('frontend.layouts.master') - -@push('viewStyles') - - -@endpush - -@section('content') -
-
- -
- @include('frontend.service.partials.service-header') - @include('frontend.service.partials.configuration-info') - @include('frontend.service.partials.transaction-info') -
- - -
-
- @if ($vmInfo) - @include('frontend.service.partials.vm-control-panel') - @else - @include('frontend.service.partials.no-vm-info') - @endif -
-
- -
-
-@endsection - -@push('viewScripts') - - - - - -@endpush diff --git a/resources/views/frontend/service/vmware.blade.php b/resources/views/frontend/service/vmware.blade.php deleted file mode 100644 index 4bf8b02..0000000 --- a/resources/views/frontend/service/vmware.blade.php +++ /dev/null @@ -1,279 +0,0 @@ -@php use Illuminate\Support\Facades\Crypt; @endphp -@extends("frontend.main") -@section("content") - @inject("Carbon",Illuminate\Support\Carbon::class) -
-
-

Đơn vị: CPU - vCore | RAM - GB | SSD - GB

-
-
-
Thông tin cấu hình
-
-
-
- IP -
-
- @if($product->IpAddress && $product->IpAddress->ip) - {{ $product->IpAddress->ip }} - @else - No Data - @endif -
-
-
-
- Port -
-
- {{ $product->port }} -
-
-
-
- User -
-
- {{ $product->user }} -
-
-
-
- Password -
-
- {{ $product->password ? SignRSA::DecryptFunc($product->password) : "" }} -
-
-
-
- Hệ điều hành -
-
- @if( $product->Os && $product->Os->OsGroup) - {{$product->Os->OsGroup->name}} {{ $product->Os->version }} - @endif - -
-
-
-
- Cấu hình (CPU - RAM - SSD): -
-
- {{$information->cpu}} - {{$information->ram}} - {{$information->disk}} -
-
-
-
- @if($addon) -
-
Dịch vụ bổ sung
-
- @foreach($addon as $_key => $_item) -
-
- Addon {{strtoupper($_key)}} -
-
- {{$_item}} -
-
- @endforeach -
-
- @endif -
-
Thông tin thanh toán
-
-
-
- Ngày đăng ký -
-
- {{ $Carbon::parse($product->created_at)->format('d/m/Y') }} -
-
-
-
- Thanh toán lần đầu -
-
- {{ number_format($product->first_payment,0,',','.') }} đ -
-
-
-
- Thanh toán định kỳ -
-
- {{ number_format($product->next_payment,0,',','.') }} đ -
-
-
-
- Hạn sử dụng -
-
- @if($Carbon::now()->diffInDays($Carbon::parse($product->next_due_date),false) > 0) - Còn {{$Carbon::now()->diffInDays($Carbon::parse($product->next_due_date),false)}} ngày - @else - Hết hạn - @endif - -
-
-
-
- Ngày hết hạn -
-
- {{ $Carbon::parse($product->next_due_date)->format('d/m/Y') }} -
-
-
-
-
-
-
-
-
Reset password
-
Gia hạn dịch vụ
-
-
-
-
-
Plesk Logo
-
Reload Panel
-
-
-
-
-
-
-
-
-
-
-
-
-
- - @include("form.renew") -@endsection -@push('viewStyles') - -@endpush -@push('viewScripts') - - -@endpush diff --git a/resources/views/frontend/shop.blade.php b/resources/views/frontend/shop.blade.php deleted file mode 100644 index f16382f..0000000 --- a/resources/views/frontend/shop.blade.php +++ /dev/null @@ -1,155 +0,0 @@ -@extends("frontend.main") -@section("content") -
- @if($type->count()) - - @endif - @if(isset($group)) - @if($group->count()) -
- @foreach($group->all() as $item) -
-
$item->Type->id,'group' => $item->id]) }}' " - class="box-form__checker {{ (int) request()->get('group') === $item->id ? "active" : "" }} shadow text-center rounded p-3"> -
{{ $item->Type->name }}
-
{{ $item->name }}
-
-
- @endforeach -
- @endif - @else - @if($type->first()->Group->count()) -
- @foreach($type->first()->Group->all() as $item) -
-
$type->first()->id,'group' => $item->id]) }}' " - class="box-form__checker {{ (int) request()->get('group') === $item->id ? "active" : "" }} shadow text-center rounded p-3"> -
{{ $type->first()->name }}
-
{{ $item->name }}
-
-
- @endforeach -
- @endif - @endif -
- @if(isset($product) && $product->count()) -
- @foreach($product->all() as $item) -
-
-
-

{{ $item->name }}

-
-
-
- @if($item->price_sale) -
- - - {{ number_format($item->price_sale,0,',','.') }}₫ - - - - {{ number_format($item->price,0,',','.') }}₫ - / 1 tháng - - - -
- - @else -
- - {{ number_format($item->price,0,',','.') }}₫ - / 1 tháng - - -
- @endif - - -
-
-
    - @foreach(explode("\r\n",$item->description) as $_item) -
  • - {{ $_item }} -
  • - @endforeach - -
-
-
-
-
- @csrf - - - - -
-
-
-
- @endforeach -
- @endif - @if(request()->get('type') == 2) - -{{--
--}} -{{--
--}} -{{-- Tìm kiếm tên miền của bạn--}} -{{--
--}} -{{--
--}} -{{-- Để xây dựng thương hiệu của bạn trên Internet, tiếp cận nhiều khách hàng tiềm năng hơn.--}} -{{--
--}} -{{-- --}} -{{--
--}} - @endif -
-@endsection diff --git a/resources/views/frontend/sidebar.blade.php b/resources/views/frontend/sidebar.blade.php deleted file mode 100644 index d175624..0000000 --- a/resources/views/frontend/sidebar.blade.php +++ /dev/null @@ -1,69 +0,0 @@ - - diff --git a/resources/views/frontend/ticket/add.blade.php b/resources/views/frontend/ticket/add.blade.php deleted file mode 100644 index a6aaea4..0000000 --- a/resources/views/frontend/ticket/add.blade.php +++ /dev/null @@ -1,100 +0,0 @@ -@extends('frontend.layouts.master') -@section('content') -
-

- {{ __('Gửi yêu cầu hỗ trợ') }} -

-
- @csrf -
- - Họ tên - - - - Email - - -
- - Tiêu đề - - -
- - Phòng ban - - - - - - - - Dịch vụ - - - @if ($itemProduct->count()) - @foreach ($itemProduct->all() as $item) - - @endforeach - @endif - - -
- - Nội dung -
- -
- - Đính kèm File - -
Hỗ trợ: .jpg, .gif, .jpeg, .png (Tối đa: 1024MB/Tệp)
-
-
- - - Trở về - - - Gửi yêu cầu - -
-
- -
-@endsection - -@push('viewStyles') - -@endpush - -@push('viewScripts') - - -@endpush diff --git a/resources/views/frontend/ticket/ticket.blade.php b/resources/views/frontend/ticket/ticket.blade.php deleted file mode 100644 index f0e1226..0000000 --- a/resources/views/frontend/ticket/ticket.blade.php +++ /dev/null @@ -1,4 +0,0 @@ -@extends("frontend.layouts.master") -@section("content") - @livewire('ticket') -@endsection diff --git a/resources/views/frontend/ticket/view.blade.php b/resources/views/frontend/ticket/view.blade.php deleted file mode 100644 index ce31c54..0000000 --- a/resources/views/frontend/ticket/view.blade.php +++ /dev/null @@ -1,230 +0,0 @@ -@php use App\Http\Helpers\Helper; @endphp -@extends("frontend.layouts.master") -@section("content") - @if($ticket->count()) -
-
-
-
- - -
-
- - - @foreach($ticket->all() as $item) - - @if($item->Reply && $item->Reply->first() && $item->Reply->first()->User) - @foreach($item->Reply as $_item) -
-
-
-
- - - -
- - {{ $_item->User->firstname .' '.$_item->User->lastname }} - -
-
- - Quản trị viên - -
{{ $_item->created_at }}
-
-
-
- {!! $_item->message !!} -
-
- @endforeach - @endif - - -
-
-
-
- - - -
- - {{ $item->Customer->firstname .' '.$item->Customer->lastname }} - -
-
- - Khách hàng - -
{{ $item->created_at }}
-
-
-
- {!! $item->description !!} -
- - @php($data = json_decode($item->data)) - @if($data->file) -
-
- @php($file_info = pathinfo(url('template/' . $data->file))) -
-
- Attachment -
-
-
- - - - {{ $file_info['basename'] }} -
-
- {{ filesize(public_path('template/' . $data->file))*0.001 }} KB -
-
-
-
-
- @endif -
- @endforeach -
- - -
-

- Thông tin Ticket -

-
-
-

Người yêu cầu

-

{{ $ticket->first()->Customer->firstname .' '.$ticket->first()->Customer->lastname }}

-
-
-

Phòng ban

-

{{ $ticket->first()->room }}

-
-
-

Đã Gửi

-

{{ $ticket->last()->created_at }}

-
-
-

Lần cập nhật cuối

-

{{ $ticket->first()->created_at }}

-
-
-

Tình trạng

- {!! Helper::get_ticket_status($ticket->first()->status,$ticket->first()->Reply->first()) !!} -
-
- -
- - - - - Trở về - -
- @csrf - @method('put') - - -
-
-
-
- @endif -@endsection - -@push('viewScripts') - - -@endpush diff --git a/resources/views/frontend/transaction.blade.php b/resources/views/frontend/transaction.blade.php deleted file mode 100644 index a4a2126..0000000 --- a/resources/views/frontend/transaction.blade.php +++ /dev/null @@ -1,4 +0,0 @@ -@extends("frontend.layouts.master") -@section("content") - @livewire('transaction') -@endsection diff --git a/resources/views/frontend/user/account.blade.php b/resources/views/frontend/user/account.blade.php deleted file mode 100644 index e0cac20..0000000 --- a/resources/views/frontend/user/account.blade.php +++ /dev/null @@ -1,218 +0,0 @@ -@extends('frontend.user.layout') - -@section('section-account') - -
-
- @csrf - @method('PUT') -
-
-

Cập nhật thông tin cá nhân

-
- - - - -
-
- - - - - - - -
- - -
-
- -
- - Họ - - - - - Tên - - - - - - Email - - - - - - Giới tính - - Nam - Nữ - - - -
- - -
- - Số điện thoại - - - - - - Công ty (Optional) - - - - - - Địa chỉ - - - - - - Ngày sinh - - - -
-
- - -
-

Upload CMND/CCCD

-
- - Số CMND/CCCD - - - -
-
- - -
- - - - - -
- - -
- - - - - -
-
-
- -
- -
-
-
-
-@endsection diff --git a/resources/views/frontend/user/layout.blade.php b/resources/views/frontend/user/layout.blade.php deleted file mode 100644 index bdd3838..0000000 --- a/resources/views/frontend/user/layout.blade.php +++ /dev/null @@ -1,49 +0,0 @@ -@extends('frontend.layouts.master') - -@section('content') -
- -
-
-
-
- Avatar -
-
-
{{ customer()->firstname . ' ' . customer()->lastname }} -
-
-
- -
-
- - @yield('section-account') - -
-@endsection diff --git a/resources/views/frontend/user/password.blade.php b/resources/views/frontend/user/password.blade.php deleted file mode 100644 index 293e524..0000000 --- a/resources/views/frontend/user/password.blade.php +++ /dev/null @@ -1,152 +0,0 @@ -@extends('frontend.user.layout') - -@section("section-account") -
-
- @csrf - @method('put') - - -
- {{ $title }} -
- - -
- - - Nhập mật khẩu cũ - - - - - - - - - - - - - Mật khẩu mới - - - - - - - - - - -
-
- -
-

-

-
-
- - - - Nhập lại mật khẩu mới - - - - - - - - - - - - Mật khẩu không khớp - - - Mật khẩu trùng khớp - - - Vui lòng xác nhận mật khẩu - - -
- - -
- - Lưu thông tin - -
-
-
- -@endsection diff --git a/resources/views/frontend/whois/index.blade.php b/resources/views/frontend/whois/index.blade.php deleted file mode 100644 index e862061..0000000 --- a/resources/views/frontend/whois/index.blade.php +++ /dev/null @@ -1,188 +0,0 @@ -@extends('frontend.layouts.master') - -@section('content') -
-
- -
-
- @csrf - -
- - {{ __('Tên miền') }} - - - -
- - -
- - - -
-
- - - - - - -
-
-
- - - -@endsection diff --git a/routes/admin.php b/routes/admin.php index bcb446d..26f1c32 100644 --- a/routes/admin.php +++ b/routes/admin.php @@ -108,8 +108,9 @@ Route::prefix('')->group(function () { }); //View All Client - Route::controller(CustomerController::class)->group(function () { + Route::prefix('customer')->controller(CustomerController::class)->group(function () { Route::get('list-customer', 'index')->name('customer.index'); + Route::get('datatable', 'datatable')->name('customer.datatable'); Route::get('view-customer', 'getCustomerInfo')->name('customer.info'); Route::get('view-profile', 'getCustomerProfile')->name('customer.profile'); Route::post('view-profile', 'storeCustomerProfile')->name('customer.profile.store');