Done so far

Add a "push" button to the existing salesforce-activity form

Still todo

  • salesforce_push_entity_crud() is not granular enough. Needs to be broken down a bit further to allow mapping objects to be pushed immediately, even if the mappings are set to use "async". So, if you have an async mapping, you'll notice that "push" just enqueues the record to be pushed on cron.
  • Add a "pull" button
  • Allow to push/pull by mapping (e.g. checkboxes for each applicable mapping), instead of trying to push all mappings related to a given Drupal entity type.

Comments

ohthehugemanatee’s picture

ohthehugemanatee’s picture

StatusFileSize
new3.1 KB

Whoops, missed an else{ :) Updated patch attached.

moss.dev’s picture

Hi ohthehugemanatee,

Thanks for the patch. I have a few issues with it though.

Firstly, I could not get it to apply automatically using the normal methods with errors like:
fatal: corrupt patch at line 32

But I could not see any issue with it.

Secondly, after applying the patch by hand, it does not really do what it says on the tin.

You describe it as "force update from salesforce or from drupal" but all I get is a checkbox with the description "Ignore updated times and overwrite Drupal objects with values from Salesforce on every Pull."

After checking the checkbox nothing happens, no pull seems to be triggered.

What I was expecting was a button to trigger a pull and another button to trigger a push.

Can you please explain what this check box should achieve and how it could be of use.

Thanks,

PS. Does anyone know of a good method to trigger a pull?

ohthehugemanatee’s picture

Ahh, makes sense. Sorry for the bungled explanation.

> Can you please explain what this check box should achieve and how it could be of use.

In a normal pull operation from Salesforce, it filters by SF's "last updated time" to make sure it's only getting updated objects from salesforce. When it's processing the queue of objects to update, it also checks the updated time of the Drupal entities, to make sure it's actually older than the SF object which will replace it.

If you hit the checkbox, both of these checks will be ignored. On any normal pull operation, your drupal objects will be overwritten. This is useful in case:

a) you've updated your mapping. I'm not 100% certain but I *think* it wouldn't otherwise consider that cause to update the Drupal object.
b) you just switched salesforce environments
c) you're adding sync with an existing SF installation to an existing Drupal site.

Maybe there are other cases as well.

If it's helpful, I used cron_debug module to let me trigger salesforce_pull separately from the rest of cron. I then used drush queue-run salesforce_pull to fire the queue.

Oh, and I also got "malformed patch" when I just tried to apply it. If you've just manually applied the patch, please re-roll!

tauno’s picture

Status: Needs review » Needs work

This is a handy feature, but it seems like this could be implemented more simply. It also needs re-testing against the current code.

Mile3’s picture

Patch in #2 works in D7 7.38 and SalesForce 7.x-3.1 on my site.

This is very useful for getting a clean pull of all records after a change in the mappings, etc. I think the patch would be a very nice feature in the module.

pianomansam’s picture

Status: Needs work » Needs review
StatusFileSize
new3.1 KB

Patch wasn't cleanly applying to latest dev, so here's a re-rolled version. In reply to tauno, perhaps there are better ways in implement this functionality, but the changes to the code are pretty simple and minimal as it is. I'm not convinced we need a different approach. But if you're interested in writing one, go for it!

aaronbauman’s picture

I had a similar thought recently, giving rise to #2559525: decompose functions in salesforce_pull to make more re-usable; pull a single record, expose to actions, etc.
If there were a "pull" action available for mapping_objects, you could accomplish this with VBO.
This would be much cleaner than going through the mapping CRUD interface.
(You could also expose a "pull" button on the %/salesforce_activity local action.)

A couple other considerations:
- adding a "force" property on SF pull queue items, which forces updates even if Drupal entity was changed more recently
- pulling records which don't have an existing mapping_object

pianomansam’s picture

@aaronbauman, I agree that type of functionality would be *very* useful.

aaronbauman’s picture

Here's what I've got so far.
This patch adds a "push" button to the existing salesforce-activity form

