Loading
ただいま大変多くのお問い合わせをいただいており、ご連絡までにお時間を頂戴しております続きを読む
Salesforce Scheduler での予定の管理
勤務時間の選択的な制限

勤務時間の選択的な制限

[シフトと共にサービステリトリーの営業時間を使用] スケジュールポリシーを有効にしている場合、Salesforce Scheduler ではシフトとサービステリトリーの業務時間の交差部分を使用して、すべてのサービスリソースの対応可能状況を決定します。ただし、数人のサービスリソースのみについては勤務時間をサービステリトリーの業務時間に制限する場合は、トリガーを使用します。

必要なエディション

使用可能なインターフェース: Lightning Experience。
使用可能なエディション: Enterprise Edition および Unlimited Edition

まず、カスタム Boolean 項目の OvertimeEnabled を作成して、サービステリトリーの業務時間を超えて作業できるリソースを指定します。次に、サービステリトリーメンバーのシフトのみを使用して予定へのサービスリソースの対応可能状況を決定するようにスケジュールポリシーを変更します。次に、シフトの作成前および更新前に実行される Apex トリガーをシフトオブジェクトに作成します。トリガーではシフト時間を検証し、OvertimeEnabled 項目値が false になっているリソースのサービステリトリーの業務時間内にシフト時間が入っていることを確認します。

  1. サービスリソースのオブジェクト管理設定から、[項目とリレーション] に移動します。
  2. [新規] をクリックします。
  3. [チェックボックス] を選択し、[次へ] をクリックします。
  4. [項目の表示ラベル] 項目に「OvertimeEnabled」と入力し、[次へ] をクリックします。
  5. 項目レベルセキュリティを設定し、必要なプロファイルへのアクセス権を指定して、[次へ] をクリックします。
  6. 変更内容を保存します。
  7. [設定] の [クイック検索] ボックスに「スケジュールポリシー」と入力し、[スケジュールポリシー] を選択します。
  8. [サービステリトリーメンバーのシフトを使用] スケジュールポリシーを選択し、[シフトと共にサービステリトリーの営業時間を使用] スケジュールポリシーを選択解除します。
  9. シフトのオブジェクト管理設定から、[トリガー] に移動します。
  10. [新規] をクリックします。
  11. デフォルトコードを次のコードに置き換えます。
    trigger ShiftValidation on Shift (before insert, before update) {
        List<Shift> shifts = Trigger.new;
    
        Set<String> sr = new Set<String>();
        for(Shift shift: shifts) {
            sr.add(shift.ServiceResourceId);
        }
        
        List<ServiceResource> extendedSr = [SELECT Id FROM ServiceResource WHERE  OvertimeEnabled__c = False AND Id IN :sr];
        
        Set<String> srIds = new Set<String>();
        for(ServiceResource sr1: extendedSr) {
            srIds.add(sr1.Id);
        }
        
        Set<Shift> confirmedShifts = new Set<Shift>();
        Set<String> territoryIds = new Set<String>();
        //We will only run this validation for Shifts with Status Category = "Confirmed" AND Service Resource can work extended hours
        for(Shift shift: shifts) {
            if(shift.StatusCategory == 'Confirmed' && srIds.contains(shift.ServiceResourceId)) {
                confirmedShifts.add(shift);
                territoryIds.add(shift.ServiceTerritoryId);
            }
        }
    
        if(confirmedShifts.size() > 0) {
            //Get all Service Territory IDs along with their OperatingHourId
            ServiceTerritory[] territoryIdsWithOperatingHours = [SELECT Id, OperatingHoursId FROM ServiceTerritory WHERE Id IN :territoryIds];
    
            Set<String> operatingHourIds = new Set<String>();
            for(ServiceTerritory st: territoryIdsWithOperatingHours) {
                //Service Territory may not have Operating Hour defined
                if(st.OperatingHoursId != null) {
                    operatingHourIds.add(st.OperatingHoursId);
                }
            }
    
            //Get Timeslot information for all Operating Hours got in previous step. We disregard all STM level concurrent timeslots (Shifts with MaxAppointments set to 1)
            TimeSlot[] timeSlots = [SELECT Id, DayOfWeek, StartTime, EndTime, OperatingHoursId FROM TimeSlot WHERE MaxAppointments = 1 AND OperatingHoursId IN :operatingHourIds];
    
            //Complex data structure to store Working hours for all Service territories. We will store empty inner map in case Service Territory does not have Operating Hour defined
            Map<String, Map<String, TimeSlot>> serviceTerritoryWithTimeSlotsPerDay = new Map<String, Map<String, TimeSlot>>();
    
            for(ServiceTerritory territory: territoryIdsWithOperatingHours) {
                Map<String, TimeSlot> timeSlotsPerDay = new Map<String, TimeSlot>();
    
                for(TimeSlot timeSlot: timeSlots) {
                    if(timeslot.OperatingHoursId == territory.OperatingHoursId) {
                        timeSlotsPerDay.put(TimeSlot.DayOfWeek.substring(0,3), TimeSlot);
                    }
                }
                serviceTerritoryWithTimeSlotsPerDay.put(territory.Id, timeSlotsPerDay);
            }
    
            //Main validation logic for all confirmed shifts
            for(Shift s: confirmedShifts) {
                String dayOfShiftStart = ((Datetime) s.StartTime).format('E').substring(0,3);
                String dayOfShiftEnd = ((Datetime) s.EndTime).format('E').substring(0,3);
    
                Map<String, TimeSlot> slots = serviceTerritoryWithTimeSlotsPerDay.get(s.ServiceTerritoryId);
    
                if(dayOfShiftStart != dayOfShiftEnd) {
                    s.addError('Shift should be within Service Territory\'s Operating hours ');
                } else if(slots.get(dayOfShiftStart) == null || slots.get(dayOfShiftEnd) == null) {
                    s.addError('Operating Hours for Service Territory not set up correctly');
                }else if(s.StartTime.time() < slots.get(dayOfShiftStart).StartTime || s.EndTime.time() > slots.get(dayOfShiftEnd).EndTime) {
                    s.addError('Shift should be within Service Territory\'s Operating hours ');
                }
            }
        }
    }
    
  12. 変更内容を保存します。
 
読み込み中
Salesforce Help | Article