public static ShipmentEntity ToDataModel(this Shipment shipment, CustomerOrderEntity orderEntity)
		{
			if (shipment == null)
				throw new ArgumentNullException("shipment");

			var retVal = new ShipmentEntity();
			retVal.InjectFrom(shipment);

			retVal.Currency = shipment.Currency.ToString();

		
			//Allow to empty address
			retVal.Addresses = new ObservableCollection<AddressEntity>();
			if (shipment.DeliveryAddress != null)
			{
				retVal.Addresses = new ObservableCollection<AddressEntity>(new AddressEntity[] { shipment.DeliveryAddress.ToDataModel() });
			}
			if(shipment.Items != null)
			{
				retVal.Items = new ObservableCollection<ShipmentItemEntity>(shipment.Items.Select(x=>x.ToDataModel(orderEntity)));
			}
			if (shipment.Packages != null)
			{
				retVal.Packages = new ObservableCollection<ShipmentPackageEntity>(shipment.Packages.Select(x => x.ToDataModel(orderEntity)));
			}
			if (shipment.TaxDetails != null)
			{
				retVal.TaxDetails = new ObservableCollection<TaxDetailEntity>();
				retVal.TaxDetails.AddRange(shipment.TaxDetails.Select(x => x.ToDataModel()));
			}
			return retVal;
		}
		public static ShipmentItemEntity ToDataModel(this ShipmentItem shipmentItem, CustomerOrderEntity orderEntity, PrimaryKeyResolvingMap pkMap)
		{
			if (shipmentItem == null)
				throw new ArgumentNullException("shipmentItem");

			var retVal = new ShipmentItemEntity();
            pkMap.AddPair(shipmentItem, retVal);
            retVal.InjectFrom(shipmentItem);

            //Try to find cart line item by shipment item
            if (!String.IsNullOrEmpty(shipmentItem.LineItemId))
            {
                retVal.LineItem = orderEntity.Items.FirstOrDefault(x => x.Id == shipmentItem.LineItemId);
            }
            if (retVal.LineItem == null && shipmentItem.LineItem != null)
            {
                retVal.LineItem = orderEntity.Items.FirstOrDefault(x => x.Id == shipmentItem.LineItem.Id);
            }
            if (retVal.LineItem == null && shipmentItem.LineItem != null)
            {
                retVal.LineItem = orderEntity.Items.FirstOrDefault(x => x.ProductId == shipmentItem.LineItem.ProductId);
            }
            if (retVal.LineItem != null && !String.IsNullOrEmpty(retVal.LineItem.Id))
            {
                retVal.LineItemId = retVal.LineItem.Id;
                retVal.LineItem = null;
            }
            return retVal;
		}
		public static ShipmentItemEntity ToDataModel(this ShipmentItem shipmentItem, CustomerOrderEntity orderEntity)
		{
			if (shipmentItem == null)
				throw new ArgumentNullException("shipmentItem");

			var retVal = new ShipmentItemEntity();
			retVal.InjectFrom(shipmentItem);
			
			if(shipmentItem.LineItem != null)
			{
				retVal.LineItem = orderEntity.Items.FirstOrDefault(x => x.ProductId == shipmentItem.LineItem.ProductId);
			}
			return retVal;
		}
		public static ShipmentPackageEntity ToDataModel(this ShipmentPackage package, CustomerOrderEntity orderEntity)
		{
			if (package == null)
				throw new ArgumentNullException("package");

			var retVal = new ShipmentPackageEntity();
			retVal.InjectFrom(package);

			if(package.Items != null)
			{
				retVal.Items = new ObservableCollection<ShipmentItemEntity>(package.Items.Select(x => x.ToDataModel(orderEntity)));
			}

			return retVal;
		}
        public static PaymentInEntity ToDataModel(this PaymentIn paymentIn, CustomerOrderEntity orderEntity)
        {
            if (paymentIn == null)
                throw new ArgumentNullException("paymentIn");

            var retVal = new PaymentInEntity();
            retVal.InjectFrom(paymentIn);

            retVal.Currency = paymentIn.Currency.ToString();
            retVal.Status = paymentIn.PaymentStatus.ToString();

         
            if (paymentIn.BillingAddress != null)
            {
                retVal.Addresses = new ObservableCollection<AddressEntity>(new AddressEntity[] { paymentIn.BillingAddress.ToDataModel() });
            }
            return retVal;
        }
		/// <summary>
		/// Patch CatalogBase type
		/// </summary>
		/// <param name="source"></param>
		/// <param name="target"></param>
		public static void Patch(this CustomerOrderEntity source, CustomerOrderEntity target)
		{
			if (target == null)
				throw new ArgumentNullException("target");

			source.Patch((OperationEntity)target);

			var patchInjectionPolicy = new PatchInjection<CustomerOrderEntity>(x => x.CustomerId, x => x.StoreId,
																		       x => x.OrganizationId, x => x.EmployeeId);
			target.InjectFrom(patchInjectionPolicy, source);

			if (!source.Addresses.IsNullCollection())
			{
				source.Addresses.Patch(target.Addresses, new AddressComparer(), (sourceItem, targetItem) => sourceItem.Patch(targetItem));
			}

			if (!source.Shipments.IsNullCollection())
			{
				source.Shipments.Patch(target.Shipments, (sourceShipment, targetShipment) => sourceShipment.Patch(targetShipment));
			}

			if (!source.Items.IsNullCollection())
			{
				source.Items.Patch(target.Items, (sourceItem, targetItem) => sourceItem.Patch(targetItem));
			}

			if (!source.InPayments.IsNullCollection())
			{
				source.InPayments.Patch(target.InPayments, (sourcePayment, targetPayment) => sourcePayment.Patch(targetPayment));
			}

			if (!source.Discounts.IsNullCollection())
			{
				source.Discounts.Patch(target.Discounts, new DiscountComparer(), (sourceDiscount, targetDiscount) => sourceDiscount.Patch(targetDiscount));
			}
			if (!source.TaxDetails.IsNullCollection())
			{
				var taxDetailComparer = AnonymousComparer.Create((TaxDetailEntity x) => x.Name);
				source.TaxDetails.Patch(target.TaxDetails, taxDetailComparer, (sourceTaxDetail, targetTaxDetail) => sourceTaxDetail.Patch(targetTaxDetail));
			}
		}
		public static CustomerOrderEntity ToDataModel(this CustomerOrder order, PrimaryKeyResolvingMap pkMap)
		{
			if (order == null)
				throw new ArgumentNullException("order");

			var retVal = new CustomerOrderEntity();
            pkMap.AddPair(order, retVal);
            retVal.InjectFrom(order);

			retVal.Currency = order.Currency.ToString();

	
			if(order.Addresses != null)
			{
				retVal.Addresses = new ObservableCollection<AddressEntity>(order.Addresses.Select(x=>x.ToDataModel()));
			}
			if(order.Items != null)
			{
				retVal.Items = new ObservableCollection<LineItemEntity>(order.Items.Select(x=>x.ToDataModel(pkMap)));
			}
			if(order.Shipments != null)
			{
				retVal.Shipments = new ObservableCollection<ShipmentEntity>(order.Shipments.Select(x => x.ToDataModel(retVal, pkMap)));
			}
			if(order.InPayments != null)
			{
				retVal.InPayments = new ObservableCollection<PaymentInEntity>(order.InPayments.Select(x => x.ToDataModel(retVal, pkMap)));
			}
			if(order.Discount != null)
			{
				retVal.Discounts = new ObservableCollection<DiscountEntity>(new DiscountEntity[] { order.Discount.ToDataModel() });
			}
			if (order.TaxDetails != null)
			{
				retVal.TaxDetails = new ObservableCollection<TaxDetailEntity>();
				retVal.TaxDetails.AddRange(order.TaxDetails.Select(x => x.ToDataModel()));
			}
			return retVal;
		}
		private ObservableChangeTracker GetChangeTracker(IRepository repository, CustomerOrderEntity customerOrderEntity)
		{
			var retVal = new ObservableChangeTracker
			{
				RemoveAction = (x) =>
				{
					repository.Remove(x);
				},
				AddAction = (x) =>
				{
					var address = x as AddressEntity;
					var shipment = x as ShipmentEntity;
					var lineItem = x as LineItemEntity;

					if (address != null)
					{
						address.CustomerOrder = customerOrderEntity;
					}
					if (shipment != null)
					{
						foreach (var shipmentItem in shipment.Items)
						{
							var orderLineItem = customerOrderEntity.Items.FirstOrDefault(item => item.Id == shipmentItem.Id);
							if (orderLineItem != null)
							{
								orderLineItem.Shipment = shipment;
							}
							else
							{
								shipmentItem.CustomerOrder = customerOrderEntity;
							}
						}
						shipment.Items = new NullCollection<LineItemEntity>();
					}
					if (lineItem != null)
					{
						lineItem.CustomerOrder = customerOrderEntity;
						lineItem.CustomerOrderId = customerOrderEntity.Id;
					}
					repository.Add(x);
				}
			};

			return retVal;
		}