What we'd *like* is for Commerce Migrate Ubercart to handle converting an Ubercart site to Drupal Commerce as almost an upgrade process. It would be great if you could go through a simple process with your working Ubercart store and end up with a Commerce store with equivalent features. We have a ways to go for this, and it may not be achievable, but this issue is to describe a roadmap.

Here's a list of wanted features in (possible) priority order:

Feature Level of Effort Issue Description
Attributes 3-5 days #1210280: Support attributes on products and mutivalue product reference fields Doing attributes means
  • The product type import has to detect and create the proper fields on the product types
  • The product importer has to import the fields
  • The product importer has to split the Ubercart products into multiple products, manufacturing new SKUs for the variations
  • The Product display node importer has to provide a reference to each product that was once an attribute
Taxonomy/Catalog 2 days #1212172: Bring Ubercart Taxonomy/Catalog into Commerce We should recreate the catalog on the Ubercart side on the Commerce side
Consolidate customer profiles 1 day #1212174: Consolidate identical Customer Profiles Currently each Ubercart order is turned into a profile. We should at least try to consolidate like profiles. However, it's possible this should be done outside/after migrate.
Customer purchase history 1 day #1211024: Capture customer purchase/payment history Currently there is no purchase history.
Customer payment history 1 day #1211024: Capture customer purchase/payment history Currently there is no payment history
Migrating Ubercart as opposed to upgrading 1 day #1206348: Ubercart: Use Cross-database import in addition to self-importing ubercart database Currently, commerce_migrate_ubercart assumes that the source database is the site where Migrate is running. This is quite messy, as it means all the ubercart modules, tables, nodes, etc. are in there, and there's no good way to clean them up. It would be far better to bring in the Ubercart store from a remote database.

Things we should probably not do at this point:

  • Taxes and the like
  • Any support for most Ubercart contrib modules

Comments

rfay’s picture

Project: Commerce Migrate » Commerce Migrate Ubercart
Issue summary: View changes

Improved roadmap

rfay’s picture

Issue summary: View changes

Added Taxonomy

recrit’s picture

Project: Commerce Migrate Ubercart » Commerce Migrate

display node comments should be added to the roadmap since they provides valuable user feedback
#1324448: Migrate product comments?

btmash’s picture

Issue tags: +Product Kits?

Figuring out a way to migrate product kits would be great (though I guess I'm not entirely sure how it all fits into commerce; I understand multiple products can be referenced though I am unsure on what else is necessary.

rfay’s picture

Project: Commerce Migrate » Commerce Migrate Ubercart
Component: Commerce Migrate Ubercart » Code
CraigBertrand’s picture

Any idea how recurring fees would come over?

rickmanelius’s picture

@CraigBetrand considering the functionality is a bit different, I don't know if there is a clear upgrade path for that... particularly since it's not part of the standard ubercart/drupal commerce packages.

nightlife2008’s picture

Hey rfay, if you're interested in enabling some exotic stuff like taxes and discounts, the following could be an option. I have figured out that the easiest way to properly have your orders contain the correct discounts and taxes, is to resave an order in the commerce site.

This actually requires someone to manually setup the "corresponding" discounts and tax rules as the ubercart, which is the easiest way as there are different possibilities (coupons, discounts, taxes, vat, etc).

Once these rules are set up in the Commerce website, the saving of an order object will trigger the necessary actions to add discounts and taxes.

The following 2 lines of code actually do the job quite well:

$order = commerce_order_load($row->order_id);
$update_status = commerce_order_save($order);

I have created the batch functions which actually do this:

define('WK_MIG_BATCH_NUM_OPS', 25);
define('WK_MIG_BATCH_COUNT', 10);
/**
 * 
 */
function MODULENAME_batch_orders_form() {
  // Give helpful information about how many nodes are being operated on.
  $order_count = db_query('SELECT COUNT(DISTINCT order_id) FROM {commerce_order}')->fetchField();
  drupal_set_message();
  $form['description'] = array(
    '#type' => 'markup',
    '#markup' => t('Process all Ubercart orders to set the correct order total, taxes and discounts.') . '<br />',
  );
  $form['description']['#markup'] .= t('There are @order_count orders so it will require @count HTTP requests.', array(
    '@order_count' => $order_count, 
    '@count' => ceil($order_count / WK_MIG_BATCH_COUNT) 
  )) . '<br />';
  
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Go',
  );
  return $form;
}


