public async Task ProceedNextOrderAsync() { if (_ordersQueue.Count == 0) { return; } OrderDto order = _ordersQueue.Dequeue(); if (order == null) { return; } await _orderService.ChangeOrderStateAsync(order, OrderStateDto.Assignment); //2. Change order state to Assignment PointDto orderLocationPoint = _pointService.GetOrderLocation(order.Id); //3. Get order destination point coordinates IEnumerable <CourierDto> couriers = _courierService.GetNearestCouriers(orderLocationPoint); //4. Find nearest couriers by next criterias (distance to point > number of assigned orders > courier state) var possibleCandidate = couriers.FirstOrDefault(courier => courier.State == CourierStateDto.Idle); if (possibleCandidate != null) { await _orderService.ChangeOrderStateAsync(order, OrderStateDto.WaitingOnWarehouse); await _courierService.AssignOrder(possibleCandidate.Id, order.Id); } else { RouteCandidate bestRoute = await FindBestCandidateAsync(couriers, orderLocationPoint); if (bestRoute == null) { await _orderService.ChangeOrderStateAsync(order, OrderStateDto.NotAssigned); _ordersQueue.Enqueue(order); } else { await _orderService.ChangeOrderStateAsync(order, OrderStateDto.WaitingOnWarehouse); await _courierService.AssignOrder(bestRoute.Courier.Id, order.Id); await _routeService.ChangeCourierCurrentRouteAsync(bestRoute.Courier.Id, bestRoute.GetRoute()); } } }