---
schema_version: "1"
id: 4a2c706ae0b1d79e218d9566feeab46b44d7cfb69457383baf57e4d8822e6460
title: Initialize Shift Work Topics with Capacity
collection: admin
version: current
locale: en-us
portal_url: https://docs.salesforce.com/admin/current/en-us/platform/264-0-0/ls_initialize_shift_work_topics_with_capacity.md
canonical_url: https://help.salesforce.com/s/articleView?id=platform.ls_initialize_shift_work_topics_with_capacity.htm&release=264.0.0&type=5
source_site: help.salesforce.com
content_type: documentation
content_hash: acdb3e47a90bc8522b91585c25ba99b5a5c7f44c56c37b1edf0e0ff6d56877ac
description: Initialize capacity for shift work topics in your org.
products:
  - Scheduler
  - Salesforce Platform
release: "264"
---
# Initialize Shift Work Topics with Capacity

Initialize capacity for shift work topics in your org.

### Required Editions

<table class="slds-table slds-table_bordered slds-max-medium-table_stacked slds-m-bottom_small edition"><colgroup><col></colgroup><tbody><tr class=""><td class="slds-cell-wrap" style="vertical-align:top;">Available in: Lightning Experience.</td></tr><tr class=""><td class="slds-cell-wrap" style="vertical-align:top;">Available in: <strong>Enterprise</strong> and <strong>Unlimited</strong> Editions</td></tr></tbody></table>

<table class="slds-table slds-table_bordered slds-max-medium-table_stacked slds-m-bottom_small permission">
        <colgroup>
          <col style="width:50%">
          <col style="width:50%">
        </colgroup>
        <thead class="slds-text-title_caps ">
          <tr class="">
            <th scope="colgroup" class="slds-cell-wrap" colspan="2" style="text-align:center;vertical-align:top;" id="d9158e66">User Permissions Needed</th>
          </tr>
        </thead>
        <tbody>
          <tr class="">
            <td data-label="User Permissions Needed" class="slds-cell-wrap" style="vertical-align:top;" headers="d9158e66 ">Run the script:</td>

            <td class="slds-cell-wrap" style="vertical-align:top;" headers="d9158e66 ">
              <p>API Enabled</p>
              <p>AND</p>
              <p>View All Data</p>
              <p>AND</p>
              <p style="margin-bottom:0;">Author Apex</p>
            </td>

          </tr>
        </tbody>
      </table>

By default, after you enable capacity-based scheduling, the capacity of your shift work topics is set to 0. Use these scripts to populate values in your shift work topics so that your schedule works as it did before you enabled capacity-based scheduling. We recommend using these scripts if you have existing shift records that you want to quickly update to ensure business continuity. Alternatively, you can manually set the capacity for the shift work topics.

