fsl-work-order-migration

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.

Best use case

fsl-work-order-migration is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

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.

Teams using fsl-work-order-migration should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/fsl-work-order-migration/SKILL.md --create-dirs "https://raw.githubusercontent.com/PranavNagrecha/AwesomeSalesforceSkills/main/skills/data/fsl-work-order-migration/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/fsl-work-order-migration/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How fsl-work-order-migration Compares

Feature / Agentfsl-work-order-migrationStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

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.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# FSL Work Order 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.

---

## Before Starting

Gather this context before working on anything in this domain:

- Confirm whether historical completed appointments are in scope or only open/scheduled records. Migrating Completed status requires the `Completed` value to be active in the ServiceAppointment Status picklist before load.
- Determine whether FSL scheduling automation (Global Optimization, territory-based auto-scheduling) should fire during migration or be disabled. AssignedResource inserts can trigger scheduling engine recalculations — this must be disabled during migration.
- Verify PricebookEntry records exist for all products that appear in ProductConsumed records. Missing PricebookEntry prevents ProductConsumed insert.
- Confirm External ID fields are added to all FSL objects used in the migration for upsert-safe re-run capability.

---

## Core Concepts

### Insert Order — FSL Object Hierarchy

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:

1. Account / Contact / Asset (if not already present)
2. WorkOrder (lookup to Account, Contact, Asset optional)
3. WorkOrderLineItem (lookup to WorkOrder)
4. ServiceAppointment (lookup to WorkOrder or WorkOrderLineItem)
5. AssignedResource (lookup to ServiceAppointment + ServiceResource)
6. ProductConsumed (lookup to WorkOrderLineItem + PricebookEntry)

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.

### Status Picklist Constraints

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.

### Scheduling Automation During Migration

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:
- Conflict with migrated scheduled times
- Generate duplicate scheduling history
- Slow the migration significantly

**Best practice:** Disable FSL optimization settings in Setup > Field Service Settings before migration. Re-enable after load completes and data is validated.

### ProductConsumed Requirements

