Operation Grouping
Operation Grouping Concepts
The parameters described here govern the way 24Flow will automatically schedule operations. Before getting into the details, we first explain general concepts.
The planning horizon is the window within which unplanned orders will be planned. The selection starts on the current day and extends for a predefined number of calendar days (the planning horizon), taking the weekend into account.
Because you may not want to replan already planned orders for the near term, 24Flow introduced the concept of a freeze horizon and a fixed horizon.
The fixed horizon means that 24Flow’s automatic scheduling will not alter anything during this time window, even when there is still capacity available.
The freeze horizon means that 24Flow’s automatic scheduling will leave all already scheduled operations untouched but may add additional operations when capacity is available.
This implies that when 24Flow starts a re-planning exercise, all orders that are in the planning window, but outside the freeze and fixed window will momentarily become unplanned and will be replanned for optimum efficiency. The minimum freeze and fixed window is zero days, which means that every planning run, all orders will be replanned. The maximum freeze window equals the planning window which means that 24Flow only optimizes new orders but does not touch orders that have previously been planned.
Regardless of the definition of fixed, freeze and planning horizon, the Operation Grouping logic will NEVER replan operations for which the corresponding order has been released.
Production Order Date Field: This is the date field that will determine whether or not the operation will fall into the planning horizon. This could e.g. be the delivery date that is retrieved from the ERP system.
Group Op. Selection Horizon: Planning horizon as explained above.
Group Op. Fixed Horizon: Fixed horizon as explained above.
Group Op. Freeze Horizon: Freeze horizon as explained above.
Group Op. Free Horizon: Horizon where orders can get rescheduled and added according to the grouping scheduler.
Group Op. Capacity Threshold: 24Flow allows you to specify a correction factor, i.e. you do not plan at 100% capacity but for a reduced capacity. Currently, this parameter is set at 90%.
The automated scheduling for operations can group operations based on multiple fields. Currently four levels are supported, and for each of the levels you can select an ascending or descending order. To make it practical, let’s consider a concrete example to see how this works:
Assume you have defined two fields: priority and product type, both ascending. 24Flow will then first schedule operations from low to high priority. When each level of priority, it will consider the product type and schedule the operations of orders of the same product type before moving on to the next product type.
Group Op. Possible Equipments: This is the field that determines the list of preferred equipment the operation should be assigned to. E.g. first check whether capacity is available on machine X, if not, check for machine Y etc.
Group Operation Equipment Assignment: Lookup field on the operation object that will be used by the grouping algorithm to assign a specific operation to a particular equipment.
Operation Grouping Offset (min.): Offset in minutes between the grouped/ chained operations. Can be useful to use in conjunction with the 24Planning settings - View Preset - Time Resolution Increment
Group Op. Last Operation per Prod.Ord: Only use the last operation in the selection in case it contains multiple operations for the same production order. This avoids getting into a loop and replanning operations multiple times.
Group Op. Run Equipment Capacity: After running the grouping logic, the equipment capacities are calculated.
Group Op. Run Team Capacity: After running the grouping logic, the team capacities are calculated.
Group Op. Publ. 24Planner Event: 24Planner is updated when operation grouping is done.
Operation Grouping Filters
Group Op. Filter Field: Add an additional SOQL WHERE filter to select operations. E.g. If you only want to select operations that are not finished for the plant 9000 a possible statement could be Group Op. Filter Field: Plant__c = '9000' AND sfy24__Is_Finished__c = FALSE
Don’t use enters in the WHERE filter
Operation Grouping - Dynamic Duration
Advanced configuration when the touch time of the operation depends on several parameters. This settings allows for the operation grouping logic to calculate the touch time dynamically depending on these parameters.
This functionality is best explained via an example. We will use the object Equipment Product, but the principles are applicable to any Salesforce object.
Firm X has 2 machines and 2 products:
Equipment 1 has a speed/product of 2 minutes for Product A and 1 minutes for Product B.
Equipment 2 has a speed/product of 3 minutes for Product A and 1 minute for Product B.
These speeds are defined on the Equipment Product object. This object will hold a record for each combination, e.g. a record with a lookup to Equipment 1 and a lookup to Product A and a value of 2 in a duration field.
In this scenario, if an operation with required quantity 50 of Product A is made on Equipment 1. The duration will be 100 minutes (50x2).
Now we just have to set the fields for MTO so it can dynamically calculate the duration.
For the operation to know the speed of product A on Equipment 1, it needs to look up the speed on the Equipment Product record.
So, on the operation record the following fields have to be filled in (see also the section on extending the data model):
Dynamic Duration Object Name: API name of the object that contains the dynamic duration. For our example above, this would be Equipment_Product__c. This way the Dynamic grouping knows where to look for the correct record.
Dynamic Duration Record Id: This is the record where the dynamic duration of the operation can be found. In our scenario the record for product A and Equipment 1 had the id ‘a1bd1000000fZoEAAU’.
In the custom metadata settings, the following has to be filled in:
Group Op. Dynamic Duration: JSON structure with all the fields for the dynamic duration. The following field names are required:
touchTimeFieldMin: The API name of the field that contains the touch time in minutes in the duration object.
operationQuantityField: The API name of the field in the Operation object that contains the quantity that has to be multiplied with the touch time. If blank/null it is just the given touch time. In our scenario this quantity is 50.
operationDynamicDurationRecordField: The API name of the lookup field in the operation for the dynamic duration record. For instance in the scenario of the equipment product, this field is populated with Equipment_Product__c.
filter: Define a filter for the selection of the operations. the “value” in the filter refers to the API lookup on the operation and the fieldname to lookup in the dynamic duration object. In the example below, only operations that have a value in ‘ProductId__c’ which is defined as ‘Product__c’ on Equipment_Product__c or operations with a value for ‘sfy24__SchedMtoEquipment__c’ which is called ‘Equipment__c’ on the Equipment_Product__c object are selected.
durationObjectName: Object name where the dynamic duration is found. Put the api name of the object that contains the durations here.
Scenario JSON example in the case that touch time is dependent on Equipment and Product: [{"touchTimeFieldMin":"Duration_In_Minutes__c","operationQuantityField":"sfy24__Quantity_Required__c","operationDynamicDurationRecordField":"Equipment_Product__c","filter":{"rows":[{"value":"ProductId__c","rows":[],"operator":"Equals","nextRowOperator":"AND","isString":null,"isPicklist":null,"isNumeric":null,"isGroup":false,"isCheckbox":null,"fields":[],"fieldName":"Product__c"},{"value":"sfy24__SchedMtoEquipment__c","rows":[],"operator":"Equals","nextRowOperator":null,"isString":null,"isPicklist":null,"isNumeric":null,"isGroup":false,"isCheckbox":null,"fields":[],"fieldName":"Equipment__c"}]},"durationObjectName":"Equipment_Product__c"}]
Quantity Based vs Time Based
Scheduling Mode (field in custom metadata) :
Time Based : The system assumes the operation takes a specific amount of time. Start and end date of the operation are based on this time input.
Quantity Based : The system assumes a specific target quantity must be produced, and the time required to do so is variable. The duration of the operation expands or contracts based on the production rate of the assigned resources.
There are two additional ways to implement dynamic quantity or time calculations, beyond what was described in the dynamic duration category. For both methods, you can define a custom class that calculates the variable duration or output based on a set of input parameters. These classes must implement a predefined interface that is part of the Make-to-Order package. This ensures that the system can invoke the custom logic in a standardized and controlled manner. By using this approach, you gain flexibility to tailor duration and output calculations to specific business rules while maintaining compatibility with the core framework.
Dynamic Touch Time
Enable Dynamic Touch Time : set this flag to true when you want to use the dynamic touch time calculator class.
Dynamic Touch Time Calculator Class : Enter the exact, case-sensitive name of the Apex class that implements the SchedMtoTouchTimeCalculatorV2 interface. This class is only used when Enable Dynamic Touch Time is checked. The scheduler will call this class to perform two critical, "inline" calculations: getTotalTouchTime(Op) and calculateOperationRunEndDate.
Dynamic Total Quantity
Data: Typically requires a custom object (like SchedMtoProductionMatrix__c) to map resources to rates.
E.g.
2 employees → output = 30
3 employees → output = 40
Enable Dynamic Total Quantity: set this flag to true when you want to use the dynamic quantity calculator class.
Dynamic Touch Time Calculator Class: Enter the exact, case-sensitive name of the Apex class that implements the SchedMtoDynamicQuantityCalculator interface. This class is only used when Enable Dyn. Total Quantity is checked. The scheduler will call this class to perform two critical, "inline" calculations: getTotalQuantityToSc(Op) and calculateOperationRunEndDate.
Operation Quantity Required Field : Set the API field name which holds the required quantity on the operation. Used in conjunction with 'Operation Run Calculate Required Qnty' and is necessary to calculate the quantity required at operation run level.
Operation Runs
This is an advanced setting that enables the visualization of actual productivity at a more granular level.
By using operation runs, you can clearly display variations in hourly productivity as well as non-working time within a longer, overarching operation. Instead of treating the entire operation as one continuous block with a fixed output rate, the operation is divided into time-based segments. This allows differences in staffing, performance, or availability during specific time slots to be accurately reflected in the planning.
Example :
.png?inst-v=5096fecb-3c80-4358-8783-9d418aefd455)
You can clearly see that there is a break between 16:30 and 17:00, as well as between 20:00 and 20:15. The visualization also shows differences in actual productivity when the effective working time is less than a full hour. In addition, it clearly indicates the periods during which production is closed.
This functionality allows productivity to be defined and adjusted at a more granular time level. Instead of applying one fixed productivity rate to the entire operation, productivity can vary per time interval (e.g. per hour). This enables more accurate capacity planning and scheduling.
Settings
Production Order Scheduling - Operation Grouping Scheduling (these are two separate pairs of settings, such that you can differentiate production order scheduling from operation grouping scheduling):
Schedule Op. Run Size (minutes) : Specifies the duration in minutes (e.g., 60) used to split operations into smaller Operation Run records during scheduling. If blank no operation run will be created/stored.
Schedule Slot-Scheduling : When enabled, operation runs (sized by the value in Schedule Run Size (minutes)) are forced to start and end on pre-defined, fixed-time boundaries. e.g. When:
Slot-disabled: Operation A has its last operation run ending at 10:03, Operation B’s first operation run will start at 10:03 and ends at 11:03.
When enabled: Operation A has its last operation run ending at 10:03, Operation B’s first operation run will start at 10:03 and ends at 11:00.
Operation Run General Settings
Operation Run Calculate Required Qnty: If operation run size is set, then also calculate the quantity required and quantity required cumulative (what should be finished taking previous runs into account) for that run.
Operation Quantity Required Field: Set the API field name which holds the required quantity on the operation. Used in conjunction with 'Operation Run Calculate Required Qnty' and is necessary to calculate the quantity required at operation run level.
Advanced
With the previous settings, you can configure the general setup for operation runs. This configuration determines how the operation is split into time-based segments and results in the automatic generation of those operation runs. However, this setup alone does not yet allow you to define differences in hourly productivity or to visualize non-working time within the operation. Additional configuration is required to reflect productivity variations or downtime at a more granular level.
Dynamic Quantity: Variable Output
Goal: Calculate exactly how much product is created within a specific time slot (e.g., 08:00 to 09:00) based on real-time resource levels.
The Interface: SchedMtoDynamicQuantityCalculatorV2
Input: SchedMtoDynamicQuantityRunInput
When the scheduling engine tries to create a run, it passes this object to your class. It contains:
runStartDate&runEndDate: The proposed calendar slot (e.g., 08:00 - 09:00).
operation&equipment: The context of what is being built and where.
cumulativeQuantity: How much has been built in previous runs.
Your Apex class uses these inputs to determine the production rate.
Example Logic (SchedMtoProductionMatrixQntyCalcV2): It queries
EmployeePlanningrecords for the specificrunStartDate. If 3 employees are present, the rate is high (e.g., 100 items). If only 1 is present, the rate is low (e.g., 20 items).
Result: SchedMtoDynamicQuantityRunResult
You return this wrapper to tell the engine what happened:
quantity (Mandatory): The specific amount produced in this slot (e.g., "50 units").
chunkStartDateOverride & chunkEndDateOverride (Optional):
Standard: Leavenull. The system creates a run exactly matching the input dates with the calculated quantity.
Advanced (Non-Working Time): If you return achunkStartDateOverridelater than the input start (e.g., Input 08:00, Return 09:00), you force the system to leave a gap (08:00-09:00) where no work is done, effectively showing non-working time on the planning board.
Dynamic Time: Variable Duration & Slot Awareness
Goal: Determine when a fixed duration of work (e.g., "1 Hour of Effort") can actually be performed on the calendar. This is used for Slot Awareness.
The Interface: SchedMtoDynamicTimeCalculatorV2
Input: SchedMtoDynamicTimeRunInput
The engine creates this object asking: "I need to schedule touchTimeForRun (e.g., 60 minutes) starting at baseDatetime (e.g., 08:00). When does it happen?"
baseDatetime: The proposed start time.
touchTimeForRun: The duration of the chunk to schedule.
Your Apex class checks constraints (like shifts or machine availability).
Example Logic (SchedMtoDynamicTimeSlotAwareCalc): It checks
EmployeePlanning. If the engine proposes 08:00, but the first employee shift doesn't start until 12:00, the logic detects a gap.
Result: SchedMtoDynamicTimeRunResult
You return the actual calendar times:
chunkStartDateOverride (The "Gap Jump"): If you return
12:00(when the input was08:00), the engine skips the time between 08:00 and 12:00. This empty space appears as non-working time on the Visual Gantt,.chunkEndDateOverride : You define exactly when the run ends. If a machine is running at 50% efficiency, you can return an End Date that is 120 minutes later, even if the "Work Content" (
touchTimeForRun) was only 60 minutes. This extends the visual bar to reflect slower productivity.