I can set up a mapping between a User account and Salesforce Contact, and a mapping between a Profile2 entity and Salesforce Contact. When I save a user profile, two distinct Salesforce Contacts are updated/created from the same Drupal user / profile entity. What is needed is a way to have the Profile2 <-> Salesforce Contact mapping sync to the same Salesforce ID as the Drupal User <-> Salesforce Contact.

This could be done with the Salesforce alter hooks documented in salesforce.api.php via a contributed module, but given the limited scope of the problem and the popularity of Profile2, it could be worth including in this Salesforce Suite.

@levelos do you have a preference on how to address this?

Comments

rickyoh’s picture

StatusFileSize
new549 bytes

My solution for this is as follows:

Add a property, computed field, whatever, which stores the value of the main user id onto each of your profile2 profile types. When creating your mapping, use that uid property as the external id for mapping a profile2 profile type to the salesforce object. In this scenario, you would have User -> Contact, User Profile -> Contact using the same id. The issue I ran into when doing this was that the salesforce_mapping_object table expects the incoming salesforce_id to be a unique value, so I just dropped the unique index.

If any issues come up with the incoming sObject and your field mappings of 1 sObject to multiple Drupal entities, you can deal with it in hook_salesforce_pull_entity_value_alter.

rickyoh’s picture

StatusFileSize
new7.38 KB

There's no reason why multiple Drupal entities shouldn't be able to map to a single sfdc object, and vice versa. We'll need this for support for modules like Profile2.

I have only been testing via the soap api so bear with me as I try to get a good patch ready to roll with both apis. Currently implemented in the attached patch:

  1. Added a column "bundle" onto the salesforce_mapping_object table.
  2. Added a function to load salesforce_mapping_object by the salesforce id, entity type, and bundle
  3. Replaced a few calls to salesforce_mapping_object_load_by_sfid with the new function to target the bundle
  4. Restructured the delete on pull function a bit
  5. Added a condition to fix bug where single record queries are returned as a single object, not in an array (this is another issue altogether and needs to be fixed across the board)

Work in progress attached.

smichel’s picture

I'm having this issue where I need to map both the user and various profile2 fields. I tried to apply the patch in #2 to Salesforce Suite 7.x-3.0-beta4+25-dev, but the patch failed:

Hunk #1 FAILED at 146.
...
1 out of 4 hunks FAILED -- saving rejects to file modules/salesforce_pull/salesforce_pull.module.rej

I'll try to apply the rest of the patch manually; but does it still apply?

smichel’s picture

My issue with the patch is because I had also applied the patch at https://drupal.org/node/1934790 that let you work with sandbox accounts. Sigh.

rickyoh’s picture

@smichel, this probably won't apply to the latest dev anymore. If a maintainer feels this functionality is worthwhile, I'd be happy to work towards getting this in better shape to roll into dev.

bisonbleu’s picture

@rickyoh can you clarify a couple of "this" for me? :-)

When you write "@smichel, this probably won't apply to the latest dev anymore", does "this" refer to:

  1. your implement-bundle-mapping.patch in #2 ?
  2. or 1934790 ?

I'm assuming that in " If a maintainer feels this functionality is worthwhile" you're referring to your patch (implement-bundle-mapping.patch).

I'm no maintainer but I think this functionality is definitely worthwhile (it will have to come sooner or later). I have to sync users & profile types with Salesforce and I'm facing this issue right now.

It would be awesome if you could push the development of this patch and have it rolled into dev!

So I vote YES!

smichel’s picture

Yes, as @ rickyoh stated, this patch no longer works for me. I'm trying to work around it, mostly alas by duplicating fields that were on the user to the profile, and updating them on user insert & update, but that's not sustainable.

rickyoh’s picture

"this" definitely means the patch and possibly means the direction of this implementation if something drastic has changed in the direction the dev release has taken. Let's see what 3.x-dev's lookin like these days....

bisonbleu’s picture

Thanks @rickyoh.

I'm in the same boat as @smichel, I can't see any other way to properly sync my profile type with a contact Salesforce object other than by

