Subcontracting with Warehouse management – Part 2

Subcontracting with Warehouse management – Part 2

Following up the 1st part of this blog series, let’s elaborate on the standard model of subcontracting promoted by Microsoft

Option 2: Subcontracting via Production order

The semi-finished product (here: M0070) has a BOM of its own. It includes all materials but also a service item (M0070_SC) for the value added by the subcontractor.

The service item drives the purchasing process with the subcontractor, is carries the purchase price of the service. We open a purchase order for a service, and provide components to the subcontractor which are either sent to the supplier from the main warehouse or procured directly to the supplier’s site. On the PO delivery note posting, the semi-finished product is received as an output of a sub-production order, it is then brought (“put away”) to the main warehouse, where it is picked for the master production order as a regular component.

The product structure transforms to a 2-level BOM:

Note that this time the service and the free issue material items belong to the same operation 5 which resides on an own route.

The standard process includes the following steps:

  1. The main order and the subcontracting order are either converted (firmed) from planned production orders, or the main order for D0003 is entered manually, then the estimation spawns the sub-production order automatically due to the type Vendor of the M0070 BOM line. The MRP explosion shows the following picture:
  2. With the firming/estimation of the sub-production order a purchase order for the service item M0070_SC is automatically generated by the system
  3. The purchase order is confirmed by the procurement department.
  4. The sub-production order is started from the screen Production / Subcontracted work. No materials or time may be consumed before this point.
  5. The transfer order for the free issue materials is released to the warehouse (it may be the same person who created and started the production order).
  6. The warehouse workers execute the picking work, confirm the TO shipment.
  7. The transfer order is getting shipped and received.

After a while the semi-finished product arrives at our doorstep. It is time to ‘receive’ the service. In standard Dynamics 365, this is not performed at a mobile scanner. Instead, a delivery note is posted against the purchase order. Thanks to the configuration described in first blog, this leads to an automatic consumption of the BOM and the route of the sub-production order. The system automatically:

– consumes both the materials delivered for free (M0071) and the service item M0070_SC itself,

– reports the route good quantity = purchase order quantity my means of a Route card journal, the same journal…

– …derives and posts a Report as finished journal which writes the semi-finished product in the stock ledger.

Normally, the last step – posting a RaF journal – is going to fail, because the license plate (SSCC pallet ID) is missing. To circumvent this, the special output location of the resource RECV-SUB can be given a “non-LP-controlled” location profile and assigned a “No putaway” work policy. This technique is described in detail in another blog of mine.

As a result, the received quantity of M0070 appears at the location 51/RECV-SUB with no license plate known and no production put-away work generated. A ‘fake’ put-away work may be triggered by the user with a special Movement by template menu item on the mobile device. The ‘from’ location in this menu item is pre-selected to RECV-SUB via the Default data setting of the menu item:

This menu item should be given a specific Directive code; a set of Location directives of the Inventory movement kind would react to this directive code and simulate the ‘put’ logic of a purchase order. The license plate number is scanned by the user during the movement. As a result of this movement, the pallet will land where it was supposed to be if we received the M0070 item from a purchase order (Option 1).

Now, the problem is that the step “Post purchase order delivery note” is not automated. Somebody needs to recognize the subcontracted PO as such, put aside the mobile device, open the rich Dynamics 365 interface and capture the quantity. In essence, this is an annoying deviation from the standard PO receipt process, a source of human error.

The suggested disruptive solution is a…

Warehouse-enabled service item

Astonishingly, it works: a service may be received on a license plate (pallet) in D365.

The stocked service item (Item model group -> Stocked product = Yes) should be given a WHS-enabled Storage dimension group with Use warehouse management process = Yes. Such an item participates in the master planning as long as it is assigned a Vendor-type BOM line, it does not have any on-hand stock at any given point in time, but it does record inventory transactions with all 5 mandatory WHS dimensions: Site, Warehouse, Location, Inventory status, License plate.

Provide the service item with the same unit, unit conversion factors, Unit sequence group, Reservation hierarchy as the subcontracted product it represents (here: M0070). Do not try to set the external supplier ID to the item number of M0070: the user would need to scan the real item ID (M0070_SC) at the baydoor.
Set the Output location of the subcontractor resource SUB_US-104 to the regular, LP-controlled location RECV. Here is what is going to happen on a timeline:

