This article covers implementing multi-warehouse logic as described here: https://world.episerver.com/documentation/developer-guides/commerce/warehouses-and-inventories/Multi-warehouse-implementations/
In the paragraph "Disable the lockout“ – there is a recommendation to replace the existing method CheckMultiWarehouse.
When overriding the CheckMultiWarehouse it is never called. It still uses the OrderGroupActivityBase class not the custom class.
Because OrderGroupActivity class is the base class.
In the documentation: "To allow multiple fulfillment warehouses, replace the existing method with the following:" protected virtualvoid CheckMultiWarehouse(){}
They make their own OrderGroupActivityBase class
Example:
public abstract class HpOrderGroupActivityBase: OrderGroupActivityBase
{
protected override IWarehouse CheckMultiWarehouse()
{
...
}
}
A lot of other classes use OrderGroupActivity. For example AdjustInventoryActivity class.
The problem: OrderGoupActivityBase is still used. Not the HpOrderGroupActivityBase class.
For example ProcessShipmentsActivity class still uses OrderGroupActivityBase not the HpOrderGroupActivityBaseclass.
The biggest problem is that we can’t see the way to replace the CheckMultWarehouse method,
because classes like ProcessShipmentsActivity extends the OrderGroupActivityBase class.
For example:
public class ProcessShipmentsActivity : OrderGroupActivityBase{...}
The solution is to use IFulfillmentWarehouseProcessor
The default processor
namespace EPiServer.Commerce.Order
{
/// <summary>
/// Gets <see cref="IWarehouse"/> for <see cref="IShipment"/>.
/// </summary>
[ServiceConfiguration(ServiceType = typeof(IFulfillmentWarehouseProcessor), Lifecycle = ServiceInstanceScope.Singleton)]
public class DefaultFulfillmentWarehouseProcessor : IFulfillmentWarehouseProcessor
...does
private IWarehouse CheckMultiWarehouse()
{
var warehouses = _warehouseRepository.List()
.Where(w => w.IsActive && w.IsFulfillmentCenter)
.ToList();
if (warehouses.Count() > 1)
{
throw new NotSupportedException("Multiple fulfillment centers without custom fulfillment process.");
}
return warehouses.SingleOrDefault();
}
So our current default implementation is
using EPiServer.ServiceLocation;
using Mediachase.Commerce.Inventory;
using Mediachase.Commerce.Orders.Managers;
using System;
using System.Linq;
namespace EPiServer.Commerce.Order
{
/// <summary>
/// Gets <see cref="IWarehouse"/> for <see cref="IShipment"/>.
/// </summary>
[ServiceConfiguration(ServiceType = typeof(IFulfillmentWarehouseProcessor), Lifecycle = ServiceInstanceScope.Singleton)]
public class DefaultFulfillmentWarehouseProcessor : IFulfillmentWarehouseProcessor
{
private readonly IWarehouseRepository _warehouseRepository;
public DefaultFulfillmentWarehouseProcessor(IWarehouseRepository warehouseRepository)
{
_warehouseRepository = warehouseRepository;
}
public IWarehouse GetFulfillmentWarehouse(IShipment shipment)
{
if (shipment == null)
{
return CheckMultiWarehouse();
}
IWarehouse warehouse;
if (!string.IsNullOrEmpty(shipment.WarehouseCode))
{
warehouse = _warehouseRepository.Get(shipment.WarehouseCode);
if (warehouse == null)
{
return null;
}
if (CanBeFulfilled(warehouse, shipment) || warehouse.IsPickupLocation)
{
return warehouse;
}
return null;
}
warehouse = GetPickupLocation(shipment);
return warehouse ?? GetDefaultFulfillmentWarehouse(shipment);
}
private IWarehouse GetPickupLocation(IShipment shipment)
{
if (shipment.ShippingMethodId == Guid.Empty)
{
return null;
}
var shippingMethod = ShippingManager.GetShippingMethod(shipment.ShippingMethodId).ShippingMethod.FirstOrDefault();
if (shippingMethod == null || !ShippingManager.IsHandoffShippingMethod(shippingMethod.Name))
{
return null;
}
if (shipment.ShippingAddress == null)
{
return null;
}
var pickupWarehouse = ShippingManager.GetHandoffLocationFromAddressName(shipment.ShippingAddress.Id);
if (pickupWarehouse == null || (!string.IsNullOrEmpty(shipment.WarehouseCode) && (pickupWarehouse.Code != shipment.WarehouseCode)))
{
return null;
}
if (!pickupWarehouse.IsActive || (!pickupWarehouse.IsPickupLocation && !pickupWarehouse.IsDeliveryLocation))
{
return null;
}
return pickupWarehouse;
}
private bool CanBeFulfilled(IWarehouse warehouse, IShipment shipment)
{
if (!warehouse.IsActive || (!warehouse.IsFulfillmentCenter && !warehouse.IsPickupLocation && !warehouse.IsDeliveryLocation))
{
return false;
}
if (shipment.ShippingMethodId == Guid.Empty)
{
return true;
}
var shippingMethod = ShippingManager.GetShippingMethod(shipment.ShippingMethodId).ShippingMethod.FirstOrDefault();
if (shippingMethod != null && ShippingManager.IsHandoffShippingMethod(shippingMethod.Name))
{
return false;
}
return true;
}
private IWarehouse GetDefaultFulfillmentWarehouse(IShipment shipment)
{
var defaultWarehouse = CheckMultiWarehouse();
if (defaultWarehouse == null)
{
return null;
}
return CanBeFulfilled(defaultWarehouse, shipment)
? defaultWarehouse
: null;
}
private IWarehouse CheckMultiWarehouse()
{
var warehouses = _warehouseRepository.List()
.Where(w => w.IsActive && w.IsFulfillmentCenter)
.ToList();
if (warehouses.Count() > 1)
{
throw new NotSupportedException("Multiple fulfillment centers without custom fulfillment process.");
}
return warehouses.SingleOrDefault();
}
}
}
Please sign in to leave a comment.