Starting from a basic recipe tree, responding to a question “What do we need to produce end-product?” we’ll progressively encode responses to more questions into our structure:
- How will all of the ingredients be fulfilled? Are they available at the place? Will they be produced or delivered from some external source?
- In what processes will the given element be used?
- When do we need a given ingredient and how subsequent processes will impact the duration of the whole process?
- Where will ingredients be processed? Do we need to transport them inside our factory?
Later we’ll explore alternative views and extensions of our model, which will meet more specific needs and allow more detailed analysis.
We’ll also take into account that reality in factories is not static so, our graphs and answers to the above questions can dynamically change.
Let’s start with the following assumptions:
- Customer orders Product, for the sake of simplicity, let’s assume it will be a mass-produced Book.
- For the production of Book we use Printed Pages and Book Cover.
- Printed Pages are produced from Ink and Cut Pages.
- Cut Pages are produced from Paper.
The points above are nothing more than simple recipes in the form of “For the production of X we need Y and Z”. To visualize the requirements, we can combine those recipes into a tree, in which root would be the ordered Product, all intermediate nodes would have children needed to produce them and leaves will be raw materials.
Information about raw materials is especially helpful here. When we’d keep our orders in such a structure, we can query all leaves to have information about all currently needed raw materials.
Recipe can be dynamically revealed (we can start printing pages before the specification of the whole recipe tree is completed, e.g. concrete Book Cover demand is not known yet) or dynamically changed. When some of the ingredients are not available, we can simply abandon subtree and replace it with a leaf or another subtree derived from another recipe. Such detached subtrees need to be taken care of by factory workers (e.g. if some ingredient will be late, we can still decide to complete it to increase future buffer).
Way of fulfillment
At this stage, our model is indeed representing dependencies but isn’t anchored anywhere in standard company procedures. Strategies of satisfying needs for ingredients may vary among companies and specific cases:
- In some cases, we can apply a strategy of keeping a safe buffer of raw materials in stock so we can start processing any order for Product (Book) right away.
- If a company uses many different raw materials, it would probably be more economical not to keep buffers but supply most ingredients externally.
- Moreover, we may want to be able to choose if we want to produce a given ingredient or order it externally, depending on the current workload.
A typical company would probably mix those strategies depending on the business sector and other, more specific factors. Whatever method we’ll choose, we need to represent the results of all decisions in the bounds of the order in our structure.
For all non-raw items in the graph, we assume that they are produced locally (it doesn’t have to be true since we can outsource some production and our model will also support that, but we won’t go into that for the sake of simplicity). Raw materials can be either available at the place or need to be ordered from a supplier, so let’s model our exemplary assumptions like this:
- Book Cover is available in Place#1
- Ink is available in Place#1
- Paper can be ordered from Supplier
Way of fulfillment for various parts of the graph can rapidly change – in case of e.g. some more urgent order was cancelled we may want to cancel supply order and use the available product instead. In the current state, it would be simply changing the label on a given node and perhaps relinking its children so they may be used for some other production or increase the future buffer of a given item.
The current state of fulfillment is just a label on our node, so we may say that label says how demand for a given product is fulfilled. But let’s imagine a situation of having just a single node for some item (just created or detached from some larger graph) in our structure. Currently, the meaning of such can be ambiguous since it can either:
- be a product of some no-input process that can be used to satisfy some needs of other processes
- correspond to customer order and waiting to be properly expanded into a complete tree
So, in other words, a node can be either a fulfillment coming from a production process or a demand coming from a customer order. To clarify this situation, we’ll split our nodes into demands (items required by the process) and fulfillments (items provided by the process). Splitting would give us an additional advantage of the possibility to satisfy single, large demand with multiple small fulfillments or satisfy multiple demands with single, large fulfillment (we’ll go deeper into this in the “Other Models” section). Such definition will also allow us to strictly attach a single node to a single process so:
- exploring our graph from perspectives of various company departments will be easier, e.g. we can quickly formulate queries like “every demand of production process that is not addressed yet.”
- there will be no fulfillment without an attached process – no item should come from “the air.”
- there will be no demand without a cause – so by design, if we expend some item we got to always start with “where and why is this needed?”, this will let us model pull system around our model
Let’s split our nodes into two (demand & fulfillment) and draw clear borders between processes in the example.
The distinction between demand and fulfillment let us handle scenarios of cancelling or changing parts of the graph better. In case e.g. order demand would be cancelled we can decide what to do with connected fulfillment, which becomes detached but still contains precise information about operations that were planned before.
Having extracted every process into a separate group of nodes, we can try to represent probably the most crucial dimension of every modern company’s reality – time. We want to save and access the data about time as:
- occurrence time of given node – point in time (or its estimation) at which given item is demanded or fulfilled, we will derive this time from evaluation of the elapsed time described below
- time elapsed in a given state – at the most granular level, we can distinguish between two kinds of such states:
- active time – when we wait for the process to complete, active time sums up to processes duration
- idle time – when we wait for a process to take its input and start transforming it, this time is spent by items inactively in buffers
This distinction fits nicely into our model, with borders drawn between processes. If a given edge is crossing the “process border” it’s idle time (item is demanded by one process later than the other process will fulfil it) and if it happens inbound of the process then it’s active time (process demands need to be fulfilled for the process to start, after process duration connected fulfillment item is ready). Having duration assigned to edges gives us a key advantage here – we can now evaluate paths in our tree according to their “duration” and compare every possible tree and subtree in this metric. Moreover, if we assign completion times to all leaf fulfillments, we can calculate fulfillment time for the end-product in a bottom-up manner.
Let’s visualize this data in our example.
In our example time of the whole process can be dictated by the availability of leaves – if they are available, they can be processed right away and if supplied externally, their availability will probably be delayed. But major delays are caused by processes via either their duration itself or their delay because of the given task’s position in the queue.
Both durations of processes and waiting times can dynamically change according to the following factors:
- processes are often part of some tasks queue (e.g. queue of production tasks for a given machine), so after reordering it, their expected execution time can change
- we can’t expect estimated process time to always match reality – the key responsibility of the system when processes are in progress should be to monitor if waiting times are always positive so no process execution would be delayed by some other dependent delay
- if some delay or speedup of the process occurs anyway, we should propagate that change across the whole graph
Having time represented, we can respond to a question if a given item is available at the demanded time, but with one crucial assumption – fulfillment satisfies demand right after being completed. Such an assumption can be problematic when different processes represented so far happen in different places (like factories, plants or units) – for our calculations to be reliable, we need to account for transport as another kind of process.
Let’s consider the following assumptions about places where processes happen:
After putting processes of transport between demands with place other than its connected fulfillment we’d get the following representation:
This way, we have built a complete model of processes that can demand items and fulfill other demands – processes can be anchored in space and time, so we’re able to visualize a concrete tree of fulfillment for an order in the company.
With such a complete model, we can derive various other data models to see our company from multiple perspectives.
Demand – Fulfillment binding other than 1-1
Graph components don’t have to be limited to single order fulfillment. We can extend our model to address multiple demands with a single fulfillment (e.g. to satisfy multiple orders with a single production) or fulfill single request with multiple fulfillments (we can split large order to be produced in various parts).
Nodes as events
Having all historical and future demands and fulfillments we can easily represent them as a chart displaying historical stock levels along with a forecast of future stock level changes. Each demand can represent a decrease of a given stock level and fulfillment can represent an increase. Such a view, grouped by ingredient, gives us a great tool when deciding what supply orders have the highest priority or where we often hold inappropriate buffers.
Flow between places
Considering we have data about all transports in our model, we may be able to wrap them up into another graph to represent places as nodes. Such visualization allows us to see the transfer rate between places in a given timeframe – this can help us make decisions about the placement of item buffers in available warehouses and organize internal logistics to reduce transfers or make the majority of them as short as possible.
We haven’t mentioned any concrete industry along the whole process since we tried to make this model as generic as possible. If we extend processes in bounds of our definitions, this model can be used to represent materials flow in a lot of industries, from manufacturing to logistic companies. If introduced in various sectors interacting with each other, we can even span graphs from multiple companies.