feat: implement VMware vCenter integration, enhance product pricing display, and update order processing logic.
This commit is contained in:
@@ -8,6 +8,12 @@ use App\Repositories\Api\Order\OrderRepository;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Enums\Order\OrderStatus;
|
||||
use Exception;
|
||||
use App\Jobs\VirtualMachine\Create\CreateVMJobs;
|
||||
use App\Models\Log as CustomerLog;
|
||||
use App\Models\ModuleIpAddress;
|
||||
use App\Models\ModuleVmware;
|
||||
use App\Models\Os;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class OrderService
|
||||
{
|
||||
@@ -24,20 +30,37 @@ class OrderService
|
||||
throw new Exception('Bạn có đơn hàng chưa thanh toán. Vui lòng thanh toán trước khi tạo đơn mới.');
|
||||
}
|
||||
|
||||
return DB::transaction(function () use ($data, $customer) {
|
||||
$product = $this->productRepo->find($data['product_id']);
|
||||
|
||||
$product = $this->productRepo->find($data['product_id']);
|
||||
if (!$product) {
|
||||
throw new Exception('Sản phẩm không tồn tại');
|
||||
}
|
||||
|
||||
if (!$product) {
|
||||
throw new Exception('Sản phẩm không tồn tại');
|
||||
$price = $this->productRepo->getPricing($product->id, $data['billing_cycle']);
|
||||
|
||||
if (is_null($price)) {
|
||||
throw new Exception('Không tìm thấy giá cho sản phẩm này');
|
||||
}
|
||||
|
||||
// Tính tổng tiền bao gồm addons
|
||||
$addonsPrice = 0;
|
||||
if (!empty($data['addons'])) {
|
||||
foreach ($data['addons'] as $addonData) {
|
||||
$addon = \App\Models\Addon::find($addonData['addon_id']);
|
||||
if ($addon) {
|
||||
$addonsPrice += $addon->price * ($addonData['qty'] ?? 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$price = $this->productRepo
|
||||
->getPricing($product->id, $data['billing_cycle']);
|
||||
$totalPrice = $price + $addonsPrice;
|
||||
|
||||
if (is_null($price)) {
|
||||
throw new Exception('Không tìm thấy giá cho sản phẩm này');
|
||||
}
|
||||
// Kiểm tra số dư tài khoản (cột total) trước khi tạo đơn
|
||||
if ($customer->total < $totalPrice) {
|
||||
throw new Exception('Số dư không đủ để đặt hàng. Vui lòng nạp thêm tiền. Số dư hiện tại: ' . number_format($customer->total) . ' VNĐ, cần: ' . number_format($totalPrice) . ' VNĐ');
|
||||
}
|
||||
|
||||
return DB::transaction(function () use ($data, $customer, $product, $price, $totalPrice) {
|
||||
|
||||
$order = $this->orderRepo->create([
|
||||
'order_num' => \App\Helpers\OrderHelper::generateOrderNumber(),
|
||||
@@ -66,10 +89,112 @@ class OrderService
|
||||
|
||||
public function pay($order, string $method)
|
||||
{
|
||||
if ($order->status !== OrderStatus::PENDING->value) {
|
||||
throw new Exception('Đơn hàng đã được xử lý hoặc hủy bỏ.');
|
||||
if (in_array($order->status, [OrderStatus::ACTIVE->value, OrderStatus::PROCESSING->value], true)) {
|
||||
throw new Exception('Đơn hàng đã được thanh toán hoặc đang xử lý.');
|
||||
}
|
||||
|
||||
return $this->orderRepo->processPayment($order, $method);
|
||||
return DB::transaction(function () use ($order, $method) {
|
||||
$customer = $order->customer;
|
||||
|
||||
// Kiểm tra số dư và trừ tiền
|
||||
if ($customer->total < $order->amount) {
|
||||
throw new Exception('Số dư không đủ để thanh toán. Vui lòng nạp thêm tiền. Số dư hiện tại: ' . number_format($customer->total) . ' VNĐ, cần: ' . number_format($order->amount) . ' VNĐ');
|
||||
}
|
||||
|
||||
$customer->total -= $order->amount;
|
||||
$customer->save();
|
||||
|
||||
CustomerLog::create([
|
||||
'agent' => 'api',
|
||||
'client_ip' => request()?->ip(),
|
||||
'customer_id' => $customer->id,
|
||||
'description' => 'Thanh toán đơn hàng #' . $order->order_num
|
||||
. ' thành công. Số tiền: ' . number_format((int) $order->amount) . ' VNĐ'
|
||||
. '. Số dư sau thanh toán: ' . number_format((int) $customer->total) . ' VNĐ',
|
||||
]);
|
||||
|
||||
// Cho phép thanh toán lại đơn đã hủy bằng cách đưa về pending trước khi process.
|
||||
if ($order->status === OrderStatus::CANCELLED->value) {
|
||||
$order->status = OrderStatus::PENDING->value;
|
||||
$order->save();
|
||||
}
|
||||
|
||||
$processedOrder = $this->orderRepo->processPayment($order, $method);
|
||||
|
||||
// Sau khi thanh toán, tạo module_vmware rồi dispatch CreateVMJobs.
|
||||
foreach ($order->orderItems as $item) {
|
||||
if (empty($item->product_id) || empty($item->os_id)) {
|
||||
Log::warning('Skip VM job: product_id/os_id is missing', [
|
||||
'order_id' => $order->id,
|
||||
'order_item_id' => $item->id,
|
||||
'product_id' => $item->product_id,
|
||||
'os_id' => $item->os_id,
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$os = Os::with('osGroup.host')->find($item->os_id);
|
||||
|
||||
if (!$os || !$os->osGroup || !$os->osGroup->module_host_id) {
|
||||
Log::warning('Skip VM job: không tìm thấy OS/OsGroup/Host', [
|
||||
'order_id' => $order->id,
|
||||
'order_item_id' => $item->id,
|
||||
'os_id' => $item->os_id,
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$ip = ModuleIpAddress::where('module_host_id', $os->osGroup->module_host_id)
|
||||
->where('status', 0)
|
||||
->lockForUpdate()
|
||||
->first();
|
||||
|
||||
if (!$ip) {
|
||||
Log::warning('Skip VM job: không còn IP khả dụng', [
|
||||
'order_id' => $order->id,
|
||||
'module_host_id' => $os->osGroup->module_host_id,
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$ip->update(['status' => 1, 'vm_name' => $item->server_name ?? 'VM-' . $order->id]);
|
||||
|
||||
$moduleVmware = ModuleVmware::create([
|
||||
'name' => $item->server_name ?? 'VM-' . $order->id,
|
||||
'module_ip_address_id' => $ip->id,
|
||||
'port' => 22,
|
||||
'order_id' => $order->id,
|
||||
'first_payment' => $order->amount,
|
||||
'next_payment' => $order->amount,
|
||||
'next_due_date' => null,
|
||||
'next_invoice' => 0,
|
||||
'user' => 'Administrator',
|
||||
'password' => '',
|
||||
'hostname' => $item->server_name ?? 'vm-' . $order->id,
|
||||
'vmware_id' => null,
|
||||
'os_id' => $item->os_id,
|
||||
'customer_id' => $order->customer_id,
|
||||
'status' => 0,
|
||||
]);
|
||||
|
||||
dispatch(new CreateVMJobs($moduleVmware->id))->delay(now()->addSeconds(10));
|
||||
|
||||
Log::info('Dispatched CreateVMJobs', [
|
||||
'order_id' => $order->id,
|
||||
'module_vmware_id' => $moduleVmware->id,
|
||||
'ip' => $ip->ip,
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Lỗi khi tạo module_vmware hoặc dispatch job', [
|
||||
'order_id' => $order->id,
|
||||
'order_item_id' => $item->id,
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
return $processedOrder;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user