Newer
Older
SlimDomainModel / WarehouseProduct.cs
@Derek Comartin Derek Comartin on 19 Sep 2023 2 KB Move Around
using System;
using System.Collections.Generic;
using SlimDomainModel;

namespace EventSourcing.Demo.Slim
{
    public class WarehouseProduct
    {
        private readonly string _sku;
        private readonly List<IEvent> _uncommittedEvents = new();

        private int _quantityOnHand = 0;

        public WarehouseProduct(string sku)
        {
            _sku = sku;
        }

        public void ShipProduct(int quantity)
        {
            if (quantity > _quantityOnHand)
            {
                throw new InvalidDomainException("Ah... we don't have enough product to ship?");
            }

            AddEvent(new ProductShipped(_sku, quantity, DateTime.UtcNow));
        }
        
        private void Apply(ProductShipped evnt)
        {
            _quantityOnHand -= evnt.Quantity;
        }

        public void ReceiveProduct(int quantity)
        {
            AddEvent(new ProductReceived(_sku, quantity, DateTime.UtcNow));
        }
        
        private void Apply(ProductReceived evnt)
        {
            _quantityOnHand += evnt.Quantity;
        }

        public void AdjustInventory(int quantity, string reason)
        {
            if (_quantityOnHand + quantity < 0)
            {
                throw new InvalidDomainException("Cannot adjust to a negative quantity on hand.");
            }

            AddEvent(new InventoryAdjusted(_sku, quantity, reason, DateTime.UtcNow));
        }

        private void Apply(InventoryAdjusted evnt)
        {
            _quantityOnHand += evnt.Quantity;
        }

        public void ApplyEvent(IEvent evnt)
        {
            switch (evnt)
            {
                case ProductShipped shipProduct:
                    Apply(shipProduct);
                    break;
                case ProductReceived receiveProduct:
                    Apply(receiveProduct);
                    break;
                case InventoryAdjusted inventoryAdjusted:
                    Apply(inventoryAdjusted);
                    break;
                default:
                    throw new InvalidOperationException("Unsupported Event.");
            }
        }

        private void AddEvent(IEvent evnt)
        {
            ApplyEvent(evnt);
            _uncommittedEvents.Add(evnt);
        }

        public IReadOnlyCollection<IEvent> Events() => _uncommittedEvents.AsReadOnly();
    }


}