using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace ExampleFiles.Models; /// /// Represents an order in an e-commerce system. /// Demonstrates properties, LINQ, async methods, and C# conventions. /// public sealed class Order : IEquatable { public Guid Id { get; } public string CustomerEmail { get; init; } public DateTime CreatedAt { get; } public OrderStatus Status { get; private set; } public IReadOnlyList Items => _items.AsReadOnly(); private readonly List _items; public Order(string customerEmail) { Id = Guid.NewGuid(); CustomerEmail = customerEmail ?? throw new ArgumentNullException(nameof(customerEmail)); CreatedAt = DateTime.UtcNow; Status = OrderStatus.Pending; _items = new List(); } // --- Computed properties --- public decimal Subtotal => _items.Sum(i => i.Total); public decimal Tax => Math.Round(Subtotal * 0.08m, 2); public decimal GrandTotal => Subtotal + Tax; public int TotalQuantity => _items.Sum(i => i.Quantity); // --- Methods --- public Order AddItem(string productName, decimal unitPrice, int quantity = 1) { ArgumentOutOfRangeException.ThrowIfNegativeOrZero(quantity); var existing = _items.FirstOrDefault(i => i.ProductName.Equals(productName, StringComparison.OrdinalIgnoreCase)); if (existing is not null) { existing.Quantity += quantity; } else { _items.Add(new LineItem(productName, unitPrice, quantity)); } return this; } public bool RemoveItem(string productName) { return _items.RemoveAll(i => i.ProductName.Equals(productName, StringComparison.OrdinalIgnoreCase)) > 0; } public Order Confirm() { if (Status != OrderStatus.Pending) throw new InvalidOperationException($"Cannot confirm an order with status {Status}"); if (!_items.Any()) throw new InvalidOperationException("Cannot confirm an empty order"); Status = OrderStatus.Confirmed; return this; } public Order Cancel(string reason) { if (Status == OrderStatus.Shipped || Status == OrderStatus.Delivered) throw new InvalidOperationException($"Cannot cancel an order that is {Status}"); Status = OrderStatus.Cancelled; return this; } /// /// Simulates sending an order confirmation email asynchronously. /// public async Task SendConfirmationAsync() { await Task.Delay(100); // Simulate network latency var summary = _items .Select(i => $" - {i.ProductName} x{i.Quantity}: {i.Total:C}") .Aggregate((a, b) => $"{a}\n{b}"); return $"Order {Id}\nStatus: {Status}\n\n{summary}\n\nTotal: {GrandTotal:C}"; } /// /// Returns the top N most expensive line items using LINQ. /// public IEnumerable TopItemsByValue(int count = 3) { return _items .OrderByDescending(i => i.Total) .Take(count); } // --- Equality --- public bool Equals(Order? other) => other is not null && Id == other.Id; public override bool Equals(object? obj) => Equals(obj as Order); public override int GetHashCode() => Id.GetHashCode(); public override string ToString() => $"Order({Id.ToString()[..8]}..., {Status}, {TotalQuantity} items, {GrandTotal:C})"; } public class LineItem { public string ProductName { get; } public decimal UnitPrice { get; } public int Quantity { get; set; } public decimal Total => UnitPrice * Quantity; public LineItem(string productName, decimal unitPrice, int quantity) { ProductName = productName; UnitPrice = unitPrice; Quantity = quantity; } } public enum OrderStatus { Pending, Confirmed, Shipped, Delivered, Cancelled }