duplicating fields that are on the user entity (e.g. email) to the profile entity, and updating them...

one way or another.

kundu’s picture

Any news on "this" issue? Could you sync profile2/user role with Salesforce contact?

Thanks.

sterlingedsrv@gmail.com’s picture

I expect we'll be needing this too.

ohthehugemanatee’s picture

Issue summary: View changes

Noting that the patches provided definitely don't apply to current dev... though broadly what's required is the same if you want to load fields this way (ie with separate Mappings for each Drupal object).

* make the salesforce_mapping_object table no longer require SFID to be a unique key.
* make salesforce_mapping_object_load_by_sfid able to handle multiple returns.
* make all implementations of salesforce_mapping_object_load_by_sfid expect multiple returns, ie push would have to differentiate between the fields coming from profile2 and the fields coming from users.

But there is another way to do this. On the Mapping interface, add the ability to include fields from a related entity in the field list. This is how search_api_solr does it, and it's extremely flexible without overcomplicating things. Then in salesforce_pull_process_records, rather than processing all the fields in an entity object, we created a fieldlist with all the fields the user selected across all related entities.

danharper’s picture

I have managed to implement the above by installing entity and the entity token module, you can drill into the related entity and select values as tokens.

Cheers Dan

amaisano’s picture

@danharper could you please elaborate on how you were able to sync values from SF into a Drupal user's Profile2 profile fields?

I have a "Customer Profile" Profile2 profile type setup for my users. I have a mapping that creates Drupal users upon updated SF data, which includes user name, email, etc. However I have separated personal details like phone, address, etc, to this "Customer Profile" and even though profile2 tokens seem to be available within that existing User mapping, they cause the following error while syncing (upon cron run, when Drupal tries to create the user account):

WD Salesforce Pull: Unknown data property [user. Processing failed for entity kjasd@lkjha.con associated[error]
with Salesforce Object ID: 00Q5000000z6wcDEAQ
WD cron: Exception: Failed to create Drupal entity when processing data from Salesforce. in             [error]
salesforce_pull_process_records() (line 283 of
/Users/Atwixtor/GIT/nexamp/public_html/sites/all/modules/salesforce/modules/salesforce_pull/salesforce_pull.module)
danharper’s picture

@amaisano did you install entity module?

I have installed it and have mappings that look like the one below.

Only local images are allowed.

amaisano’s picture

Yes, I have Entity API (7.x-1.6) installed. On my SF User Mapping, I'm using this token:

[user:profile-customer:field-c-phone-number]

But as soon as I add this token to the field map, I receive the mentioned errors upon sync.

This is a User Entity Type and User Bundle SF Mapping. Was yours also a User mapping?

Maybe I need to be using the dev version of Salesforce Suite? I'm on the current stable..

Field Mapping

danharper’s picture

You will probably need to use [user:profile-customer:field_c_phone_number] to get the raw number to pass to salesforce, this will also mean that the salesforce field type is just raw text.

Cheers Dan

amaisano’s picture

I received the same errors regardless of the token. In fact, I removed all Field Mappings that involved Profile2 fields, and simply tried syncing information in the [user:name-raw] field, and it failed with the same error. Only "Properties" seem to work, not tokens.

Apparently tokens cannot be used in either a "Sync" or "SF to Drupal" situation, according to this issue: https://www.drupal.org/node/1950292 - only in a "Drupal to SF" direction, which is useless in getting data into Profile2 fields.

How else is it possible to get something like a Phone Number into a Profile2 field *from* SF into Drupal? Were you able to achieve this in a "Sync" or "SF to Drupal" mapping, @danharper?

danharper’s picture

i didn't know that was a limitation, this makes things difficult for me also.

amaisano’s picture

Priority: Normal » Major

How exactly do 'related entities' work? The documentation is a bit confusing about that. I feel like there *should* be a way to make a connection between the user and their profile, perhaps by a known (in SF) profile ID that matches what Drupal has mapped to that user account? Like:

Drupal:
User = 47 (users->UID)
Profile = 298 (profile->PID)

SF:
User Profile = 298

Sync:
User/Related Entity/Customer Profile = 298 (or, looks up profile with matching user UID)

Problem is, that assumes 'Related Entities' work like I think they do, and we get around the issue of Profile IDs not being available the first time a user is created in Drupal from Salesforce (but would be on subsequent syncs).

Really need to find a way to make this work.

danharper’s picture

But you can't map the same salesforce object type twice, so you couldn't for example map several profile2 profile types to a single account type in salesforce. Somebody has suggested there is a way to do it as that's how solr works but that would require patching the module.

amaisano’s picture

Would that patch be related to what was happening on #785286: Provide ability to create one-to-many fieldmaps?

ohthehugemanatee’s picture

You're _supposed_ to address this with a contributed module, just as you said.

But more useful - and more tricky - would be a UI for managing related entities. You could probably take a clue or two from search_api_solr's admin UI.

davidpugh’s picture

I'm still trying to get the user table to sync with the SF contact table and also have the Profile2 table sync with the contact table.

I currently still trying to get the user table and a profile2 profile to both sync to the contact table on Salesforce.

I first created a mapping for the user table. I added a field on the salesforce contact for the drupal user id.

Here is the image of the mapping:
http://elaw.org/salesforce_sync_problems_throw_away/user_table_sync_to_c...

This works and I can synchronize perfectly from the user table to contact and contact to the user table. The problem is when I also try to set up mapping for my profile.

I then set up mapping for my profile to SF contacts.
I am trying to use the "Related Entities" Drupal Salesforce module configuration to link the Profile mapping to the user mapping I already had set up.
Here is the image of the mapping:
http://elaw.org/salesforce_sync_problems_throw_away/profile_table_sync_t...

When I save both mappings and try to update the "Addl Emergency Email" which is one of the mapped profile2 fields for my profile I get an error:

PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '003M000000eTx9wIAC' for key 'salesforce': INSERT INTO {salesforce_mapping_object}
3)The error syncs the change with salesforce but it doesn’t save it on the drupal side.

