public async Task <AddOrderLineValidationResult> Execute(AddOrderLineCommand command)
        {
            if (command == null)
            {
                throw new ArgumentNullException(nameof(command));
            }

            if (string.IsNullOrWhiteSpace(command.ProductId))
            {
                return(new AddOrderLineValidationResult(string.Format(ErrorDescriptions.TheParameterIsMandatory, Constants.DtoNames.OrderLineNames.ProductId)));
            }

            var product = await _productRepository.Get(command.ProductId);

            if (product == null)
            {
                return(new AddOrderLineValidationResult(ErrorDescriptions.TheProductDoesntExist));
            }

            if (command.Quantity <= 0)
            {
                return(new AddOrderLineValidationResult(ErrorDescriptions.TheOrderLineQuantityIsInvalid));
            }

            if (command.Quantity > product.AvailableInStock)
            {
                return(new AddOrderLineValidationResult(ErrorDescriptions.TheOrderLineQuantityIsTooMuch));
            }

            var shop = await _shopRepository.Get(product.ShopId);

            if (shop == null)
            {
                return(new AddOrderLineValidationResult(ErrorDescriptions.TheShopDoesntExist));
            }

            if (shop.Subject == command.Subject)
            {
                return(new AddOrderLineValidationResult(ErrorDescriptions.TheProductCannotBeOrderedByYou));
            }


            return(new AddOrderLineValidationResult(product));
        }
        public async Task Handle(AddOrderLineCommand message)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            string id      = null;
            var    product = await _productRepository.Get(message.ProductId);

            var orders = await _orderRepository.Search(new SearchOrdersParameter
            {
                Shops   = new[] { product.ShopId },
                Clients = new[] { message.Subject },
                Status  = new[] { (int)OrderAggregateStatus.Created }
            });

            if (orders.Content.Count() > 1)
            {
                return;
            }


            var bestDiscountId = string.Empty; // Fetch the best discount.

            if (product.ActiveDiscounts != null && product.ActiveDiscounts.Any())
            {
                bestDiscountId = product.ActiveDiscounts.First(ad => ad.MoneySaved == product.ActiveDiscounts.Max(d => _discountPriceCalculatorHelper.CalculateMoneySaved(product, d))).Id;
            }

            if (orders.Content.Count() == 1) // Update existing order.
            {
                var order      = orders.Content.First();
                var orderLines = order.OrderLines.ToList();
                var orderLine  = orderLines.FirstOrDefault(l => l.ProductId == message.ProductId);
                if (orderLine == null)
                {
                    orderLine = new OrderAggregateLine
                    {
                        Id        = message.Id,
                        ProductId = message.ProductId,
                        Quantity  = message.Quantity
                    };
                    orderLines.Add(orderLine);
                }
                else
                {
                    orderLine.Quantity += message.Quantity;
                }

                order.OrderLines = orderLines;
                await _orderPriceCalculatorHelper.Update(order);

                await _orderRepository.Update(order);

                id = order.Id;
            }
            else // Add new order.
            {
                var newOrder = new OrderAggregate
                {
                    Id             = Guid.NewGuid().ToString(),
                    CreateDateTime = DateTime.UtcNow,
                    ShopId         = product.ShopId,
                    Subject        = message.Subject,
                    Status         = OrderAggregateStatus.Created,
                    UpdateDateTime = DateTime.UtcNow,
                    OrderLines     = new[]
                    {
                        new OrderAggregateLine
                        {
                            Id                = message.Id,
                            ProductId         = product.Id,
                            Quantity          = message.Quantity,
                            OrderLineDiscount = string.IsNullOrWhiteSpace(bestDiscountId) ? null : new OrderAggregateLineDiscount
                            {
                                Id = bestDiscountId
                            }
                        }
                    }
                };

                await _orderPriceCalculatorHelper.Update(newOrder);

                await _orderRepository.Insert(newOrder);

                id = newOrder.Id;
            }

            _eventPublisher.Publish(new OrderAddedEvent
            {
                CommonId    = message.CommonId,
                Subject     = message.Subject,
                OrderId     = id,
                OrderLineId = message.Id
            });
        }