refactor: Remove extensive unused administrative UI, styling, and JavaScript assets, and introduce a new payment API controller.
This commit is contained in:
@@ -3,26 +3,56 @@
|
||||
namespace App\Http\Controllers\Api\Admin\Customer;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\CreateCustomerRequest;
|
||||
use App\Http\Resources\Api\Admin\CustomerResource;
|
||||
use App\Repositories\Admin\Customer\AdminCustomerRepositoryInterface;
|
||||
use App\Jobs\Mail\PasswordRecoverJob;
|
||||
use App\Models\Customer;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Order;
|
||||
use App\Models\Transaction;
|
||||
use App\Repositories\Customer\CustomerRepositoryInterface;
|
||||
use App\Repositories\Invoice\InvoiceRepositoryInterface;
|
||||
use App\Repositories\InvoiceItem\InvoiceItemRepositoryInterface;
|
||||
use App\Repositories\Module\Domain\DomainRepositoryInterface;
|
||||
use App\Repositories\Module\Hosting\HostingRepositoryInterface as ModuleHostingRepositoryInterface;
|
||||
use App\Repositories\Module\Vmware\VmwareRepositoryInterface;
|
||||
use App\Repositories\Order\OrderRepositoryInterface;
|
||||
use App\Repositories\Transaction\TransactionRepositoryInterface;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Str;
|
||||
use Yajra\DataTables\Facades\DataTables;
|
||||
|
||||
class CustomerController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly AdminCustomerRepositoryInterface $customers,
|
||||
private readonly CustomerRepositoryInterface $customerRepository,
|
||||
private readonly InvoiceRepositoryInterface $invoiceRepository,
|
||||
private readonly InvoiceItemRepositoryInterface $invoiceItemRepository,
|
||||
private readonly ModuleHostingRepositoryInterface $moduleHostingRepository,
|
||||
private readonly VmwareRepositoryInterface $vmwareRepository,
|
||||
private readonly OrderRepositoryInterface $orderRepository,
|
||||
private readonly TransactionRepositoryInterface $transactionRepository,
|
||||
private readonly DomainRepositoryInterface $moduleDomainRepository,
|
||||
) {}
|
||||
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$perPage = min((int) $request->get('per_page', 15), 100);
|
||||
$paginator = $this->customers->paginate($request->only('filter', 'status'), $perPage);
|
||||
$paginator = $this->customerRepository->filter(
|
||||
$request->all(),
|
||||
[],
|
||||
['hosting', 'vps', 'domain'],
|
||||
['*'],
|
||||
false
|
||||
);
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'data' => [
|
||||
'items' => CustomerResource::collection($paginator->items()),
|
||||
'items' => CustomerResource::collection($paginator),
|
||||
'total' => $paginator->total(),
|
||||
'per_page' => $paginator->perPage(),
|
||||
'current_page' => $paginator->currentPage(),
|
||||
@@ -30,4 +60,426 @@ class CustomerController extends Controller
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function datatable(Request $request): JsonResponse
|
||||
{
|
||||
$query = $this->customerRepository->filter(
|
||||
$request->all(),
|
||||
[],
|
||||
['hosting', 'vps', 'domain'],
|
||||
['*'],
|
||||
true
|
||||
);
|
||||
|
||||
return DataTables::eloquent($query)
|
||||
->addColumn('status', fn($d) => $d->status)
|
||||
->addColumn('action', fn($d) => $d->id)
|
||||
->rawColumns(['status', 'action'])
|
||||
->make(true);
|
||||
}
|
||||
|
||||
public function store(CreateCustomerRequest $request): JsonResponse
|
||||
{
|
||||
$request->validated();
|
||||
|
||||
$existingCustomer = $this->customerRepository->findBy('email', $request->get('email'));
|
||||
if ($existingCustomer) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => 'Email already exists on the system!'
|
||||
], 422);
|
||||
}
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
$data = $request->all();
|
||||
$data['password'] = Hash::make($request->password);
|
||||
$data['email_marketing'] = $request->email_marketing === "on" ? 1 : 0;
|
||||
|
||||
$customer = $this->customerRepository->create($data);
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Customer created successfully',
|
||||
'data' => new CustomerResource($customer)
|
||||
], 201);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function show(int $id): JsonResponse
|
||||
{
|
||||
$customer = $this->customerRepository->findWithRelationships(
|
||||
$id,
|
||||
['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 response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find customer by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'data' => new CustomerResource($customer)
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(int $id, CreateCustomerRequest $request): JsonResponse
|
||||
{
|
||||
$customer = $this->customerRepository->find($id);
|
||||
|
||||
if (!$customer) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find customer by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
$request->validated();
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
$data = $request->except(['_token', 'password']);
|
||||
|
||||
if (!empty($request->password)) {
|
||||
$data['password'] = Hash::make($request->password);
|
||||
}
|
||||
|
||||
$this->customerRepository->update($id, $data);
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Customer updated successfully',
|
||||
'data' => new CustomerResource($this->customerRepository->find($id))
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function destroy(int $id): JsonResponse
|
||||
{
|
||||
$customer = $this->customerRepository->find($id);
|
||||
|
||||
if (!$customer) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find customer by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
Invoice::where('customer_id', $id)->delete();
|
||||
Order::where('customer_id', $id)->delete();
|
||||
Transaction::where('customer_id', $id)->delete();
|
||||
$customer->delete();
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Customer deleted successfully'
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function trash(Request $request): JsonResponse
|
||||
{
|
||||
$query = $this->customerRepository->onlyTrashed([], ['hosting', 'vps', 'domain']);
|
||||
|
||||
return DataTables::eloquent($query)
|
||||
->addColumn('status', fn($d) => $d->status)
|
||||
->addColumn('action', fn($d) => $d->id)
|
||||
->rawColumns(['status', 'action'])
|
||||
->make(true);
|
||||
}
|
||||
|
||||
public function restore(int $id): JsonResponse
|
||||
{
|
||||
$customer = $this->customerRepository->find($id);
|
||||
if (!$customer) {
|
||||
$customer = $this->customerRepository->onlyTrashed()->find($id);
|
||||
}
|
||||
|
||||
if (!$customer) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find customer by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
$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();
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Customer restored successfully'
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function forceDelete(int $id): JsonResponse
|
||||
{
|
||||
$customer = $this->customerRepository->onlyTrashed()->find($id);
|
||||
|
||||
if (!$customer) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find customer by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
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();
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Customer permanently deleted'
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function resetPassword(Request $request, int $id): JsonResponse
|
||||
{
|
||||
$customer = $this->customerRepository->find($id);
|
||||
|
||||
if (!$customer) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find customer by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
$password = Str::random(10);
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
$this->customerRepository->update($id, ['password' => Hash::make($password)]);
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Password reset successfully',
|
||||
'data' => ['new_password' => $password]
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function addCredit(Request $request, int $id): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'amount' => 'required|numeric|min:1',
|
||||
'action' => 'required|in:+,-'
|
||||
]);
|
||||
|
||||
$customer = $this->customerRepository->find($id);
|
||||
|
||||
if (!$customer) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find customer by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
$amount = (int) $request->amount;
|
||||
|
||||
if ($request->action === "+") {
|
||||
$this->customerRepository->update($id, [
|
||||
'credit' => (int) $customer->credit + $amount,
|
||||
'total' => (int) $customer->total + $amount,
|
||||
]);
|
||||
} else {
|
||||
$this->customerRepository->update($id, [
|
||||
'credit' => (int) $customer->credit - $amount,
|
||||
'total' => (int) $customer->total - $amount,
|
||||
]);
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Credit updated successfully'
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function getProducts(int $id): JsonResponse
|
||||
{
|
||||
$customer = $this->customerRepository->find($id);
|
||||
|
||||
if (!$customer) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find customer by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
$hostingServices = $this->moduleHostingRepository->filter(['customer_id' => $id], ['server']);
|
||||
$vpsServices = $this->vmwareRepository->filter(
|
||||
['customer_id' => $id],
|
||||
['ipaddress.host.datacenter.vCenter', 'os.osGroup']
|
||||
);
|
||||
|
||||
$allService = collect();
|
||||
|
||||
foreach ($hostingServices as $hosting) {
|
||||
$allService->push([
|
||||
'product_id' => $hosting->id,
|
||||
'product_type' => 3,
|
||||
'name' => $hosting->name,
|
||||
'description' => $hosting->name . ' (Hosting)'
|
||||
]);
|
||||
}
|
||||
|
||||
foreach ($vpsServices as $vps) {
|
||||
$allService->push([
|
||||
'product_id' => $vps->id,
|
||||
'product_type' => 4,
|
||||
'name' => $vps->name,
|
||||
'description' => $vps->name . ' (VPS)'
|
||||
]);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'data' => $allService->values()
|
||||
]);
|
||||
}
|
||||
|
||||
public function getInvoices(int $id, Request $request): JsonResponse
|
||||
{
|
||||
$customer = $this->customerRepository->find($id);
|
||||
|
||||
if (!$customer) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find customer by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
$invoices = $this->invoiceRepository->filter(
|
||||
['customer_id' => $id],
|
||||
['payment']
|
||||
);
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'data' => $invoices
|
||||
]);
|
||||
}
|
||||
|
||||
public function getTransactions(int $id, Request $request): JsonResponse
|
||||
{
|
||||
$customer = $this->customerRepository->find($id);
|
||||
|
||||
if (!$customer) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find customer by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
$transactions = $this->transactionRepository->filter(['customer_id' => $id]);
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'data' => $transactions
|
||||
]);
|
||||
}
|
||||
|
||||
public function getDomains(int $id, Request $request): JsonResponse
|
||||
{
|
||||
$customer = $this->customerRepository->find($id);
|
||||
|
||||
if (!$customer) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find customer by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
$domains = $this->moduleDomainRepository->filter(
|
||||
['customer_id' => $id],
|
||||
['customer']
|
||||
);
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'data' => $domains
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,31 +3,254 @@
|
||||
namespace App\Http\Controllers\Api\Admin\Invoice;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\InvoiceRequest;
|
||||
use App\Http\Resources\Api\Admin\InvoiceResource;
|
||||
use App\Repositories\Admin\Invoice\AdminInvoiceRepositoryInterface;
|
||||
use App\Models\Customer;
|
||||
use App\Models\Payment;
|
||||
use App\Repositories\Invoice\InvoiceRepositoryInterface;
|
||||
use App\Repositories\InvoiceItem\InvoiceItemRepositoryInterface;
|
||||
use App\Repositories\Order\OrderRepositoryInterface;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Yajra\DataTables\Facades\DataTables;
|
||||
|
||||
class InvoiceController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly AdminInvoiceRepositoryInterface $invoices,
|
||||
private readonly InvoiceRepositoryInterface $invoiceRepository,
|
||||
private readonly OrderRepositoryInterface $orderRepository,
|
||||
private readonly InvoiceItemRepositoryInterface $invoiceItemRepository,
|
||||
) {}
|
||||
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$perPage = min((int) $request->get('per_page', 15), 100);
|
||||
$paginator = $this->invoices->paginate($request->only('filter', 'status'), $perPage);
|
||||
$query = $this->invoiceRepository->filter(
|
||||
$request->all(),
|
||||
['payment', 'customer'],
|
||||
[],
|
||||
['*'],
|
||||
true
|
||||
);
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'data' => [
|
||||
'items' => InvoiceResource::collection($paginator->items()),
|
||||
'total' => $paginator->total(),
|
||||
'per_page' => $paginator->perPage(),
|
||||
'current_page' => $paginator->currentPage(),
|
||||
'last_page' => $paginator->lastPage(),
|
||||
'data' => [
|
||||
'items' => InvoiceResource::collection($query->get())->resolve(),
|
||||
'total' => $query->count(),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function datatable(Request $request): JsonResponse
|
||||
{
|
||||
$query = $this->invoiceRepository->filter(
|
||||
$request->all(),
|
||||
['payment', 'customer'],
|
||||
[],
|
||||
['*'],
|
||||
true
|
||||
);
|
||||
|
||||
return DataTables::eloquent($query)
|
||||
->addColumn('invoice_num', fn($d) => $d->invoice_num)
|
||||
->addColumn('date', fn($d) => $d->date)
|
||||
->addColumn('customer', fn($d) => $d->customer?->fullname)
|
||||
->addColumn('payment', fn($d) => $d->payment?->name)
|
||||
->addColumn('total', fn($d) => $d->total)
|
||||
->addColumn('status', fn($d) => $d->status)
|
||||
->addColumn('action', fn($d) => $d->id)
|
||||
->rawColumns(['invoice_num', 'date', 'customer', 'payment', 'total', 'status', 'action'])
|
||||
->make(true);
|
||||
}
|
||||
|
||||
public function store(Request $request): JsonResponse
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'customer_id' => 'required|numeric',
|
||||
'payment_id' => 'required|numeric',
|
||||
'sub_total' => 'required|numeric',
|
||||
'total' => 'required|numeric',
|
||||
]);
|
||||
|
||||
$invoiceData = [
|
||||
'date' => time(),
|
||||
'due_date' => time() + (7 * 24 * 60 * 60),
|
||||
'sub_total' => $validated['sub_total'],
|
||||
'tax' => $validated['sub_total'] * 0.1,
|
||||
'total' => $validated['total'],
|
||||
'payment_id' => $validated['payment_id'],
|
||||
'customer_id' => $validated['customer_id'],
|
||||
'status' => 0,
|
||||
];
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
$invoice = $this->invoiceRepository->create($invoiceData);
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Invoice created successfully',
|
||||
'data' => new InvoiceResource($invoice)
|
||||
], 201);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function show(int $id): JsonResponse
|
||||
{
|
||||
$invoice = $this->invoiceRepository->findWithRelationships($id, ['payment', 'invoiceItem', 'customer']);
|
||||
|
||||
if (!$invoice) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find invoice by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'data' => new InvoiceResource($invoice)
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(InvoiceRequest $request, int $id): JsonResponse
|
||||
{
|
||||
$invoice = $this->invoiceRepository->find($id);
|
||||
|
||||
if (!$invoice) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find invoice by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
$request->validated();
|
||||
|
||||
$status = match (strtolower($request->get('action'))) {
|
||||
"paid" => 1,
|
||||
"cancel" => 2,
|
||||
default => 0
|
||||
};
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
$this->invoiceRepository->update($id, [
|
||||
'status' => $status,
|
||||
'date_paid' => $status === 1 ? time() : null
|
||||
]);
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Invoice updated successfully'
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function destroy(int $id): JsonResponse
|
||||
{
|
||||
$invoice = $this->invoiceRepository->find($id);
|
||||
|
||||
if (!$invoice) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find invoice by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
$this->orderRepository->updateBy('invoice_id', $id, ['invoice_id' => 0]);
|
||||
$this->invoiceRepository->delete($id);
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Invoice deleted successfully'
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function markAsPaid(int $id): JsonResponse
|
||||
{
|
||||
$invoice = $this->invoiceRepository->find($id);
|
||||
|
||||
if (!$invoice) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find invoice by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
$this->invoiceRepository->update($id, [
|
||||
'status' => 1,
|
||||
'date_paid' => time()
|
||||
]);
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Invoice marked as paid'
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function cancel(int $id): JsonResponse
|
||||
{
|
||||
$invoice = $this->invoiceRepository->find($id);
|
||||
|
||||
if (!$invoice) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find invoice by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
$this->invoiceRepository->update($id, [
|
||||
'status' => 2,
|
||||
'date_paid' => null
|
||||
]);
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Invoice cancelled'
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,31 +3,488 @@
|
||||
namespace App\Http\Controllers\Api\Admin\Order;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Helpers\Helper;
|
||||
use App\Http\Requests\OrderRequest;
|
||||
use App\Http\Requests\UpdateOrderRequest;
|
||||
use App\Http\Resources\Api\Admin\OrderResource;
|
||||
use App\Repositories\Admin\Order\AdminOrderRepositoryInterface;
|
||||
use App\Jobs\Hosting\CreateHostingJobs;
|
||||
use App\Jobs\VirtualMachine\Create\CreateVMJobs;
|
||||
use App\Jobs\VirtualMachine\Upgrade\UpgradeVirtualMachine;
|
||||
use App\Models\Order;
|
||||
use App\Repositories\Addon\AddonRepositoryInterface;
|
||||
use App\Repositories\Hosting\HostingRepositoryInterface;
|
||||
use App\Repositories\Invoice\InvoiceRepositoryInterface;
|
||||
use App\Repositories\InvoiceItem\InvoiceItemRepositoryInterface;
|
||||
use App\Repositories\Module\Hosting\HostingRepositoryInterface as ModuleHostingRepositoryInterface;
|
||||
use App\Repositories\Module\HostingServer\HostingServerRepositoryInterface;
|
||||
use App\Repositories\Module\IpAddress\IpAddressRepositoryInterface;
|
||||
use App\Repositories\Module\Vmware\VmwareRepositoryInterface;
|
||||
use App\Repositories\Order\OrderRepositoryInterface;
|
||||
use App\Repositories\Os\OsRepositoryInterface;
|
||||
use App\Repositories\VPS\VPSRepositoryInterface;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Yajra\DataTables\Facades\DataTables;
|
||||
|
||||
class OrderController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly AdminOrderRepositoryInterface $orders,
|
||||
private readonly OrderRepositoryInterface $orderRepository,
|
||||
private readonly HostingRepositoryInterface $hostingRepository,
|
||||
private readonly VPSRepositoryInterface $vPSRepository,
|
||||
private readonly InvoiceRepositoryInterface $invoiceRepository,
|
||||
private readonly InvoiceItemRepositoryInterface $invoiceItemRepository,
|
||||
private readonly ModuleHostingRepositoryInterface $moduleHostingRepository,
|
||||
private readonly VmwareRepositoryInterface $moduleVmwareRepository,
|
||||
private readonly HostingServerRepositoryInterface $moduleHostingServerRepository,
|
||||
private readonly OsRepositoryInterface $osRepository,
|
||||
private readonly IpAddressRepositoryInterface $ipAddressRepository,
|
||||
private readonly AddonRepositoryInterface $addonRepository,
|
||||
) {}
|
||||
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$perPage = min((int) $request->get('per_page', 15), 100);
|
||||
$paginator = $this->orders->paginate($request->only('filter', 'status'), $perPage);
|
||||
$perPage = min((int) $request->get('per_page', 15), 100);
|
||||
|
||||
$query = $this->orderRepository->filter(
|
||||
$request->all(),
|
||||
['payment', 'customer', 'invoice'],
|
||||
[],
|
||||
['*'],
|
||||
true
|
||||
);
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'data' => [
|
||||
'items' => OrderResource::collection($paginator->items()),
|
||||
'total' => $paginator->total(),
|
||||
'per_page' => $paginator->perPage(),
|
||||
'current_page' => $paginator->currentPage(),
|
||||
'last_page' => $paginator->lastPage(),
|
||||
'data' => [
|
||||
'items' => OrderResource::collection($query->get())->resolve(),
|
||||
'total' => $query->count(),
|
||||
'per_page' => $perPage,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function datatable(Request $request): JsonResponse
|
||||
{
|
||||
$query = $this->orderRepository->filter(
|
||||
$request->all(),
|
||||
['payment', 'customer', 'invoice'],
|
||||
[],
|
||||
['*'],
|
||||
true
|
||||
);
|
||||
|
||||
return DataTables::eloquent($query)
|
||||
->addColumn('order_num', fn($d) => $d->order_num)
|
||||
->addColumn('date', fn($d) => $d->date)
|
||||
->addColumn('customer', fn($d) => $d->customer?->fullname)
|
||||
->addColumn('payment', fn($d) => $d->payment?->name)
|
||||
->addColumn('amount', fn($d) => $d->amount)
|
||||
->addColumn('invoice_status', fn($d) => $d->invoice?->status)
|
||||
->addColumn('status', fn($d) => $d->status)
|
||||
->addColumn('action', fn($d) => $d->id)
|
||||
->rawColumns(['order_num', 'date', 'customer', 'payment', 'amount', 'invoice_status', 'status', 'action'])
|
||||
->make(true);
|
||||
}
|
||||
|
||||
public function store(OrderRequest $request): JsonResponse
|
||||
{
|
||||
$request->validated();
|
||||
|
||||
$total = 0;
|
||||
$product_item = [];
|
||||
$relid_data = [];
|
||||
|
||||
foreach ($request->product as $key => $item) {
|
||||
$product = null;
|
||||
$relid_data[$key]['type'] = $item['type'];
|
||||
|
||||
$product = match ((int) $item['type']) {
|
||||
3 => $this->hostingRepository->find($item['product_id']),
|
||||
4 => $this->vPSRepository->find($item['product_id']),
|
||||
default => null
|
||||
};
|
||||
|
||||
if (!$product) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Invalid product."
|
||||
], 422);
|
||||
}
|
||||
|
||||
$message = $product->name;
|
||||
$relid_data[$key]['data'] = [
|
||||
'customer_id' => $request->customer_id,
|
||||
'status' => 0,
|
||||
'name' => $item['domain']
|
||||
];
|
||||
|
||||
$billingDetails = $this->calculateBillingDetails($item['billing']);
|
||||
$relid_data[$key]['data'] = array_merge($relid_data[$key]['data'], $billingDetails);
|
||||
|
||||
$price_select = $item['price_custom'] ?? $product->price_sale ?? $product->price;
|
||||
$relid_data[$key]['data']['first_payment'] = $price_select * $billingDetails['billing'];
|
||||
$relid_data[$key]['data']['next_payment'] = ($item['price_custom'] ?? $product->price) * $billingDetails['billing'];
|
||||
|
||||
$generalCode = Helper::generateUniqueCode();
|
||||
|
||||
$product_item[$key] = [
|
||||
'customer_id' => $request->customer_id,
|
||||
'type_id' => $item['type'],
|
||||
'product_id' => $item['product_id'],
|
||||
'description' => $message,
|
||||
'amount' => $price_select,
|
||||
'billing' => $item['billing'],
|
||||
'tax' => 1,
|
||||
'due_date' => Carbon::today()->hour(23)->minute(59)->second(59)->timestamp,
|
||||
'code' => $generalCode
|
||||
];
|
||||
|
||||
$relid_data[$key]['code'] = $generalCode;
|
||||
|
||||
if ($item['quantity'] > 1) {
|
||||
for ($i = 1; $i < $item['quantity']; $i++) {
|
||||
$newCode = Helper::generateUniqueCode();
|
||||
$product_item[] = array_merge($product_item[$key], ['code' => $newCode]);
|
||||
$relid_data[] = array_merge($relid_data[$key], ['code' => $newCode]);
|
||||
}
|
||||
}
|
||||
|
||||
$total += $item['quantity'] * ($item['price_custom'] ?? ($product->price_sale ?? $product->price)) * $billingDetails['billing'];
|
||||
}
|
||||
|
||||
$order_item = [
|
||||
'order_num' => Helper::generateUniqueCode(),
|
||||
'customer_id' => $request->customer_id,
|
||||
'date' => Carbon::today()->timestamp,
|
||||
'invoice_id' => 0,
|
||||
'discount_id' => $request->discount_id ?? 0,
|
||||
'amount' => $total + ($total * (10 / 100)),
|
||||
'payment_id' => $request->payment_id,
|
||||
'user_id' => Auth::guard('admins-api')->id(),
|
||||
'status' => $request->status,
|
||||
'client_ip' => $request->getClientIp()
|
||||
];
|
||||
|
||||
$invoice_data = [
|
||||
'date' => Carbon::today()->timestamp,
|
||||
'due_date' => Carbon::today()->hour(23)->minute(59)->second(59)->timestamp,
|
||||
'date_paid' => (int)$request->status === 1 ? Carbon::today()->timestamp : null,
|
||||
'sub_total' => $total,
|
||||
'tax' => $total * (10 / 100),
|
||||
'total' => $total + ($total * (10 / 100)),
|
||||
'payment_id' => $request->payment_id,
|
||||
'customer_id' => $request->create_invoice ? $request->customer_id : 0,
|
||||
'status' => $request->status
|
||||
];
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
$invoice = $this->invoiceRepository->create($invoice_data);
|
||||
|
||||
$product_item = array_map(function ($array) use ($invoice) {
|
||||
$array['invoice_id'] = $invoice->id;
|
||||
return $array;
|
||||
}, $product_item);
|
||||
|
||||
if ($request->create_invoice) {
|
||||
$order_item['invoice_id'] = $invoice->id;
|
||||
}
|
||||
|
||||
$order = $this->orderRepository->create($order_item);
|
||||
|
||||
$relid_data = array_map(function ($array) use ($order) {
|
||||
$array['data']['order_id'] = $order->id;
|
||||
return $array;
|
||||
}, $relid_data);
|
||||
|
||||
$relid = [];
|
||||
|
||||
foreach ($relid_data as $item) {
|
||||
$code = $item['code'];
|
||||
|
||||
switch ($item['type']) {
|
||||
case 3:
|
||||
$relid_id = $this->moduleHostingRepository->create($item['data']);
|
||||
$relid[$code] = $relid_id->id;
|
||||
break;
|
||||
case 4:
|
||||
$item['data']['status'] = 2;
|
||||
$relid_id = $this->moduleVmwareRepository->create($item['data']);
|
||||
$relid[$code] = $relid_id->id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$product_item = array_filter(array_map(function ($array) use ($relid) {
|
||||
if (isset($relid[$array['code']])) {
|
||||
$array['relid'] = $relid[$array['code']];
|
||||
unset($array['code']);
|
||||
return $array;
|
||||
}
|
||||
return null;
|
||||
}, $product_item));
|
||||
|
||||
$this->invoiceItemRepository->insert($product_item);
|
||||
|
||||
$last_id = $this->invoiceItemRepository->filter(['limit' => count($product_item)], [], [], ['id'])->pluck('id')->toArray();
|
||||
|
||||
$order->orderItem()->sync($last_id);
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Order created successfully',
|
||||
'data' => new OrderResource($order)
|
||||
], 201);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function show(int $id): JsonResponse
|
||||
{
|
||||
$order = $this->orderRepository->findWithRelationships(
|
||||
$id,
|
||||
['orderItem', 'user', 'customer.invoiceItem.type', 'payment', 'discount', 'invoice.invoiceItem']
|
||||
);
|
||||
|
||||
if (!$order) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find order by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'data' => new OrderResource($order)
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(int $id, UpdateOrderRequest $request): JsonResponse
|
||||
{
|
||||
$order = $this->orderRepository->findWithRelationships($id, ['invoice', 'orderItem']);
|
||||
|
||||
if (!$order) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find order by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
$status = match ($request->action) {
|
||||
"accept" => 1,
|
||||
"cancel" => 2,
|
||||
default => 0
|
||||
};
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
$this->orderRepository->update($id, ['status' => $status]);
|
||||
|
||||
if ($status === 1 && $request->module == 1) {
|
||||
$jobs = [];
|
||||
$addon = [];
|
||||
$product = 0;
|
||||
|
||||
foreach ($order->orderItem as $key => $item) {
|
||||
switch ((int) $item->type_id) {
|
||||
case 1:
|
||||
$itemData = $this->addonRepository->find($item->relid);
|
||||
if ($itemData) {
|
||||
$price = match ((int) $item->billing) {
|
||||
2 => $item->amount / 1,
|
||||
3 => $item->amount / 3,
|
||||
4 => $item->amount / 6,
|
||||
5 => $item->amount / 12,
|
||||
default => 0
|
||||
};
|
||||
$addon[strtolower($itemData->name)] = (int) $price / $itemData->price;
|
||||
$product = $item->parent_id;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
$hostingServer = $this->moduleHostingServerRepository->get_active();
|
||||
if ($hostingServer) {
|
||||
$this->moduleHostingRepository->update($item->relid, ['module_server_id' => $hostingServer->first()->id]);
|
||||
$jobs[] = new CreateHostingJobs($item->relid);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
$product = $this->moduleVmwareRepository->find($item->relid);
|
||||
|
||||
if ($product && $product->os_id) {
|
||||
$os = $this->osRepository->findWithRelationships($product->os_id, ['osGroup']);
|
||||
if (!$os || !$os->osGroup->isNotEmpty()) break;
|
||||
|
||||
$ip_address = $this->ipAddressRepository->filter([
|
||||
'module_host_id' => $os->osGroup->module_host_id,
|
||||
'status' => 0
|
||||
]);
|
||||
|
||||
if (count($ip_address) > 0) {
|
||||
$this->moduleVmwareRepository->update($item->relid, [
|
||||
'module_ipaddress_id' => $ip_address->first()->id,
|
||||
]);
|
||||
$this->ipAddressRepository->update($ip_address->first()->id, [
|
||||
'status' => 1
|
||||
]);
|
||||
$jobs[] = new CreateVMJobs($product->id);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (count($order->orderItem) === count($addon)) {
|
||||
dispatch(new UpgradeVirtualMachine($product, $addon, $order->id))->delay(now()->addSeconds(10));
|
||||
}
|
||||
|
||||
foreach ($jobs as $item) {
|
||||
dispatch($item)->delay(now()->addSeconds(10));
|
||||
}
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Order updated successfully'
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function destroy(int $id): JsonResponse
|
||||
{
|
||||
$order = Order::with('Invoice', 'Invoice.InvoiceItem')->find($id);
|
||||
|
||||
if (!$order) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find order by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
if ($order->Invoice) {
|
||||
$order->Invoice->delete();
|
||||
|
||||
if ($order->Invoice->InvoiceItem->count()) {
|
||||
foreach ($order->Invoice->InvoiceItem->all() as $item) {
|
||||
$item->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$order->delete();
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Order deleted successfully'
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function accept(int $id): JsonResponse
|
||||
{
|
||||
$order = $this->orderRepository->findWithRelationships($id, ['invoice', 'orderItem']);
|
||||
|
||||
if (!$order) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find order by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
$this->orderRepository->update($id, ['status' => 1]);
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Order accepted successfully'
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function cancel(int $id): JsonResponse
|
||||
{
|
||||
$order = $this->orderRepository->find($id);
|
||||
|
||||
if (!$order) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find order by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
$this->orderRepository->update($id, ['status' => 2]);
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Order cancelled successfully'
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
private function calculateBillingDetails($billing): array
|
||||
{
|
||||
$months = match ($billing) {
|
||||
2 => 1,
|
||||
3 => 3,
|
||||
4 => 6,
|
||||
5 => 12,
|
||||
default => 0
|
||||
};
|
||||
|
||||
return [
|
||||
'next_due_date' => $months ? Carbon::today()->addMonths($months)->timestamp : null,
|
||||
'next_invoice' => $months ? Carbon::today()->addMonths($months)->timestamp : null,
|
||||
'billing' => $months ?: 1
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Admin\Payment;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\PaymentRequest;
|
||||
use App\Models\Payment;
|
||||
use App\Repositories\Payment\PaymentReppositoryInterface;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class PaymentController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly PaymentReppositoryInterface $paymentRepository
|
||||
) {}
|
||||
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$payments = $this->paymentRepository->filter($request->all());
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'data' => $payments
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(PaymentRequest $request): JsonResponse
|
||||
{
|
||||
$request->validated();
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
$payment = $this->paymentRepository->create($request->all());
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Payment method created successfully',
|
||||
'data' => $payment
|
||||
], 201);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function show(int $id): JsonResponse
|
||||
{
|
||||
$payment = $this->paymentRepository->find($id);
|
||||
|
||||
if (!$payment) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find payment method by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'data' => $payment
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(int $id, PaymentRequest $request): JsonResponse
|
||||
{
|
||||
$payment = $this->paymentRepository->find($id);
|
||||
|
||||
if (!$payment) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find payment method by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
$request->validated();
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
$this->paymentRepository->update($id, $request->all());
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Payment method updated successfully',
|
||||
'data' => $this->paymentRepository->find($id)
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function destroy(int $id): JsonResponse
|
||||
{
|
||||
$payment = $this->paymentRepository->find($id);
|
||||
|
||||
if (!$payment) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find payment method by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
$this->paymentRepository->delete($id);
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Payment method deleted successfully'
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Admin\VPS;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Services\vCenter;
|
||||
use App\Repositories\Module\Vmware\VmwareRepositoryInterface;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class VPSController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly VmwareRepositoryInterface $vmwareRepository,
|
||||
private readonly vCenter $vCenterService
|
||||
) {}
|
||||
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$vpsList = $this->vmwareRepository->filter(
|
||||
$request->all(),
|
||||
['ipaddress.host.datacenter.vCenter', 'os.osGroup', 'order']
|
||||
);
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'data' => $vpsList
|
||||
]);
|
||||
}
|
||||
|
||||
public function show(int $id): JsonResponse
|
||||
{
|
||||
$vps = $this->vmwareRepository->findWithRelationships(
|
||||
$id,
|
||||
['ipaddress.host.datacenter.vCenter', 'os.osGroup', 'order']
|
||||
);
|
||||
|
||||
if (!$vps) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find VPS by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'data' => $vps
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(Request $request, int $id): JsonResponse
|
||||
{
|
||||
$vps = $this->vmwareRepository->find($id);
|
||||
|
||||
if (!$vps) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find VPS by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
$this->vmwareRepository->update($id, $request->all());
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'VPS updated successfully',
|
||||
'data' => $this->vmwareRepository->find($id)
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $e->getMessage()
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function powerOn(int $id): JsonResponse
|
||||
{
|
||||
$vps = $this->vmwareRepository->findWithRelationships(
|
||||
$id,
|
||||
['vCenter', 'ipaddress.host.datacenter.vCenter']
|
||||
);
|
||||
|
||||
if (!$vps) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find VPS by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
$vcenter = $vps->vCenter ?? $vps->ipaddress?->host?->datacenter?->vCenter;
|
||||
|
||||
if (!$vcenter || !$this->vCenterService->loginServer($vcenter)) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't connect to vCenter"
|
||||
], 400);
|
||||
}
|
||||
|
||||
$result = $this->vCenterService->restartVM($vps, $vps->vmware_id);
|
||||
|
||||
if (is_string($result)) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $result
|
||||
], 400);
|
||||
}
|
||||
|
||||
if ($result['error'] ?? true) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $result['message'] ?? 'Failed to power on VM'
|
||||
], 400);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'VM powered on successfully'
|
||||
]);
|
||||
}
|
||||
|
||||
public function powerOff(int $id): JsonResponse
|
||||
{
|
||||
$vps = $this->vmwareRepository->findWithRelationships(
|
||||
$id,
|
||||
['vCenter', 'ipaddress.host.datacenter.vCenter']
|
||||
);
|
||||
|
||||
if (!$vps) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find VPS by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
$vcenter = $vps->vCenter ?? $vps->ipaddress?->host?->datacenter?->vCenter;
|
||||
|
||||
if (!$vcenter || !$this->vCenterService->loginServer($vcenter)) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't connect to vCenter"
|
||||
], 400);
|
||||
}
|
||||
|
||||
$result = $this->vCenterService->restartVM($vps, $vps->vmware_id);
|
||||
|
||||
if (is_string($result)) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $result
|
||||
], 400);
|
||||
}
|
||||
|
||||
if ($result['error'] ?? true) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $result['message'] ?? 'Failed to power off VM'
|
||||
], 400);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'VM powered off successfully'
|
||||
]);
|
||||
}
|
||||
|
||||
public function restart(int $id): JsonResponse
|
||||
{
|
||||
$vps = $this->vmwareRepository->findWithRelationships(
|
||||
$id,
|
||||
['vCenter', 'ipaddress.host.datacenter.vCenter']
|
||||
);
|
||||
|
||||
if (!$vps) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find VPS by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
$vcenter = $vps->vCenter ?? $vps->ipaddress?->host?->datacenter?->vCenter;
|
||||
|
||||
if (!$vcenter || !$this->vCenterService->loginServer($vcenter)) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't connect to vCenter"
|
||||
], 400);
|
||||
}
|
||||
|
||||
$result = $this->vCenterService->restartVM($vps, $vps->vmware_id);
|
||||
|
||||
if (is_string($result)) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $result
|
||||
], 400);
|
||||
}
|
||||
|
||||
if ($result['error']) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $result['message'] ?? 'Failed to restart VM'
|
||||
], 400);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'VM restart command sent successfully'
|
||||
]);
|
||||
}
|
||||
|
||||
public function getConsoleTicket(int $id): JsonResponse
|
||||
{
|
||||
$vps = $this->vmwareRepository->findWithRelationships(
|
||||
$id,
|
||||
['ipaddress.host.datacenter.vCenter', 'vCenter']
|
||||
);
|
||||
|
||||
if (!$vps) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find VPS by ID #" . $id
|
||||
], 404);
|
||||
}
|
||||
|
||||
$vcenter = $vps->vCenter ?? $vps->ipaddress?->host?->datacenter?->vCenter;
|
||||
|
||||
if (!$vcenter) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't find vCenter information"
|
||||
], 404);
|
||||
}
|
||||
|
||||
if (!$this->vCenterService->loginServer($vcenter)) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't connect to vCenter"
|
||||
], 400);
|
||||
}
|
||||
|
||||
$ticket = $this->vCenterService->GetConsoleTickets($vps->vmware_id);
|
||||
|
||||
if ($ticket === 'Login_Again') {
|
||||
if ($this->vCenterService->loginServer($vcenter)) {
|
||||
$ticket = $this->vCenterService->GetConsoleTickets($vps->vmware_id);
|
||||
} else {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Can't reconnect to vCenter"
|
||||
], 400);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_string($ticket)) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => "Failed to get console ticket: $ticket"
|
||||
], 400);
|
||||
}
|
||||
|
||||
if ($ticket['error']) {
|
||||
return response()->json([
|
||||
'error' => true,
|
||||
'message' => $ticket['data']
|
||||
], 400);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'data' => [
|
||||
'ticket' => $ticket['data'],
|
||||
'host' => $vcenter->host
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -174,11 +174,22 @@ class ServiceController extends Controller
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'message' => 'Lấy dữ liệu thành công',
|
||||
'page_type' => 'service',
|
||||
'page_type' => $this->resolvePageType($product->product_type),
|
||||
'data' => new ServiceResource($product),
|
||||
]);
|
||||
}
|
||||
|
||||
private function resolvePageType(?string $productType): string
|
||||
{
|
||||
return match ($productType) {
|
||||
'vps', 'cloud' => 'service_vps',
|
||||
'hosting', 'email', 'ssl' => 'service_hosting',
|
||||
'domain' => 'service_domain',
|
||||
'blog' => 'blog',
|
||||
default => 'service_vps',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get addons for a specific product
|
||||
* GET /v1/products/{productId}/addons
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Http\Controllers\admin;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\ModuleIpAddress;
|
||||
use App\Models\ModuleVmware;
|
||||
use App\Models\VirtualMachines;
|
||||
use App\Repositories\Module\Datacenter\DatacenterRepositoryInterface;
|
||||
use App\Repositories\Module\Datastore\DatastoreRepositoryInterface;
|
||||
use App\Repositories\Module\Folder\FolderRepositoryInterface;
|
||||
@@ -13,6 +14,7 @@ use App\Repositories\Module\IpAddress\IpAddressRepositoryInterface;
|
||||
use App\Repositories\Module\Network\NetworkRepositoryInterface;
|
||||
use App\Repositories\vCenter\vCenterRepositoryInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Yajra\DataTables\Facades\DataTables;
|
||||
|
||||
class VCenterManagerController extends Controller
|
||||
@@ -437,4 +439,144 @@ class VCenterManagerController extends Controller
|
||||
return response()->json(['error' => $e->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function powerOn(Request $request)
|
||||
{
|
||||
$vmId = (int) $request->input('vm_id');
|
||||
|
||||
$vm = VirtualMachines::find($vmId);
|
||||
|
||||
if (!$vm) {
|
||||
return response()->json(['error' => true, 'message' => 'VM not found'], 404);
|
||||
}
|
||||
|
||||
$vmwareId = $vm->vm_id;
|
||||
|
||||
if (!$vmwareId) {
|
||||
return response()->json(['error' => true, 'message' => 'VM VMware ID not found'], 400);
|
||||
}
|
||||
|
||||
if ($vm->power_state === 'POWERED_ON') {
|
||||
return response()->json(['error' => true, 'message' => 'VM is already powered on'], 400);
|
||||
}
|
||||
|
||||
$vcenter = null;
|
||||
|
||||
if ($vm->datacenter?->vCenter) {
|
||||
$vcenter = $vm->datacenter->vCenter;
|
||||
}
|
||||
|
||||
if (!$vcenter && $vm->host?->datacenter?->vCenter) {
|
||||
$vcenter = $vm->host->datacenter->vCenter;
|
||||
}
|
||||
|
||||
if (!$vcenter) {
|
||||
return response()->json(['error' => true, 'message' => 'vCenter not found'], 400);
|
||||
}
|
||||
|
||||
$vCenterService = new \App\Http\Services\vCenter();
|
||||
|
||||
if (!$vCenterService->loginServer($vcenter)) {
|
||||
return response()->json(['error' => true, 'message' => 'Cannot login to vCenter'], 400);
|
||||
}
|
||||
|
||||
$response = Http::withoutVerifying()
|
||||
->withHeaders([
|
||||
'vmware-api-session-id' => $vCenterService->token
|
||||
])
|
||||
->post("https://{$vCenterService->apiUri}/rest/vcenter/vm/$vmwareId/power/start");
|
||||
|
||||
if ($response->status() === 200) {
|
||||
$vm->update(['power_state' => 'POWERED_ON']);
|
||||
return response()->json(['error' => false, 'message' => 'Power on command sent successfully']);
|
||||
}
|
||||
|
||||
$errorData = $response->json();
|
||||
if (isset($errorData['error_type']) && $errorData['error_type'] === 'ALREADY_IN_DESIRED_STATE') {
|
||||
$vm->update(['power_state' => 'POWERED_ON']);
|
||||
return response()->json(['error' => false, 'message' => 'VM is already powered on']);
|
||||
}
|
||||
|
||||
return response()->json(['error' => true, 'message' => $errorData['value'] ?? $errorData['error_type'] ?? 'Failed to power on VM'], 400);
|
||||
}
|
||||
|
||||
public function powerOff(Request $request)
|
||||
{
|
||||
$vmId = (int) $request->input('vm_id');
|
||||
|
||||
$vm = VirtualMachines::find($vmId);
|
||||
|
||||
if (!$vm) {
|
||||
return response()->json(['error' => true, 'message' => 'VM not found'], 404);
|
||||
}
|
||||
|
||||
$vmwareId = $vm->vm_id;
|
||||
|
||||
if (!$vmwareId) {
|
||||
return response()->json(['error' => true, 'message' => 'VM VMware ID not found'], 400);
|
||||
}
|
||||
|
||||
if ($vm->power_state === 'POWERED_OFF') {
|
||||
return response()->json(['error' => true, 'message' => 'VM is already powered off'], 400);
|
||||
}
|
||||
|
||||
$vcenter = null;
|
||||
|
||||
if ($vm->datacenter?->vCenter) {
|
||||
$vcenter = $vm->datacenter->vCenter;
|
||||
}
|
||||
|
||||
if (!$vcenter && $vm->host?->datacenter?->vCenter) {
|
||||
$vcenter = $vm->host->datacenter->vCenter;
|
||||
}
|
||||
|
||||
if (!$vcenter) {
|
||||
return response()->json(['error' => true, 'message' => 'vCenter not found'], 400);
|
||||
}
|
||||
|
||||
$vCenterService = new \App\Http\Services\vCenter();
|
||||
|
||||
if (!$vCenterService->loginServer($vcenter)) {
|
||||
return response()->json(['error' => true, 'message' => 'Cannot login to vCenter'], 400);
|
||||
}
|
||||
|
||||
$response = Http::withoutVerifying()
|
||||
->withHeaders([
|
||||
'vmware-api-session-id' => $vCenterService->token
|
||||
])
|
||||
->post("https://{$vCenterService->apiUri}/rest/vcenter/vm/$vmwareId/power/stop");
|
||||
|
||||
if ($response->status() === 200) {
|
||||
$vm->update(['power_state' => 'POWERED_OFF']);
|
||||
return response()->json(['error' => false, 'message' => 'Power off command sent successfully']);
|
||||
}
|
||||
|
||||
$errorData = $response->json();
|
||||
if (isset($errorData['error_type']) && $errorData['error_type'] === 'ALREADY_IN_DESIRED_STATE') {
|
||||
$vm->update(['power_state' => 'POWERED_OFF']);
|
||||
return response()->json(['error' => false, 'message' => 'VM is already powered off']);
|
||||
}
|
||||
|
||||
return response()->json(['error' => true, 'message' => $errorData['value'] ?? $errorData['error_type'] ?? 'Failed to power off VM'], 400);
|
||||
}
|
||||
|
||||
public function getPoweredOffVms()
|
||||
{
|
||||
$vms = VirtualMachines::whereNotNull('vm_id')
|
||||
->where('power_state', 'POWERED_OFF')
|
||||
->get()
|
||||
->map(function ($vm) {
|
||||
return [
|
||||
'id' => $vm->id,
|
||||
'name' => $vm->name,
|
||||
'vm_id' => $vm->vm_id,
|
||||
'power_state' => $vm->power_state,
|
||||
];
|
||||
});
|
||||
|
||||
return response()->json([
|
||||
'error' => false,
|
||||
'data' => $vms
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user