Subject says it all.
I love the order->Opportunity mapping, and the order products -> Opportunity Products mappings.
For a complete trifecta, I'd like to see a UC Product -> SF Product

I'll give it a go if I get a chance in the next couple weeks.

Not even a release on the project page and already submitting a feature request... heh.

Comments

bibeksahu’s picture

The UC "product" type is just a node, isn't it?

We're already mapping "donation" products (which are an extension of "product" nodes, provided by the "uc_donation" module) to a custom Salesforce type on our production system.

We use a "node" fieldmap to accomplish that.

Or do you mean something different?

aaronbauman’s picture

The base object of UC Product is a node, but UC extends the node and the extra fields are not exposed.
For example, price, cost, weight, shippable, SKU, etc, are not available to salesforce_api.

bibeksahu’s picture

Ah yes. I'll address that this week.

rjacobs’s picture

We are also very curious about this.

At the moment our temporary solution is to create a redundant "unit price" field for our product nodes with CCK (as CCK fields can be mapped). Of course, this means that an editor would need to enter the price in 2 places when creating a product node.

Wouldn't this be related to sf_node as opposed to uc_salesforce (after all, the mapping involves a node as opposed to any of the "special" order/line-item objects that uc_salesforce creates)? Or can uc_salesforce actually "expose" these fields to sf_node? I'm just thinking out loud as I really don't know enough about how the API works.

Cheers!
Ryan

aaronbauman’s picture

ATM sf_node only exposes core and CCK fields to the SF API. uc_salesforce takes responsibility for exposing ubercart-specific fields, as mentioned in #2.

At some point the idea was kicked around to roll sf_node or salesforce_api with a set of "contrib" support functionality, ie. implementations of hook_fieldmap_objects for each module or set of fields. Anyway, that's more of an implementation detail IMO.

EvanDonovan’s picture

This is the "Ubercart order product", correct? Marked as fixed, since I think that's in the latest version (i.e., #811258: Compatibility with latest dev, code cleanup, some bug fixes). Feel free to reopen if there are additional fields that Ubercart is adding which are part of the $order object, but which aren't mapped yet.

EvanDonovan’s picture

Status: Active » Fixed

Status: Fixed » Closed (fixed)

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

rjacobs’s picture

Status: Closed (fixed) » Active

Actually I think there was a bit of confusion on this.... it's important to note the difference between an "Ubercart order product" and a "UC Product". The "Ubercart order product" is more akin to a "line item" that's part of an order whereas a "UC Product" would be akin to an actual product item in a product catalog (the product node). The "Ubercart order product" only points to a "UC Product".

Mapping a UC Product would be independent of any orders or purchases, and could be seen as syncing the Ubercart product catalog with the salesforce product catalog. In this regard it's possible to map any product enabled nodes to a salesforce product object ("product__c" for example), but as noted in #2 there are numerous ubercart fields (price, cost, weight, etc.) that are not available for mapping.

It looks like the point from #5 ("contrib" support functionality) is part of the API now... so perhaps that's the key to address this? I have not looked at it deeply enough (nor do I know if my coding knowledge is advanced enough to take this on) but I just wanted to point out the fact that I don't think this has been addressed yet.

EvanDonovan’s picture

Title: Support for UC Product -> SF Product mapping fields » Add support for mapping UC Product node fields -> SF Product custom object

Thanks, rjacobs for the clarification. I will have to look into whether the fields that Ubercart adds to a node type which is a product are available for mapping.

If not, this would easily be accomplished either by extending the current uc_sf_order_fieldmap_objects() (a hook_fieldmap_objects() implementation), or else by implementing hook_fieldmap_objects() in your own custom module - with export handlers to process these types of fields. At some point, I would like to document how to do that more for the latest dev of the Salesforce module, but so far have been too busy with my own development off of it.

Were you the one who extensively tested the original version of this module? If so, I would appreciate it if you could try it again, if you still have use for it, as it has changed dramatically, including some bug fixes, but as yet has not gained wide adoption. There's also a few patches in the queue that need review. They are all rolled off of the latest dev build.

EvanDonovan’s picture

@rjacobs: Also, as per aaronbauman's concept in #5, there is an sf_contrib module in the Salesforce package now, but it only does this for Location and (standard) CCK fields currently. UC Product node fields could be added as a patch to that module, but I think it would be better to keep them in this project.

rjacobs’s picture

Hi Evan,

Yeah, I now remember seeing hook_fieldmap_objects being used in uc_sf to help power the OCR stuff. I think this will be quite useful in the short-term. In addition to mapping some special ubercart node fields (price, sku, etc), we also have interest in mapping some attributes as part of "Ubercart order products". As you noted, I think this could also be accomplished with a custom (case-specific) module that uses hook_fieldmap_objects.

I think I was originally under the impression that sf_contrib opened up some other special hooks or something like that... I didn't realize it catered to specific contrib modules directly. I think I understand better now, and I agree that exposing Ubercart-specific fields (on any Drupal object) should be kept within uc_sf.

I was indeed the one who worked a bit with Bibek when he first posted this code as a project. I just did a bit of testing, provided feedback, and submitted a couple (small) patches that gave admins better control over what uc_sf was doing (interface options).