In practice, the consumption of M0070_SC in the below example will happen at the location 005 (the default WH production input location):
51/RECV +10 ea M0070_SC
51/005 -10 ea M0070_SC
This works even without the negative stock option set, because there is no such a thing as a service stock level: it is neither maintained nor controlled by the system. The location stock imbalance is not a problem for the inventory settlement and closing, because the location dimension is never a ‘financial’ one: the overall stock level at the warehouse level is zero, the (+) and (-) transactions will be settled and will mutually annihilate.

Subsequently, at the start of the sub-production order to the warehouse the system is going to say “The total quantity for production BOM XXXXXX could not be fulfilled. No work was created for wave USMF-YYYYYYYYY. See the work creation history log for details.”, because the item M0070_SC cannot be really picked, and this warning message can be safely ignored.

The scenario then continues as follows:

  1. The service from the purchase order is “received”, the license plate number is scanned or generated. Interestingly, the system does not build any put-away work for the item, probably because a service item cannot be reserved in any location.
  2. The delivery note (en-us: packing slip) posting should better be automated. In standard D365, this doesn’t work, because the batch mode posting requires a unique delivery note number. With a little customization this obstacle may be overcome by feeding the system with a fake delivery note number “DUMMY”. With the posting running in the batch mode and automatically updating every 2 minutes any purchase order with some quantity in the status Registered, this step may be fully automated:
  3. In standard D365 FO, the automatic posting of the picking list journal is going to fail because of the missing location (the Location dimension in the BOM of any WHS-enabled item is always empty, because it awaits a production order release to reserve at the location level according to the location directives, but a service cannot be reserved by definition), and the automatic posting of the Report as finished journals is going to ask for a license plate ID due to the LP-controlled location RECV. 2 little customizations outlined in the next chapter help: the service Licence plate ID propagates the production order and generates the RaF put-away work.
  4. The RaF put away location directives should be configured in exactly the same manner as the purchase order put-away locations. They can react to the M0070 item number or sense any other attribute of the sub-production order, such as a specific pool or a presence of a Vendor operation on the joined production route.The put-away work should be processed at the mobile device. A Print work line may be added to the Work template to print or re-print the pallet label which now has the proper Item ID: M0070 instead of the M0070_SC (beware that the Zebra ZPL printing language cannot carve a substring out of the printing stream or perform any other string manipulations).
  5. The semi-finished product is now placed in the main warehouse and the main production order may be reserved and released to the warehouse. A picking work for the subcontracted SFG is created.
  6. The picking work is performed at the mobile scanner:
  7. The main production order may be stated and the materials may be consumed with a Picking list in any eligible way.

ProdBOM table customization

The above scenario needs a little extension of the ProdBOM table:
– the location of the service may not remain empty. The method setInventDimId() has been extended to populate any WHS-enables service BOM line with the Default production input location of the warehouse. The location does not need to match the inbound location for the reasons described above.

– the license plate number of the service received with the purchase order should propagate the marked subcontracted production order. The method postVendorProdRoute() has been extended to write the service LP number right into the production order inventory dimensions. Obviously, this allows for the receipt of 1 pallet at a time, and updates the production order with the most recent license plate.

This does not contradict the current system logic though, as partial receipts can anyways only be enabled by an undocumented feature ProdJournalPostVendorProdBOMInOrderFeature:
This feature enables partial receipt of subcontracted items. Before, when reporting a partial quantity on a purchase order for a sub contracted service item, the full quantity was updated on the related picking list journal on the production order. Now, the correct partial received quantity is updated. This feature also fixes an issue with an incorrect updated scrap quantity when using BOM lines of type Vendor.

The source code can be downloaded here: ProdBOMLine_SubcontractingLicensePlate.axpp
Feel free to use, but I do not give any guarantees 😉

Conclusion, pros and contras

2 options have been presented:

