Use this skill when migrating Work Order, Work Order Line Item, Service Appointment, AssignedResource, and ProductConsumed data into a Salesforce Field Service org. Trigger keywords: FSL data migration, WorkOrder import, ServiceAppointment migration, AssignedResource load, ProductConsumed migration, work order history data load. NOT for Case data migration, standard Account/Contact migration without FSL objects, or configuring FSL after a migration.
This skill activates when a data migration project includes Field Service Lightning (FSL) work order objects: WorkOrder, WorkOrderLineItem, ServiceAppointment, AssignedResource, and ProductConsumed. FSL's object hierarchy, status-based automation, and scheduling engine introduce insert-order constraints and automation-firing risks not present in standard CRM migrations.
Gather this context before working on anything in this domain:
Completed value to be active in the ServiceAppointment Status picklist before load.FSL's object model has strict parent-child dependencies. Attempting to insert child records before parents fail with lookup validation errors. The correct sequence is:
Each step must complete with zero errors before proceeding to the next. Use External IDs and upsert operations so failed loads can be re-run without duplicates.
ServiceAppointment has a Status picklist whose values are tied to FSL lifecycle transitions. Attempting to insert a ServiceAppointment record with a status value (e.g., Completed, Cannot Complete) that does not exist as an active picklist value in the target org will fail.
Before migration, verify all source status values are active in the target org's ServiceAppointment Status picklist. For historical closed appointments, this means activating Completed, Cannot Complete, and any custom values present in the source system.
When AssignedResource records are inserted, FSL's territory-based scheduling engine may interpret the insert as a new assignment and trigger optimization jobs, recalculations, or time-slot evaluations. These can:
Best practice: Disable FSL optimization settings in Setup > Field Service Settings before migration. Re-enable after load completes and data is validated.
ProductConsumed records represent parts actually used on a job. They require a PricebookEntryId lookup to a valid PricebookEntry for the product. If the PricebookEntry does not exist (e.g., product is not in the org's standard pricebook), the insert fails.
Pre-migration step: load or confirm all Products and their PricebookEntry records in the standard pricebook before loading ProductConsumed.
When to use: All FSL migration loads to ensure re-runnable, duplicate-safe loads.
How it works: Add a custom External ID field (e.g., Legacy_Id__c) to WorkOrder, WorkOrderLineItem, ServiceAppointment, AssignedResource, and ProductConsumed. Use Data Loader or the Bulk API 2.0 upsert operation with the external ID as the match key.
// Data Loader upsert mapping
WorkOrder.Legacy_Id__c → Source.WORK_ORDER_ID
WorkOrder.Account__r.Legacy_Account_Id__c → Source.ACCOUNT_ID
Why not insert: Plain insert with no External ID makes re-runs create duplicates. Upsert allows resuming a failed migration without cleanup.
When to use: Any time AssignedResource or ServiceAppointment records are loaded in bulk.
How it works:
FinServ__TriggerSettings__c custom setting equivalent for FSL — or use the FSL Trigger Settings custom setting to disable individual triggers| Situation | Recommended Approach | Reason |
|---|---|---|
| Historical closed appointments | Activate Completed/CannotComplete status values before load | Status picklist insert validation fails otherwise |
| Large volume AssignedResource load | Disable FSL optimization before load | Prevents automation interference and slowdown |
| ProductConsumed missing PricebookEntry | Pre-load Products + PricebookEntry first | Hard dependency — insert fails without it |
| Need re-runnable migration | Use upsert with External IDs on all objects | Prevents duplicates on re-run |
| Migrating only open/scheduled (not historical) | Disable Completed status loading, focus on None/Scheduled | Simplifies status picklist requirements |
Step-by-step instructions for an AI agent or practitioner working on this task:
Legacy_Id__c (or equivalent) External ID fields to WorkOrder, WorkOrderLineItem, ServiceAppointment, AssignedResource, and ProductConsumed.Non-obvious platform behaviors that cause real production problems:
INVALID_OR_NULL_FOR_RESTRICTED_PICKLIST. This stops bulk loads and requires picklist activation before the load, not after.FIELD_INTEGRITY_EXCEPTION.| Artifact | Description |
|---|---|
| FSL migration sequence table | Ordered list of objects to load with dependency notes |
| Pre-migration configuration checklist | Status values, External IDs, automation disable steps |
| Post-migration validation SOQL | Queries to verify record counts and data integrity |