Microsoft have created an excellent description of this in the Assortment management doc-page. Retail assortments are essential to define what products that should be available across retail channels. Assigning a product to an assortment, will assign the product to the stores that have the assortment. This makes it possible to sell the product in the store.
But there is something missing, and that is to use assortments for replenishment and procurement. Retailers want the master planning to only suggest procurement and transfers on products that belongs to the stores assortments. You can control requirement parameters per warehouse, but there is no standard way to use the assortment to control the generation of planned orders.
This blog post is to show how to make a very small extension that allows you to make sure that only products that belongs to a stores assortment will generate planned orders. The solution I will make use of is to look into how the product lifecycle state functionality is working, and extend this with an assortment planning parameter. I have called this parameter “Is lifecycle state active for assortment procurement”
What it will do, is to validate if a product is in the assortment of the store, and if it is, then the product will be requirement calculated and will generate planned orders. If the product is not in the assortment of the store, that no planned orders will be generated.
To make this happen, I needed to create 4 extensions. The three first is adding a new field on the product lifecycle form. For an experienced developer this is easy to create, and no need to spend time on in this this blog-post.
The real fun is how to manage and control the planned order generation. This happens in in an extension to the ReqSetupDim class. Here there is a lookup to the assortment on the product, and checks if the store have this assortment. If not, then the masterplanning will not generate any planned orders. I therefore create an extention class and use the new method wrapping/CoC feature to add some additional code.
/// Contains extension methods for the ReqSetupDim class.
final class ReqSetupDim_extension
/// Validates if a product should be assortment planned
/// The parm of the ReqSetupDim class.
/// false if the product is not assortment planned; otherwise, return default value.
public boolean mustReqBeCreated(InventDim _inventDimComplete)
Boolean ret = next mustReqBeCreated(_inventDimComplete);
//Fetching fields from inventtable
select firstonly ProductLifecycleStateId, Product from inventtable where inventtable.ItemId == this.itemId();
//validating if the product is active for planning and that also assortment planning is enabled.
select firstonly RecId from ecoResProductLifecycleState
where ecoResProductLifecycleState.IsActiveForAssortmentPlanning == true
&& ecoResProductLifecycleState.IsActiveForPlanning == true
&& ecoResProductLifecycleState.StateId == inventtable.ProductLifecycleStateId;
//Finding OMOperatingUnitID from the inventlocationId
while select firstonly OMOperatingUnitID from store
where store.inventlocation == inventdim.InventLocationId
//Check if the product is in the assortment of the store in question
select RecId from product
where product.RecId == inventtable.product
exists join assortmentLookupInclude
where assortmentLookupInclude.ProductId == product.RecId
&& assortmentLookupInclude.lineType == RetailAssortmentExcludeIncludeType::Include
exists join assortmentLookupChannelGroupInclude
where assortmentLookupChannelGroupInclude.OMOperatingUnitId == store.OMOperatingUnitID
&& assortmentLookupChannelGroupInclude.AssortmentId == assortmentLookupInclude.AssortmentId
notexists join assortmentLookupExclude
where assortmentLookupExclude.ProductId == product.RecId
&& assortmentLookupExclude.lineType == RetailAssortmentExcludeIncludeType::Exclude
exists join assortmentLookupChannelGroupExclude
where assortmentLookupChannelGroupExclude.OMOperatingUnitId == store.OMOperatingUnitID
&& assortmentLookupChannelGroupExclude.AssortmentId == assortmentLookupExclude.AssortmentId;
ret = false; //The product does NOT belong to the stores assortment, and should not be planned
I also have code to restrict creation of manual purchase orders, and where simular code can be used, but let’s hope that Microsoft can further extend standard Dynamics 365 with assortment based procurement planning.
Copy with pride, and let’s hope next year will give us 365 more opertunities.