Subcontracting via Purchase order

  • + A lightweight implementation can be easily adopted by the logistics department.
  • + It does not require any customizations.
  • – The raw material transfer to the subcontractor may be scheduled too late if we maintain the subcontracting lead time at the route operation level.
  • – The cost price of the semi-finished product only includes the cost of the subcontracting service, but not the materials. The standard price model will always show deviations.
  • – The free issue raw materials are only consumed at the next operation. On long-running orders this distorts the WIP value.

Subcontracting via Production order

  • – The solution contains too many moving parts: the sub-production order must be in the Started status, all raw material levels at the external warehouse must be exact.
  • – The segregation of duties between the procurement, logistics, warehouse and production departments is broken.
  • – Such a ‘deviant’ process is not easily adopted by the warehouse people: they must know when to use the normal purchase put-away menu items and when to leverage the production put-away menu.
  • – Comfortable work is not possible without the above production BOM and purchase delivery note auto-posting customizations
  • + The cost price of the semi-finished product is correct at all times.

Choose for yourself, but the CFO may let you reconsider 😉

There is a video recording in German explaining fine aspects of the 2 scenarios.

Subcontracting with Warehouse management – Part 1

Subcontracting with Warehouse management – Part 1


A typical real-world scenario for subcontracting in discrete manufacturing looks like this: the local production needs a part at one of the steps which is procured from a 3rd party. This supplier aka subcontractor is provided with some materials for free (“free issue materials”) to perform the work. The free issue materials remain in our local balance. They come back as a semi-finished product with a value-added service on top.

In standard D365FO, a sub-contracted operation is designated with a certain type in the route, and the bill of materials entails a service item representing the value added by the subcontractor. As the production order is getting estimated or converted from a planned production order in the MRP, a purchase order is opened with the supplier for the service item. The receipt of the service item in procurement (with a Delivery note i.e. Packing list or with an Invoice) may report the operation on the route as finished, consume materials associated with this operation, and absorb the sub-contracting cost into the value of the finished product.

The simulation by Microsoft resembles this story, but it misses one key element: the receipt of the semi-finished product at the inbound location with the mobile scanning device (Warehouse management). Let’s get one thing straight: this just doesn’t work in Dynamics 365 for SCM for the following reason:

Assume, we need a perforated plate for the proverbial Contoso speaker from the Dynamics 365 demo database. We inform the supplier about the need for the perforation with a purchase order, send them the steel plate with a transfer order, receive the perforated plate back, put it on stock and use it in one or many production orders of our own.

Physically we treat the semi-finished product “Perforated plate” as a normal purchase order inbound delivery, but the purchase order is raised only for the service ‘inside’: “Perforation”. In theory, one may even capture a stocked service on a mobile scanner, but it cannot pass the license plate (pallet) number to the subcontracting production order, which is open for a different product number.

Two possible solutions– non-standard and standard – are presented below. None of them is fully satisfactory, though. As Germans figuratively put it, it is “die Wahl zwischen Pest und Cholera”, a choice between the devil and the deep blue sea.

above *) „Knight at the Crossroads“, 1882, by a Russian romantic and early art nouveau painter Viktor Vasnetsov

Prerequisites setup

For this study, we need a new route operation (“Perforation”), and a new Route group (Production control > Setup > Routes > Route groups). The route group Sub will be somewhat special:

The added value is absorbed with the service item, therefore the estimation and costing of the subcontractor’s time it turned off; you will probably create a separate hour cost category with the price of zero.
The Automatic route consumption Quantity is set to Yes to trigger the automatic reporting as finished (RaF) of the semi-finished production upon the PO receipt. Typically, you do not plan the subcontractor’s capacity and consider them a “black box” with a quantity-independent lead time, but for the automatic route consumption and MRP you MUST activate the Process job. The lead time may be entered either in the default order properties of the SFG released product, or in the subcontracting route as a constant Transport time.

Another part of the puzzle for the automatic RaF is the Automatic report as finished flag in the Production control > Setup > Production control parameters:

If you capture production time and yield at Job card terminals with Manufacturing execution, then the ME route/job journals will neglect this flag, and the automatic RaF will only be triggered on manual route journals and subcontracting purchase order posting.
This was about the automatic reporting as finished; the automatic consumption of materials and routes (i.e. quantity reporting + RaF) is triggered by the 2 parameters on the Automatic update tab:

