littleshop/TeleBot/TeleBot/Models/ShoppingCart.cs
2025-10-03 19:36:52 +01:00

203 lines
7.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using LittleShop.Client.Models;
namespace TeleBot.Models
{
public class ShoppingCart
{
public string Id { get; set; } = Guid.NewGuid().ToString();
public List<CartItem> Items { get; set; } = new();
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
// New method that accepts Product and variants list
public CartItem AddItem(Product product, int quantity = 1, Guid? multiBuyId = null, Guid? variantId = null, List<string>? selectedVariants = null)
{
decimal price = product.Price;
Guid? productVariantId = null;
// If variant selected, get the variant price override (if set)
if (variantId.HasValue && product.Variants != null)
{
var variant = product.Variants.FirstOrDefault(v => v.Id == variantId.Value);
if (variant != null)
{
productVariantId = variant.Id;
// Use variant price if it has an override, otherwise use product price
if (variant.Price.HasValue)
{
price = variant.Price.Value;
}
}
}
// If multi-buy selected, get the multi-buy price (overrides variant price)
if (multiBuyId.HasValue && product.MultiBuys != null)
{
var multiBuy = product.MultiBuys.FirstOrDefault(mb => mb.Id == multiBuyId.Value);
if (multiBuy != null)
{
price = multiBuy.Price;
quantity = multiBuy.Quantity; // Use the multi-buy quantity
}
}
// Create unique key for comparison
var variantKey = selectedVariants != null && selectedVariants.Any()
? string.Join(",", selectedVariants.OrderBy(v => v))
: null;
// Check if item already exists
var existingItem = Items.FirstOrDefault(i =>
i.ProductId == product.Id &&
i.MultiBuyId == multiBuyId &&
i.ProductVariantId == productVariantId &&
(i.SelectedVariant == variantKey ||
(i.SelectedVariants != null && string.Join(",", i.SelectedVariants.OrderBy(v => v)) == variantKey)));
if (existingItem != null)
{
// For multi-buys, we don't add quantities - each multi-buy is a separate bundle
if (!multiBuyId.HasValue)
{
existingItem.Quantity += quantity;
existingItem.UpdateTotalPrice();
}
return existingItem;
}
else
{
var newItem = new CartItem
{
ProductId = product.Id,
MultiBuyId = multiBuyId,
ProductVariantId = productVariantId,
SelectedVariant = selectedVariants?.Count == 1 ? selectedVariants[0] : null,
SelectedVariants = selectedVariants ?? new List<string>(),
ProductName = product.Name,
UnitPrice = price,
Quantity = quantity
};
newItem.UpdateTotalPrice();
Items.Add(newItem);
UpdatedAt = DateTime.UtcNow;
return newItem;
}
}
// Keep the old method for backward compatibility
public void AddItem(Guid productId, string productName, decimal price, int quantity = 1, Guid? multiBuyId = null, string? selectedVariant = null)
{
var existingItem = Items.FirstOrDefault(i =>
i.ProductId == productId && i.MultiBuyId == multiBuyId && i.SelectedVariant == selectedVariant);
if (existingItem != null)
{
// For multi-buys, we don't add quantities - each multi-buy is a separate bundle
// For regular items, we add the quantities together
if (!multiBuyId.HasValue)
{
existingItem.Quantity += quantity;
existingItem.UpdateTotalPrice();
}
// If it's a multi-buy and already exists, we don't add it again
// (user should explicitly add another multi-buy bundle if they want more)
}
else
{
var newItem = new CartItem
{
ProductId = productId,
MultiBuyId = multiBuyId,
SelectedVariant = selectedVariant,
ProductName = productName,
UnitPrice = price,
Quantity = quantity
};
newItem.UpdateTotalPrice(); // Ensure total is calculated after all properties are set
Items.Add(newItem);
}
UpdatedAt = DateTime.UtcNow;
}
public void RemoveItem(Guid productId)
{
Items.RemoveAll(i => i.ProductId == productId);
UpdatedAt = DateTime.UtcNow;
}
public void UpdateQuantity(Guid productId, int quantity)
{
var item = Items.FirstOrDefault(i => i.ProductId == productId);
if (item != null)
{
if (quantity <= 0)
{
RemoveItem(productId);
}
else
{
item.Quantity = quantity;
item.UpdateTotalPrice();
UpdatedAt = DateTime.UtcNow;
}
}
}
public void Clear()
{
Items.Clear();
UpdatedAt = DateTime.UtcNow;
}
public decimal GetTotalAmount()
{
return Items.Sum(i => i.TotalPrice);
}
public int GetTotalItems()
{
return Items.Sum(i => i.Quantity);
}
public bool IsEmpty()
{
return !Items.Any();
}
}
public class CartItem
{
public Guid ProductId { get; set; }
public Guid? MultiBuyId { get; set; } // For quantity pricing (e.g., 3 for £25)
public Guid? ProductVariantId { get; set; } // For variant with potential price override
public string? SelectedVariant { get; set; } // For single items - one variant (deprecated, use ProductVariantId)
public List<string> SelectedVariants { get; set; } = new(); // For multi-buys - multiple variants
public string ProductName { get; set; } = string.Empty;
public int Quantity { get; set; }
public decimal UnitPrice { get; set; } // For multi-buys, this is the bundle price; for regular items, it's per-unit
public decimal TotalPrice { get; set; }
public CartItem()
{
// Don't calculate total in constructor - wait for properties to be set
}
public void UpdateTotalPrice()
{
// For multi-buys, UnitPrice is already the total bundle price
// For regular items, we need to multiply by quantity
if (MultiBuyId.HasValue)
{
TotalPrice = UnitPrice; // Bundle price, not multiplied
}
else
{
TotalPrice = UnitPrice * Quantity; // Regular per-unit pricing
}
}
}
}