internal IResult Execute(IEnumerable <ModifyInventoryParameters> inventoryModifications, InventoryTransactionParameters transactionParameters)
        {
            if (inventoryModifications == null)
            {
                throw new ArgumentNullException("inventoryModifications");
            }

            var transactionCommand = new CreateInventoryTransactionCommand(_inventoryUnitOfWork);

            var groupedModifications = inventoryModifications.GroupBy(a => a.InventoryKey);
            var finalModifications   = groupedModifications.Select(g => new ModifyInventoryParameters(g.Key, g.Sum(a => a.ModifyQuantity)));

            var resultingInventory = new List <Data.Models.Inventory>();

            foreach (var modification in finalModifications.Where(a => a.ModifyQuantity != 0))
            {
                var modifyResult = ModifyInventory(modification);
                if (!modifyResult.Success)
                {
                    return(modifyResult);
                }

                resultingInventory.Add(modifyResult.ResultingObject);

                if (transactionParameters != null)
                {
                    var transactionResult = transactionCommand.Create(transactionParameters, modification.InventoryKey, modification.ModifyQuantity);
                    if (!transactionResult.Success)
                    {
                        return(transactionResult);
                    }
                }
            }

            var negativeLots = resultingInventory
                               .Where(i => i != null && i.Quantity < 0)
                               .Select(i => new LotKey(i).KeyValue)
                               .Distinct().ToList();

            if (negativeLots.Any())
            {
                return(new InvalidResult(string.Format(UserMessages.NegativeInventoryLots, negativeLots.Aggregate((string)null, (c, n) => string.Format("{0}{1}", c == null ? "" : ", ", n)))));
            }

            return(new SuccessResult());
        }
        internal IResult <IntraWarehouseOrder> Create(DateTime timestamp, ICreateIntraWarehouseOrderParameters parameters)
        {
            var orderResult = GetUpdatedOrder(timestamp, null, parameters);

            if (!orderResult.Success)
            {
                return(orderResult);
            }
            var order = orderResult.ResultingObject;

            order.TrackingSheetNumber = parameters.TrackingSheetNumber;

            if (parameters.PickedItems == null || !parameters.PickedItems.Any())
            {
                return(new InvalidResult <IntraWarehouseOrder>(null, UserMessages.PickedItemsManifestRequired));
            }

            var items = parameters.PickedItems.ToParsedParameters();

            if (!items.Success)
            {
                return(items.ConvertTo <IntraWarehouseOrder>());
            }

            var locationKey = items.ResultingObject.Select(i => new LocationKey(i.InventoryKey)).First();
            var location    = UnitOfWork.LocationRepository.FindByKey(locationKey, l => l.Facility.Locations);

            if (location == null)
            {
                return(new InvalidResult <IntraWarehouseOrder>(null, string.Format(UserMessages.LocationNotFound, locationKey)));
            }

            var locationKeys = location.Facility.Locations.Select(l => new LocationKey(l)).ToList();

            if (items.ResultingObject.Any(i => locationKeys.All(k => !k.Equals(i.InventoryKey)) || locationKeys.All(k => !k.Equals(i.CurrentLocationKey))))
            {
                return(new InvalidResult <IntraWarehouseOrder>(null, UserMessages.IntraWarehouseOrderDifferentWarehouses));
            }

            var pickedResult = UpdatePickedInventory(null, order.Employee, order.TimeStamp, order.PickedInventory, items.ResultingObject, true);

            if (!pickedResult.Success)
            {
                return(pickedResult.ConvertTo <IntraWarehouseOrder>());
            }

            var transactionParameters    = new InventoryTransactionParameters(order, order.TimeStamp, InventoryTransactionType.InternalMovement, order.TrackingSheetNumber.ToString());
            var createTransactionCommand = new CreateInventoryTransactionCommand(UnitOfWork);

            foreach (var item in items.ResultingObject)
            {
                var result = createTransactionCommand.Create(transactionParameters, item.InventoryKey, -item.Quantity);
                if (!result.Success)
                {
                    return(result.ConvertTo <IntraWarehouseOrder>());
                }

                result = createTransactionCommand.Create(transactionParameters, new InventoryKey(item.InventoryKey, item.InventoryKey, item.CurrentLocationKey, item.InventoryKey, item.InventoryKey.InventoryKey_ToteKey), item.Quantity);
                if (!result.Success)
                {
                    return(result.ConvertTo <IntraWarehouseOrder>());
                }
            }

            return(new SuccessResult <IntraWarehouseOrder>(order));
        }