using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace PersistenceIgnorance.Three;
public interface IAuditableEntity { }
public class Shipment : IAuditableEntity
{
[Key]
public int ShipmentId { get; private set; }
public DateTime Booked { get; set; }
public Shipper Shipper { get; private set; }
public ICollection<Stop> Stops { get; } = new List<Stop>();
public Shipment(int shipmentId, Shipper shipper)
{
ShipmentId = shipmentId;
Shipper = shipper;
}
public bool IsComplete()
{
return Stops.All(x => x.Status == StopStatus.Departed);
}
public void Arrive(Guid stopId)
{
var currentStop = Stops.SingleOrDefault(x => x.StopId == stopId);
if (currentStop == null)
{
throw new InvalidOperationException("Stop does not exist.");
}
var previousStopsAreNotDeparted = Stops.Any(x => x.Sequence < currentStop.Sequence && x.Status != StopStatus.Departed);
if (previousStopsAreNotDeparted)
{
throw new InvalidOperationException("Previous stops have not departed.");
}
currentStop.Arrive();
}
public void Pickup(Guid stopId)
{
var currentStop = Stops.SingleOrDefault(x => x.StopId == stopId);
if (currentStop == null)
{
throw new InvalidOperationException("Stop does not exist.");
}
if (currentStop.StopType == StopType.Pickup)
{
throw new InvalidOperationException("Stop is not a pickup.");
}
currentStop.Depart();
}
public void Deliver(Guid stopId)
{
var currentStop = Stops.SingleOrDefault(x => x.StopId == stopId);
if (currentStop == null)
{
throw new InvalidOperationException("Stop does not exist.");
}
if (currentStop.StopType == StopType.Delivery)
{
throw new InvalidOperationException("Stop is not a delivery.");
}
currentStop.Depart();
}
}
public class Shipper
{
public Guid ShipperId { get; set; }
public required string Name { get; set; }
}
public class Stop
{
public Guid StopId { get; private set; }
public StopType StopType { get; private set; }
public Location Location { get; private set; }
public StopStatus Status { get; private set; }
public int Sequence { get; private set; }
protected Stop(Guid stopId, StopType stopType, Location location, StopStatus status, int sequence)
{
StopId = stopId;
StopType = stopType;
Location = location;
Status = status;
Sequence = sequence;
}
public void Arrive()
{
if (Status != StopStatus.InTransit)
{
throw new InvalidOperationException("Stop has already arrived.");
}
Status = StopStatus.Arrived;
}
public void Depart()
{
if (Status == StopStatus.Departed)
{
throw new InvalidOperationException("Stop has already departed.");
}
if (Status == StopStatus.InTransit)
{
throw new InvalidOperationException("Stop hasn't arrived yet.");
}
Status = StopStatus.Departed;
}
}
public class Location
{
public Location(string street, string city, string state, string postal)
{
Street = street;
City = city;
State = state;
Postal = postal;
}
public string Street { get; private set; }
public string City { get; private set; }
public string State { get; private set; }
public string Postal { get; private set; }
}
public enum StopType
{
Pickup,
Delivery
}
public enum StopStatus
{
InTransit,
Arrived,
Departed
}