I wasn't sure how to resolve this, so I was experimenting and removed the "Unique" key on the salesforce_id on the table "salesforce_mapping_object", and then tried to update values on the profile on Drupal and it synchronized to Salesforce. But I did encounter a problem when I tried to update values on SF and then my user table data synchronized back to drupal but my Profile2 profile data did not.

Seems like this "Related Entities" should work for User/Profile synchronizing, but I don't know how to get it to work.
If this WILL NOT WORK can someone let me know that I am barking up the wrong tree and lead me to a better tree?

Thanks,

gopikakrish84’s picture

Hi davidpugh,

Where you able to find a fix for the issue. I have also synced user and profile2 with contact in salesforce. But now I am always getting error "Integrity constraint violation: 1062 Duplicate entry " when user tries to enter profile details. Is there a way where I can sync both to salesforce.

Any pointers would be great

Thanks

tremor’s picture

This feature would be crucial to my organization - who do I have to pay to get this fixed? It would also be useful to be add a "custom" mapping option.

amaisano’s picture

I ended up ditching the Profile2 module all together and using a combo of Display Suite and Contextual View Modes to play with role-based visibility of fields which are all attached to the main User object, and not an abstracted layer like Profile2 which just doesn't jive with a couple main integrations we have, including SF.

bob.hinrichs’s picture

We suddenly began getting this issue on our production server when using asynchronous mode. It is unfortunately a critical failure.

Any time the system tries to push, it results in this error (salesforce id is altered)
PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '0033600000TzUJWxA3' for key 'salesforce': INSERT INTO {salesforce_mapping_object} (revision_id, salesforce_id, entity_id, entity_type, created, entity_updated, last_sync, last_sync_action, last_sync_status, last_sync_message) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6, :db_insert_placeholder_7, :db_insert_placeholder_8, :db_insert_placeholder_9); Array

The only way to resolve seems to be to turn off asynchronous mode. This seems it should be a fixable bug.

damienmckenna’s picture

Assigned: levelos » Unassigned
aaronbauman’s picture

Status: Active » Closed (won't fix)

7.x is no longer supported

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.