function MODULENAME_batch_orders_form_submit($form, &$form_state) {
  $_SESSION['MODULENAME']['orders_request_count'] = 0; // reset counter for debug information.
  $batch = MODULENAME_batch_orders();
  batch_set($batch);
}


/**
 * 
 */
function MODULENAME_batch_orders() {
  $operations = array();
  $operations[] = array('MODULENAME_batch_orders_op', array());
  $batch = array(
    'operations' => $operations,
    'finished' => 'MODULENAME_batch_orders_finished',
    'title' => t('Processing orders'),
    'init_message' => t('Post-process Orders is starting.'),
    'progress_message' => t('Processed @current out of @total.'),
    'error_message' => t('Post-process Orders has encountered an error.'),
    'file' => drupal_get_path('module', 'MODULENAME') . '/MODULENAME.admin.inc'
  );
  return $batch;
}

/**
 * 
 */
function MODULENAME_batch_orders_op(&$context) { 
  // Use the $context['sandbox'] at your convenience to store the
  // information needed to track progression between successive calls.
  if (empty($context['sandbox'])) {
    $context['sandbox'] = array();
    $context['sandbox']['progress'] = 0;
    $context['sandbox']['current_order'] = 0;

    // Save order count for the termination message.
    $context['sandbox']['max'] = db_query('SELECT COUNT(DISTINCT order_id) FROM {commerce_order}')->fetchField();
  }

  // Retrieve the next group of orderids.
  $result = db_select('commerce_order', 'co')
    ->fields('co', array('order_id'))
    ->orderBy('co.order_id', 'ASC')
    ->where('co.order_id > :order_id', array(':order_id' => $context['sandbox']['current_order']))
    ->extend('PagerDefault')
    ->limit(WK_MIG_BATCH_COUNT)
    ->execute();
  foreach ($result as $row) {
    $order = commerce_order_load($row->order_id);
    $update_status = commerce_order_save($order);
    $update_status = ($update_status) ? t('Success') : t('Failed');
    // Store some results for post-processing in the 'finished' callback.
    // The contents of 'results' will be available as $results in the
    // 'finished' function (in this example, MODULENAME_batch_orders_finished()).
    $context['results'][] = $order->order_id . ' : ' . check_plain($order->mail) . ' (' . $order->status . ') >>> ' . $update_status;
    
    // Update our progress information.
    $context['sandbox']['progress']++;
    $context['sandbox']['current_order'] = $order->order_id;
    $context['message'] = $order->order_id . ' : ' . check_plain($order->mail);
  }

  // Inform the batch engine that we are not finished,
  // and provide an estimation of the completion level we reached.
  if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
    $context['finished'] = ($context['sandbox']['progress'] >= $context['sandbox']['max']);
  }
  _MODULENAME_batch_orders_update_http_requests();
}

/**
 * Batch 'finished' callback used by both batch 1 and batch 2.
 */
function MODULENAME_batch_orders_finished($success, $results, $operations) {
  if ($success) {
    // Here we could do something meaningful with the results.
    // We just display the number of nodes we processed...
    drupal_set_message(t('@count results processed in @requests HTTP requests.', array('@count' => count($results), '@requests' => _MODULENAME_batch_orders_get_http_requests())));
    //drupal_set_message(t('The final result was "%final"', array('%final' => end($results))));
    //dpm($results);
  }
  else {
    // An error occurred.
    // $operations contains the operations that remained unprocessed.
    $error_operation = reset($operations);
    drupal_set_message(t('An error occurred while processing @operation with arguments : @args', array('@operation' => $error_operation[0], '@args' => print_r($error_operation[0], TRUE))));
  }
}

/**
 * Utility function to count the HTTP requests in a session variable.
 */
function _MODULENAME_batch_orders_update_http_requests() {
  $_SESSION['MODULENAME']['orders_request_count']++;
}

function _MODULENAME_batch_orders_get_http_requests() {
  return !empty($_SESSION['MODULENAME']['orders_request_count']) ? $_SESSION['MODULENAME']['orders_request_count'] : 0;
}
nightlife2008’s picture

Issue summary: View changes

Add issues to each item in table

Anonymous’s picture

Status: Active » Closed (fixed)

Most of these items are now in the 7.x-2.x branch or can be achieved by using the latest migrate_d2d in the UI.

Attributes is the only item that stands out as might be needing some work so please take any patches over to that issue and roll against 7.x-2.x.