public void OnUpdated(Shipment entity) { var orderItems = entity.ShipmentItems.Select(x => x.OrderItem).ToList(); foreach (var orderItem in orderItems) { _purchaseAccountant.EvaluateOrderStatus(orderItem.Order); } //if the shipment status is InTransit/Returned, that means we should update the inventory, as the item has been shipped/returned if (entity.ShipmentStatus == ShipmentStatus.InTransit || entity.ShipmentStatus == ShipmentStatus.Returned) { var warehouseId = entity.WarehouseId; var shippedProductIds = orderItems.Select(x => x.ProductId).ToList(); var inventories = _warehouseInventoryService.GetByProducts(shippedProductIds, warehouseId).ToList(); foreach (var shippedItem in entity.ShipmentItems) { var quantityShipped = shippedItem.Quantity; var shippedProductId = shippedItem.OrderItem.ProductId; var variantId = shippedItem.OrderItem.ProductVariantId; var inventory = shippedItem.OrderItem.ProductVariantId > 0 ? inventories.FirstOrDefault(x => x.ProductVariantId == variantId) : inventories.FirstOrDefault(x => x.ProductId == shippedProductId); if (inventory == null) { continue; //weird it's not there. but we can't do anything for this. something is wrong. this shouldn't have hit } if (entity.ShipmentStatus == ShipmentStatus.InTransit) { inventory.ReservedQuantity -= quantityShipped; inventory.TotalQuantity -= quantityShipped; } else { inventory.TotalQuantity += quantityShipped; } _warehouseInventoryService.Update(inventory); } } //update shipment history //get the history var shipmentHistoryItems = _shipmentStatusHistoryService.Get(x => x.ShipmentId == entity.Id).OrderByDescending(x => x.Id).ToList(); //if the current status is already there as the latest one, no need to do anything, if (shipmentHistoryItems.Any() && shipmentHistoryItems.First().ShipmentStatus == entity.ShipmentStatus) { return; } //we'll add this to the history now var shipmentHistory = new ShipmentHistory() { CreatedOn = DateTime.UtcNow, ShipmentStatus = entity.ShipmentStatus, ShipmentId = entity.Id }; _shipmentStatusHistoryService.Insert(shipmentHistory); }
/// <summary> /// Gets order fulfillments based on the following rules. /// - If all the products in an order are present in multiple warehouses, select a warehouse that has lowest order and can fulfill all the products /// - If all the products in an order are present in only one of the warehouses, select that warehouse irrespective of order /// - If some products are present in one warehouse and others are present in other warehouse, apply warehouse selection based on their order for each product. /// </summary> private IList <OrderFulfillment> GetAutoOrderFulfillments(Order order, OrderFulfillmentType orderFulfillmentType) { //the product ids for this order var productIds = order.OrderItems.Select(x => x.ProductId).Distinct().ToList(); var warehouseInventories = _warehouseInventoryService.GetByProducts(productIds).ToList(); var availableWarehouses = warehouseInventories.Select(x => x.Warehouse).Distinct().OrderBy(x => x.DisplayOrder).ToList(); var fulfillments = new List <OrderFulfillment>(); foreach (var warehouse in availableWarehouses) { var wInventories = warehouseInventories.Where(x => x.WarehouseId == warehouse.Id).ToList(); var warehouseCheckSuccess = true; foreach (var orderItem in order.OrderItems) { if (fulfillments.Any(x => x.OrderItemId == orderItem.Id && x.Quantity == orderItem.Quantity)) { continue; //do we already have fulfilled this item, yes and so skip the item now } WarehouseInventory warehouseInventory; if (orderItem.ProductVariantId > 0) { warehouseInventory = wInventories.FirstOrDefault(x => x.ProductVariantId == orderItem.ProductVariantId && x.AvailableQuantity >= orderItem.Quantity); //do we have any inventory for this variant in this warehouse, if not, we don't need to proceed if (warehouseInventory == null) { if (orderFulfillmentType == OrderFulfillmentType.WholeFromSingleWarehouse) { warehouseCheckSuccess = false; break; } } } else { warehouseInventory = wInventories.FirstOrDefault(x => x.ProductId == orderItem.ProductId && x.AvailableQuantity >= orderItem.Quantity); //do we have any inventory for this product in this warehouse, if not, we don't need to proceed if (warehouseInventory == null) { if (orderFulfillmentType == OrderFulfillmentType.WholeFromSingleWarehouse) { warehouseCheckSuccess = false; break; } } } //add only if fulfillment can be done if (warehouseInventory?.AvailableQuantity >= orderItem.Quantity) { fulfillments.Add(new OrderFulfillment() { Warehouse = warehouse, Order = order, OrderItem = orderItem, OrderId = order.Id, OrderItemId = orderItem.Id, Quantity = orderItem.Quantity, WarehouseId = warehouse.Id, Verified = false, WarehouseInventory = warehouseInventory }); } else { warehouseCheckSuccess = false; break; } } if (!warehouseCheckSuccess) { if (orderFulfillmentType == OrderFulfillmentType.WholeFromSingleWarehouse) { fulfillments.Clear(); //avoid the fulfillment by this warehouse } } else { return(fulfillments); //we got the warehouse, so return } } return(fulfillments); }