1. Depending on the Scheduler for Health Cloud setting in your org, use one of these scripts.
    - Disabled
        
        ```
        //For Health Cloud Disabled
        global class InitialiseExistingSWTWithCapacity implements Database.Batchable<SObject> {
          global Database.QueryLocator start(Database.BatchableContext BC) {
            return Database.getQueryLocator([SELECT Id, StartTime, EndTime FROM Shift]);
          }
        
          global void execute(Database.BatchableContext BC, List<SObject> scope) {
            List<String> shiftIds = new List<String>();
        
            for (Shift shift : (List<Shift>) scope) {
              shiftIds.add(shift.Id);
            }
        
            // create maps to avoid queries in the loop
            List<Shift> shiftInfo = [
              SELECT ServiceTerritoryId, Id, StartTime, EndTime
              FROM Shift
              WHERE Id IN :shiftIds
            ];
            List<String> serviceTerriroryIds = new List<String>();
            for (Shift shift : shiftInfo) {
              serviceTerriroryIds.add(shift.ServiceTerritoryId);
            }
        
            Map<String, String> mapStToServiceAppointmentLimitType = new Map<String, String>();
            List<ServiceTerritory> sts = [
              SELECT ServiceAppointmentLimitType, Id
              FROM ServiceTerritory
              WHERE Id IN :serviceTerriroryIds
            ];
            for (ServiceTerritory st : sts) {
              mapStToServiceAppointmentLimitType.put(
                st.Id,
                st.ServiceAppointmentLimitType
              );
            }
            Map<String, String> mapShiftToServiceTerritory = new Map<String, String>();
            Map<String, Decimal> mapShiftToDuration = new Map<String, Decimal>();
        
            for (Shift shift : shiftInfo) {
              mapShiftToServiceTerritory.put(shift.Id, shift.ServiceTerritoryId);
              Decimal shiftDuration =
                (shift.EndTime.getTime() - shift.StartTime.getTime()) / (1000 * 60);
              mapShiftToDuration.put(shift.Id, shiftDuration);
            }
            Map<String, Decimal> mapWorkTypeToDuration = new Map<String, Decimal>();
        
            List<WorkType> wts = [SELECT Id, DurationInMinutes FROM WorkType];
            for (WorkType wt : wts) {
              mapWorkTypeToDuration.put(wt.Id, wt.DurationInMinutes);
            }
        
            Map<String, List<String>> mapShiftToWorkTypeGroupList = new Map<String, List<String>>();
        
            List<ShiftWorkTopic> shiftWorkTopics = [
              SELECT Id, WorkTypeGroupId, ShiftId, MaxAppointments
              FROM ShiftWorkTopic
              WHERE ShiftId IN :shiftIds AND WorkTypeGroupId != NULL
            ];
        
            for (ShiftWorkTopic swt : shiftWorkTopics) {
              List<String> existingSWTList = mapShiftToWorkTypeGroupList.get(
                swt.ShiftId
              );
              if (existingSWTList == null) {
                existingSWTList = new List<String>{ (String) swt.WorkTypeGroupId };
              } else {
                existingSWTList.add(swt.WorkTypeGroupId);
              }
              mapShiftToWorkTypeGroupList.put(swt.ShiftId, existingSWTList);
            }
        
            Map<String, String> mapWorkTypeGroupToWorkType = new Map<String, String>();
            List<WorkTypeGroupMember> wtgms = [
              SELECT Id, WorkTypeGroupId, WorkTypeId
              FROM WorkTypeGroupMember
            ];
            for (WorkTypeGroupMember wtgm : wtgms) {
              mapWorkTypeGroupToWorkType.put(wtgm.WorkTypeGroupId, wtgm.WorkTypeId);
            }
        
            Map<String, List<ShiftWorkTopic>> mapShiftToSWTList = new Map<String, List<ShiftWorkTopic>>();
        
            for (ShiftWorkTopic swt : shiftWorkTopics) {
              List<ShiftWorkTopic> existingSWTList = mapShiftToSWTList.get(swt.ShiftId);
              if (existingSWTList == null) {
                existingSWTList = new List<ShiftWorkTopic>{ swt };
              } else {
                existingSWTList.add(swt);
              }
              mapShiftToSWTList.put(swt.ShiftId, existingSWTList);
            }
            Map<String, Integer> mapSWTToConcurrency = new Map<String, Integer>();
            for (ShiftWorkTopic swt : shiftWorkTopics) {
              if (swt.MaxAppointments != null) {
                mapSWTToConcurrency.put(swt.Id, swt.MaxAppointments);
              } else {
                mapSWTToConcurrency.put(swt.Id, 1);
              }
            }
            // main code starts here
        
            for (String shiftId : shiftIds) {
              String ServiceAppointmentLimitType = mapStToServiceAppointmentLimitType.get(
                mapShiftToServiceTerritory.get(shiftId)
              );
              if (
                ServiceAppointmentLimitType == 'Maximum Limit' ||
                ServiceAppointmentLimitType == null
              ) {
                Double shiftDuration = mapShiftToDuration.get(shiftId);
                for (ShiftWorkTopic swt : mapShiftToSWTList.get(shiftId)) {
                  Double workTypeDuration = mapWorkTypeToDuration.get(
                    mapWorkTypeGroupToWorkType.get((swt.WorkTypeGroupId))
                  );
                  Double concurrency = mapSWTToConcurrency.get(swt.Id);
                  swt.ServiceAppointmentLimit = ((shiftDuration / workTypeDuration)
                      .intValue() * concurrency)
                    .intValue();
                }
              } else if (ServiceAppointmentLimitType == 'Achievable Limit') {
                List<ShiftWorkTopic> swtList = mapShiftToSWTList.get(shiftId);
                if (swtList == null) {
                  // No SWT in this shift do no process
                  continue;
                }
                Integer maximumCapacity = 0;
                Decimal shiftDuration = mapShiftToDuration.get(shiftId);
        
                for (ShiftWorkTopic swt : mapShiftToSWTList.get(shiftId)) {
                  Integer concurrency = mapSWTToConcurrency.get(swt.Id);
                  Double workDuration = mapWorkTypeToDuration.get(
                    mapWorkTypeGroupToWorkType.get((swt.WorkTypeGroupId))
                  );
                  maximumCapacity = Math.max(
                    maximumCapacity,
                    (shiftDuration / workDuration).intValue() * concurrency
                  );
                }
                Integer finalCapacity = 0;
        
                for (Integer cap = 0; cap <= maximumCapacity; cap++) {
                  Double sumLHS = 0;
        
                  for (ShiftWorkTopic swt : mapShiftToSWTList.get(shiftId)) {
                    Integer concurrency = mapSWTToConcurrency.get(swt.Id);
                    Double workDuration = mapWorkTypeToDuration.get(
                      mapWorkTypeGroupToWorkType.get((swt.WorkTypeGroupId))
                    );
                    sumLHS += Math.ceil((1.0 * cap) / concurrency) * workDuration;
                  }
                  if (sumLHS <= shiftDuration) {
                    finalCapacity = cap;
                  } else {
                    break;
                  }
                }
        
                for (ShiftWorkTopic swt : mapShiftToSWTList.get(shiftId)) {
                  swt.ServiceAppointmentLimit = finalCapacity;
                }
              }
            }
            update shiftWorkTopics;
          }
        
          global void finish(Database.BatchableContext BC) {
            // Send notification or log the completion
            System.debug('Batch job completed successfully.');
          }
        }
        ```
    - Enabled
        
        `//For Health Cloud Enabled global class InitialiseExistingSWTWithCapacity implements Database.Batchable<SObject> {   global Database.QueryLocator start(Database.BatchableContext BC) {     return Database.getQueryLocator([SELECT Id, StartTime, EndTime FROM Shift]);   }    global void execute(Database.BatchableContext BC, List<SObject> scope) {     List<String> shiftIds = new List<String>();      for (Shift shift : (List<Shift>) scope) {       shiftIds.add(shift.Id);     }      // create maps to avoid queries in the loop     List<Shift> shiftInfo = [       SELECT ServiceTerritoryId, Id, StartTime, EndTime       FROM Shift       WHERE Id IN :shiftIds     ];     List<String> serviceTerriroryIds = new List<String>();     for (Shift shift : shiftInfo) {       serviceTerriroryIds.add(shift.ServiceTerritoryId);     }      Map<String, String> mapSwtToServiceAppointmentLimitType = new Map<String, String>();      Map<String, String> mapStToServiceAppointmentLimitType = new Map<String, String>();     List<ServiceTerritory> sts = [       SELECT ServiceAppointmentLimitType, Id       FROM ServiceTerritory       WHERE Id IN :serviceTerriroryIds     ];     for (ServiceTerritory st : sts) {       mapStToServiceAppointmentLimitType.put(         st.Id,         st.ServiceAppointmentLimitType       );     }     Map<String, String> mapShiftToServiceTerritory = new Map<String, String>();     Map<String, Decimal> mapShiftToDuration = new Map<String, Decimal>();      for (Shift shift : shiftInfo) {       mapShiftToServiceTerritory.put(shift.Id, shift.ServiceTerritoryId);       Decimal shiftDuration =         (shift.EndTime.getTime() - shift.StartTime.getTime()) / (1000 * 60);       mapShiftToDuration.put(shift.Id, shiftDuration);     }     Map<String, Decimal> mapWorkTypeToDuration = new Map<String, Decimal>();      List<WorkType> wts = [SELECT Id, DurationInMinutes FROM WorkType];     for (WorkType wt : wts) {       mapWorkTypeToDuration.put(wt.Id, wt.DurationInMinutes);     }      Map<String, List<String>> mapShiftToWorkTypeGroupList = new Map<String, List<String>>();      List<ShiftWorkTopic> shiftWorkTopics = [       SELECT Id, WorkTypeId, ShiftId, MaxAppointments       FROM ShiftWorkTopic       WHERE ShiftId IN :shiftIds AND WorkTypeId != NULL     ];      for (ShiftWorkTopic swt : shiftWorkTopics) {       List<String> existingSWTList = mapShiftToWorkTypeGroupList.get(         swt.ShiftId       );       if (existingSWTList == null) {         existingSWTList = new List<String>{ (String) swt.WorkTypeId };       } else {         existingSWTList.add(swt.WorkTypeId);       }       mapShiftToWorkTypeGroupList.put(swt.ShiftId, existingSWTList);     }      Map<String, List<ShiftWorkTopic>> mapShiftToSWTList = new Map<String, List<ShiftWorkTopic>>();      for (ShiftWorkTopic swt : shiftWorkTopics) {       List<ShiftWorkTopic> existingSWTList = mapShiftToSWTList.get(swt.ShiftId);       if (existingSWTList == null) {         existingSWTList = new List<ShiftWorkTopic>{ swt };       } else {         existingSWTList.add(swt);       }       mapShiftToSWTList.put(swt.ShiftId, existingSWTList);     }     Map<String, Integer> mapSWTToConcurrency = new Map<String, Integer>();     for (ShiftWorkTopic swt : shiftWorkTopics) {       if (swt.MaxAppointments != null) {         mapSWTToConcurrency.put(swt.Id, swt.MaxAppointments);       } else {         mapSWTToConcurrency.put(swt.Id, 1);       }     }      // main code starts here      for (String shiftId : shiftIds) {       String ServiceAppointmentLimitType = mapStToServiceAppointmentLimitType.get(         mapShiftToServiceTerritory.get(shiftId)       );       if (         ServiceAppointmentLimitType == 'Maximum Limit' ||         ServiceAppointmentLimitType == null       ) {         if (mapShiftToSWTList.get(shiftId) == null) {           // No SWT in this shift do no process           continue;         }         Double shiftDuration = mapShiftToDuration.get(shiftId);         for (ShiftWorkTopic swt : mapShiftToSWTList.get(shiftId)) {           Double workTypeDuration = mapWorkTypeToDuration.get(swt.WorkTypeId);           Double concurrency = mapSWTToConcurrency.get(swt.Id);           swt.ServiceAppointmentLimit = ((shiftDuration / workTypeDuration)               .intValue() * concurrency)             .intValue();         }       } else if (ServiceAppointmentLimitType == 'Achievable Limit') {         List<ShiftWorkTopic> swtList = mapShiftToSWTList.get(shiftId);         if (swtList == null) {           // No SWT in this shift do no process           continue;         }         Integer maximumCapacity = 0;         Decimal shiftDuration = mapShiftToDuration.get(shiftId);          for (ShiftWorkTopic swt : mapShiftToSWTList.get(shiftId)) {           Integer concurrency = mapSWTToConcurrency.get(swt.Id);           Double workDuration = mapWorkTypeToDuration.get((swt.WorkTypeId));           maximumCapacity = Math.max(             maximumCapacity,             (shiftDuration / workDuration).intValue() * concurrency           );         }         Integer finalCapacity = 0;          for (Integer cap = 0; cap <= maximumCapacity; cap++) {           Double sumLHS = 0;            for (ShiftWorkTopic swt : mapShiftToSWTList.get(shiftId)) {             Integer concurrency = mapSWTToConcurrency.get(swt.Id);             Double workDuration = mapWorkTypeToDuration.get(swt.WorkTypeId);             sumLHS += Math.ceil((1.0 * cap) / concurrency) * workDuration;           }           if (sumLHS <= shiftDuration) {             finalCapacity = cap;           } else {             break;           }         }          for (ShiftWorkTopic swt : mapShiftToSWTList.get(shiftId)) {           swt.ServiceAppointmentLimit = finalCapacity;         }       }     }      update shiftWorkTopics;   }    global void finish(Database.BatchableContext BC) {     // Send notification or log the completion     System.debug('Batch job completed successfully.');   } }`
2. Create an Apex Class called InitialiseExistingSWTWithCapacity to trigger approval workflows. See [Define Apex Classes](https://help.salesforce.com/s/articleView?id=platform.code_define_package.htm&type=5&language=en_US).
3. From Setup, select **Developer Console**.
4. In the Developer Console, click **Debug**, then click **Open Execute Anonymous Window**.
5. **Execute** this code.
    
    `InitialiseExistingSWTWithCapacity batchJob = new InitialiseExistingSWTWithCapacity();  Integer batchSize = 200;  Database.executeBatch(batchJob, batchSize);`
6. To view the progress of the script, in Setup, find and select **Apex Jobs**.