In Spring ’22 Salesforce Release – Scheduler Product introduced the Manage Service Resource Availability by Using Shifts feature which gave flexibility for service resources to work flexible hours instead of the Service Territory Operating Hours. This feature was extended in Winter ’23 with the flexibility to create Recurring Shifts – which gave an easy way for Territory Managers and Service Resources to create multiple shifts with a single record data entry.
This was made possible by capturing the recurring pattern of the shift during data entry.
And Salesforce saves this recurring shift as a single record with Type field as “Recurring”.
Salesforce Scheduler saves the recurrence pattern when the original recurrence shift record is saved. The information is saved in “RecurrencePattern” field on the same Shift record. An example pattern as saved on the record
This information corelates to what gets saved as shown in the screenshot – Weekly recurring Event which occurs every Monday, Wednesday and Friday for the next 4 occurrences and repeats every week.
NOTE: Salesforce Scheduler considers the recurrence period in the service territory’s timezone. The period of recurrence is limited to 120 days. For example, you create a recurring shift on July 1, 2022. You can choose an end date that’s either less than or equal to 120 days from July 1, 2022, or the number of occurrences that are repeated within 120 days from July 1, 2022.
Cloning Shift Records
Scheduler product also gave the option to clone shift records. When a user tries to clone a Shift record with the Type field value set to Recurring, the new record creation screen that opens, Salesforce prepopulates the Start and End Times of the Shift, Status, Service Territory, Service Resource and the Time Slot Type fields. You will notice, it does NOT prepopulate the recurring Pattern (at this point of time).
This is a limitation in the current scheduler product, until this feature gets included in future (Roadmap).
In this blog we are going to look at an option to clone the Shift along with its recurring Pattern using Apex
Cloning Shift Records with Recurring Pattern
We want to keep it simple here in this blog. This is just a quick and dirty work around, but feel free to take it to the next level. As you have noticed when using the Clone button on the Shift (with type as recurring) – the new shift screen that opens has all the information from the previous record copied, except for the Recurrence pattern.
The copying of recurrence pattern is handled in the trigger which will copy it from the Original Shift where we are cloning the record from.
Use the sample trigger code below on the Shift Object to copy the recurrence pattern
trigger CloningRecurringShift on Shift (Before insert) { for(Shift sh : Trigger.New){ if(sh.Type =='Recurring' && sh.IsClone()==true && sh.RecurrencePattern=='RRULE:INTERVAL=1;'){ String sourceId = sh.getCloneSourceId(); Shift orginalShift = [Select RecurrencePattern from shift where ID=:sh.getCloneSourceId()]; System.debug('Orginal Shift recurring patternt ' + orginalShift.RecurrencePattern); sh.put('RecurrencePattern',orginalShift.RecurrencePattern);
} } }
Note: If updating the other fields (not the recurrence type section) that were copied over when you tried to Clone, the saved record will consider the new updated values.
In recurring shift we have added 2 new fields which will allow users to upload daily weekly and monthly shift. A sample request payload is given below for the steps 7 in the above doc.
/services/data/<version number>/jobs/ingest/<job Id>/batchesUse the contentUrl from the POST method and append a forward slash (/) at its beginning.Example:/services/data/v54.0/jobs/ingest/7505j000005JqZrAAK/batches
HTTP Method
PUT
Headers
Content-Type: text/csvAccept: application/json
Request Body
The contents of the CSV file. Example:ShiftId,WorkTypeId,WorkTypeGroupId,AreAllTopicsSupported0a0x000000003Q6AAI,,,TRUE0a0x000000005kuAAA,,,TRUE0a0x000000003QBAAY,,0VSx00000002UgzGAE,0a0x000000003QBAAY,,0VSx00000002Uh4GAE,
C. Rest same from steps number 8 from above reference doc
Bulk shift upload for multiple channels and multiple topic
Upload Channel to Shift
Create the Shift and get the Shift Id for which the user want to add multple chanel
Get all the channel Id which user wants want to add to shift
/services/data/<version number>/jobs/ingest/<job Id>/batchesUse the contentUrl from the POST method and append a forward slash (/) at its beginning.Example:/services/data/v54.0/jobs/ingest/7505j000005JqZrAAK/batches
HTTP Method
PUT
Headers
Content-Type: text/csvAccept: application/json
Request Body
The contents of the CSV file. Example:ShiftId,EngagementChannelTypeId,AreAllEngmtChnlSupported0a0x000000005vZAAQ,0eFx00000000006EAA,0a0x000000005vaAAA,0eFx00000000006EAA,0a0x000000005vaAAA,0eFx0000000000BEAQ,0a0x000000005vbAAA,,TRUE0a0x000000005vcAAA,,TRUE
Rest same from steps number 8 from above reference doc
https://unofficialsf.com/wp-content/uploads/2022/09/largeUCSF-300x133.png00Ahttps://unofficialsf.com/wp-content/uploads/2022/09/largeUCSF-300x133.pngA2022-08-09 20:34:552022-08-09 20:38:07By Mrityunjoy Chowdhury: Bulk Shift upload with recurring Shift and Add multiple topic and channel
Shift is one of the major additions made in Salesforce Scheduler, It provides the user with enormous flexibility and makes the entire process of appointment scheduling less cumbersome. The diagram below shows the interaction between Shift and various other entities involved in scheduling a Service Appointment.
A Service Territory Member can have multiple Shifts associated with it and as a result the time slot selected for the Service Appointment can fall between more than one overlapping shifts (considering both the required and primary Service Resources).
In the following sections we will figure out a way to reverse map all the associated Shifts with corresponding Service Appointment.
Creating a custom object
For completing the purpose of reverse mapping Shift with Service Appointment a custom object(Service appointment shift) is used as a junction object. It comprises of the following custom fields:-
ServiceAppointnmentId – Referring to a Service Appointment.
ShiftId – Referring to a Shift whose startTime and endTime completely encloses the Service Appointment’s time slot.
Modified – A boolean flag to help backtrack all the updates made to Service Appointment.Only the records with the flag value false should be considered as reliable entries.
Canceled – A boolean flag which is set to true only when the associated Service Appointment is canceled.
As evident from the design proposed whenever a Service Appointment is scheduled we need to obtain all the Shifts associated with the Service Appointment.For each associated Shift, one record comprising of ServiceAppointmentId,ShiftId
and Modified(initially false) must be made.
For achieving our goal of reverse mapping we will be writing triggers on two entities:
Service Appointment
Assigned Resource
Creating a Service Appointment
We must do the reverse mapping the moment a Service Appointment is created.Whenever a Service Appointment is created necessary inserts are made in Assigned Resource and this will invoke the trigger that we will be writing for Assigned Resource .
Pseudocode
Let us first discuss the pseudocode for triggers when new Service Appointments are created.
Create a trigger which runs after inserts are made in Assigned Resource.
Fetch all the linked Service Appointments using the just inserted Assigned Resource records.
Check for any previous entries for obtained Service Appointments in the custom object and for all those records set the Modified as true.
Design a map of Service Appointment and all the required resources for that appointment.
Loop through all the Service Appointments in the map and obtain the associated Shifts of the Service Resource.
Do the inserts for Service Appointment and Shift mapping records.
Updating a Service Appointment
Whenever a Service Appointment is modified we can make changes in the time slot and the required resources of the Service Appointment.Once a Service Appointment is updated we must set the Modified field for all the records of this Service Appointment in the custom object to true and obtain new associated Shifts. Let’s have a look at the possible scenarios and the way we are handling it.
Deletion of required SR from Appointment(will invoke an after delete trigger on Assigned Resource)
Addition of required SR to Appointment(will invoke an after insert trigger on Assigned Resource)
Moving of SR from required to optional resource(will invoke an after update trigger on Assigned Resource)
Moving of SR from optional to required resource(will invoke an after update trigger on Assigned Resource)
Change in Appointment start time and/or end time
Change in Appointment WTG/WT (Appointment duration)
Changing the time slot at the same time altering the Assigned Resources.
For these cases we will be using one update and a delete trigger on Assigned Resource wherein we implement a similar logic as mentioned above.
Disclaimer: The following code is meant to be verbose and easily understandable from a Salesforce Developer perspective. Given a choice between performance vs readability I have strived for the latter. It is a proof of concept to demonstrate the feature and should be modified and tested thoroughly as per different data shapes and existing code in the org.
trigger getassociatedshifts on AssignedResource (after insert,after update,after delete) {
/* fetching all the linked service appointments from the trigger */
List<ServiceAppointment> AllAppointments = new List<ServiceAppointment>();
if(Trigger.isDelete) {
List<String> AffectedAppointments = new List<String>();
For(AssignedResource a:Trigger.old) {
AffectedAppointments.add(a.ServiceAppointmentId);
}
AllAppointments = [Select Id,ServiceTerritoryId,SchedStartTime,SchedEndTime,WorkTypeId from ServiceAppointment where Id In :AffectedAppointments];
} else {
AllAppointments = [Select Id,ServiceTerritoryId,SchedStartTime,SchedEndTime,WorkTypeId from ServiceAppointment where Id In (Select ServiceAppointmentId from AssignedResource where Id In :Trigger.New)];
}
/*
check for any previous entries for obtained service appointments in the custom object
and for all those records set the modified flag as true
ServiceResourceToServiceAppointment = [Select ServiceResourceId,ServiceAppointmentId from AssignedResource where ServiceAppointmentId in:AllAppointments
For(Service_appointment_shift__c all:[Select id,modified__c from Service_appointment_shift__c where Service_Appointment__c In :changed]) {
all.Canceled__c =true;
all.Modified__c = true;
ServiceAppointmentShiftToUpdate.add(all);
}
/* updating the records */
update ServiceAppointmentShiftToUpdate;
}
https://unofficialsf.com/wp-content/uploads/2022/09/largeUCSF-300x133.png00Sunilhttps://unofficialsf.com/wp-content/uploads/2022/09/largeUCSF-300x133.pngSunil2022-04-28 03:54:132022-06-22 01:58:39From Adwait & Mrityunjoy Chowdhury: Reverse Map Service Appointment to the appropriate shift