private List <StockReductionDto> GenerateStockReductions(FinalisedOrderDto order)
        {
            var stockReductionList = new List <StockReductionDto>();

            foreach (OrderedItemDto item in order.OrderedItems)
            {
                stockReductionList.Add(_mapper.Map <StockReductionDto>(item));
            }
            return(stockReductionList);
        }
 private bool ValidateOrder(FinalisedOrderDto order)
 {
     if (order == null || order.Total < 0)
     {
         return(false);
     }
     if (order.OrderedItems == null || order.OrderedItems.Count() == 0)
     {
         return(false);
     }
     foreach (OrderedItemDto item in order.OrderedItems)
     {
         if (!ValidateOrderedItem(item))
         {
             return(false);
         }
     }
     return(true);
 }
        public async Task <IActionResult> Create(FinalisedOrderDto order)
        {
            GetTokenDetails();
            if (!ValidateOrder(order))
            {
                return(UnprocessableEntity());
            }
            var customer = _mapper.Map <CustomerDto>(await _orderRepository.GetCustomer(order.CustomerId));

            if (customer == null || !customer.Active)
            {
                return(NotFound());
            }
            if ((role == "Customer" && customer.CustomerAuthId != authId) ||
                !ValidContactDetails(customer) ||
                !customer.CanPurchase)
            {
                return(Forbid());
            }
            if (!await _orderRepository.ProductsExist(_mapper.Map <List <ProductRepoModel> >(order.OrderedItems)))
            {
                return(NotFound());
            }
            if (!await _orderRepository.ProductsInStock(_mapper.Map <List <ProductRepoModel> >(order.OrderedItems)))
            {
                return(Conflict());
            }
            //reduce stock before creating order (it's worse customer service to allow a customer to order something out of stock
            //than for the company to innacurately display stock levels as lower than they are if an order fails
            var stockReductionList = GenerateStockReductions(order);

            if (!await _staffProductFacade.UpdateStock(stockReductionList))
            {
                return(NotFound());
            }
            order.OrderDate = ValidateDate(order.OrderDate);
            order.OrderId   = await _orderRepository.CreateOrder(_mapper.Map <FinalisedOrderRepoModel>(order));

            if (order.OrderId == 0)
            {
                return(NotFound());
            }
            if (!await _invoiceFacade.NewOrder(_mapper.Map <OrderInvoiceDto>(order)))
            {
                await _orderRepository.DeleteOrder(order.OrderId);

                return(NotFound());
            }
            PurchaseDto purchases = _mapper.Map <PurchaseDto>(order);

            purchases.CustomerAuthId = authId;
            if (!await _reviewFacade.NewPurchases(purchases))
            {
                //record to local db to attempt resend later
                //insufficient time to implement however system continues to function
                //customer service issue as customer cannot leave review
            }
            await _orderRepository.ClearBasket(order.CustomerId);

            //return ok regardless of if the basket successfully clears because the order is complete
            //better customer service than clearing basket only to have order fail and customer needs
            //to re-add everything to basket
            return(Ok());
        }