At one point a whole cluster of social service nonprofits that I work with were wanting to use Salesforce as their CRMs... so this integration was paramount. However, these orgs are now opting to use CiviCRM, so the Salesforce part of the project dissolved. That said, I still have an active project with a NPO art school, and we will be using Drupal and Salesforce in some pretty interesting ways (managing memberships, syncing a class catalog, plus all the related transactional stuff that links their site's eComm to their salesforce CRM).

So we'll indeed be getting back into this in the coming weeks... and I'll see what feedback I can provide. So you recommend using the dev version at this point?

Ryan

EvanDonovan’s picture

The dev release *should* be the most stable, although it has not yet been tested by anyone other than me (and possibly aaronbauman?), so you may uncover some issues. I also have patches pending in the queue to resolve other known bugs, though, which I have not committed yet. I am actually running a forked version of the module right now myself since I had a lot of special cases I need to handle in my own integration.

At some point, I might unfork myself to decrease the maintenance burden for me, but for right now, getting my own initial integration between Ubercart and Salesforce finished is taking precedence over module maintainership, since the reason I became maintainer was so that I could get the module working again, after aaronbauman's updates to Salesforce module broke it.

You are correct about sf_contrib. It provides no new hooks, since Aaron has added all the necessary hooks to the Salesforce API itself. I think that ultimately a new uc_product module, under the uc_salesforce directory of this module, would make the best architecture, since theoretically either it or uc_sf_order could be enabled separately.

Your NPO art school project sounds very interesting. It definitely sounds like the kind of thing that I am having to do for my college registration system integration, except possibly more complex.

As you get farther along in the project, don't hesitate to contact me by my Drupal contact form and I can share with you what I have learned along the way for this (now approaching 2 month long) project, which has been my first working with the Salesforce API (and pretty much my first with the Ubercart API). I could also share my opinions on the CiviCRM vs. Salesforce condundrum, since we at TechMission have used both on our organization's websites, and have used them also with partners.

EvanDonovan’s picture

What fields would this entail again?

I think a uc_sf_product module that adds mappable fields to the node types that are Ubercart product types would be the best way forward.

rjacobs’s picture

From my recollection, this entailed capturing everything in the "Product information" box on the Ubercart-enabled node as mappable fields for product nodes. This would pretty-much include all the fields that are already available for mappings of Ubercart Order Products (sell price, cost, weight, SKU/model, etc.).

In our case we only need to map the SKU and the price as part of the product node, so I have the following in a custom module:

/**
 * Implementation of hook_fieldmap_objects_alter().
 */
function eac_sf_fieldmap_objects_alter(&$objects) {
  // **** Additions for all nodes, though these will really only be used for products
  $extra_fields = array();
  $extra_fields = array_merge($extra_fields, array(
    'sku' => array(
      'label' => t('SKU'),
      'group' => t('Special Data'),
      'type' => SALESFORCE_FIELD_SOURCE_ONLY,
      'export' => '_eac_sf_export_values'),
    'price' => array(
      'label' => t('Sell Price'),
      'group' => t('Special Data'),
      'type' => SALESFORCE_FIELD_SOURCE_ONLY,
      'export' => '_eac_sf_export_values'),
  ));
  foreach (node_get_types() as $type) {
    foreach ($extra_fields as $obj_key => $obj_def) {
      $objects['drupal']['node_'. $type->type]['fields'][$obj_key] = $obj_def;
    }
  }
}

and then:

// Callback to process custom field exports
function _eac_sf_export_values($source, $field) {
  switch ($field) {
    // **** Additions for all nodes, those these will really only be used for products
    case 'sku':
      if ($source->model) {
        return $source->model;
      }
    case 'price':
      if ($source->sell_price) {
        return $source->sell_price;
      }
  }
}

Of course that's just a quick-and-dirty custom module example, for only 2 of the needed fields, but I assume this could more gracefully be added to uc_salesforce or an independent uc_sf_product module (the latter seems to make the most sense given the direction you are taking things with the most recent dev).

Ryan

EvanDonovan’s picture

Thanks for sharing the code. This will go into uc_sf_product then. It should be trivial if they are just directly on the $node object. I can just dpm() to find out what they all are. I will only add these fields to node types that Ubercart identifies as a product node type, though - otherwise, the exports could fail in an unexpected way, although they would probably do so without any errors, fatal or otherwise.

It's a bit crazy, perhaps, to have so many different modules, but I want to make this codebase more granular since not everyone will want or need all the parts of the integration.

EvanDonovan’s picture

@rjacobs: I just remembered I am pretty sure you don't a custom export callback to simply return $source->$fieldname, since that is the default behavior. I will confirm that later today.

Here are all the fields we could implement. I've noted for each whether they would need a callback.

  • model
  • list_price
  • cost
  • sell_price
  • weight
  • weight_units (maybe?)
  • length
  • width
  • height
  • length_units (maybe?)
  • pkg_qty
  • default_qty
  • ordering (maybe?)
  • shippable (maybe?)
  • shipping_type (is machine name - yes)
  • shipping_address (is array - yes)

For now, I think I will just create a model exposing the ones that don't require an export callback. The rest could be handled later in a follow-up issue, but are not needed for my purposes, so someone would probably have to write the patch. It would be a simple patch though.

EvanDonovan’s picture

Status: Active » Fixed

Ok, I have pushed a module out to dev that handles the fields that don't have export handlers. Testing welcome.

rjacobs’s picture

Evan, good point about the need (or lack of need) for callbacks. That code snippet was part of a bunch of other custom fields we were adding, many of which did need callbacks because there was specific logic that needed to be run to get a result, so I guess I just got into the pattern of putting everything in one big switch statement.

Your approach of capturing everything that can be mapped directly out of the product object (no callback) is a good one for now I think. I didn't realize there was a shipping address in the ubercart details for the product itself.

EvanDonovan’s picture

EvanDonovan’s picture

I've definitely done "one big switch statement" before for Ubercart integration. When it's totally custom, that's the easiest. But for something generic, I wanted a lighter-weight solution.

Status: Fixed » Closed (fixed)

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