When syncing an object like a "Note" or "Campaign Member" which has non-updateable fields (like the Parent on both of these), the initial sync works great but we've had to use hook_salesforce_push_params_alter() to avoid sending these items on update operations, as the Salesforce API refuses the entire update if you include them.

The API actually provides an "updateable" flag for these fields, and we can just use that to determine whether to send these field values during updates. I've attached a relatively simple patch to do this.

CommentFileSizeAuthor
dont_update_non_updateable_fields.patch2.46 KBgcb

Comments

gcb created an issue. See original summary.

aaronbauman’s picture

Status: Needs review » Reviewed & tested by the community

hard to argue with that

gcb’s picture

@tauno has pointed out that we need to test the behavior with upserts, which I haven't done. Any chance you looked at that Aaron? I suspect it will work fine but flagging it here so it gets looked at before committing.

aaronbauman’s picture

I think this patch is a step in the right direction.
The only 100% safe way to do an upsert is to only send values which are both createable and updateable.

We could add error handling to deal with non-createable and non-updateable fields for upserts, but I think those errors will mostly be edge cases. In my own experience, I'm mostly using update-only or create-only fields as pull-only. Do you have different use cases in mind?

When #2186153: Provide additional Salesforce push/pull hooks for pre_export changes. gets in, we'll be able to delegate the edge cases to other contrib.

gcb’s picture

Well, the upsert functions are different API calls on Salesforce, so my assumption is that Salesforce won't complain about sending non-updateable fields in a case where we are explicitly uncertain if we are doing an insert or an update: we just need to test that assumption. Hopefully that's accurate and all is fine: we also need to make sure that my code hasn't stopped those values from populating in upserts.

aaronbauman’s picture

Actually I'd guess that SF will complain if you try to update a non-updateable field, even when using upsert, but I can't find anything to test and I can't find any answers in SF documentation.

That said, a createable-but-not-updateable field is an edge case.
There are none on standard objects like Account, Contact, Opportunity, Campaign, Case.
All the non-updateable fields on these objects are also non-createable.
"IsConverted" flag on a Lead is createable-but-not-updateable, but not a useful example because it's tied into SF's core lead-conversion workflow, and heavily locked down.
And, there's no way (at least not through the UI) to create a custom createable-but-not-updateable field.

gcb’s picture

The common create-able but not update-able fields that I use regularly are all object references. For both Notes and Campaign Memberships, the parent object reference is non-updateable. The same is true for Campaign Member's Contact reference: these are the use cases this patch was specifically written to handle.

aaronbauman’s picture

gotcha, i think those are both Master-Detail relationships.

Upsert will complain.

Here's my drush test with CampaignMember and an external foreign key called "TEST_FK__c":

> drush ev '$api = salesforce_get_api(); print_r($api->objectUpsert("CampaignMember", "TEST_FK__c", 2, array("CampaignId" => "701q0000000IBP1", "ContactId" => "003q000000Nd9eP")));'
Array
(
    [id] => 00vq00000021VzmAAE
    [success] => 1
    [errors] => Array
        (
        )

)
> drush ev '$api = salesforce_get_api(); print_r($api->objectUpsert("CampaignMember", "TEST_FK__c", 2, array("CampaignId" => "701q0000000IBP1", "ContactId" => "003q000000Nd9eP")));'
WD php: SalesforceException: Unable to create/update fields: ContactId, CampaignId. Please check the security settings of this field and verify that [error]
it is read/write for your profile or permission set. in Salesforce->checkResponseDataForApiError() (line 155 of
salesforce/includes/salesforce.inc).

All that said, this bug is already present in this module, and probably merits its own issue.

  • tauno committed 4f445d3 on 7.x-3.x authored by gcb
    Issue #2601416 by gcb: Updates pushing to non-updateable fields causes...
tauno’s picture

Status: Reviewed & tested by the community » Fixed

Committed in 4f445d3. I'm not sure there's a good way of handling the upsert case. Extending hook_salesforce_push_fail to be called for REST push failures would make it easier to handle the upsert failures.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.