views:

51

answers:

0

Hi,

I originally posted about how I should use the state pattern correctly in an ecommerce application. I didn't get any replies so I have now completed my implementation and thought I would post it to get feedback.

This is how I am managing inventory. It would seem that the only real reason for having an enumeration to also represent state is so that you can persist the appropriate concrete state to data store (perhaps if you wish to analyse your data in another application).

Thoughts, comments, suggestions - appreciated.

    public enum InventoryStatus {
    InStock = 1,
    BackOrder = 2,
    PreOrder = 3,
    SpecialOrder = 4,
    Discontinued = 5,
    CurrentlyUnavailable = 6
}

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string SKU { get; set; }
    public decimal Price { get; set; }
    public int StockQuantity { get; set; }
    public bool AllowBackOrder { get; set; }
    public InventoryState CurrentInventory { get; set; }

    public Product() { } 

    public Product(int id, string name, string sku, decimal price, int stockQuantity, bool allowBackOrder)
    {
        Id = id;
        Name = name;
        Price = price;
        StockQuantity = stockQuantity;
        AllowBackOrder = allowBackOrder;

        CurrentInventory = InventoryState.SetState(this, stockQuantity, allowBackOrder);
    }
}

public abstract class InventoryState
{
    protected Product _item;

    public bool CanAddToCart {
        get { return this is InStock || this is OnBackOrder; }
    }

    // sets initial inventory state
    public static InventoryState SetState(Product item, int stockQuantity, bool allowBackOrder)
    {
        InventoryState result = null;
        if (item.IsUnavailable())
        {
            result = new Unavailable(item);
        }
        else if (item.IsOnBackOrder())
        {
            result = new OnBackOrder(item);
        }
        else
        {
            result = new InStock(item);
        }
        return result;
    }

    public virtual string Description { get { return "Available"; } }
    public virtual int DeliveryDelayDays { get { return 0; } }
    public virtual bool CanView { get { return true; } }
    public virtual bool ReOrderFlag { get { return false; } }
    public virtual InventoryStatus StatusEnum { get { return InventoryStatus.InStock; } }

    public virtual void SetAsAvailable()
    {
        _item.CurrentInventory = new InStock(_item);
    }

    public virtual void PutOnBackOrder()
    {
        _item.CurrentInventory = new OnBackOrder(_item);
    }

    public virtual void TakeOfflline()
    {
        _item.CurrentInventory = new Unavailable(_item);
    }
}

public class InStock : InventoryState
{
    public InStock(Product item) {
        _item = item;
    }
}

public class OnBackOrder : InventoryState
{
    public OnBackOrder(Product item) {
        _item = item;
    }

    public override bool CanView { get { return true; } }
    public override int DeliveryDelayDays { get { return 14; }}
    public override string Description { get { return "On Backorder";} }
    public override InventoryStatus StatusEnum { get{ return InventoryStatus.BackOrder; }}
}

public class Unavailable : InventoryState
{
    public Unavailable(Product item) {
        _item = item;
    }

    public override bool CanView { get { return false; }}
    public override int DeliveryDelayDays { get { return -1; } }
    public override string Description { get { return "This item is unavailable";} }
    public override InventoryStatus StatusEnum { get { return InventoryStatus.CurrentlyUnavailable;}}
}