Salesforce — customize field mappings & sync custom objects

Out of the box, Turtini ships default mappings for Salesforce Account, Contact, and Opportunity. The Mappings editor lets you customize what each Salesforce field maps to in Turtini, and add mappings for any other SObject your org exposes — including custom `__c` objects.

Where to find it:
Settings → Integrations → Salesforce → "Mappings" tab (visible once your org is connected).

Editing an existing mapping:
1. Click the mapping row to expand it (Account / Contact / Opportunity are seeded as "Default" and can't be deleted, but every field row is editable)
2. Pick a Salesforce field from the dropdown — Turtini fetches the live SObject schema via Salesforce's `describe` API and caches it, so custom fields appear automatically
3. Set the Turtini field — for canonical destinations (Accounts / Contacts / Opportunities) it's a free-text dot-path like `billing.line1` or `address.city`, so nested-object writes work without a special editor
4. Optionally pick a Transform — `Text` / `Number` / `Currency` / `Date` / `True/False` / `Lowercase`, plus two Turtini-specific maps:
• `Pipeline stage (SF → Turtini)` translates Salesforce StageName values into Turtini's canonical pipeline stages
• `Deal type (SF → Turtini)` translates Salesforce Type values into Turtini's deal-type field
5. (Optional) Set a per-field Conflict policy — see Phase 5 below

Adding a mapping for a custom object:
1. Click "+ Add mapping"
2. Pick the SObject from the list (queryable + custom objects are all listed — `Project__c`, `Engagement__c`, whatever you have)
3. Choose a target:
• Canonical — write into `accounts`, `contacts`, or `opportunities` (good when the custom object is really an extension of one of those)
• External — write into `salesforceRecords`, a generic per-org collection that captures everything else. Custom objects land here by default; the source-of-truth view in Turtini shows them under "External Salesforce records"
4. Pick the Account lookup field (if you chose Contact / Opportunity as the canonical target) — Turtini uses it to link the synced record back to the parent Account
5. Add field-mapping rows the same way as editing
6. Save — Turtini saves the mapping and immediately runs a one-shot backfill for the object so you don't have to wait for the next sync

Enabling / disabling individual mappings:
Use the toggle on each mapping row to pause it without disconnecting. A paused mapping won't run on scheduled sync, manual "Sync now," or real-time CDC — useful while you're iterating on a field map and don't want partial writes landing in production.

What gets stored where:
• Mapping definitions live in `orgs/{orgId}/salesforceMappings/{mappingId}` — versioned and audited
• Synced records carry `salesforceId` (and `salesforceRecordType` for external rows), so you can always trace them back
• The SObject field cache is keyed by `{orgId, sobject}` so re-describing only happens when you click "Refresh fields"

Custom-field caveats:
• Formula fields work — they read fine but are read-only on the Salesforce side, so writeback is auto-disabled for them
• Picklist values map by API name, not label — make sure the value side of any transform matches what Salesforce actually stores
• Person Accounts: only the Account-side fields are visible; the Contact-half PersonAccount fields come through as Contact mappings

Permissions: only owners and admins can see or edit mappings. The Salesforce user that powers the connection still needs Read access in Salesforce to the fields you map — Turtini surfaces a Salesforce permission error inline if a describe or query fails.