The supplier (en-us: vendor) needs an external warehouse of the Vendor type and a resource of the Vendor type. The subcontractor’s warehouse (here: EUS-104) must belong to the same site as the main warehouse (here: 5). This is because the materials in the semi-finished product BOM are tagged with the subcontractor warehouse in order to trigger a replenishment (“refill”) by an outbound transfer order. Yet the sub-production order may be pointing to our own warehouse (here: 51) to directly post the receipt of the SFG at the local site, if the inbound fransfer EUS-104 -> 51 is organized by the supplier. Such a ‘mix’ of warehouses in one BOM is only possible within the same site in D365FO.

In 99% of the cases, the external warehouse does not Use warehouse management processes, i.e. it is not an ‘advanced’ one, because there is no one from our organization to capture the inbound license plates. Instead, it requires a default receipt and issue location (here: IN_OUT).

The production resource uses this unique Input warehouse, therefore it requires an own dedicated resource group: resource <=> resource group <=> input warehouse.

Should the inbound transfer order from the supplier to our premises be managed by us, then the Output warehouse = Input warehouse = EUS-104.
The Output location is an interesting topic of its own. In reality, the output warehouse comes from the MRP planning, from the MRP demand. The MRP demand comes from the production BOM line which is deemed to consume the subcontracted SFG. Whatever the consumption warehouse is set there, it propagates the planned production order for the SFG, unless the inbound transport is managed by us (then it requires a separate replenishment setting EUS-104 -> 51).

If the same subcontractor delivers products to different warehouses of our own, then the sub-production order does not always comply with the above Warehouse setting at the resource level.
Fortunately, the developer of the method \Data Dictionary\Tables\ProdTable\Methods\defaultOutputLocation() was not sophisticated enough to check if the warehouse in the production order matches the warehouse of the last resource on the production route: the Output location is overwritten unconditionally on reporting the product as finished. It suffices if all warehouses have an output location with the same code RECV-SUB.

Finally, we need a set of released products:

