public async Task <ActionResult <PurchaseOrderResponse> > PlaceOrder(List <OrderDto> orders, CancellationToken cancellationToken)
        {
            var orderId = Guid.NewGuid();
            var builder = new SharedUriBuilder(OrderActorServiceKey);

            // Calls Actor creation using unique order Id identifier
            var orderProxy = ActorProxy.Create <IOrderActor>(new ActorId(orderId), builder.ToUri());

            try
            {
                await orderProxy.SubmitOrderAsync(orders, cancellationToken);

                ServiceEventSource.Current.Message("Order has been submitted successfully. Actor with OrderId: {0} has been created", orderId);
            }
            catch (InvalidOperationException ex)
            {
                ServiceEventSource.Current.Message("Actor service: Actor rejected {0}: {1}", orders, ex);
                throw;
            }
            catch (Exception ex)
            {
                ServiceEventSource.Current.Message("Actor service: Exception {0}: {1}", orders, ex);
                throw;
            }

            return(new PurchaseOrderResponse
            {
                OrderId = orderId
            });
        }
        public async Task <ActionResult <AddInventoryResponse> > AddNew(
            AddInventoryRequest request,
            CancellationToken cancellationToken)
        {
            if (null == request?.Inventory)
            {
                throw new ArgumentNullException(nameof(request.Inventory));
            }

            AddInventoryResponse response;

            var builder = new SharedUriBuilder(InventoryServiceNameKey);
            var inventoryServiceClient = ServiceProxy.Create <IInventoryService>(builder.ToUri());

            try
            {
                var status = await inventoryServiceClient.CreateInventoryItemAsync(request.Inventory);

                response = new AddInventoryResponse {
                    Status = status
                };
            }
            catch (Exception ex)
            {
                ServiceEventSource.Current.Message("There are one or more errors while creating inventory {0}: {1}",
                                                   request.Inventory.Id, ex);
                throw;
            }

            return(response);
        }
        private async Task ExecuteOrderAsync()
        {
            await SetOrderStatusAsync(OrderStatusTypeDto.InProcess);

            var orderedItems = await StateManager.GetStateAsync <List <OrderDto> >(OrdersKey);

            ActorEventSource.Current.ActorMessage(this, "Executing customer order. ID: {0}. Items: {1}", Id.GetGuidId(), orderedItems.Count);

            foreach (var item in orderedItems)
            {
                ActorEventSource.Current.Message("Order contains:{0}", item);
            }

            // Throught all ordered items
            foreach (var item in orderedItems.Where(x => x.Remaining > 0))
            {
                var inventoryService = _serviceProxyFactory.CreateServiceProxy <IInventoryService>(_builder.ToUri());

                // Check the item is listed in inventory
                if (await inventoryService.IsItemInInventoryAsync(item.Item.Id, _tokenSource.Token) == false)
                {
                    await SetOrderStatusAsync(OrderStatusTypeDto.Canceled);

                    return;
                }

                var numberItemsRemoved =
                    await
                    inventoryService.RemoveStockAsync(
                        item.Item.Id,
                        item.Quantity,
                        new OrderActorMessageId(
                            new ActorId(Id.GetGuidId()),
                            await StateManager.GetStateAsync <long>(RequestIdPropertyKey)));

                item.Remaining -= numberItemsRemoved;
            }

            var items = await StateManager.GetStateAsync <IList <OrderDto> >(OrdersKey);

            bool backordered = false;

            // Set proper status
            foreach (var item in items)
            {
                if (item.Remaining > 0)
                {
                    backordered = true;
                    break;
                }
            }

            if (backordered)
            {
                await SetOrderStatusAsync(OrderStatusTypeDto.Backordered);
            }
            else
            {
                await SetOrderStatusAsync(OrderStatusTypeDto.Shipped);
            }

            ActorEventSource.Current.ActorMessage(
                this,
                "{0}; Executed: {1}. Backordered: {2}",
                await GetOrderStatusAsStringAsync(),
                items.Count(x => x.Remaining == 0),
                items.Count(x => x.Remaining > 0));

            long messageRequestId = await StateManager.GetStateAsync <long>(RequestIdPropertyKey);

            await StateManager.SetStateAsync(RequestIdPropertyKey, ++messageRequestId);
        }