using Microsoft.AspNetCore.Http; namespace KernelRecordsMVC.Controllers; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using KernelRecordsMVC.Data; using KernelRecordsMVC.Models; using KernelRecordsMVC.Domain.Enums; using KernelRecordsMVC.Application.ViewModels; public class OrderController : Controller { private readonly KernelRecordsContext _context; public OrderController(KernelRecordsContext context) { _context = context; } // ========================================== // ADD PRODUCT TO ORDER // UC007 // ========================================== [HttpGet] public IActionResult AddProduct(long id) { var userId = GetUserId(); if (userId == null) return RedirectToAction( "Login", "Account"); var product = _context.Products .Include(p => p.Release) .FirstOrDefault(p => p.ProductId == id); if (product == null) return NotFound(); if (product.Stock <= 0) { TempData["Error"] = "This product is currently out of stock."; return RedirectToAction( "Details", "Release", new { id = product.ReleaseId }); } // Find an existing pending order. var order = _context.Orders .Include(o => o.OrderProducts) .FirstOrDefault(o => o.UserId == userId.Value && o.Status == OrderStatusType.PENDING); // If there is no pending order, create one. if (order == null) { order = new Order { OrderId = GetNextOrderId(), UserId = userId.Value, // The actual payment method will be // selected during checkout. PaymentMethod = PaymentMethodType.CARD, PurchaseDate = DateTime.Today, PointsEarned = 0, PointsUsed = null, Status = OrderStatusType.PENDING }; _context.Orders.Add(order); _context.SaveChanges(); } // Check whether product is already in cart. var existingItem = order.OrderProducts .FirstOrDefault(x => x.ProductId == product.ProductId); if (existingItem != null) { if (existingItem.Quantity + 1 > product.Stock) { TempData["Error"] = "There is not enough stock available."; return RedirectToAction( "Details", "Release", new { id = product.ReleaseId }); } existingItem.Quantity++; } else { var orderProduct = new OrderProduct { OrderId = order.OrderId, ProductId = product.ProductId, PriceAtPurchase = product.Price, Quantity = 1 }; _context.OrderProducts.Add(orderProduct); } _context.SaveChanges(); return RedirectToAction(nameof(Cart)); } // ========================================== // CART // ========================================== [HttpGet] public IActionResult Cart() { var userId = GetUserId(); if (userId == null) { return RedirectToAction( "Login", "Account"); } var order = _context.Orders .Include(o => o.OrderProducts) .ThenInclude(op => op.Product) .ThenInclude(p => p.Release) .FirstOrDefault(o => o.UserId == userId.Value && o.Status == OrderStatusType.PENDING); var viewModel = new CartViewModel(); if (order != null) { viewModel.Items = order.OrderProducts .Select(op => new CartItemViewModel { ProductId = op.ProductId, ReleaseId = op.Product.ReleaseId, ReleaseTitle = op.Product.Release.Title, Format = op.Product.Format.ToString(), Price = op.PriceAtPurchase, Quantity = op.Quantity, Stock = op.Product.Stock }) .ToList(); } return View(viewModel); } // ========================================== // REMOVE PRODUCT // ========================================== [HttpPost] [ValidateAntiForgeryToken] public IActionResult RemoveProduct(long id) { var userId = GetUserId(); if (userId == null) return RedirectToAction( "Login", "Account"); var item = _context.OrderProducts .Include(x => x.Order) .FirstOrDefault(x => x.ProductId == id && x.Order.UserId == userId.Value && x.Order.Status == OrderStatusType.PENDING); if (item != null) { _context.OrderProducts.Remove(item); _context.SaveChanges(); } return RedirectToAction(nameof(Cart)); } // ========================================== // UPDATE QUANTITY // ========================================== [HttpPost] [ValidateAntiForgeryToken] public IActionResult UpdateQuantity( long id, long quantity) { var userId = GetUserId(); if (userId == null) return RedirectToAction( "Login", "Account"); if (quantity <= 0) { return RemoveProduct(id); } var item = _context.OrderProducts .Include(x => x.Order) .Include(x => x.Product) .FirstOrDefault(x => x.ProductId == id && x.Order.UserId == userId.Value && x.Order.Status == OrderStatusType.PENDING); if (item == null) return NotFound(); if (quantity > item.Product.Stock) { TempData["Error"] = "The requested quantity exceeds available stock."; return RedirectToAction(nameof(Cart)); } item.Quantity = quantity; _context.SaveChanges(); return RedirectToAction(nameof(Cart)); } // ========================================== // USER ID // ========================================== private long? GetUserId() { var value = HttpContext.Session.GetString("UserId"); if (long.TryParse(value, out var userId)) return userId; return null; } // ========================================== // ORDER ID // ========================================== private long GetNextOrderId() { var maxId = _context.Orders .Select(x => (long?)x.OrderId) .Max(); return (maxId ?? 0) + 1; } }