Item numberNameProduct typeStor dim groupItem model groupUoMUnit seq. groupReserv. hier
D0003StandardSpeaker (FG)Item     
M0070Perforated plate (SFG)ItemWare (=WHS-managed)e.g. FIFO (stocked)EaEa PLDefault
M0070_SC*Perforation (service)ServiceWare (WHS) or SiteWH (non-WHS)e.g. FIFO (stocked)EaEa PL or noneDefault or None
M0071Steel plate (RMServiceWaree.g. FIFO (stocked)EaEa PLDefault

*Option 2 only

In standard D365 SCM (hereafter ‘Option 2’), there will be a ‘twin’ service item (here: M0070_SC) defined for every semi-finished product (M0070). As they put it, “…the service product is used to identify the arrival of the semi-finished product”.

Option 1: Subcontracting via Purchase order

1-level BOM: in this case subcontracting is managed through a ‘trading’ flow. The subcontracted semi-finished product is procured via a purchase order and received in stock as a regular inbound shipment. In other words, the subcontracted product does not originate in a production order as otherwise prescribed by the D365 best practices. The component(s) of the product are either provided for free or directly sold to the subcontractor and remain in the master product’s BOM.

In fact, the subcontracting operation “5” in the route on the diagram is not even required, everything is managed through the BOM:

According to the documentation,
to use subcontracting of route operations for production or batch orders, the product that is used for the procurement of the service must be defined as a product of the Service type. However, an undocumented feature of D365FO allows for stocked products of the type Product (not Service!) in the Vendor-type line.

An analysis of the source code in
\Data Dictionary\Tables\ProdBOM\Methods\postVendorProdBOM
\Data Dictionary\Tables\ProdBOM\Methods\postVendorProdRoute

has shown, that an automatic consumption of the BOM or the route is not supported for Products, unless you extend the ProdBOM.verifyItemType() method. However, it is not such a bad thing: the automatic BOM consumption of a service PO receipt would have consumed the service itself, then any other material at the same route operation (Op 10). But we don’t want to consume the SFG M0070 immediately! The product has to be received, put away to the main warehouse, picked from the warehouse, brought to the step “Assembly” and then consumed.

To backflush the material M0071, it has been attached to the same operation 10 Assembly (note the external warehouse for consumption):

This is not ideal, because the material is needed at the moment of the Op 5 scheduled start. The operation 10 is scheduled later. To mitigate shortages, one should choose the transfer lead times of the free issue materials carefully.
Resource consumption = Yes means the material is picked from the location of the respective machine 5110 (here: 51/002)

Let’s create a production order for D0003 at the site “5”, estimate it and check the MRP explosion:

The estimation of the production order resulted in a purchase order for M0070. In addition, a planned transfer order has been created for the raw material from our site to their site. After the confirmation of the PO by the supplier, this transfer order must be dealt with soon, to ensure the smooth execution of their work. Potentially – depending on the MRP settings – this can be also a purchase order delivered directly to the subcontractor.

To proceed, firm the transfer order, locate the transfer order in the list Inventory management > Inbound orders > Transfer order list by looking at the target warehouse, contact the shipping carrier and organize a pick-up of the goods, then use Ship / Release to warehouse to initiate warehouse work for the reserved (!) material. Process the work at the mobile device: Outbound / Transfer pick. Check out my earlier blog how to call the mobile device emulator:

Once picked and ready to be loaded into the truck, the shipment appears in the list Warehouse management > Shipments > Shipments ready to ship. Print a packing list, confirm the shipment. The transfer order is now officially Shipped. Receive the transfer order for the whole quantity immediately, as this external warehouse is unmanaged. The plates for perforation are now at the warehouse EUS-104.

Someday, the plates come back, full of holes. They need to be received at the mobile scanner (Inbound / Purchase receive). The SSCC number typically exists and can be scanned, there can be an option to print an own label with the product ID and name. Next, the pallet is Put away to the main stock:

With a little customization, the purchase order may be updated with a delivery note by an automated batch for the whole registered quantity, yet this delivery note does not kick off any automatic action in production due to the wrong product type of M0070.
The production may be released now! Make sure the newly received subcontracted product has been reserved, then go for a Release. It creates warehouse work to pick the perforated plate and bring it to the assembly resource. At this moment, M0070 becomes reserved at the location level. Process the work at the mobile device: Production / Production pick

The perforated plate has been brought to the location 002 of the machine. From now on, the production order may be started, and a picking list for the ultimate material consumption may be posted in a vast number of ways. The material M0071 previously brought to the supplier is backflushed too:

Check out the 2nd part: Subcontracting via Production order.

Semi-finished goods in an advanced warehouse

Semi-finished goods in an advanced warehouse

The management of semi-finished goods in the Production control module in Dynamics 365 SCM is notoriously messy in conjunction with the WHS (warehouse management), see my blog Missing flushing principle. The challenge is posed by the system if the material flows on the production shop floor do not require license plate handling, i.e. if people only need scanners to pick raw materials from the warehouse, but do not need them when passing semi-finished products from one working station to another. It becomes even harder if production orders overlap, i.e. if the downstream production order relies on a constant inflow of semi-finished orders and is started shortly after the upstream production order.


We evaluated various scenarios:

  • a separate non-advanced warehouse in production is awkward, because every demand of raw materials results then in a transfer order which is a substantial overhead both in shipping and receiving. Moreover, transfer order put away directives do not ‘sense’ warehouse locations with material shortage, i.e. you cannot ‘aim’ multiple work station locations in one transfer order. Managing multiple transfer orders to different logical warehouses is even a greater overhead compared to a warehouse production picking wave, which flexibly consolidates all picking work for a production order or even for a set of production orders;
  • withdrawal Kanbans are awkward, because they require standalone rules for every material and every workstation. Managing BOMs is much easier than managing Kanban flows and withdrawal Kanban rules (where you don’t even have a data entity to import or update them in bulk!).
    Moreover, Kanbans do not ‘sense’ locations either, and rely on the MRP to trigger them. But the master planning usually does not consider the warehouse location level: if you do so, this renders the advanced warehouse management obsolete. We end up with logical warehouses per machine again. Finally, the MRP is not instant, the master planning may run for hours, but you need the material now!
  • phantom sub-assemblies do not invoke any movements at the warehouse and remain a viable and very safe alternative: the first inventory transaction will be at the very end of the last machine in the chain. This approach is not always possible (at least no at all stages in production) if the factory is required to count WIP items or builds up a safety stock of them.

The approach described below uses classic BOMs and production routes in combination with work policies or automatic work. Every route has a resource (machine, work station), and every resource is associated with one inbound and one outbound warehouse location. Materials in the BOM are marked for Resource consumption i.e. to be consumed from the inbound location of the respective machine. Provided that the locations are NOT license plate controlled, the warehouse management module may be configured to automatically pass the semi-finished materials from one location to another.

Converging or sequential material flows

Consider the following scenario: whatever the semi-finished products are, one machine supplies with them just one downstream machine. Or 2 or more machines feed together the next one, and the path never changes. In this case, the output location of the upstream machine can be defined the same as the input location of the downstream machine.

In the below example the outbound location of the machine 145 equals the inbound of 146: O145 = I146.
Converging material flowsThe inbound and outbound locations are set for a resource (Production control > Setup > Resources > Resource) in connection with a resource group. The group in turn specifies the [advanced] inbound and the outbound warehouses, which are normally the same (unless it’s subcontracting).
Resource locations

However, on an attempt to select a non-license plate controlled warehouse location (the one where in the Location profile the parameter Use license plate tracking = No) for the output, a warning message comes up: “A work policy does not exist for location %1. A work policy must exist for a non-license plate controlled output location”.
Indeed, a work policy must be created first to inhibit any put-away work on reporting products as finished into this location:
No put work policy
An unprocessed put away work is bad even if it points into the same location I146 -> I146, because it reserves the semi-finished product and makes it unavailable to the next machine. With the above policy no put-away work is going to be created out of the location I146, the material is reported as finished into this location and stays there, ready to be reserved and consumed by the downstream resource.

Diverging material flows

Forks in the material flow make it much harder to configure. For example, if one resource may feed different downstream resources depending on the context, then the above setup with a work policy is not going to work.
Diverging material flows
In short, one needs 3 ‘ingredients’:

  • a Work template with an automatic processing;
  • a specially prepared Location;
  • a set of “put” Location directives (“pick” directives are not necessary, because the picking location is always dictated by the resource).

The Work template (Warehouse management > Setup > Work > Work templates) for the Finished goods put away work order type should have a typical Pick-Put pair, the Automatically process flag (!) set and a distinct Query to react to pre-defined semi-finished products.
Work template for Automatic processing
Bear in mind that (1) the automatic work processing requires a Default work user ID in the Warehouse management parameters; (2) the automatic work processing fails if the product is serial number controlled; (3) a number sequence for the license plates must exist: the system is going to take a temporary target LP.

The Location should not be license plate controlled, because if it was, the production worker would have to manually select a distinct LP on the Report as finished or the Manufacturing execution Feedback screen.
However, such a location cannot be selected in a resource, as we know. On the one hand, you don’t wish to have license plates, on another hand you need an automatic put away work to a certain location, and a prohibitive put work policy is not an option anymore.
This is not intended by Microsoft to work, but one can trick the system into it. First, assign a LP-tracked profile to the output location, and select it in the resource. Second, change the profile of the location to a Non-LP-tracked one!

The Put Location directives (Warehouse management > Setup > Location directives) for the Finished goods put away work react to certain products or resources with the help of the directive header Query (one can join the production table with the production route in the query) and divert the automatic put operation from one location to another:
Putaway location directives
The target location is “hardcoded” in the Location directive action Query.

Let the worker report the production order as finished: the system creates and executes put away work despite the missing license plate. One product goes ‘left’ and another goes ‘right’ from the same station fully automatically:
Automatically executed work


It is possible to “hard-wire“ a certain material flow between machines into the Warehouse management. Overlapping production orders remains a nuisance, because BOM lines do not exhibit a location if the warehouse is an “advanced” one. The input location of the machine is derived dynamically and the WHS module works through the reservation: the raw material must be reserved in the inbound location prior to consumption. But how do you reserve a material if it did not exist as you started the downstream production order?! The orders may be chained by the “Pegged supply” or automatically “re-released to warehouse” every X minutes.