Shift Demands

From 3B Knowledge
Jump to navigation Jump to search

Intro

Shift Demands is a feature in 3B that allows us to record multi-person requirements and represent them as single instances in the scheduler. The benefit of using shift demands are:

a) Taking up less space in the requirements swimlane

b) Shift Demands are tightly linked to their child shifts (also called Demand Shifts)

c) Reporting and analytics benefits (fill ratio, over/under providing)


Shift Demands are perfectly suited for high-volume blue collar workflows.

Version 7.0 of the WFM package introduces Shift Demands.

Naming

  • Shift Demand - this is a shift record that can only live in the requirements line and has the Required Staff number set to anything over 1. It represents the parent of the Demand Shift entries.
  • Demand Shift - this is a shift record that is linkect to a Shift Demand through the Shift Demand parent lookup field.
  • Shift - this is a regular shift where the Required Staff is null or less than or equal to 1 and the Shift Demand field is null.

Configuration

Version 7.0 of the WFM package introduces the following new fields:

  • Required Staff (on Shift) - number field - indicates how many people are required for a given demand
  • Shift Demand (on Shift) - lookup field - indicates which demand is responsible for the contextual shift

Furthermore, this release introduces the following required Scheduling Context Provider metadata items:

  • "demandParentFieldPath": "b3s__Shift_Demand__c" - a string property directly on the shift schedulable, designating the field to be used for mapping a demand shift to a shift demand
  • "demandRequiredStaffFieldPath": "b3s__Required_Staff__c" a string property directly on the shift schedulable, designating the field to be used for setting a shift as a shift demand
  • "demandAssignFieldsFlush": [] - an array of field flusher entries (e.g. { "field": "b3s__Required_Staff__c", "value": 1 }). The field is the field name on the shift and the value is the value you wish that field to be set to, once the Shift Demand is assigned to a Contact.
  • "demandUpdateFieldsSync": [] - an array of strings, indicating which fields will propagate to child demand shifts as the parent shift demand is updated


Example:

{
    ...
    "schedulables": {
         "shift": {
            "objectType": "b3s__Shift__c",
            ...
            "demandParentFieldPath": "b3s__Shift_Demand__c",
            "demandRequiredStaffFieldPath": "b3s__Required_Staff__c",
            ...
            "demandAssignFieldsFlush": [
                    {
                        "field": "b3s__Required_Staff__c",
                        "value": 1
                    }
            ],
            "demandUpdateFieldsSync": [
                "b3s__Site__c",
                "b3s__Site__r",
                "b3s__Job__c",
                "b3s__Job__r",
                "b3s__Status__c",
                "b3s__Scheduled_Start_Time__c",
                "b3s__Scheduled_End_Time__c"
            ],
            "recordFormFields": [
                {
                    "field": "b3s__Scheduled_Start_Time__c:b3s__Scheduled_End_Time__c",
                    "props": {
                        "hideDate": true
                    },
                    "labelOverride": "Scheduled Times",
                    "type": "field-time-range-selector",
                    "views": {
                        "shiftView": true,
                        "bulkEditView": false,
                        "blukCreateView": true
                    },
                    "required": true,
                    "disabled": {
                        "condition": {
                            "allOrSome": "all",
                            "selectors": [
                                {
                                    "field": "b3s__Shift_Demand__c",
                                    "operator": "isnull",
                                    "value": false
                                }
                            ]
                        }
                    }
                },
                {
                    "isSeparator": true,
                    "label": "Demand",
                    "columns": "col-span-2",
                    "views": {
                        "shiftView": true,
                        "bulkEditView": true,
                        "blukCreateView": false
                    },
                    "showIf": {
                        "condition": {
                            "allOrSome": "all",
                            "selectors": [
                                {
                                    "field": "b3s__Contact__c",
                                    "operator": "isnull",
                                    "value": true
                                }
                            ]
                        }
                    }
                },
                {
                    "field": "b3s__Required_Staff__c",
                    "type": "field-number-input",
                    "props": {
                        "helptext": ""
                    },
                    "views": {
                        "shiftView": true,
                        "bulkEditView": false,
                        "blukCreateView": true
                    },
                    "required": false,
                    "showIf": {
                        "condition": {
                            "allOrSome": "all",
                            "selectors": [
                                {
                                    "field": "b3s__Contact__c",
                                    "operator": "isnull",
                                    "value": true
                                }
                            ]
                        }
                    },
                    "default": "1"
                }
            ]
         }
         ...
    }
}

