Files

908 lines
29 KiB
PHP

<?php
namespace App\Http\Controllers\admin;
use App\Http\Controllers\Controller;
use App\Http\Facade\SignRSA;
use App\Http\Requests\AddPayRequest;
use App\Http\Requests\CreateCustomerRequest;
use App\Jobs\Mail\PasswordRecoverJob;
use App\Models\Invoice;
use App\Models\Order;
use App\Models\Transaction;
use App\Repositories\Customer\CustomerRepositoryInterface;
use App\Repositories\Hosting\HostingRepositoryInterface;
use App\Repositories\Invoice\InvoiceRepositoryInterface;
use App\Repositories\InvoiceItem\InvoiceItemRepositoryInterface;
use App\Repositories\Log\LogRepositoryInterface;
use App\Repositories\Mail\MailRepositoryInterface;
use App\Repositories\Module\Domain\DomainRepositoryInterface;
use App\Repositories\Module\Hosting\HostingRepositoryInterface as ModuleHostingRepositoryInterface;
use App\Repositories\Module\IpAddress\IpAddressRepositoryInterface;
use App\Repositories\Module\Vmware\VmwareRepositoryInterface;
use App\Repositories\Transaction\TransactionRepositoryInterface;
use App\Repositories\VPS\VPSRepositoryInterface;
use Carbon\Carbon;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
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
{
public function __construct(
public CustomerRepositoryInterface $customerRepository,
public InvoiceItemRepositoryInterface $invoiceItemRepository,
public ModuleHostingRepositoryInterface $moduleHostingRepository,
public VmwareRepositoryInterface $vmwareRepository,
public IpAddressRepositoryInterface $ipaddressRepository,
public HostingRepositoryInterface $hostingRepository,
public VPSRepositoryInterface $vPSRepositoryInterface,
public LogRepositoryInterface $logRepository,
public DomainRepositoryInterface $moduleDomainRepository,
public InvoiceRepositoryInterface $invoiceRepository,
public TransactionRepositoryInterface $transactionRepository,
public MailRepositoryInterface $mailRepository
) {
}
public function index(Request $request)
{
$customers = $this->customerRepository->filter(
$request->merge(['page' => $request->get('page') ?? 1])->all(),
[],
['hosting', 'vps', 'domain'],
);
$title = 'View All Customer';
return view('administrator.pages.customer.index', compact('customers', 'title'));
}
//Validate userid
/**
* Get customer Information
*/
public function getCustomerInfo(Request $request)
{
//Validate userid
$userid = $this->validateUserid();
if (!$userid) {
return redirect()->route('customer.index')->withErrors('No data found for this user');
}
//find data after validate
$customer = $this->customerRepository->findWithRelationships(
$userid,
[
'mail',
'file'
],
[
'invoice' => [
'invoices_status_count_1' => [
'key' => 'status',
'condition' => '=',
'value' => 1
],
'invoices_status_count_0' => [
'key' => 'status',
'condition' => '=',
'value' => 0
]
],
'hosting' => 'hosting_count',
'vps' => 'vps_count',
'domain' => 'domain_count',
'ticket' => 'ticket_count'
],
[
'invoice' => [
'invoices_status_1' => [
'key' => 'status',
'condition' => '=',
'value' => 1,
'sum' => 'total'
],
'invoices_status_0' => [
'key' => 'status',
'condition' => '=',
'value' => 0,
'sum' => 'total'
]
]
]
);
if (!$customer) {
return redirect()->route('customer.index')->withErrors('No data found for this user');
}
$title = "#" . $customer->id . " " . $customer->fullname;
return view("administrator.pages.customer.info", compact('customer', 'title', 'userid'));
}
protected function validateUserid()
{
$validate = Validator::make(\request()->all(), [
'userid' => 'numeric|required'
]);
if ($validate->fails()) {
return false;
}
return \request()->userid;
}
/**
* Get customer Profile
*/
public function getCustomerProfile(Request $request)
{
//Validate userid
$userid = $this->validateUserid();
if (!$userid) {
return redirect()->route('customer.index')->withErrors('No data found for this user');
}
//find data after validate
$customer = $this->customerRepository->findWithRelationships($userid, ['snapshot']);
if (!$customer) {
return redirect()->route('customer.index')->withErrors('No data found for this user');
}
$title = "#" . $customer->id . " " . $customer->fullname;
return view("administrator.pages.customer.profile", compact('customer', 'title', 'userid'));
}
/**
* Save profile update
*/
public function storeCustomerProfile(Request $request)
{
//Validate userid
$userid = $this->validateUserid();
if (!$userid) {
return redirect()->route('customer.index')->withErrors('No data found for this user');
}
//validate data after validate userid
$request->validate([
'fullname' => 'required',
'email' => 'required'
]);
//find user
$customer = $this->customerRepository->findWithRelationships($userid, ['snapshot']);
if (!$customer) {
return redirect()->route('customer.index')->withErrors('No data found for this user');
}
try {
DB::beginTransaction();
$data = $request->except(['_token', 'userid', 'password', 'email_marketing', 'snapshot_limit']);
$request->email_marketing === "on" ? $data['email_marketing'] = 1 : $data['email_marketing'] = 0;
if (!empty($request->password)) {
$data['password'] = password_hash($request->password, PASSWORD_BCRYPT);
}
$this->customerRepository->update($userid, $data);
$customer->snapShot->limit = $request->snapshot_limit;
$customer->snapShot->save();
DB::commit();
} catch (Exception $error) {
DB::rollBack();
return back()->withErrors($error->getMessage());
}
return back()->with('success', 'Updated successfully');
}
/**
* Get all product for customer
*/
public function getCustomerProduct(Request $request)
{
//Validate userid
$userid = $this->validateUserid();
if (!$userid) {
return redirect()->route('customer.index')->withErrors('No data found for this user');
}
$customer = $this->customerRepository->find($userid);
if (!$customer) {
return redirect()->route('customer.index')->withErrors('Invalidated Request');
}
// Lấy tất cả hosting và VPS của customer
$hostingServices = $this->moduleHostingRepository->filter(
['customer_id' => $userid],
['server']
);
$vpsServices = $this->vmwareRepository->filter(
['customer_id' => $userid],
['ipaddress.host.datacenter.vCenter', 'os.osGroup']
);
// Kết hợp và format dữ liệu
$allService = collect();
foreach ($hostingServices as $hosting) {
$allService->push((object) [
'product_id' => $hosting->id,
'product_type' => 3,
'name' => $hosting->name,
'description' => $hosting->name . ' (Hosting)'
]);
}
foreach ($vpsServices as $vps) {
$allService->push((object) [
'product_id' => $vps->id,
'product_type' => 4,
'name' => $vps->name,
'description' => $vps->name . ' (VPS)'
]);
}
// Lấy invoice_item cụ thể cho sản phẩm
$invoice_item = $this->invoiceItemRepository->findBy(
$userid,
[
'key' => 'customer_id',
'condition' => '=',
'value' => $userid
]
);
$type = null;
$product = null;
$productName = '';
if ($invoice_item) {
$product_id = $invoice_item->product_id ?? null;
$product_module_id = $request->get('product') ?? $invoice_item->product_id ?? null;
$type = $request->get('type') ?? $invoice_item->product_type ?? null;
} else {
$product_id = null;
$product_module_id = $request->get('product');
$type = $request->get('type');
}
switch ($type) {
case 3:
$product = $this->moduleHostingRepository->findWithRelationships(
$product_module_id,
[
'order.payment',
'server'
]
);
// Tìm template hosting dựa trên product_id
$productName = $this->hostingRepository->find($product_id);
break;
case 4:
$product = $this->vmwareRepository->findWithRelationships(
$product_module_id,
[
'order.payment',
'ipaddress.host.datacenter.vCenter',
'os.osGroup'
]
);
// Tìm template VPS dựa trên product_id
$productName = $this->vPSRepositoryInterface->find($product_id);
break;
}
$title = "#" . $customer->id . " " . $customer->fullname;
return view(
'administrator.pages.customer.product',
compact(
'title',
'userid',
'type',
'product',
'allService',
'productName',
'invoice_item'
)
);
}
public function storeCustomerProduct(Request $request)
{
if (!$request->product_type) {
return back()->with($request->except(['_token', '_method']))->withErrors('Invalid Request');
}
$product = null;
$data = null;
$rules = [];
switch ($request->product_type) {
case 3:
$rules = [
'product_id' => 'required',
'next_due_date' => 'required',
'next_payment' => 'required',
'status' => 'required'
];
$product = $this->moduleHostingRepository->find($request->product_id);
$data = $this->handleHosting($request);
break;
case 4:
$rules = [
'product_id' => 'required',
'next_due_date' => 'required',
'next_payment' => 'required',
'status' => 'required'
];
$product = $this->vmwareRepository->find($request->product_id);
$data = $this->handleVmware($request);
break;
}
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
return back()->withErrors($validator->errors()->first());
}
if (!$product) {
return back()->withErrors('Product not found');
}
try {
DB::beginTransaction();
$product->update($data);
$this->ipaddressRepository->updateBy(['ip' => $request->ip], ['status' => 1, 'vm_name' => $request->name]);
DB::commit();
} catch (Exception $exception) {
DB::rollBack();
return back()->with($request->except(['_token', '_method']))->withErrors($exception->getMessage());
}
return back()->with('success', 'Update information successfully');
}
protected function handleHosting($request)
{
return [
'name' => $request->name,
'module_server_id' => $request->module_server_id,
'next_payment' => $request->next_payment,
'next_due_date' => Carbon::createFromFormat('d/m/Y', $request->next_due_date)->timestamp,
'next_invoice' => Carbon::createFromFormat('d/m/Y', $request->next_due_date)->timestamp,
'username' => $request->user,
'password' => $request->password ? SignRSA::EncryptFunc($request->password) : '',
'status' => $request->status
];
}
protected function handleVmware($request)
{
return [
'name' => $request->name,
'module_ipaddress_id' => $request->ip,
'port' => $request->port,
'user' => $request->user,
'password' => $request->password ? SignRSA::EncryptFunc($request->password) : '',
'hostname' => $request->hostname,
'vmware_id' => $request->vmware_id,
'os_id' => $request->os_version,
'next_payment' => $request->next_payment,
'next_due_date' => Carbon::createFromFormat('d/m/Y', $request->next_due_date)->timestamp,
'next_invoice' => Carbon::createFromFormat('d/m/Y', $request->next_due_date)->timestamp,
'status' => $request->status
];
}
/**
* Get Domain for customer
*/
public function getCustomerDomain(Request $request)
{
//Validate userid
$userid = $this->validateUserid();
if (!$userid) {
return redirect()->route('customer.index')->withErrors('No data found for this user');
}
$customer = $this->customerRepository->find($userid);
if (!$customer) {
return redirect()->route('customer.index')->withErrors('Invalid Request');
}
$domains = $this->moduleDomainRepository->filter(
[
'customer_id' => $userid,
'page' => $request->get('page') ?? 1
],
['customer']
);
$title = "#" . $customer->id . " " . $customer->fullname;
return view('administrator.pages.customer.domain', compact('userid', 'title', 'domains'));
}
/**
* Get Invoice for customer
*/
public function getCustomerInvoice(Request $request)
{
//Validate userid
$userid = $this->validateUserid();
if (!$userid) {
return redirect()->route('customer.index')->withErrors('No data found for this user');
}
$customer = $this->customerRepository->find($userid);
if (!$customer) {
return redirect()->route('customer.index')->withErrors('No data found for this user');
}
$invoices = $this->invoiceRepository->filter(
[
'customer_id' => $userid,
'page' => $request->get('page') ?? 1
],
[
'payment'
]
);
$title = "#" . $customer->id . " " . $customer->fullname;
return view('administrator.pages.customer.invoice', compact('userid', 'title', 'invoices'));
}
/**
* Get Transactions for customer
*/
public function getCustomerTransactions(Request $request)
{
//Validate userid
$userid = $this->validateUserid();
if (!$userid) {
return redirect()->route('customer.index')->withErrors('No data found for this user');
}
$customer = $this->customerRepository->find($userid);
if (!$customer) {
return redirect()->route('customer.index')->withErrors('No data found for this user');
}
$transactions = $this->transactionRepository->filter(
[
'customer_id' => $userid,
'page' => $request->get('page') ?? 1
]
);
$title = "#" . $customer->id . " " . $customer->fullname;
return view('administrator.pages.customer.transaction', compact('userid', 'title', 'transactions'));
}
/**
* Get Mail for customer
*/
public function getCustomerEmail(Request $request)
{
$userid = $this->validateUserid();
if (!$userid) {
return redirect()->route("customer.index")->withErrors("No data found for this user");
}
$customer = $this->customerRepository->find($userid);
if (!$customer) {
return redirect()->route('customer.index')->withErrors('No data found for this user');
}
$emails = $this->mailRepository->filter(
[
'customer_id' => $userid,
'page' => $request->get('page') ?? 1
]
);
$title = "#" . $customer->id . " " . $customer->fullname;
if (isset($request->email_id)) {
$template = $this->mailRepository->find($request->get('email_id'));
if ($template) {
$title = $template->subject;
return view("emails.render", compact('title', 'template'));
}
}
return view('administrator.pages.customer.mail', compact('userid', 'title', 'emails'));
}
/**
* Get Log for customer
*/
public function getCustomerLog(Request $request)
{
$userid = $this->validateUserid();
if (!$userid) {
return redirect()->route("customer.index")->withErrors("No data found for this user");
}
$customer = $this->customerRepository->find($userid);
if (!$customer) {
return redirect()->route('customer.index')->withErrors('Invalid Request');
}
$logs = $this->logRepository->filter([
'customer_id' => $userid,
'page' => $request->get('page') ?? 1
], ['customer']);
$title = "#" . $customer->id . " " . $customer->fullname;
return view('administrator.pages.customer.log', compact('userid', 'title', 'logs'));
}
/**
* Save new customer
*/
public function store(CreateCustomerRequest $request)
{
$request->validated();
$user = $this->customerRepository->findBy('email', $request->get('email'));
if ($user) {
return back()->withErrors("Email already exists on the system!");
}
try {
DB::beginTransaction();
$data = $request->all();
$data['password'] = password_hash($request->password, PASSWORD_BCRYPT);
$request->email_marketing === "on" ? $data['email_marketing'] = 1 : $data['email_marketing'] = 0;
$this->customerRepository->create($data);
DB::commit();
} catch (Exception $error) {
DB::rollBack();
return back()->withErrors($error->getMessage());
}
return redirect()->route('customer.index')->with('success', 'New user added successfully');
}
/**
* add new customer
*/
public function create()
{
return view('administrator.pages.customer.add', ['title' => 'Thêm Customer']);
}
public function PasswordReset(Request $request)
{
$validator = Validator::make(
$request->all(),
[
'userid' => 'required|numeric|not__in:0'
],
[
'userid' => [
'required' => 'Invalid request'
]
]
);
if ($validator->fails()) {
return back()->withErrors($validator);
}
$password = Str::random(10);
try {
DB::beginTransaction();
$this->customerRepository->update(
$request->get('userid'),
[
'password' => Hash::make($password)
]
);
$data = [
'company_name' => setting('company'),
'company_logo' => setting('logo'),
'password' => $password,
];
$jobs = new PasswordRecoverJob($data, $this->customerRepository->find($request->get('userid')));
dispatch($jobs)->delay(now()->addSeconds(10));
DB::commit();
} catch (Exception $exception) {
DB::rollBack();
return back()->withErrors($exception->getMessage());
}
return back()->with('success', "Change and Send new password to email successfully");
}
public function addPay(Request $request)
{
$validator = Validator::make(
$request->all(),
[
'userid' => 'required|numeric|not__in:0'
],
[
'userid' => [
'required' => 'Invalid request'
]
]
);
if ($validator->fails()) {
return back()->withErrors($validator);
}
$userid = $request->userid;
$customer = $this->customerRepository->find($userid);
if (!$customer) {
return redirect()->route('customer.index')->withErrors('No data found for this user');
}
$title = "Add Pay for Customer";
return view('administrator.pages.customer.addPay', compact('title', 'userid'));
}
public function addPayStore(AddPayRequest $request)
{
$request->validated();
$customer = $this->customerRepository->find($request->get('userid'));
if (!$customer) {
return redirect()->route('customer.index')->withErrors('Invalid Request');
}
try {
DB::beginTransaction();
match ($request->action) {
"+" => $this->customerRepository->update($request->get('userid'), [
'credit' => (int) $customer->credit + (int) $request->get('amount'),
'total' => (int) $customer->total + (int) $request->get('amount'),
]),
"-" => $this->customerRepository->update($request->get('userid'), [
'credit' => (int) $customer->credit - (int) $request->get('amount'),
'total' => (int) $customer->total - (int) $request->get('amount'),
]),
};
DB::commit();
} catch (Exception $exception) {
DB::rollBack();
return back()->withErrors($exception->getMessage());
}
return back()->with('success', 'Recharge for user successfully');
}
public function LoginWithCustomer(Request $request)
{
$validator = Validator::make(
$request->all(),
[
'userid' => 'required|numeric|not__in:0'
],
[
'userid' => [
'required' => 'Invalid request'
]
]
);
if ($validator->fails()) {
return back()->withErrors($validator);
}
$customer = $this->customerRepository->find($request->get('userid'));
if (!$customer) {
return back()->withErrors('Invalid request');
}
// TODO: impersonation feature needs redesign for JWT — session login does not work with JWT guard
// This is a legacy Livewire admin feature; will be removed when portal-admin migration is complete
Auth::guard('client')->login($customer);
session()->put('admin_login_for_customer', true);
return redirect()->route('home');
}
public function LogoutWithCustomer()
{
Auth::guard('client')->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('status', function ($d) {
return view('administrator.pages.customer.datatable.status', ['row' => $d])->render();
})
->addColumn(
'action',
function ($d) {
return view('administrator.pages.customer.datatable.action', ['row' => $d])->render();
}
)
->rawColumns(['status', 'action'])
->make(true);
}
public function edit(int $id = 0)
{
$customer = $this->customerRepository->find($id);
if (!$customer) {
return back()->withErrors('Invalid request.');
}
$title = 'Edit Customer';
return view('administrator.pages.customer.edit', compact('title', 'customer'));
}
public function update(int $id = 0, CreateCustomerRequest $request)
{
$customer = $this->customerRepository->find($id);
if (!$customer) {
return back()->withErrors('Invalid request.');
}
$request->validated();
try {
DB::beginTransaction();
$data = $request->except(['_token', 'password']);
if (!empty($request->password)) {
$data['password'] = password_hash($request->password, PASSWORD_BCRYPT);
}
$this->customerRepository->update($id, $data);
DB::commit();
} catch (Exception $error) {
DB::rollBack();
return back()->withErrors($error->getMessage());
}
return redirect()->route('customer.index')->with('success', 'Update customer successfully!');
}
public function destroy(int $id = 0)
{
$customer = $this->customerRepository->find($id);
if (!$customer) {
return back()->withErrors('Invalid request.');
}
DB::beginTransaction();
try {
Invoice::where('customer_id', $id)->delete();
Order::where('customer_id', $id)->delete();
Transaction::where('customer_id', $id)->delete();
$customer->delete();
DB::commit();
} catch (Exception $error) {
DB::rollBack();
return back()->withErrors($error->getMessage());
}
return redirect()->route('customer.index')->with('success', 'Deleted customer successfully!');
}
public function trash()
{
$title = 'Trash Customers';
return view('administrator.pages.customer.trash', compact('title'));
}
public function datatableTrash(Request $request)
{
$query = $this->customerRepository->onlyTrashed(
[],
['hosting', 'vps', 'domain']
);
return DataTables::eloquent($query)
->addColumn('status', function ($d) {
return view('administrator.pages.customer.datatable.status', ['row' => $d])->render();
})
->addColumn(
'action',
function ($d) {
return view('administrator.pages.customer.datatable.action-trash', ['row' => $d])->render();
}
)
->rawColumns(['status', 'action'])
->make(true);
}
public function restore(int $id = 0)
{
$customer = $this->customerRepository->find($id);
if (!$customer) {
$customer = $this->customerRepository->onlyTrashed()->find($id);
}
if (!$customer) {
return back()->withErrors('Invalid request.');
}
DB::beginTransaction();
try {
$customer->restore();
Invoice::withTrashed()->where('customer_id', $id)->restore();
Order::withTrashed()->where('customer_id', $id)->restore();
Transaction::withTrashed()->where('customer_id', $id)->restore();
DB::commit();
} catch (Exception $error) {
DB::rollBack();
return back()->withErrors($error->getMessage());
}
return back()->with('success', 'Restored customer successfully!');
}
public function forceDelete(int $id = 0)
{
$customer = $this->customerRepository->onlyTrashed()->find($id);
if (!$customer) {
return back()->withErrors('Invalid request.');
}
DB::beginTransaction();
try {
Invoice::withTrashed()->where('customer_id', $id)->forceDelete();
Order::withTrashed()->where('customer_id', $id)->forceDelete();
Transaction::withTrashed()->where('customer_id', $id)->forceDelete();
$customer->forceDelete();
DB::commit();
} catch (Exception $error) {
DB::rollBack();
return back()->withErrors($error->getMessage());
}
return back()->with('success', 'Permanently deleted customer!');
}
}