Don't miss out Virtual Happy Hour this Friday (April 26).

Try our conversational search powered by Generative AI!

Giuliano Dore
Feb 20, 2021
  1557
(7 votes)

How to migrate from uCommerce to EPiServer Commerce part 0: skus and tree structure

Intro

For one of our projects, we have the opportunity to migrate data from a uCommerce database / project into EPiServer Commerce. Migrating from one e-commerce platform to another is often a bumpy ride; the conventions are not the same, the data might not fit within the new data structures, and testing can take quite some time. I am hoping that this article will help developers who are facing the same challenges that we did.

Disclaimer: the versions of the tools / frameworks discussed in this article are listed below:

  • uCommerce for Sitecore 6.6.6.15141
  • Sitecore 8.2
  • EPiServer CMS 11.20
  • EPiServer Commerce 13.25

Disclaimer: the statements in this article are based on the version that we used for our migration; some definitions might have been updated in the latest versions of the e-commerce platforms listed above. Feel free to drop a comment if you are doing a migration and you want to share some nuggets of wisdom šŸ˜Š

Now that we have the basics covered, let’s get started šŸ˜Š.

Products and variants skus: it’s different

In uCommerce, products and variants are stored in the same table called Product. In this table, a “product” (as row) can have a sku and a variant sku. What this structure means is that products and their variants share the same sku.

The following structure is possible in UCommerce:

  • Product 1 – sku: product_1
    • Product 1 variant 1 – sku: product_1
    • Product 1 variant 2 – sku: product_1
  • Product 2 – sku: product_2

The main issue with this approach is that the sku property in UCommerce is not a unique identifier. How do we differentiate all the products and variant then? By using the variant sku property:

  • Product 1 – sku: product_1, variant sku: null (not a variant)
    • Product 1 variant 1 – sku: product_1, variant sku: var_1
    • Product 1 variant 2 – sku : product_1, variant sku: var_2

At this stage, we are thinking: that’s fine, I will use the variant sku as unique identifier. WRONG.

The variant sku is not a unique identifier either.

First, it can be null, which is never a good sign for a unique identifier. Second, the variant sku can be shared between variants as long as they don’t depend on the same product:

  • Product 1
    • Product 1 variant 1 – variant sku: var_1
  • Product 2
    • Product 2 variant 1 – variant sku: var_1

People familiar with the EPiServer Commerce conventions already know that it’s not possible to share a sku between products and variants. It must be unique and non-nullable regardless of your parent product.

So, what’s a unique identifier in uCommerce? It’s the combination between a sku and their variant sku.

As a side note, this ‘a unique code is actually a combination of 2 properties’ is not really my cup of tea. It sounds like a very challenging technical design to maintain.

So, what’s the move regarding the migration? I went with the following approach in EPiServer:

  1. We must extend products and variants using meta classes to allow 2 properties: legacy sku and legacy variant sku that will be mapped with the properties in that we discussed previously.
  2. When importing, we let EPiServer generate the ‘code’ property to avoid issues with duplicates.
  3. The content / commerce team can then look at the code property inside the EPiServer Commerce backoffice and update it accordingly.

While we are running the script, we might be thinking ‘why are we even importing those properties?’ the reason is very simple:

  1. During migrations, it’s a good practice to import as much data as you can, you can always decide to delete unnecessary data after successfully migrating your content.
  2. Tables / objects like orders in uCommerce are using the sku and variant sku as identifier for the content of the order items. Without those properties, it will be impossible to import order history.

Finally, it’s important to notice that products and variants in EPiServer offer a slightly different approach to data definition. EPiServer Commerce allows the ability to create distinct definitions for products and variants as meta classes. As the definitions are separated, it’s possible to have different properties between products and variants.

As an example:

  • A ‘CleaningProduct’ will have the following properties
    • Property1
    • Property2

And it will allow the following variant types:

  • ‘CleaningVariantXY’ and will have the following properties:
    • Property3
    • Property4
  • ‘CleaningVariantRT’ will have the following properties:
    • Property5
    • Property6

In this example, the definition for CleaningVariantXY doesn’t have a definition for Property1 and Property2 by default.

In uCommerce, there’s no separate definition available for variants; variants are extensions of products; they share the same definitions.  If we want to “flag” a property as available at the variant level, we must define the property as ‘variant property’. Once this is done, we can create a variant for the product we selected and the property will be available and editable.

The catalogue tree structure

uCommerce has the following tree structure:

  • Stores (Called Product Catalog Groups in database)
    • Catalogues
      • Categories
        • Products
        • Categories
          • Products

EPiServer has the following tree structure:

  • Catalogues
    • Categories
      • Products
      • Categories
        • Products

