The module fails to handle existing entities. For example, when I set up a new synchronization process for users, keyed by the username field, I get integrity constraint PDO errors on sync complaining that Salesforce_pull is trying to create users with duplicate 'name' values.

Attaching a patch which tries to failover intelligently. If salesforce_pull doesn't find an existing mapping record for a given salesforce object, it queries Drupal based on the salesforce key field. If Drupal has an existing entity with the correct value in the key field, we create a new salesforce mapping record.

Comments

ohthehugemanatee’s picture

ohthehugemanatee’s picture

Wow, I posted a duplicate of my own issue lol. Updating the patch here, and closing #2238875 .

So I truncated salesforce_mapping, and patched salesforce_pull. When it can't find an entry in salesforce_mapping_object for a given SFID, it falls back on looking for a drupal entity with the right value in the "key" field defined in the mapping. If it finds a drupal entity, it creates a mapping. Normal sync proceeds from there.

I also found that some fields which are unique in Drupal, are not unique in Salesforce... and that can cause SQL errors. Specifically I'm talking about $user->mail, which is unique in Drupal. You can't alter the attributes of the SF Email field, so there are possibilities of multiples. For this reason I added a sanity check and abort to make sure there isn't already a mapping for this Drupal object. That's included in this patch because I only encountered it when I started create mapping objects asynchronously with Drupal objects. It's possible this is actually a broader problem which should be addressed elsewhere, so let me know if that part should go in a separate issue/patch.

aaronbauman’s picture

Status: Needs review » Needs work

This is definitely a problem, but the approach in this patch is not quite right.
I can see scenarios in which you would NOT want to automatically match existing entities.
Or where we want to match existing entities, but not on the same key we're using for upserts.
Lastly, this won't work for mappings which do not have any key.

bburg’s picture

This code seems a bit brittle, in that I'm running into situations, where $keyfield is not set, and errors like...

EntityFieldQueryException: Field storage engine not found. in EntityFieldQuery->queryCallback() (line 1190 of                             
/vagrant/public/includes/entity.inc).

...are triggered as a result (I think). I tried wrapping that EFQ in the patch in a check that $keyfield exists. But my understanding of the problem/code at this point makes me feel like a monkey banging on it with a hammer. Also, doing the leads to what seems like several of the same record with only slightly different SalesForce IDs.

deivamagalhaes’s picture

I was having the same issue and was able to make it work by implementing hook_salesforce_pull_mapping_object_alter and creating the mapping object if there is a Drupal entity with the same value for the key field.

/**
 * Implements hook_salesforce_pull_mapping_object_alter().
 *
 * @param mixed $mapping_object
 *   The mapping object that was detected based on existing mappings or FALSE
 *   if no exisitng mapping object exists.
 * @param array $sf_object
 *   The salesforce object data that will be used in this pull.
 * @param SalesforceMapping $mapping
 *   The salesforce mapping that will be used during the pull.
 */
function ppu_salesforce_mapping_salesforce_pull_mapping_object_alter(&$mapping_object, $sf_object, $mapping) {
  if (!$mapping_object) {
    // Look for an existing entity by key field and create a mapping object.
    foreach ($mapping->field_mappings as $field_mapping) {
      if ($field_mapping['key'] == TRUE) {
        $keyfield = $field_mapping;
      }
    }
    if (!isset($keyfield)) {
      return FALSE;
    }
    $result = db_select('rsa_places_map', 'p')
      ->fields('p', array('id'))
      ->condition($keyfield['drupal_field']['fieldmap_value'], $sf_object[$keyfield['salesforce_field']['name']], '=')
      ->execute()
      ->fetchAssoc();
    if (!empty($result)) {
      $entity_id = $result['id'];
      // Create mapping object.
      $mapping_object = entity_create('salesforce_mapping_object', array(
        'salesforce_id' => $sf_object['Id'],
        'entity_type' => $mapping->drupal_entity_type,
        'entity_id' => $entity_id,
      ));
      $mapping_object->save();
    }
  }
}
bburg’s picture

My issue in #4 was that somehow my mapping had been created without a key field actually set. Which shouldn't be possible as it is a required field. I'm not sure how that situation occurred (possibly Features?).

damienmckenna’s picture

At the very least the affected code has been changed since the patch was last written, so it needs to be rerolled.

damienmckenna’s picture

FYI I'm not having this problem with the current codebase, but I am seeing it trying to create duplicate 'salesforce_mapping_object' records.

aaronbauman’s picture

Component: Code » salesforce.module
Status: Needs work » 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.