Notice how we have added "showIf" property to the b3s__Required_Staff__c field and the "Demand" separator. In addition, we are conditionally disabling the Start/End fields on the Demand Shift records to prevent users from editing the times for a given demand shift.


Finally, we also need to define a new property on the view object called "object" like so:

{
    "views": [
        {
            "type": "Worker",
            "name": "byWorker",
            "object": "Contact",
            "active": true,
            ....
        }
}

Adding the "object" property helps us distinguish the current view type and manage shift demands appropriately. This is a required step for any client upgraded from version prior to 7.0.

Expected Behaviour

Below are a list of operations that are unique to the Shift Demands:

  • Assigning a shift demand to a Contact resource will result in a new shift record being created (called "demand shift") that is linked to the shift demand via the field defined in the metadata in the key "demandParentFieldPath". The action of assigning a shift demand to a contact resource will update the counter at the top of the shift demand to indicate that one new shift is assined.
  • A shift demand with multiple demand shifts can be moved between days. When a shift demand is moved to a different day, all child demand shifts are also updated
  • If a shift demand is updated (via the "Edit Shift"), if the fields updated are also in the demandUpdateFieldsSync array, the child demand shifts will also be updated to match the updates on the shift demand. E.g. if the Job is updated on a shift demand, the child demand shifts will also be updated to match the Job set on the demand shift.
  • If a shift demand is copied and pasted to a contact resource and on the same day column, this will be considered as an assignment (i.e. a child demand shift will be created linked to the parent shift demand)
  • If a shift demand is cut and pasted to a different day (in the unassigned lane), all child demand shifts will be deleted and will not be pasted in the target location
  • If a shift demand is copied and pasted to a different day and different resource, we will create a regular shift record (detatched from the shift demand)
  • If a demand shift is copied and pasted to a different day and different resource, we will create a regular shift record (detatched from the shift demand)
  • If a demand shift is cancelled (where the "isCancelled" shift schedulable definition is covered), we will decrease the count of assigned shifts on a shift demand's header
  • In views other than the "Contact" view, we will follow the above rules, but will also allow assigning shift demands and demand shifts to the "unassigned" lane - e.g. if we are in a Site view and the shift demand's site is "Location XYZ", moving the shift demand to the "unassigned" lane will clear the site on the shift demand and any child demand shifts.

Blocked actions

  • A demand shift cannot be moved to a different day in any view type. An error message will be displayed.
  • A demand shift cannot be moved to the "unassigned" lane in a Contact view type (where the view's object is set to "Contact")

Filtering

Below you can find a sample filter that shows/hides shifts, demands or demand shifts. Modify as required.

{
    name: "Demands",
    label: "Demands",
    type: 'shift',
    isDefaultOpen: true,
    items: function () {
        return [
            {label: 'Show Shift Demands', name: 'show-shift-demands'},
            {label: 'Show Demand Shifts', name: 'show-demand-shifts'},
            {label: 'Show Shifts', name: 'show-shifts'}
        ]    
    },
    matchesItems: function (event, filterItems = []) {
        return filterItems.some(filterItem => {
            console.log('filterItem', filterItem);
            if(filterItem === 'show-shift-demands'){
                return event.extendedProps?.record?.b3s__Required_Staff__c > 1;
            }else if(filterItem === 'show-demand-shifts'){
                return !!event.extendedProps?.record?.b3s__Shift_Demand__c;
            }else if(filterItem === 'show-shifts'){
                return !event.extendedProps?.record?.b3s__Shift_Demand__c && (event.extendedProps?.record?.b3s__Required_Staff__c ?? 1) < 2;
            }
            return false;
        });
    }
}