private void AdjustStockItemQuantity(LineItem lineItem)
        {
            if (String.IsNullOrEmpty(lineItem.CatalogItemId) ||
                lineItem.CatalogItemId.StartsWith("@"))
            {
                return;
            }

            var catalogHelper = new CatalogClient(CatalogRepository, null, CustomerSessionService, CacheRepository, InventoryRepository);
            var item = catalogHelper.GetItem(lineItem.CatalogItemId);

			if (item != null && item.TrackInventory)
			{
                var repo = InventoryRepository;
                var inventory = catalogHelper.GetItemInventory(lineItem.CatalogItemId, lineItem.FulfillmentCenterId, false);
			    if (inventory != null)
			    {
				    if (AdjustStockInventoryQuantity(lineItem, inventory))
				    {
					    repo.UnitOfWork.Commit();
				    }
				    else
				    {
					    throw new InvalidWorkflowException(string.Format("Failed to adjust inventory for lineItem {0}", lineItem.LineItemId));
				    }
			    }
			}
        }
		/// <summary>
		/// Populates the line item.
		/// </summary>
		/// <param name="entry">The entry.</param>
		/// <param name="lineItem">The line item.</param>
		private void PopulateLineItem(ref PromotionEntry entry, LineItem lineItem)
		{
			entry.Quantity = lineItem.Quantity;
			entry.Owner = lineItem;
			entry.Outline = lineItem.CatalogOutline;
			entry.EntryId = lineItem.CatalogItemId;
			entry.ParentEntryId = lineItem.ParentCatalogItemId;
			entry.EntryCode = lineItem.CatalogItemCode;

			// Save line item id, so it is easier to distinguish to which item discount is applied
			entry["LineItemId"] = lineItem.LineItemId;
			entry["ShippingAddressId"] = lineItem.ShippingAddressId;
			
			entry["MinQuantity"] = lineItem.MinQuantity;
			entry["MaxQuantity"] = lineItem.MaxQuantity;
			entry["LineItemDiscountAmount"] = lineItem.LineItemDiscountAmount;
			//entry["OrderLevelDiscountAmount"] = lineItem.OrderLevelDiscountAmount;
			entry["ShippingMethodName"] = lineItem.ShippingMethodName ?? string.Empty;
			entry["ExtendedPrice"] = lineItem.ExtendedPrice;
			entry["Description"] = lineItem.Description ?? string.Empty;
			entry["Status"] = lineItem.Status ?? string.Empty;
			entry["DisplayName"] = lineItem.DisplayName ?? string.Empty;
			entry["AllowBackordersAndPreorders"] = lineItem.AllowBackorders && lineItem.AllowPreorders;
			entry["InStockQuantity"] = lineItem.InStockQuantity;
			entry["PreorderQuantity"] = lineItem.PreorderQuantity;
			entry["BackorderQuantity"] = lineItem.BackorderQuantity;
			entry["InventoryStatus"] = lineItem.InventoryStatus;
		}
        protected void RegisterWarning(string code, LineItem lineItem, string message)
        {
            var parameters = new Dictionary<string, string>
	            {
		            {"ItemId", lineItem.CatalogItemId},
		            {"LineItemId", lineItem.LineItemId},
		            {"DisplayName", lineItem.DisplayName},
		            {"Message", message}
	            };

	        RegisterWarning(code, parameters);
        }
		[RepositoryTheory] // fixed be setting LineItemId explicitly
		public void Can_add_shipmentitem()
		{
			var order = TestOrderBuilder.BuildOrder()
				.WithAddresess()
				.WithShipment()
				.GetOrder();

			var repository = GetRepository();
			repository.Add(order);
			repository.UnitOfWork.Commit();

			RefreshRepository(ref repository);
			order = repository.Orders
				.ExpandAll()
				.Expand("RmaRequests/RmaReturnItems/RmaLineItems/LineItem")
				.Expand("RmaRequests/Order")
				.Expand("OrderForms/Shipments/OrderForm/OrderGroup")
				.Expand("OrderForms/Shipments/ShipmentItems/LineItem")
				.Expand("OrderForms/Shipments/ShipmentItems/Shipment/OrderForm/OrderGroup")
				.FirstOrDefault();

			// adding new LineItem first
			var newLineItem = new LineItem
			{
				CatalogItemId = "ItemId",
				CatalogItemCode = "ItemCode",
				Quantity = 1,
				PlacedPrice = 10,
				TaxTotal = 1
			};
			order.OrderForms[0].LineItems.Add(newLineItem);

			// adding new ShipmentItem
			var item = new ShipmentItem();
			item.LineItem = newLineItem;
			item.LineItemId = item.LineItem.LineItemId; // this line shouldn't be necessary. But it is.
			//item.Shipment = order.OrderForms[0].Shipments[0]; // this line of code was causing exception in original	code
			order.OrderForms[0].Shipments[0].ShipmentItems.Add(item);
			repository.UnitOfWork.Commit();

			RefreshRepository(ref repository);
			order = repository.Orders
				.ExpandAll()
				.Expand("OrderForms/Shipments/ShipmentItems")
				.Expand("OrderForms/LineItems")
				.FirstOrDefault();

			Assert.True(order.OrderForms[0].LineItems.Any(x => x.LineItemId == newLineItem.LineItemId));
			Assert.True(order.OrderForms[0].Shipments[0].ShipmentItems.Any(x => x.LineItemId == newLineItem.LineItemId));
		}
		/// <summary>
		/// Returns the package option array when method id and package that needs to be send is passed.
		/// Use passed message string to pass errors back to the application if any occurred.
		/// </summary>
		/// <param name="shippingMethod">The shipping method.</param>
		/// <param name="items">The items.</param>
		/// <param name="message">The message.</param>
		/// <returns>
		/// empty array if no results found
		/// </returns>
		public ShippingRate GetRate(string shippingMethod, LineItem[] items, ref string message)
		{
			if (items == null || items.Length == 0)
				return null;

			IShippingRepository repository = ServiceLocator.Current.GetInstance<IShippingRepository>();
			ShippingOption[] options = repository.ShippingOptions.ExpandAll().ToArray();

			var method = (from o in options from m in o.ShippingMethods where m.ShippingMethodId.Equals(shippingMethod, StringComparison.OrdinalIgnoreCase) select m).SingleOrDefault();

			if (method != null)
			{
				return new ShippingRate(method.ShippingMethodId, method.Name, method.BasePrice, method.Currency);
			}
			else
			{
				message = "The shipping method could not be loaded.";
				return null;
			}
		}
        public ShippingRate GetRate(string shippingMethod, LineItem[] items, ref string message)
        {
            if (items == null || items.Length == 0)
            {
                message = "No line items provided";
                return null;
            }


            var repository = ServiceLocator.Current.GetInstance<IShippingRepository>();
            var options = repository.ShippingOptions.ExpandAll().ToArray();

            var method = (from o in options from m in o.ShippingMethods where m.ShippingMethodId.Equals(shippingMethod, StringComparison.OrdinalIgnoreCase) select m).SingleOrDefault();

            if (method == null)
            {
                message = "The shipping method could not be loaded.";
                return null;
            }

            var retVal = new ShippingRate(method.ShippingMethodId, method.Name, method.BasePrice, method.Currency);

            var prop = method.ShippingOption.ShippingGatewayPropertyValues.FirstOrDefault(
                x => x.Name == UnitWeightPricePropertyName);

            if (prop != null && !string.IsNullOrWhiteSpace(prop.ShortTextValue) && decimal.TryParse(prop.ShortTextValue, NumberStyles.Number, CultureInfo.InvariantCulture, out defaultWeghtUnitPriceDecimal))
            {
                //just ok
            }

            //Calculate price for item weight
            foreach (var item in items)
            {
                retVal.Price += item.Weight * defaultWeghtUnitPriceDecimal * item.Quantity;
            }

            return retVal;
        }
        public ShippingRate[] GetShippingRates(string[] shippingMethods, LineItem[] items)
        {
            if (items == null || items.Length == 0)
                return null;

            if (shippingMethods == null || shippingMethods.Length == 0)
                return null;

            var options = GetAllShippingOptions();
            var methods = (from o in options from m in o.ShippingMethods where shippingMethods.Contains(m.ShippingMethodId, StringComparer.OrdinalIgnoreCase) select m).ToArray();

            if (methods.Length == 0)
                return null;

            var rates = new List<ShippingRate>();
            foreach (var method in methods)
            {
				var classType = method.ShippingOption.ShippingGateway.ClassType;//.GetParent()).ClassType;
                var type = Type.GetType(classType);
                if (type == null)
                {
                    throw new TypeInitializationException(classType, null);
                }

                var message = String.Empty;
                var provider = (IShippingGateway)Activator.CreateInstance(type);

                var rate = provider.GetRate(method.ShippingMethodId, items.ToArray(), ref message);
                if (rate != null)
                {
                    rates.Add(rate);
                }
            }

            return rates.ToArray();
        }
		private LineItem Sku2LineItem(Item sku, decimal quantity)
		{
			var session = CustomerSessionService.CustomerSession;
			var price = PriceListRepository.FindLowestPrice(session != null ? session.Pricelists : null, sku.ItemId, quantity);
			var retVal = new LineItem
				{
					CatalogItemId = sku.ItemId,
					CatalogItemCode = sku.Code,
					DisplayName = sku.Name,
					Quantity = quantity,
					Catalog = sku.CatalogId,
					MaxQuantity = sku.MaxQuantity,
					MinQuantity = sku.MinQuantity,
					PlacedPrice = price != null ? (price.Sale ?? price.List) : 0,
					ListPrice = price != null ? (price.Sale ?? price.List) : 0,
                    CatalogOutline = OutlineBuilder.BuildCategoryOutline(CustomerSessionService.CustomerSession.CatalogId, sku.ItemId).ToString()
				};

			return retVal;
		}
		private PromotionEntry GetPromotionEntryFromLineItem(LineItem lineItem)
		{
			var populate = PromotionEntryPopulate;
			var entry = new PromotionEntry(lineItem.Catalog, lineItem.CatalogItemId, lineItem.ExtendedPrice / lineItem.Quantity);
			populate.Populate(ref entry, lineItem);
			return entry;
		}
		private void ChangeShipmentsLineItemQty(LineItem lineItem, decimal delta)
		{
			var order = CurrentOrderGroup;
			foreach (var form in order.OrderForms)
			{
				var allShipmentContainsLineItem = form.Shipments
					.Where(x => x.ShipmentItems.Select(si => si.LineItem).Contains(lineItem))
					.SelectMany(s => s.ShipmentItems);

				foreach (var shipmentLineItems in allShipmentContainsLineItem)
				{
					//Decrease qty in all shipment contains line item
					var shipmentQty = shipmentLineItems.Quantity;
					var newShipmentQty = shipmentQty - delta;
					newShipmentQty = newShipmentQty > 0 ? newShipmentQty : 0;
					//Set new line item qty in shipment
					shipmentLineItems.Quantity = newShipmentQty;
					delta -= Math.Min(delta, shipmentQty);

					if (delta == 0)
						break;
				}
			}
		}
		private void DeleteLineItemFromShipments(LineItem lineItem)
		{
			var order = CurrentOrderGroup;
			foreach (var form in order.OrderForms)
			{
				var allShipmentItems = form.Shipments.SelectMany(s => s.ShipmentItems.ToArray()).Where(x => x.LineItem == lineItem);

				foreach (var shipmentLineItem in allShipmentItems)
				{
					shipmentLineItem.Shipment.ShipmentItems.Remove(shipmentLineItem);
				}
			}
		}
		private decimal GetNewLineItemQty(LineItem lineItem, List<string> changeQtyReason, out bool isUsingBackordersAndPreorders)
		{
			isUsingBackordersAndPreorders = false;
			var newLineItemQty = lineItem.Quantity;
			if (newLineItemQty < lineItem.MinQuantity || newLineItemQty > lineItem.MaxQuantity)
			{
				newLineItemQty = Math.Max(lineItem.MinQuantity, newLineItemQty);
				if (newLineItemQty != lineItem.Quantity)
				{
					changeQtyReason.Add("by Min Quantity setting");
				}
				newLineItemQty = Math.Min(lineItem.MaxQuantity, newLineItemQty);
				if (newLineItemQty != lineItem.Quantity)
				{
					changeQtyReason.Add("by Max Quantity setting");
				}
			}

			if (lineItem.InventoryStatus == InventoryStatus.Enabled.ToString())
			{
				// Check Inventory
				// item exists with appropriate quantity
				if (lineItem.InStockQuantity < newLineItemQty)
				{
					if (lineItem.InStockQuantity > 0) // there still exist items in stock
					{
						// check if we can backorder some items
						if (lineItem.AllowBackorders)
						{
							isUsingBackordersAndPreorders = true;
							//Increase stock qty by backorder qty if 
							var availStockAndBackorderQty = lineItem.InStockQuantity + lineItem.BackorderQuantity;
							if (availStockAndBackorderQty < newLineItemQty)
							{
								newLineItemQty = availStockAndBackorderQty;
								changeQtyReason.Add("by BackOrder quantity");
							}
						}
						else
						{
							newLineItemQty = lineItem.InStockQuantity;
						}
					}
					else if (lineItem.InStockQuantity == 0)
					{
						if (lineItem.AllowPreorders && lineItem.PreorderQuantity > 0)
						{
							isUsingBackordersAndPreorders = true;
							if (lineItem.PreorderQuantity < newLineItemQty)
							{
								newLineItemQty = lineItem.PreorderQuantity;
								changeQtyReason.Add("by Preorder quantity");
							}
						}
						else if (lineItem.AllowBackorders && lineItem.BackorderQuantity > 0)
						{
							isUsingBackordersAndPreorders = true;
							if (lineItem.BackorderQuantity < newLineItemQty)
							{
								newLineItemQty = lineItem.BackorderQuantity;
								changeQtyReason.Add("by BackOrder quantity");
							}
						}
						else
						{
							newLineItemQty = 0;
						}
					}
				}
			}
			return newLineItemQty;
		}
        /// <summary>
        /// Gets the line item adjusted quantity.
        /// </summary>
        /// <param name="lineItem">The line item.</param>
        /// <returns></returns>
        private static decimal GetLineItemAdjustedQuantity(LineItem lineItem)
        {
			//Need to find a way to determine if item was added removed or modified
			//Should return positive qty if item was removed, negative if added and exact qty when modified
            var retVal = -lineItem.Quantity;
            return retVal;
        }
        /// <summary>
        /// Adds the specified order group to the existing cart.
        /// </summary>
        /// <param name="orderGroup">The order group.</param>
        /// <param name="lineItemRollup">if set to <c>true</c> [line item rollup].</param>
        /// <exception cref="System.ArgumentNullException">orderGroup</exception>
        public virtual void Add(OrderGroup orderGroup, bool lineItemRollup)
        {
            if (orderGroup == null)
            {
                throw new ArgumentNullException("orderGroup");
            }

            if ((orderGroup.OrderForms != null) && (orderGroup.OrderForms.Count != 0))
            {
                // need to set meta data context before cloning
                foreach (var form in orderGroup.OrderForms)
                {
                    var orderForm = Cart.OrderForms.FirstOrDefault(f => f.Name.Equals(form.Name, StringComparison.OrdinalIgnoreCase));
                    if (orderForm == null)
                    {
                        orderForm = new OrderForm { Name = form.Name };
                        Cart.OrderForms.Add(orderForm);
                    }

                    orderForm.OrderGroupId = Cart.OrderGroupId;
                    orderForm.OrderGroup = Cart;

                    var count = form.LineItems.Count;
                    for (var i = 0; i < count; i++)
                    {
                        var newLineItem = new LineItem();

                        // preserve the new id
                        var id = newLineItem.LineItemId;
                        newLineItem.InjectFrom(form.LineItems[i]);
                        newLineItem.LineItemId = id;

                        Add(orderForm, newLineItem, lineItemRollup);
                    }
                }
            }
        }
        /// <summary>
        /// Populates the inventory information.
        /// </summary>
        /// <param name="inventory">The inventory.</param>
        /// <param name="lineItem">The line item.</param>
		private void PopulateInventoryInfo(Inventory inventory, LineItem lineItem)
		{
			
			if (inventory == null)
			{
				return;
			}

			// Inventory info
			lineItem.AllowBackorders = inventory.AllowBackorder &&
					 inventory.BackorderAvailabilityDate.HasValue &&
					 inventory.BackorderAvailabilityDate.Value <= DateTime.Now;

			lineItem.AllowPreorders = inventory.AllowPreorder &&
								inventory.PreorderAvailabilityDate.HasValue &&
								inventory.PreorderAvailabilityDate.Value <= DateTime.Now;


			//Init quantities once
			lineItem.BackorderQuantity = lineItem.BackorderQuantity == 0 ? inventory.BackorderQuantity : lineItem.BackorderQuantity;
			lineItem.InStockQuantity = lineItem.InStockQuantity == 0 ? inventory.InStockQuantity - inventory.ReservedQuantity : lineItem.InStockQuantity;
			lineItem.PreorderQuantity = lineItem.PreorderQuantity == 0  ? inventory.PreorderQuantity : lineItem.PreorderQuantity;
			lineItem.InventoryStatus = ((InventoryStatus)inventory.Status).ToString();
		}
        /// <summary>
        /// Populates the variation information.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <param name="lineItem">The line item.</param>
	    private void PopulateVariationInfo(Item item, LineItem lineItem)
		{
			if (item == null)
			{
				return;
			}

			lineItem.MaxQuantity = item.MaxQuantity;
			lineItem.MinQuantity = item.MinQuantity;

			var priceListHelper = new PriceListClient(PricelistRepository, CustomerSessionService, PriceListEvaluator, PriceListEvalContext, CacheRepository);

			var itemPrice = priceListHelper.GetLowestPrice(item.ItemId, lineItem.Quantity);

			if (itemPrice == null)
			{
				RemoveLineItem(lineItem);
				return;
			}

			// Get old and new prices for comparison.
			var oldPrice = lineItem.ListPrice;

            // new logic is to have the price always be replaced
            var newPrice = itemPrice.Sale ?? itemPrice.List;

			newPrice = Math.Round(newPrice, 2); // Comparison. The LineItem.ListPrice property rounds values.

			// Get old and new currencies for comparison.
			var oldCurrencyCode = CurrentOrderGroup.BillingCurrency;
			var newCurrencyCode = CustomerSessionService.CustomerSession.Currency;
			if (string.IsNullOrEmpty(oldCurrencyCode))
			{
				oldCurrencyCode = newCurrencyCode;
			}

			// Check for price changes OR currency changes.
			if (oldPrice == newPrice && oldCurrencyCode == newCurrencyCode)
			{
				return;
			}

			// Set new price and currency vales on line item.
			lineItem.ListPrice = newPrice;
            lineItem.PlacedPrice = newPrice;
            lineItem.ExtendedPrice = lineItem.PlacedPrice * lineItem.Quantity;
			CurrentOrderGroup.BillingCurrency = newCurrencyCode;
		}
        /// <summary>
        /// Removes the line item.
        /// </summary>
        /// <param name="lineItem">The line item.</param>
        private void RemoveLineItem(LineItem lineItem)
        {
	        foreach (var form in CurrentOrderGroup.OrderForms.Where(form => form.LineItems.Contains(lineItem)))
	        {
		        form.LineItems.Remove(lineItem);

                foreach (var shipmentLineItem in form.Shipments.SelectMany(s => s.ShipmentItems.ToArray()).Where(x => x.LineItem == lineItem))
                {
                    shipmentLineItem.Shipment.ShipmentItems.Remove(shipmentLineItem);
                }
	        }
        }
        /// <summary>
        /// Removes the specified line item.
        /// </summary>
        /// <param name="lineItem">The line item.</param>
        public virtual void Remove(LineItem lineItem)
        {
            //We must also remove shipmentItems that are not used when item is removed
            foreach (var shipmentItem in lineItem.OrderForm.Shipments.SelectMany(s => s.ShipmentItems)
                                                 .Where(si => si.LineItemId == lineItem.LineItemId).ToList())
            {
                shipmentItem.Shipment.ShipmentItems.Remove(shipmentItem);
                OrderRepository.Remove(shipmentItem);
            }

            lineItem.OrderForm.LineItems.Remove(lineItem);
            OrderRepository.Remove(lineItem);
        }
		public LineItem[] GenerateLineItemsConstant()
		{
			var retVal = new List<LineItem>();

			var items = new[]{ 
                new { Name = "Apple 30 GB iPod with Video Playback Black (5th Generation)", Price = 100m, Quantity = 1 },
                new { Name = "Sony MDR-IF240RK Wireless Headphone System", Price = 10.11m, Quantity = 8 },
                new { Name = "Samsung DVD-HD841 Up-Converting DVD Player", Price = 1000m, Quantity = 3 },
                new { Name = "Apple QuickTake 200 - Digital camera - compact - 0.35 Mpix - supported memory: SM", Price = 250m, Quantity = 2 },
                new { Name = "Samsung YP-T9JAB 4 GB Digital Multimedia Player (Black)", Price = 340m, Quantity = 1 },
                new { Name = "EFC-1B1NBECXAR Carrying Case for 10.1", Price = 222m, Quantity = 6 },
                new { Name = "Sony SGPFLS1 Tablet S LCD Protection Sheet", Price = 3422m, Quantity = 2 }
            };

			for (var i = 0; i < items.Count(); i++)
			{
				var lineItem = new LineItem { DisplayName = items[i].Name, Quantity = items[i].Quantity, ListPrice = items[i].Price };
				lineItem.PlacedPrice = lineItem.ListPrice;
				lineItem.ExtendedPrice = lineItem.PlacedPrice * items[i].Quantity;
				lineItem.CatalogItemId = "v-b0000u9h40";
				lineItem.CatalogItemCode = "v-b0000u9h40";

				retVal.Add(lineItem);
			}
			return retVal.ToArray();
		}
        /// <summary>
        /// Creates the line item.
        /// </summary>
        /// <param name="item">The entry.</param>
        /// <param name="parent">Parent item</param>
        /// <param name="quantity">The quantity.</param>
        /// <returns>LineItem.</returns>
        private LineItem CreateLineItem(Item item, Item parent, decimal quantity)
        {
            var lineItem = new LineItem();

            if (parent != null)
            {
                lineItem.DisplayName = item.DisplayName(String.Format("{0}: {1}", parent.Name, item.Name));
                lineItem.ParentCatalogItemId = parent.ItemId;

                //Build options
                var relations = CatalogClient.GetItemRelations(parent.ItemId);

                var relationGroups = relations.Select(rel => rel.GroupName).Distinct();
                foreach (var prop in item.ItemPropertyValues.LocalizedProperties().Where(p => relationGroups.Contains(p.Name)))
                {
                    var option = new LineItemOption
                        {
                            LineItemId = item.ItemId,
                            OptionName = prop.Name,
                            OptionValue = prop.ToString()
                        };
                    lineItem.Options.Add(option);
                }
            }
            else
            {
                lineItem.DisplayName = item.DisplayName();
                lineItem.ParentCatalogItemId = String.Empty;
            }

            lineItem.CatalogItemId = item.ItemId;
            lineItem.CatalogItemCode = item.Code;
            var price = PriceListClient.GetLowestPrice(item.ItemId, quantity, false);

            if (price != null)
            {
                lineItem.ListPrice = price.Sale ?? price.List;
                lineItem.PlacedPrice = price.Sale ?? price.List;
                lineItem.ExtendedPrice = lineItem.PlacedPrice * quantity;
            }

            lineItem.MaxQuantity = item.MaxQuantity;
            lineItem.MinQuantity = item.MinQuantity;
            lineItem.Quantity = quantity;
            lineItem.Weight = item.Weight;
            lineItem.Catalog = CustomerSession.CatalogId;
            lineItem.FulfillmentCenterId = StoreHelper.StoreClient.GetCurrentStore().FulfillmentCenterId;
            //lineItem.CatalogOutline = CatalogOutlineBuilder.BuildCategoryOutline(CatalogClient.CatalogRepository, CustomerSession.CatalogId, item);
            lineItem.CatalogOutline = CatalogOutlineBuilder.BuildCategoryOutline(CustomerSessionService.CustomerSession.CatalogId, item.ItemId).ToString();

            return lineItem;
        }
        private static bool AdjustStockInventoryQuantity(LineItem lineItem, Inventory inventory)
        {
            var delta = GetLineItemAdjustedQuantity(lineItem);

			var allowBackorder = inventory.AllowBackorder && 
				inventory.BackorderAvailabilityDate.HasValue && 
				inventory.BackorderAvailabilityDate.Value <= DateTime.Now;

			var allowPreorder = inventory.AllowPreorder &&
				inventory.PreorderAvailabilityDate.HasValue &&
				inventory.PreorderAvailabilityDate.Value <= DateTime.Now;

	        var inventoryAdjusted = false;

            //arrival
            if (delta > 0)
            {
                // need distribute delta between InStock, Backorder, Preorder.
                if (lineItem.InStockQuantity > 0)
                {                                 
	                var inStock = delta;

	                if (allowPreorder)
	                {
						var preorderdelta = Math.Min(delta, lineItem.PreorderQuantity - inventory.PreorderQuantity);
		                inventory.PreorderQuantity += preorderdelta;
						inStock -= preorderdelta;
	                }
	                if (allowBackorder)
	                {
						var backorderDelta = Math.Min(delta, lineItem.BackorderQuantity - inventory.BackorderQuantity);
		                inventory.BackorderQuantity += backorderDelta;
		                inStock -= backorderDelta;
	                }
					inventory.InStockQuantity += inStock;
					inventoryAdjusted = true;
                } //need distribute delta between Preorder and Backorder
                else if (lineItem.InStockQuantity == 0)
                {
                    if (lineItem.PreorderQuantity > 0 && allowPreorder)
                    {
                        inventory.PreorderQuantity += delta;
						inventoryAdjusted = true;
                    }
                    else if (lineItem.BackorderQuantity > 0 && allowBackorder)
                    {
                        inventory.BackorderQuantity += delta;
						inventoryAdjusted = true;
                    }
                }
            }//consumption
            else
            {
                delta = Math.Abs(delta);
                var instock = inventory.InStockQuantity - inventory.ReservedQuantity;
                if (instock >= delta) // Adjust the main inventory
                {
                    inventory.InStockQuantity -= delta;
					inventoryAdjusted = true;
                }
                else if (instock > 0) // there still exist items in stock
                {
	                if (allowBackorder)
	                {
		                // Calculate difference between currently available and backorder
		                var backorderDelta = delta - instock;

		                if (inventory.BackorderQuantity >= backorderDelta)
		                {
			                // Update inventory
			                inventory.InStockQuantity -= instock;
			                inventory.BackorderQuantity -= backorderDelta;
							inventoryAdjusted = true;
		                }
	                }
                }
                else if (instock == 0)
                {
					if (allowBackorder && inventory.BackorderQuantity >= delta)
					{
						inventory.BackorderQuantity -= delta;
						inventoryAdjusted = true;
					}
					else if (allowPreorder && inventory.PreorderQuantity >= delta)
					{
						inventory.PreorderQuantity -= delta;
						inventoryAdjusted = true;
					}
                }
            }

			return inventoryAdjusted;
        }
        /// <summary>
        /// Adds the specified form.
        /// </summary>
        /// <param name="form">The form.</param>
        /// <param name="value">The value.</param>
        /// <param name="lineItemRollup">if set to <c>true</c> [line item rollup].</param>
        /// <returns>System.Int32.</returns>
        /// <exception cref="System.ArgumentNullException">value</exception>
        public virtual int Add(OrderForm form, LineItem value, bool lineItemRollup)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            LineItem existingItem = null;

            foreach (var item in form.LineItems)
            {
                if (ReferenceEquals(value, item))
                {
                    return form.LineItems.IndexOf(value);
                }

                if (item.CatalogItemId == value.CatalogItemId)
                {
                    existingItem = item;
                    break;
                }
            }

            if (lineItemRollup && (existingItem != null))
            {
                existingItem.Quantity += value.Quantity;
                return form.LineItems.IndexOf(existingItem);
            }
            value.OrderFormId = form.OrderFormId;
            value.OrderForm = form;
            form.LineItems.Add(value);
            return form.LineItems.IndexOf(value);
        }
		public LineItem[] GenerateLineItems(int count)
		{
			var retVal = new List<LineItem>();

			var names = new[] { "Apple 30 GB iPod with Video Playback Black (5th Generation)",
									   "Sony MDR-IF240RK Wireless Headphone System",
									   "Samsung DVD-HD841 Up-Converting DVD Player", 
									   "Apple QuickTake 200 - Digital camera - compact - 0.35 Mpix - supported memory: SM", 
									   "Samsung YP-T9JAB 4 GB Digital Multimedia Player (Black)", 
									   "EFC-1B1NBECXAR Carrying Case for 10.1", 
										"Sony SGPFLS1 Tablet S LCD Protection Sheet", 
										"Galaxy Tab 8.9 3G Android Honeycomb Tablet (16GB, 850/1900 3G)",
										"Samsung Galaxy Tab Gt-p7500 16gb, Wi-fi + 3g Unlocked"};
			var codes = new[] { "v-0239432c",
									   "MDR-IF240RK",
									   "DVD-HD841", 
									   "v-b12223cc2", 
									   "YP-T9JAB0012", 
									   "EFC-1B1NBECXAR", 
										"v-bc22234088d", 
										"v-2112393vd0",
										"v-b85699233c"};

			var rnd = new Random();
			for (var i = 0; i < count; i++)
			{
				var lineItem = new LineItem();
				var index = rnd.Next(names.Length);

				lineItem.DisplayName = names[index];
				lineItem.Quantity = 1 + rnd.Next(19);
				lineItem.ListPrice = rnd.Next(200);
				lineItem.PlacedPrice = lineItem.ListPrice;
				lineItem.CatalogItemCode = codes[index];
				lineItem.CatalogItemId = codes[index];

				retVal.Add(lineItem);
			}
			return retVal.ToArray();
		}