// EN: Table aggregate root for FnB. // VI: Aggregate root Table cho FnB. using FnbEngine.Domain.Exceptions; using FnbEngine.Domain.SeedWork; namespace FnbEngine.Domain.AggregatesModel.TableAggregate; /// /// EN: Table aggregate root - represents a dining table. /// VI: Aggregate root Table - đại diện cho bàn ăn. /// public class Table : Entity, IAggregateRoot { private Guid _shopId; private string _tableNumber = null!; private int _capacity; private string? _zone; private TableStatus _status = null!; private DateTime _createdAt; private DateTime? _updatedAt; public Guid ShopId => _shopId; public string TableNumber => _tableNumber; public int Capacity => _capacity; public string? Zone => _zone; public TableStatus Status => _status; public int StatusId { get; private set; } public DateTime CreatedAt => _createdAt; public DateTime? UpdatedAt => _updatedAt; protected Table() { } public Table(Guid shopId, string tableNumber, int capacity, string? zone = null) { if (shopId == Guid.Empty) throw new DomainException("Shop ID cannot be empty"); if (string.IsNullOrWhiteSpace(tableNumber)) throw new DomainException("Table number cannot be empty"); if (capacity <= 0) throw new DomainException("Capacity must be greater than zero"); Id = Guid.NewGuid(); _shopId = shopId; _tableNumber = tableNumber.Trim(); _capacity = capacity; _zone = zone?.Trim(); _status = TableStatus.Available; StatusId = TableStatus.Available.Id; _createdAt = DateTime.UtcNow; } public void MarkAsOccupied() { if (_status != TableStatus.Available && _status != TableStatus.Reserved) throw new DomainException($"Cannot occupy table with status {_status.Name}"); _status = TableStatus.Occupied; StatusId = TableStatus.Occupied.Id; _updatedAt = DateTime.UtcNow; } public void MarkAsAvailable() { _status = TableStatus.Available; StatusId = TableStatus.Available.Id; _updatedAt = DateTime.UtcNow; } public void MarkAsCleaning() { _status = TableStatus.Cleaning; StatusId = TableStatus.Cleaning.Id; _updatedAt = DateTime.UtcNow; } }