feat: Enhance product support in Cart and OrderItem models

- Added new fields 'billing_cycle' and 'product_pricing_id' to Cart and OrderItem models.
- Updated product retrieval logic to support both new and legacy systems.
- Introduced relationships for Product and ProductPricings in Cart and OrderItem models.
- Created migration to add new fields to the carts and order_item tables.
- Updated frontend service index to handle new pricing structure and billing cycles.
- Improved UI components for better user experience in product selection and pricing display.
- Refactored action buttons in various views for consistency and improved styling.
This commit is contained in:
pbao9
2026-02-09 08:04:56 +07:00
parent 4d4bf020d4
commit 057353a2e1
15 changed files with 590 additions and 250 deletions
@@ -14,7 +14,10 @@ use App\Models\InvoiceItem;
use App\Models\ModuleHosting;
use App\Models\ModuleVmware;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\Os;
use App\Models\Product;
use App\Models\ProductPricings;
use App\Models\VPS;
use Exception;
use Illuminate\Http\Request;
@@ -36,36 +39,85 @@ class CartController extends Controller
public function addCart(Request $request)
{
$userId = customer()?->id;
$months = $request->input('months');
$productId = $request->product_id;
$typeId = $request->type_id;
if (!$userId) {
return back()->with('error', 'Bạn cần đăng nhập để thêm sản phẩm vào giỏ hàng.');
}
// Validate input data
if (!$productId || !$typeId || !$months) {
return back()->with('error', 'Dữ liệu không hợp lệ.');
// Get request data
$productId = $request->product_id;
$typeId = $request->type_id; // Can be null for new Product system
$months = $request->input('months');
$billingCycle = $request->input('billing_cycle'); // New: billing cycle
$productPrice = $request->input('product_price'); // Price from form
// Validate basic input
if (!$productId) {
return back()->with('error', 'Sản phẩm không hợp lệ.');
}
// Use updateOrCreate instead of delete + create for better performance
try {
CartModel::updateOrCreate(
['customer_id' => $userId], // Only one cart item per user
[
'product_id' => $productId,
'type_product' => $typeId,
'months' => $months,
]
);
// Check if this is new Product system or legacy (Hosting/VPS)
$product = Product::find($productId);
return redirect()->route('cart.index')->with('success', 'Sản phẩm đã được thêm vào giỏ hàng!');
if ($product) {
// NEW FLOW: Using Product table
$pricingId = null;
$finalPrice = $productPrice;
// Find the pricing based on billing_cycle
if ($billingCycle) {
$pricing = ProductPricings::where('product_id', $productId)
->where('billing_cycle', $billingCycle)
->where('is_active', 1)
->first();
if ($pricing) {
$pricingId = $pricing->id;
$finalPrice = $pricing->price_sale ?: $pricing->price;
}
}
// Add to cart
CartModel::updateOrCreate(
['customer_id' => $userId],
[
'product_id' => $productId,
'type_product' => null, // New system doesn't use type_product
'months' => $months,
'billing_cycle' => $billingCycle,
'product_pricing_id' => $pricingId,
'price' => $finalPrice,
'quantity' => 1,
]
);
return redirect()->route('cart.index')->with('success', 'Sản phẩm đã được thêm vào giỏ hàng!');
} else {
// LEGACY FLOW: Using old Hosting/VPS system
if (!$typeId || !$months) {
return back()->with('error', 'Dữ liệu không hợp lệ.');
}
CartModel::updateOrCreate(
['customer_id' => $userId],
[
'product_id' => $productId,
'type_product' => $typeId,
'months' => $months,
'price' => $productPrice,
]
);
return redirect()->route('cart.index')->with('success', 'Sản phẩm đã được thêm vào giỏ hàng!');
}
} catch (\Exception $e) {
Log::error('Cart add error: ' . $e->getMessage(), [
'user_id' => $userId,
'product_id' => $productId,
'type_id' => $typeId
'type_id' => $typeId,
'billing_cycle' => $billingCycle ?? null,
'trace' => $e->getTraceAsString()
]);
return back()->with('error', 'Có lỗi xảy ra khi thêm sản phẩm vào giỏ hàng.');
}