`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.

---

## Common Patterns

### Upsert with External IDs

**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.

### Disabling Automation Before Migration

**When to use:** Any time AssignedResource or ServiceAppointment records are loaded in bulk.

**How it works:**
1. Setup > Field Service Settings > Scheduling > uncheck "Enable Optimization"
2. If using FSL Triggers (managed package), disable via `FinServ__TriggerSettings__c` custom setting equivalent for FSL — or use the FSL Trigger Settings custom setting to disable individual triggers
3. Load migration data
4. Re-enable settings
5. Validate assigned resource records and scheduled times

---

## Decision Guidance

| 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 |

---

## Recommended Workflow

Step-by-step instructions for an AI agent or practitioner working on this task:

1. **Inventory all source status values** — Extract distinct ServiceAppointment Status values from source data. Confirm each is active in the target org's Status picklist. Activate missing values before migration begins.
2. **Disable FSL scheduling automation** — In Setup > Field Service Settings, disable optimization before loading any AssignedResource or ServiceAppointment records.
3. **Add External ID fields** — Add `Legacy_Id__c` (or equivalent) External ID fields to WorkOrder, WorkOrderLineItem, ServiceAppointment, AssignedResource, and ProductConsumed.
4. **Pre-load Products and PricebookEntry records** — Ensure all products referenced by ProductConsumed have active PricebookEntry records in the standard pricebook.
5. **Load in strict hierarchy order** — Account/Contact/Asset → WorkOrder → WorkOrderLineItem → ServiceAppointment → AssignedResource → ProductConsumed. Validate zero errors at each step before proceeding.
6. **Re-enable FSL automation** — After all records are loaded and spot-validated, re-enable scheduling optimization in Field Service Settings.
7. **Validate data integrity** — Run SOQL to confirm all ServiceAppointments have at least one AssignedResource where expected, all ProductConsumed records have valid PricebookEntryId, and status values match source data.

---

## Review Checklist

- [ ] All source ServiceAppointment status values are active in target org
- [ ] FSL optimization disabled before AssignedResource load
- [ ] External IDs added to all FSL migration objects
- [ ] Products and PricebookEntry records exist for all ProductConsumed references
- [ ] Migration runs in strict hierarchy order with zero errors at each step
- [ ] FSL optimization re-enabled and validated after migration
- [ ] Post-load SOQL validation run to check record counts and key field values

---

## Salesforce-Specific Gotchas

Non-obvious platform behaviors that cause real production problems:

1. **Status picklist validation is hard — not advisory** — Inserting a ServiceAppointment with a status value not in the org's picklist throws `INVALID_OR_NULL_FOR_RESTRICTED_PICKLIST`. This stops bulk loads and requires picklist activation before the load, not after.
2. **AssignedResource inserts trigger FSL scheduling engine** — Inserting AssignedResource records without disabling optimization can trigger time-slot recalculations that overwrite migrated scheduled times or generate spurious history records.
3. **ProductConsumed requires PricebookEntry, not just Product** — A Product2 record alone is insufficient. The product must have an active PricebookEntry in a pricebook assigned to the Work Order's account. Missing PricebookEntry throws `FIELD_INTEGRITY_EXCEPTION`.
4. **Case migration and Work Order migration are separate** — Work Orders may be related to Cases but the two objects have independent migration paths. Loading WorkOrders that reference non-existent Case records will fail on the lookup field — migrate Cases first if WO-Case relationships are in scope.

---

## Output Artifacts

| 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 |

---

## Related Skills

- data/fsl-territory-data-setup — Service territory, operating hours, and resource data setup required before FSL work order migration
- data/fsl-resource-and-skill-data — ServiceResource and ServiceResourceSkill data that AssignedResource records reference

Related Skills

network-security-and-trusted-ips

8
from PranavNagrecha/AwesomeSalesforceSkills

Configure and audit Salesforce network security controls — trusted IP ranges (org-wide Network Access), login IP ranges on profiles, CSP Trusted Sites for Lightning components, CORS allowlists for external JavaScript, and TLS requirements — and troubleshoot login-blocked-by-IP or CSP violation errors. NOT for org-wide session settings, MFA configuration, or real-time Transaction Security Policies.

customer-data-request-workflow

8
from PranavNagrecha/AwesomeSalesforceSkills

Implement GDPR/CCPA data subject rights (access, deletion, rectification) using Salesforce Privacy Center and/or custom workflow. NOT for general backup or org-level data retention policy.

vlocity-to-native-omnistudio-migration

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when migrating an org from the Vlocity managed package (vlocity_ins, vlocity_cmt, vlocity_ps) to native OmniStudio. Trigger keywords: Vlocity to OmniStudio migration, namespace migration, vlocity_ins to omnistudio, OmniStudio Migration Tool, DataRaptor namespace update, OmniScript JSON export, managed package to native. NOT for new OmniStudio setup in greenfield orgs, nor for migrating between OmniStudio-native orgs, nor for Salesforce CPQ to Industries CPQ migration.

omnistudio-lwc-omniscript-migration

8
from PranavNagrecha/AwesomeSalesforceSkills

Migrate classic Visualforce-based OmniScripts to LWC-based runtime with feature parity and regression testing. NOT for new OmniScript design.

visualforce-to-lwc-migration

8
from PranavNagrecha/AwesomeSalesforceSkills

Migrating Visualforce pages and components to Lightning Web Components: controller-to-Apex-method translation, viewstate replacement, custom URL parameter handling, PageReference-to-NavigationMixin mapping, Lightning Out coexistence, and inline VF retention strategy. NOT for new LWC development from scratch (use lwc-fundamentals) or Aura-to-LWC migration (use aura-to-lwc-migration).

lwc-locker-to-lws-migration

8
from PranavNagrecha/AwesomeSalesforceSkills

Migrating LWCs from Lightning Locker Service to Lightning Web Security (LWS) — flipping the org switch safely, identifying components likely to break, removing Locker workarounds that are now insecure, and validating third-party libraries that previously failed under SecureWindow/SecureElement proxies. NOT for Aura → LWC migration — see lwc/aura-to-lwc-migration. NOT for general LWC security review (XSS, public-API hardening) — see lwc/lwc-security and lwc/lwc-public-api-hardening.

aura-to-lwc-migration

8
from PranavNagrecha/AwesomeSalesforceSkills

Migrating Aura components to LWC: feature mapping, interoperability wrappers, event translation, navigation patterns, and Aura-LWC coexistence strategies. NOT for new LWC development from scratch or Aura feature development.

slack-workflow-builder

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when designing or troubleshooting Slack Workflow Builder workflows that call Salesforce — especially the Salesforce connector step Run a Flow, mapping inputs/outputs, handling failures, and understanding limits. Triggers on: Slack Workflow Builder Salesforce, Run a Flow from Slack, autolaunched flow from Slack, Slack automation calling Salesforce. NOT for Salesforce Flow Builder tutorials unrelated to Slack (use flow skills), not for Flow Core Actions that send Slack messages from Salesforce (use flow-for-slack), not for initial org-to-workspace connection (use slack-salesforce-integration-setup), and not for building custom Slack apps outside Workflow Builder.

workflow-rule-to-flow-migration

8
from PranavNagrecha/AwesomeSalesforceSkills

Migrate Workflow Rules to record-triggered Flows: field update mapping, email alert migration, outbound message alternatives using Flow Core Actions, time-based workflow replacement with Scheduled Paths. NOT for Process Builder migration (use process-builder-to-flow-migration), NOT for building new flows from scratch.

process-builder-to-flow-migration

8
from PranavNagrecha/AwesomeSalesforceSkills

Migrate Process Builder processes to record-triggered Flows using the native Migrate to Flow tool or manual rebuild. Covers conversion tool usage, pattern mapping, order-of-execution changes, testing migrated flows, and bulk behavior improvements. NOT for building new flows from scratch, NOT for Workflow Rule migration (use workflow-rule-to-flow-migration), NOT for net-new automation design.

flow-record-save-order-interaction

8
from PranavNagrecha/AwesomeSalesforceSkills

Reason about how record-triggered flows interleave with the Salesforce Save Order (validation, before-save flows, before triggers, duplicate rules, after-save flows, workflow, after triggers, assignment, auto-response, escalation). Trigger keywords: save order, before-save flow, after-save flow, dml order, trigger vs flow order. Does NOT cover writing trigger handlers, approval process setup, or workflow rule migration.

flow-migration-from-trigger

8
from PranavNagrecha/AwesomeSalesforceSkills

Decide whether an existing Apex trigger should be rewritten as a Flow, and execute the migration safely. Covers the decision criteria (complexity, ownership, performance), side-by-side rollout, test-coverage parity, and the inverse case (recognize when Flow should stay Apex). NOT for migrating Process Builder / Workflow Rule to Flow (use those migration skills). NOT for brand-new automation decisions (use automation-selection.md).