We also know the following:

  • Every item template (stores, catalogues, categories, products) in the uCommerce tree can have a custom definition where we can set custom properties for the template to fit our needs. In EPiServer Commerce we can add definitions by using MetaClasses to extend the list of properties that a commerce object can contain.
  • EPiServer Catalogues (CatalogContent) do not inherit from IMetaData; I couldn’t find a way online to use MetaClasses with catalogues so I assumed it was not possible. Luckily for me, the stores that I was pulling from the database didn’t contain any custom properties.
  • It is possible to have as many layers of categories as needed. Categories can have sub-categories and sub-sub-categories without any limit to the number of levels we need.

If there is information inside your uCommerce stores objects that you need to keep, the following options are available:

  • Use a separate persistent entity to match the properties that are needed like a DataStore or custom tables with a direct relation to the CatalogContent
  • Move the properties one level down as categories in EPiServer can use MetaClasses to extend the list of properties.

I believe the goal of a migration is to migrate data while offering a smooth transition; it involves keeping as much data as possible in a familiar structure. My goal here was not to challenge the previous data structure but making sure all the data was successfully migrated. It is absolutely possible to challenge a data structure but I would recommend to migrate first and then offer to refactor once the migration is complete.  

Once we have an understanding of our legacy commerce tree and we have the definitions for the new tree, we can start to programmatically add items in our commerce tree. In my scenario, this is the before/after:

Before

  • Store1
    • Catalog1
      • Category1
        • Product1
        • Product2
      • Category2
        • Product3
        • Product4
      • Catalog2
        • Category3
          • Product5
        • Store2
          • Catalog3
            • Category4
              • Product6

 

After

  • Catalog1 (previously identified as Store1)
    • Category1 (previously identified as Catalog1)
      • SubCategory1 (previously identified as Category1)
        • Product1
        • Product2
      • SubCategory2 (previously identified as Category2)
        • Product3
        • Product4
      • Category2 (previously identified as Catalog2)
        • SubCategory3 (previously identified as Category3)
          • Product5
        • Catalog2 (previously identified as Store2)
          • Category3 (previously identified as Catalog3)
            • SubCategory4 (previously identified as Category4)
              • Product6

A note about migration strategies

Migration scripts can be tricky depending on the volume of data to transfer. For some lucky scenarios, you might be able to have a single script that imports everything in one go, happy days.

Unfortunately, most enterprise databases are pretty heavy and sometimes your only option will be to split your migration into multiple scripts.  

 We could have the following scenarios:

  • A script for catalogs and categories, a script for products, a script for product “custom” properties or
  • A script for catalogs, a script for categories, a script for products and their properties or
  • A script for every single list of data to transfer, catalogs, categories, sub categories, products, product properties, category properties, etc.

If you have to run multiple scripts one after another – for example adding products to categories that we just created – your best bet is to save the previous database items ids inside your new EPiServer Commerce definitions.

Examples:  

  • Are you looking for the parent category of your product? Define a ‘legacy category id’ property in your category meta class so you can find refer to that property when saving a product.
  • Are you looking to update a product with properties from the legacy database? A ‘Legacy product id’ is your best bet to find the product.

That’s it for today šŸ˜Š

For the next articles, I will be looking to write about the functions to use to save data inside the Commerce database, pricing and how to export data from a database at a code level.

I hope it was helpful. If you are familiar with migrations please reach out, I would love to hear your feedback about this article.

Many thanks to the EPiServer Community and especially Praful, Quan and Sanjay for their help.

Feb 20, 2021

Comments

Sanjay Kumar
Sanjay Kumar Feb 21, 2021 04:44 AM

Great job Giuliano!

Giuliano Dore
Giuliano Dore Feb 21, 2021 01:21 PM

Thanks Sanjay šŸ˜Š 

Adam B
Adam B Feb 22, 2021 10:58 AM

This is really helpful Giuliano!

Giuliano Dore
Giuliano Dore Feb 22, 2021 04:03 PM

Thanks Adam šŸ˜Š

Please login to comment.
Latest blogs
Solving the mystery of high memory usage

Sometimes, my work is easy, the problem could be resolved with one look (when Iā€™m lucky enough to look at where it needs to be looked, just like th...

Quan Mai | Apr 22, 2024 | Syndicated blog

Search & Navigation reporting improvements

From version 16.1.0 there are some updates on the statistics pages: Add pagination to search phrase list Allows choosing a custom date range to get...

Phong | Apr 22, 2024

Optimizely and the never-ending story of the missing globe!

I've worked with Optimizely CMS for 14 years, and there are two things I'm obsessed with: Link validation and the globe that keeps disappearing on...

Tomas Hensrud Gulla | Apr 18, 2024 | Syndicated blog

Visitor Groups Usage Report For Optimizely CMS 12

This add-on offers detailed information on how visitor groups are used and how effective they are within Optimizely CMS. Editors can monitor and...

Adnan Zameer | Apr 18, 2024 | Syndicated blog