/// <inheritdoc /> public async Task <IList <Lot> > TryGetAdjustedLots( ISalesOrderWorkItemRepository salesOrderWorkItemRepository, string salesOrderNumber, string salesOrderItemNumber ) { try { var lots = await _repository.ReadAllAsync(item => item.ItemNumber == salesOrderItemNumber).ConfigureAwait(false); var adjustmentTasks = lots.Select(lot => AdjustLot( salesOrderWorkItemRepository, salesOrderNumber, lot )); return(await Task.WhenAll(adjustmentTasks)); } catch (Exception ex) { _logService.WriteErrorLogEntry($"Failed to read lots: {ex}"); ex.Report(); return(new List <Lot>()); } }
/// <summary> /// Filter deliver sales order that has yet to be picked. /// </summary> /// <param name="salesOrderWorkItemRepository"></param> /// <param name="salesOrder"></param> /// <returns></returns> private async Task <SalesOrder> FilterUnPickedSalesOrder( ISalesOrderWorkItemRepository salesOrderWorkItemRepository, SalesOrder salesOrder ) { var atLeastOneItemPicked = await AtLeastOneSalesOrderWorkItemHasBeenPicked( salesOrderWorkItemRepository, salesOrder.SalesOrderNumber ); if (!atLeastOneItemPicked) { return(null); } // The quantity is fulfilled, check the status of the work items. var allWorkItemsArePicked = await SalesOrderItemsAreAllOfStatus( salesOrderWorkItemRepository, salesOrder.SalesOrderNumber, SalesOrderWorkItemStatus.Picked ).ConfigureAwait(false); return(allWorkItemsArePicked // All of the work item statuses were picked meaning could be displayed in Deliver. ? salesOrder // Sales order pick has yet to be confirmed. : null); }
public DashboardViewModel( IServiceBundle serviceBundle, ISalesOrderRepository salesOrderRepository, IInboundShipmentRepository inboundShipmentRepository, ISalesOrderWorkItemRepository salesOrderWorkItemRepository, ISalesOrderItemRepository salesOrderItemRepository, IInboundTransferRepository inboundTransferRepository, IConfigurationService configurationService, ICloudService cloudService, INetworkService networkService, ISyncService syncService, ILogService logService ) : base(serviceBundle) { _configurationService = configurationService; _cloudService = cloudService; _networkService = networkService; _syncService = syncService; _logService = logService; _salesOrderRepository = salesOrderRepository; _inboundShipmentRepository = inboundShipmentRepository; _salesOrderWorkItemRepository = salesOrderWorkItemRepository; _salesOrderItemRepository = salesOrderItemRepository; _inboundTransferRepository = inboundTransferRepository; SubscribeToEvents(); }
/// <inheritdoc /> public async Task <int> TryGetUnfulfilledDeliveryCount( ISalesOrderWorkItemRepository salesOrderWorkItemRepository, Expression <Func <SalesOrder, bool> > filter = null ) => (await TryGetUnfulfilledDeliveries( salesOrderWorkItemRepository, filter ).ConfigureAwait(false)).Count;
/// <summary> /// Adjust the provided SalesOrderItem instance by taking existing SalesOrderWorkItem /// instances into account. /// </summary> /// <param name="salesOrderWorkItemRepository">An ISalesOrderWorkItemRepository instance.</param> /// <param name="salesOrderItem">The SalesOrderWorkItem instance to adjust.</param> /// <param name="salesOrderItemLotNumber">The lot number of the sales order item.</param> /// <returns> /// An asynchronous Task that returns an adjusted SalesOrderWorkItem instance upon completion. /// </returns> private static async Task <SalesOrderItem> AdjustSalesOrderItem( ISalesOrderWorkItemRepository salesOrderWorkItemRepository, SalesOrderItem salesOrderItem, string salesOrderItemLotNumber ) { var workItems = await salesOrderWorkItemRepository.TryGetSalesOrderWorkItems( salesOrderItem.SalesOrderNumber, salesOrderItem.ItemNumber, salesOrderItemLotNumber ).ConfigureAwait(false); // Need to filter the workitems by OriginalSequence becuase we could have duplicate sales order items... workItems = workItems.Where(item => item.OriginalSequence == salesOrderItem.Seq).ToList(); var workItemSum = workItems.Sum(i => i.PickedQuantity); var workItemDeltaSum = workItems.Sum(i => i.QuantityDelta); var accountedForQuantity = workItemSum + workItemDeltaSum; // All items accounted for set item quantity to 0. if (accountedForQuantity == salesOrderItem.ItemQuantity) { salesOrderItem.ItemQuantity = 0; return(salesOrderItem); } salesOrderItem.ItemQuantity -= workItemSum + workItemDeltaSum; return(salesOrderItem); }
public LotSelectionViewModel( IServiceBundle serviceBundle, ILotRepository lotRepository, ISalesOrderWorkItemRepository salesOrderWorkItemRepository ) : base(serviceBundle) { _lotRepository = lotRepository; _salesOrderWorkItemRepository = salesOrderWorkItemRepository; }
public DeliverViewModel( IServiceBundle serviceBundle, ISalesOrderWorkItemRepository salesOrderWorkItemRepository, ISalesOrderRepository salesOrderRepository ) : base(serviceBundle) { _salesOrderWorkItemRepository = salesOrderWorkItemRepository; _salesOrderRepository = salesOrderRepository; }
public DeliverSalesOrderWorkItemDetailsViewModel( IServiceBundle serviceBundle, ISalesOrderWorkItemRepository salesOrderWorkItemRepository, ILogService logService ) : base(serviceBundle) { _salesOrderWorkItemRepository = salesOrderWorkItemRepository; _logService = logService; }
/// <inheritdoc /> public async Task <bool> CanBatchConfirmSalesOrderPick( ISalesOrderWorkItemRepository salesOrderWorkItemRepository, ISalesOrderItemRepository salesOrderItemRepository, string salesOrderNumber ) => (await salesOrderItemRepository.TryGetAdjustedSalesOrderItems( salesOrderWorkItemRepository, salesOrderNumber ).ConfigureAwait(false)) // We are only concerned with items that had to have their lot number explicitly set. .Where(i => i.IsLotControlled && string.IsNullOrWhiteSpace(i.LotNumber)) // The remaining item quantity for these items must sum to zero if they can be batch confirmed. .Sum(i => i.ItemQuantity) == 0;
public SalesOrderDetailsEditViewModel( IServiceBundle serviceBundle, ISalesOrderWorkItemRepository salesOrderWorkItemRepository, ISalesOrderItemRepository salesOrderItemRepository, ISalesOrderRepository salesOrderRepository, ILotRepository lotRepository ) : base(serviceBundle) { _salesOrderWorkItemRepository = salesOrderWorkItemRepository; _salesOrderItemRepository = salesOrderItemRepository; _salesOrderRepository = salesOrderRepository; _lotRepository = lotRepository; }
/// <inheritdoc /> public async Task <bool> IsSalesOrderQuantityFulfilled( ISalesOrderWorkItemRepository salesOrderWorkItemRepository, ISalesOrderItemRepository salesOrderItemRepository, string salesOrderNumber ) { var adjustedItems = await salesOrderItemRepository.TryGetAdjustedSalesOrderItems( salesOrderWorkItemRepository, salesOrderNumber ).ConfigureAwait(false); return(adjustedItems.Sum(i => i.ItemQuantity) <= 0); }
public PickViewModel( IServiceBundle serviceBundle, ISalesOrderWorkItemRepository salesOrderWorkItemRepository, ISalesOrderItemRepository salesOrderItemRepository, ISalesOrderRepository salesOrderRepository, ILogService logService ) : base(serviceBundle) { _salesOrderWorkItemRepository = salesOrderWorkItemRepository; _salesOrderItemRepository = salesOrderItemRepository; _salesOrderRepository = salesOrderRepository; _logService = logService; }
/// <summary> /// Batch confirm the sales order pick if possible. This will fulfill all sales order items that /// are lot controlled and have their lot numbers set. This make it easier on the user so they don't /// have to go into each sales order item and confirm it explicitly. /// </summary> /// <param name="salesOrderWorkItemRepository">An ISalesOrderWorkItemRepository instance.</param> /// <param name="salesOrderItemRepository">An ISalesOrderItemRepository instance.</param> /// <param name="salesOrderNumber">The sales order number.</param> /// <param name="lotRepository">An ILotRepository instance.</param> /// <returns> /// An asynchronous Task that returns whether or not the batch confirm was successful. /// </returns> private async Task <bool> BatchConfirmSalesOrderPick( ISalesOrderWorkItemRepository salesOrderWorkItemRepository, ISalesOrderItemRepository salesOrderItemRepository, ILotRepository lotRepository, string salesOrderNumber ) { // Check if we can batch confirm the sales order. var canBatchConfirm = await CanBatchConfirmSalesOrderPick( salesOrderWorkItemRepository, salesOrderItemRepository, salesOrderNumber ); // Can't batch confirm, do nothing. if (!canBatchConfirm) { return(false); } // Only lot controlled items with their lot numbers set from Cresco should remain. var adjustedItems = (await salesOrderItemRepository.TryGetAdjustedSalesOrderItems( salesOrderWorkItemRepository, salesOrderNumber ).ConfigureAwait(false)) // We only want lot controlled items with remaining quantities. These will unconfirmed // read-only items pulled down from Cresco. .Where(i => i.IsLotControlled && !string.IsNullOrWhiteSpace(i.LotNumber) && i.ItemQuantity != 0 || (!i.IsLotControlled && i.ItemQuantity != 0) ).ToList(); // Create a work item for each sales order that was lot controlled with a lot number set. await Task.WhenAll(adjustedItems.Select(item => salesOrderWorkItemRepository.TryUpsertSalesOrderWorkItem( this, salesOrderItemRepository, lotRepository, SalesOrderWorkflow.Pick, salesOrderNumber, item.ItemNumber, item.Seq, item.LotNumber, item.LotNumber, item.ItemQuantity, item.ItemQuantity, item.ItemQuantity ))); return(true); }
public async Task IssueDeliveryNotification( ISalesOrderWorkItemRepository salesOrderWorkItemRepository, ISalesOrderRepository salesOrderRepository, string salesOrderNumber, bool sendToCustomer, bool sendToSalesRep ) { var salesOrder = await salesOrderRepository.TryGetSalesOrder(salesOrderNumber).ConfigureAwait(false); if ( salesOrder == null || (string.IsNullOrWhiteSpace(salesOrder.SalesRepMobileNumber) && (string.IsNullOrWhiteSpace(salesOrder.CustomerMobileNumber))) ) { return; } var workItems = await salesOrderWorkItemRepository.TryGetSalesOrderWorkItems(salesOrderNumber).ConfigureAwait(false); // No work items (weird), do nothing. if (workItems.Count == 0) { return; } var notesWorkItemTable = await PinnacleApp.Get <ICloudService>().GetTableAsync <NoteWorkItem>(); var noteItems = (await notesWorkItemTable.ReadItemsAsync( 0, int.MaxValue, item => item.NoteParentFk == salesOrderNumber ).ConfigureAwait(false)).ToList(); var salesOrderDelivery = BuildDeliveryRecord(salesOrder, workItems, noteItems, sendToCustomer, sendToSalesRep); var deliveryString = JsonConvert.SerializeObject(salesOrderDelivery); if (_networkService.IsConnected) { //await SendMessage(deliveryString).ConfigureAwait(false); await ProcessUnsentDeliveryNotification().ConfigureAwait(false); } else { await _salesOrderDeliveryRepository.CreateAsync(new SalesOrderDeliveryString { Body = deliveryString }).ConfigureAwait(false); } }
public SalesOrderDetailsViewModel( IServiceBundle serviceBundle, ISalesOrderRepository salesOrderRepository, ISalesOrderItemRepository salesOrderItemRepository, ISalesOrderWorkItemRepository salesOrderWorkItemRepository, ILotRepository lotRepository, ISyncService syncService ) : base(serviceBundle) { _salesOrderRepository = salesOrderRepository; _salesOrderItemRepository = salesOrderItemRepository; _salesOrderWorkItemRepository = salesOrderWorkItemRepository; _lotRepository = lotRepository; _syncService = syncService; }
/// <inheritdoc /> public async Task <Lot> TryGetLotAdjusted( ISalesOrderWorkItemRepository salesOrderWorkItemRepository, string salesOrderNumber, string lotNumber, string salesOrderItemNumber ) { var lot = await TryGetLot(lotNumber, salesOrderItemNumber).ConfigureAwait(false); return(await AdjustLot( salesOrderWorkItemRepository, salesOrderNumber, lot ).ConfigureAwait(false)); }
public SubmitViewModel( IServiceBundle serviceBundle, ILogService logService, ICloudService cloudService, IInboundTransferRepository inboundTransferRepository, IInboundShipmentRepository inboundShipmentRepository, ISalesOrderWorkItemRepository salesOrderWorkItemRepository ) : base(serviceBundle) { _logService = logService; _cloudService = cloudService; _inboundTransferRepository = inboundTransferRepository; _inboundShipmentRepository = inboundShipmentRepository; _salesOrderWorkItemRepository = salesOrderWorkItemRepository; }
public DeliverSalesOrderConfirmViewModel( IServiceBundle serviceBundle, ISalesOrderWorkItemRepository salesOrderWorkItemRepository, ISignatureWorkItemRepository signatureWorkItemRepository, ISalesOrderRepository salesOrderRepository, ISalesOrderDeliveryNotificationRepository salesOrderDeliveryNotificationRepositoy, ISyncService syncService ) : base(serviceBundle) { _salesOrderWorkItemRepository = salesOrderWorkItemRepository; _signatureWorkItemRepository = signatureWorkItemRepository; _salesOrderRepository = salesOrderRepository; _salesOrderDeliveryNotificationRepositoy = salesOrderDeliveryNotificationRepositoy; _syncService = syncService; }
/// <summary> /// Determine if any of the work items related to a sales order number have /// been picked. This is done using the PickedWhen property. /// </summary> /// <param name="salesOrderWorkItemRepository">An ISalesOrderWorkItemRepository instance.</param> /// <param name="salesOrderNumber">The sales order number of the order to check.</param> /// <returns>If at least one picked, true. Else, false.</returns> private async Task <bool> AtLeastOneSalesOrderWorkItemHasBeenPicked( ISalesOrderWorkItemRepository salesOrderWorkItemRepository, string salesOrderNumber ) { if (string.IsNullOrWhiteSpace(salesOrderNumber)) { return(false); } var workItems = await salesOrderWorkItemRepository.TryGetSalesOrderWorkItems( salesOrderNumber ); return(workItems.Any(i => i.PickedWhen != null)); }
/// <inheritdoc /> private async Task <bool> PickedSalesOrderItemsHaveLocationSet( ISalesOrderWorkItemRepository salesOrderWorkItemRepository, string salesOrderNumber ) { if (string.IsNullOrWhiteSpace(salesOrderNumber)) { return(false); } var workItems = await salesOrderWorkItemRepository.TryGetSalesOrderWorkItems( salesOrderNumber ).ConfigureAwait(false); return(workItems.Count > 0 && workItems.All(item => (item.PickedLatitude != 0.0) && (item.PickedLongitude != 0.0))); }
/// <inheritdoc /> public async Task <bool> CompleteSalesOrderDelivery( ISalesOrderWorkItemRepository salesOrderWorkItemRepository, ISignatureWorkItemRepository signatureWorkItemRepository, bool isDriverSignature, string salesOrderNumber, string encodedSignature, bool sendNotification = true ) { // Signature is required, do nothing. if (string.IsNullOrWhiteSpace(encodedSignature)) { return(false); } var workItems = await salesOrderWorkItemRepository.TryGetSalesOrderWorkItems(salesOrderNumber).ConfigureAwait(false); // No work items (weird), do nothing. if (workItems.Count == 0) { return(false); } var position = await _locationService.GetPositionAsync().ConfigureAwait(false); var userId = _configurationService.GetString(Constants.Config.UserId); // Set all sales order work item instances to delivered state. await Task.WhenAll(workItems.Select(item => SetSalesOrderWorkItemToDelivered( salesOrderWorkItemRepository, item, position, userId ))); // Create a new SignatureWorkItem instance. await signatureWorkItemRepository.TryCreateSignatureWorkItem(new SignatureWorkItem { SalesOrderNumber = salesOrderNumber, EncodedSignatureImage = encodedSignature, IsDriverSignature = isDriverSignature, SendNotification = sendNotification }).ConfigureAwait(false); return(true); }
/// <inheritdoc /> public async Task ConfirmSalesOrderPick( ISalesOrderWorkItemRepository salesOrderWorkItemRepository, ISalesOrderItemRepository salesOrderItemRepository, ILotRepository lotRepository, SalesOrder salesOrder ) { var canBatchConfirm = await CanBatchConfirmSalesOrderPick( salesOrderWorkItemRepository, salesOrderItemRepository, salesOrder.SalesOrderNumber ).ConfigureAwait(false); // We can batch confirm so do it. if (canBatchConfirm) { await BatchConfirmSalesOrderPick( salesOrderWorkItemRepository, salesOrderItemRepository, lotRepository, salesOrder.SalesOrderNumber ).ConfigureAwait(false); } var isFulfilled = await IsSalesOrderQuantityFulfilled( salesOrderWorkItemRepository, salesOrderItemRepository, salesOrder.SalesOrderNumber ).ConfigureAwait(false); // Sales order is not fulfilled, do nothing. if (!isFulfilled) { return; } // Get the device position. var position = await _locationService.GetPositionAsync().ConfigureAwait(false); // Set all of the work items to picked along with the device location. await salesOrderWorkItemRepository.TryConfirmSalesOrderWorkItems( salesOrder.SalesOrderNumber, position ).ConfigureAwait(false); }
/// <inheritdoc /> public async Task <IList <SalesOrderItem> > TryGetAdjustedSalesOrderItems( ISalesOrderWorkItemRepository salesOrderWorkItemRepository, string salesOrderNumber ) { var salesOrderItems = await TryGetSalesOrderItems(salesOrderNumber).ConfigureAwait(false); var adjustmentTasks = salesOrderItems .Select(async item => await AdjustSalesOrderItem( salesOrderWorkItemRepository, item, item.LotNumber ).ConfigureAwait(false)); return(await Task.WhenAll( adjustmentTasks )); }
/// <inheritdoc /> public async Task <bool> SalesOrderItemsAreAllOfStatus( ISalesOrderWorkItemRepository salesOrderWorkItemRepository, string salesOrderNumber, SalesOrderWorkItemStatus status ) { if (string.IsNullOrWhiteSpace(salesOrderNumber)) { return(false); } var workItems = await salesOrderWorkItemRepository.TryGetSalesOrderWorkItems( salesOrderNumber ).ConfigureAwait(false); return(workItems.Count > 0 && workItems.All(item => item.Status == status)); }
/// <summary> /// Adjust the provided Lot instance using any existing work items. /// </summary> /// <param name="salesOrderWorkItemRepository">An ISalesOrderWorkItemRepository instance.</param> /// <param name="salesOrderNumber">The sales order number.</param> /// <param name="lot">The lot.</param> /// <returns>An asynchronous Task that returns an adjusted Lot on completion.</returns> private static async Task <Lot> AdjustLot( ISalesOrderWorkItemRepository salesOrderWorkItemRepository, string salesOrderNumber, Lot lot ) { if (lot == null) { return(null); } var salesOrderWorkItems = (await salesOrderWorkItemRepository.TryGetSalesOrderWorkItems( salesOrderNumber, lot.ItemNumber )).Where(i => i.LotNumber == lot.LotNumber); // Adjust the lot quantity by subtracting the sum of sales order work item quantities. lot.Quantity -= salesOrderWorkItems.Sum(i => i.PickedQuantity); return(lot); }
/// <inheritdoc /> public async Task <IList <SalesOrder> > TryGetUnfulfilledPicks( ISalesOrderWorkItemRepository salesOrderWorkItemRepository, ISalesOrderItemRepository salesOrderItemRepository, Expression <Func <SalesOrder, bool> > filter = null ) { // Get all sales orders var salesOrders = filter == null ? await _repository.ReadAllAsync().ConfigureAwait(false) : await _repository.ReadAllAsync(filter).ConfigureAwait(false); var result = await Task.WhenAll(salesOrders.Select(async s => await FilterUnfulfilledSalesOrderPick( salesOrderWorkItemRepository, salesOrderItemRepository, s ))); return(result .Where(i => i != null) .ToList()); }
/// <summary> /// Set the provided SalesOrderWorkItem insance to delivered. This is done by updating the /// item delivered latitude and longitude properties as well as its status. /// </summary> /// <param name="salesOrderWorkItemRepository">An ISalesOrderWorkItemRepository instnace.</param> /// <param name="salesOrderWorkItem">The item to set as delivered.</param> /// <param name="position">The location of the device at the time of delivery.</param> /// <returns>An asynchronous Task.</returns> private static async Task SetSalesOrderWorkItemToDelivered( ISalesOrderWorkItemRepository salesOrderWorkItemRepository, SalesOrderWorkItem salesOrderWorkItem, Location position, string deliveredByUser ) { salesOrderWorkItem.DeliveredLatitude = position?.Latitude ?? 0; salesOrderWorkItem.DeliveredLongitude = position?.Longitude ?? 0; salesOrderWorkItem.DeliveredBy = deliveredByUser; salesOrderWorkItem.DeliveredByName = PinnacleApp.Get <IAuthService>().CurrentUser.Name; salesOrderWorkItem.DeliveredWhen = DateTime.UtcNow; if (salesOrderWorkItem.DeliveredQuantity == 0) { salesOrderWorkItem.DeliveredQuantity = salesOrderWorkItem.PickedQuantity; } salesOrderWorkItem.Status = SalesOrderWorkItemStatus.Delivered; await salesOrderWorkItemRepository .TryUpdateSalesOrderWorkItem(salesOrderWorkItem).ConfigureAwait(false); }
/// <inheritdoc /> public async Task <IList <SalesOrder> > TryGetUnfulfilledDeliveries( ISalesOrderWorkItemRepository salesOrderWorkItemRepository, Expression <Func <SalesOrder, bool> > filter = null ) { // Get all sales orders var salesOrders = filter == null ? await _repository.ReadAllAsync().ConfigureAwait(false) : await _repository.ReadAllAsync(filter).ConfigureAwait(false); var filterResults = await Task.WhenAll(salesOrders.Select(async salesOrder => await FilterUnPickedSalesOrder( salesOrderWorkItemRepository, salesOrder ) )); return(filterResults .Where(salesOrder => salesOrder != null) .ToList()); }
/// <inheritdoc /> public async Task <SalesOrderItem> TryGetAdjustedSalesOrderItem( ISalesOrderWorkItemRepository salesOrderWorkItemRepository, string salesOrderNumber, string salesOrderItemNumber, string salesOrderItemLotNumber, int seq ) { var salesOrderItem = await TryGetSalesOrderItem( salesOrderNumber, salesOrderItemNumber, salesOrderItemLotNumber, seq ).ConfigureAwait(false); return(salesOrderItem == null ? null : await AdjustSalesOrderItem( salesOrderWorkItemRepository, salesOrderItem, salesOrderItemLotNumber ).ConfigureAwait(false)); }
/// <summary> /// Filter pick sales order that has yet to be fulfilled or confirmed. /// </summary> /// <param name="salesOrderWorkItemRepository"></param> /// <param name="salesOrderItemRepository"></param> /// <param name="salesOrder"></param> /// <returns></returns> private async Task <SalesOrder> FilterUnfulfilledSalesOrderPick( ISalesOrderWorkItemRepository salesOrderWorkItemRepository, ISalesOrderItemRepository salesOrderItemRepository, SalesOrder salesOrder ) { // TODO: THIS IS A HACK TO PREVENT WORK ITEMS FROM MOVING FROM DELIVER BACK TO PICK. // The reason this exists is because we don't have a way, or the time, to track the status // outside of the work items. What we really need to do is create a sales order table and // track the status seperately. var atLeastOneItemPicked = await AtLeastOneSalesOrderWorkItemHasBeenPicked( salesOrderWorkItemRepository, salesOrder.SalesOrderNumber ).ConfigureAwait(false); if (atLeastOneItemPicked) { return(null); } var isFulfilled = await IsSalesOrderQuantityFulfilled( salesOrderWorkItemRepository, salesOrderItemRepository, salesOrder.SalesOrderNumber ); // Quantity not fulfilled, return unfulfilled sales order. if (!isFulfilled) { return(salesOrder); } else { // Even if the quantities are fulfilled, we want to return the salesOrder // if the picked position is empty on any workitem var allPickedWorkItemsHaveLocation = await PickedSalesOrderItemsHaveLocationSet( salesOrderWorkItemRepository, salesOrder.SalesOrderNumber ).ConfigureAwait(false); if (!allPickedWorkItemsHaveLocation) { return(salesOrder); } } // The quantity is fulfilled, check the status of the work items. var allWorkItemsArePicked = await SalesOrderItemsAreAllOfStatus( salesOrderWorkItemRepository, salesOrder.SalesOrderNumber, SalesOrderWorkItemStatus.Picked ).ConfigureAwait(false); var allWorkItemsAreDelivered = await SalesOrderItemsAreAllOfStatus( salesOrderWorkItemRepository, salesOrder.SalesOrderNumber, SalesOrderWorkItemStatus.Delivered ).ConfigureAwait(false); return(allWorkItemsArePicked || allWorkItemsAreDelivered // All of the work item statuses were picked or delivered, meaning fulfilled. ? null // Sales order pick has yet to be confirmed. : salesOrder); }