namespace LibraryApp.Domain.Entities; public enum BookInstanceStatus { OnShelf, Lent, PutAside, Lost } public class BookInstance { public BookInstanceId Id { get; private set; } public BookId BookId { get; private set; } public ShelfId ShelfId { get; private set; } public BookInstanceBarcode Barcode { get; private set; } public BookInstanceStatus Status { get; private set; } public BookInstance(BookId bookId, ShelfId shelfId, BookInstanceBarcode barcode) : this(new BookInstanceId(string.Empty), bookId, shelfId, barcode, BookInstanceStatus.OnShelf) { } public BookInstance(BookInstanceId id, BookId bookId, ShelfId shelfId, BookInstanceBarcode barcode, BookInstanceStatus status) { Id = id; BookId = bookId; ShelfId = shelfId; Barcode = barcode; Status = status; } public BookInstance MarkAsLent() { if (Status != BookInstanceStatus.OnShelf) throw new InvalidOperationException($"Cannot lend a book that is not on the shelf. Current status: {Status}."); Status = BookInstanceStatus.Lent; return this; } public BookInstance ReturnToShelf() { if (Status != BookInstanceStatus.Lent) throw new InvalidOperationException($"Cannot return a book that is not lent out. Current status: {Status}."); Status = BookInstanceStatus.OnShelf; return this; } public BookInstance MarkAsPutAside() { if (Status != BookInstanceStatus.OnShelf) throw new InvalidOperationException($"Cannot put aside a book that is not on the shelf. Current status: {Status}."); Status = BookInstanceStatus.PutAside; return this; } public BookInstance PlaceOnShelf(ShelfId shelfId) { if (Status != BookInstanceStatus.PutAside) throw new InvalidOperationException($"Cannot place on shelf a book that is not put aside. Current status: {Status}."); ShelfId = shelfId; Status = BookInstanceStatus.OnShelf; return this; } public BookInstance MarkAsLost() { if (Status != BookInstanceStatus.OnShelf) throw new InvalidOperationException($"Cannot mark as lost a book that is not on the shelf. Current status: {Status}."); Status = BookInstanceStatus.Lost; return this; } public BookInstance UnmarkAsLost() { if (Status != BookInstanceStatus.Lost) throw new InvalidOperationException($"Cannot unmark as lost a book that is not marked as lost. Current status: {Status}."); Status = BookInstanceStatus.OnShelf; return this; } } public record BookInstanceId : DbId { public BookInstanceId(string id) : base(id) {} } public record BookInstanceBarcode { public string Barcode { get; init; } public BookInstanceBarcode(string barcode) { if(string.IsNullOrWhiteSpace(barcode)) { throw new ArgumentException("Barcode cannot be empty."); } Barcode = barcode; } }