Still todo:
- Right now salesforce_push_entity_crud() is not granular enough. Needs to be broken down a bit further to allow mapping objects to be pushed immediately, even if the mappings are set to use "async". So, if you have an async mapping, you'll notice that "push" just enqueues the record to be pushed on cron.
- Add a "pull" button
- Allow to push/pull by mapping (e.g. checkboxes for each applicable mapping), instead of trying to push all mappings related to a given Drupal entity type.

  • aaronbauman committed 4acc573 on 7.x-3.x
    - Issue #2223673 by ohthehugemanatee, pianomansam, aaronbauman: add "...
aaronbauman’s picture

Title: option to force update from salesforce or from drupal » Option to force synchronous push to salesforce or pull to drupal
Issue summary: View changes
Status: Needs review » Active

patch from #10 is committed.

updating status back to active, re TODO items in #10 and updating summary and title.

aaronbauman’s picture

chrisolof’s picture

Just ran into a situation where I needed to re-pull everything fresh from SF for a mapping (the mapping changed). I'd imagine this is a pretty common scenario so I'd be interested to here what others are doing to make this happen once things are live and you can't just wipe the entities down and truly start fresh (as you could in, say, a dev environment).

Right now I'm zeroing out the last pull variable for the SF object type and then changing the relevant mapping objects' entity_updated property to zero. Pretty cumbersome and makes the sync history a little inaccurate - but it works. I should note I'm running in asynchronous (cron) mode.

If this new functionality was exposed on the admin/structure/salesforce/mappings form that would be nice because you could check off all or some of the mappings and maybe select "Re-Pull" or "Re-Push" from a bulk actions select box below the mappings - potentially re-pulling or re-pushing everything under multiple mappings in a single operation.

A simpler approach may be to simply add "re-pull" and "re-push" action links to the right of each mapping.

nyl_auster’s picture

Hello all !
Here is what i did in a custom module to create a new item menu forcing re-pull of datas :

// create a new menu in admin
YOURMODULE_menu() {
  $items['admin/config/salesforce/force-pull'] = array(
    'title' => t('Force objects re-pull'),
    'type' => MENU_NORMAL_ITEM,
    'page callback' => 'custom_salesforce_force_pull',
    'access arguments' => ['administer site configuration'],
  );
  return $items;
}

// custom function to pull datas
function custom_salesforce_force_pull() {

  // on réinitialise les variables de type "sync"
  foreach ($GLOBALS['conf'] as $name => $value) {
    if (strpos($name, 'salesforce_pull_last_sync') === 0) {
      $GLOBALS['conf'][$name] = NULL;
    }
  }
  $GLOBALS['conf']['salesforce_pull_throttle'] = 0;
  $GLOBALS['conf']['c43_salesforce_force_pull'] = TRUE;
  salesforce_pull_get_updated_records();
  $compteur = 0;
  if (salesforce_pull()) {
    // Queue is populated, but not processed yet so we manually do some of what
    // drupal_cron_run() does to trigger processing of our pull queue.
    $queues = salesforce_cron_queue_info();
    $info = $queues[SALESFORCE_PULL_QUEUE];
    $callback = $info['worker callback'];
    $end = time() + (isset($info['time']) ? $info['time'] : 15);
    $queue = DrupalQueue::get(SALESFORCE_PULL_QUEUE);
    while (time() < $end && ($item = $queue->claimItem())) {
      try {
        call_user_func($callback, $item->data);
        $compteur++;
        $queue->deleteItem($item);
      }
      catch (Exception $e) {
        // In case of exception log it and leave the item in the queue
        // to be processed again later.
        watchdog_exception('salesforce_pull', $e);
      }
    }
  }
  $GLOBALS['conf']['c43_salesforce_force_pull'] = FALSE;
  drupal_set_message("$compteur objects re-pulled");
  return " ";
}

/**
 * Make saleforces module believe that all entities need an update
 * Implements hook_entity_load()
 * @param $entities
 * @param $type
 */
function YOURMODULE_entity_load($entities, $type) {
  if(!empty($GLOBALS['conf']['c43_salesforce_force_pull'])) {
    foreach ($entities as $entity) {
      $entity->updated = -1; 
    }
  }
}

antoniog4’s picture

StatusFileSize
new3.34 KB

