feat: implement VM snapshot management, enhance client resource loading, and refactor deployment workflow for production

This commit is contained in:
pbao9
2026-05-11 11:09:55 +07:00
parent 8aef607e1f
commit 96778e7bed
51 changed files with 2536 additions and 1249 deletions
@@ -7,12 +7,14 @@ use App\Enums\Order\OrderStatus;
use App\Helpers\OrderHelper;
use App\Http\Controllers\Controller;
use App\Jobs\VirtualMachine\Action\VMJobs;
use App\Jobs\VirtualMachine\Create\CreateVirtualMachineJob;
use App\Jobs\VirtualMachine\Provision\RetryProvisioningOrchestrator;
use App\Models\Log as CustomerActivityLog;
use App\Http\Requests\Api\Order\PayOrderRequest;
use App\Http\Requests\Api\Order\StoreOrderRequest;
use App\Models\Invoice;
use App\Models\InvoiceItem;
use App\Models\ModuleVmware;
use App\Models\Order;
use App\Models\Product;
use App\Models\Service;
@@ -194,6 +196,41 @@ class OrderController extends Controller
}
}
/**
* POST /v1/client/orders/{id}/retry — retry VM provisioning for a paid order
*
* Dispatches RetryProvisioningOrchestrator which:
* 1. Searches vSphere for existing VM by server_name
* 2. If found → links VM to module_vmware + services
* 3. If not found → dispatches CreateVirtualMachineJob
* 4. Each failure step notifies Telegram
*/
public function retryOrderProvisioning(Request $request, int $id): JsonResponse
{
try {
$order = Order::where('id', $id)
->where('customer_id', $request->user()->id)
->first();
if (!$order) {
return $this->notFound('Đơn hàng không tồn tại.');
}
if (!$order->invoice || (int) $order->invoice->status !== InvoiceStatus::PAID->value) {
return $this->error('Đơn hàng chưa được thanh toán.');
}
RetryProvisioningOrchestrator::dispatch($order->id, $request->user()->id);
return response()->json([
'success' => true,
'message' => 'Đã yêu cầu khởi tạo lại dịch vụ. Hệ thống sẽ kiểm tra và xử lý trong vài phút.',
]);
} catch (\Exception $e) {
return $this->error($e->getMessage());
}
}
// =========================================================================
// Invoices
// =========================================================================
@@ -305,15 +342,13 @@ class OrderController extends Controller
{
try {
$services = Service::query()
->with(['product', 'addons', 'invoice', 'orderItem'])
->with(['product', 'addons', 'invoice', 'orderItem', 'vmware.ipAddress', 'vmware.os'])
->where('customer_id', $request->user()->id)
->orderByDesc('created_at')
->get();
$data = $services->map(function (Service $service) {
$vmware = $service->vm_id
? ModuleVmware::with(['ipAddress', 'os'])->find((int) $service->vm_id)
: null;
$vmware = $service->vmware;
return [
'id' => $service->id,
@@ -357,7 +392,7 @@ class OrderController extends Controller
{
try {
$service = Service::query()
->with(['product', 'addons', 'invoice', 'orderItem'])
->with(['product', 'addons', 'invoice', 'orderItem', 'vmware.ipAddress', 'vmware.os', 'vmware.vCenter'])
->where('uuid', $uuid)
->where('customer_id', $request->user()->id)
->first();
@@ -366,9 +401,7 @@ class OrderController extends Controller
return $this->notFound('Không tìm thấy dịch vụ.');
}
$vmware = $service->vm_id
? ModuleVmware::with(['ipAddress', 'os', 'vCenter'])->find((int) $service->vm_id)
: null;
$vmware = $service->vmware;
$data = [
'id' => $service->id,