159 lines
7.1 KiB
PHP
159 lines
7.1 KiB
PHP
|
|
/**
|
|
* 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.'));
|
|
}
|
|
}
|