Since I needed the original behavior of #7, I redid the patch to include the force pull with a debug option.

  • aaronbauman committed fb5c32f on 8.x-3.x
    Issues #2223673 #2593901 #1969034 #2554163 #2602918 - drush pull /...
rogerrogers’s picture

The latest patch in this thread doesn't apply cleanly with the latest dev release of the 7.x module. This is a pretty basic and critical feature - would be good if it got included in the module. I've never learned how to create a Drupal patch and don't have the time at the moment, so here is a git commit that shows the diff:

diff --git a/modules/salesforce_mapping/includes/salesforce_mapping.admin.inc b/modules/salesforce_mapping/includes/salesforce_mapping.admin.inc
index bb9f1f5..de6aee9 100644
--- a/modules/salesforce_mapping/includes/salesforce_mapping.admin.inc
+++ b/modules/salesforce_mapping/includes/salesforce_mapping.admin.inc
@@ -380,6 +380,13 @@ function salesforce_mapping_form($form, &$form_state, SalesforceMapping $mapping
   $push_batch_description = t('Push items will be processed in a single batch to the Salesforce API rather than one at a time. This may be preferable if API limits are of concern, although changes are not reflected immediately in Salesforce.');
   $form['push_batch']['#description'] = $requirements_description . ' ' . $push_batch_description;
 
+  $form['force_update'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('DEBUG: Force update Drupal entities'),
+    '#default_value' => variable_get('salesforce_pull_force_update_' . $salesforce_object_type, ''),
+    '#description' => t('Ignore updated times and overwrite Drupal objects with values from Salesforce on every Pull.'),
+  );
+
   $form['actions'] = array('#type' => 'actions');
   $form['actions']['submit'] = array(
     '#value' => t('Save mapping'),
@@ -743,6 +750,13 @@ function salesforce_mapping_form_submit($form, &$form_state) {
 
   $mapping->save();
 
+  if ($values['force_update']) {
+    variable_set('salesforce_pull_force_update_' . $values['salesforce_object_type'], '1');
+  }
+  else {
+    variable_set('salesforce_pull_force_update_' . $values['salesforce_object_type'], '');
+  }
+
   salesforce_set_message(t('Salesforce field mapping saved.'));
   $form_state['redirect'] = 'admin/structure/salesforce/mappings';
 }
diff --git a/modules/salesforce_pull/salesforce_pull.module b/modules/salesforce_pull/salesforce_pull.module
index 2171aa4..831104d 100644
--- a/modules/salesforce_pull/salesforce_pull.module
+++ b/modules/salesforce_pull/salesforce_pull.module
@@ -256,7 +256,12 @@ function salesforce_pull_get_updated_records() {
     ));
 
     // If no lastupdate, get all records, else get records since last pull.
-    $sf_last_sync = variable_get('salesforce_pull_last_sync_' . $type, NULL);
+    if (variable_get('salesforce_pull_force_update_' . $type, '')) {
+      $sf_last_sync = NULL;
+    }
+    else {
+      $sf_last_sync = variable_get('salesforce_pull_last_sync_' . $type, NULL);
+    }
     if ($sf_last_sync) {
       $last_sync = gmdate('Y-m-d\TH:i:s\Z', $sf_last_sync);
       $soql->addCondition($mapping->pull_trigger_date, $last_sync, '>');
@@ -341,11 +346,13 @@ function salesforce_pull_process_records($sf_object) {
         else {
           // Flag this entity as having been processed. This does not persist,
           // but is used by salesforce_push to avoid duplicate processing.
+
+
           $entity->salesforce_pull = TRUE;
           $entity_updated = isset($entity->updated) ? $entity->updated : $mapping_object->entity_updated;
 
           $sf_object_updated = strtotime($sf_object[$sf_mapping->pull_trigger_date]);
-          if ($sf_object_updated > $entity_updated) {
+          if ($sf_object_updated > $entity_updated || variable_get('salesforce_pull_force_update_' . $sf_object['attributes']['type'], '') ) {
             $wrapper = entity_metadata_wrapper($sf_mapping->drupal_entity_type, $entity);
 
             // Set fields values on the Drupal entity.


aaronbauman’s picture

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