Monday, November 23, 2015

Working with the uCommerce API in Sitecore

uCommerce is a very powerful e-commerce module available for both Sitecore and Umbraco. The API that comes out of the box is equally powerful and have methods which make it possible to import a full product catalog from the third party system. This post will provide example calls into the uCommerce API, which should be everything needed to import data for a full catalog. Many of the methods assume one product catalog (which is a static variable).


Catalog

Each uCommerce shop can have a number of catalogs. The code example below allows you to get a catalog by it's name.
/// <summary>
/// Get a catalogue
/// </summary>
/// <param name="catalogueName">name of the catalogue</param>
/// <returns>Product catalogue</returns>
public static ProductCatalog GetCatalogue(string catalogueName)
{
    List<ProductCatalog> catalogs = UCommerce.Api.CatalogLibrary.GetAllCatalogs();
    return catalogs.FirstOrDefault(productCatalog => productCatalog.Name == catalogueName);
}

Categories

Below are the methods to get all/single categories, to create a category and to hide a category (set it to not display on web).
/// <summary>
/// Gets all categories
/// </summary>
/// <returns>All categories</returns>
public static List<Category> GetCategories()
{
    return Catalog.Categories.ToList();
}

/// <summary>
/// Add a cataegory
/// </summary>
/// <param name="categoryName">Name of the catagory</param>
/// <returns>The new category</returns>
public static Category AddCategory(string categoryName)
{
    if (Catalog == null)
    {
        return null;
    }

    var category = new Category
    {
        DisplayOnSite = true,
        Name = categoryName,
        ProductCatalog = Catalog,
        Definition = Definition.FirstOrDefault(x => x.Guid == DefaultCategoryDefinitionGuid)
    };

    category.AddCategoryDescription(new CategoryDescription()
    {
        DisplayName = categoryName
    });

    try
    {
        category.Save();
    }
    catch (Exception ex)
    {
        return null;
    }

    return category;
}

/// <summary>
/// Get a category
/// </summary>
/// <param name="categoryName">Name of a category</param>
/// <returns>catagory</returns>
public static Category GetCategory(string categoryName)
{
    return Catalog.Categories.ToList().FirstOrDefault(x => x.Name == categoryName);
}

/// <summary>
/// Hides a category
/// </summary>
/// <param name="categoryName">Name of a category</param>
/// <returns>Action result</returns>
public static bool HideCategory(string categoryName)
{
    var category = Catalog.Categories.ToList().FirstOrDefault(x => x.Name == categoryName);

    if (category != null)
    {
        if (category.DisplayOnSite)
        {
            category.DisplayOnSite = false;
            category.Save();
        }
    }
    else
    {
        return false;
    }

    return true;
}

Products & Variants

Below are a number of helper methods which include: setting custom properties on products, hiding products, getting product form category and getting a variant from it's parent product.
/// <summary>
/// Set a custom property on a product
/// </summary>
/// <param name="product">Product</param>
/// <param name="propertyName">Property name</param>
/// <param name="propertyValue">Property value</param>
public static void SetCustomProperty(Product product, string propertyName, string propertyValue)
{
    var property = product[propertyName];
    property.Value = propertyValue;
    property.Save();
}

/// <summary>
/// Set a product to a category
/// </summary>
/// <param name="categoryName">category name</param>
/// <param name="product">Product</param>
/// <returns>Action result</returns>
public static bool SetProductCategory(string categoryName, Product product)
{
    var category = GetCategory(categoryName);

    if (category == null)
    {
        return false;
    }

    var relation = new CategoryProductRelation
    {
        Product = product,
        Category = category
    };

    try
    {
        relation.Save();
    }
    catch (Exception ex)
    {
        return false;
    }

    return true;
}

/// <summary>
/// Hide a product
/// </summary>
/// <param name="product">Product</param>
/// <returns>Action result</returns>
public static bool HideProduct(Product product)
{
    if (product != null)
    {
        if (product.DisplayOnSite)
        {
            product.DisplayOnSite = false;
            product.Save();
        }
    }
    else
    {
        return false;
    }

    return true;
}

/// <summary>
/// Get a product from a given category
/// </summary>
/// <param name="category">Category</param>
/// <param name="productName">Product name</param>
/// <returns>Product</returns>
public static Product GetProductFromCategory(Category category, string productName)
{
    return category.Products.FirstOrDefault(x => x.Name == productName);
}

/// <summary>
/// Get a variant from a product
/// </summary>
/// <param name="product">Product</param>
/// <param name="variantSku">Variant SKU</param>
/// <returns>Variant product</returns>
public static Product GetVariantFromProduct(Product product, string variantSku)
{
    return product.Variants.FirstOrDefault(x => x.VariantSku == variantSku);
}
Then are the actual methods for creating products and variants.
private static readonly Guid ProductDefinitionGuid = new Guid("{9B19A3A0-287B-4DA4-B45E-018BD94F2718}"); // Product (template in SC content tree)
private static readonly Guid ProductVariantDefinitionGuid = new Guid("{70D1C14E-15FA-F05C-28D9-2E6DEAAD2A27}"); // Product Variant (template in SC content tree)
private static readonly PriceGroup AuPriceGroup = PriceGroup.SingleOrDefault(x => x.Name == "AU 10 pct");

// Model to create a product
public class CreateProductModel
{
    public string Sku { get; set; }
    public string Name { get; set; }
    public bool AllowOrdering { get; set; }
    public bool DisplayOnSite { get; set; }
    public string CategoryName { get; set; }
    public decimal? Price { get; set; }
}

// Model to create a product variant
public class CreateProductModel
{
    public string Sku { get; set; }
    public string Name { get; set; }
    public bool AllowOrdering { get; set; }
    public bool DisplayOnSite { get; set; }
    public string CategoryName { get; set; }
    public decimal? Price { get; set; }
    public Product ParentProduct { get; set; }
}

/// <summary>
/// Crate a product
/// </summary>
/// <param name="prod">Product model</param>
/// <returns>Product</returns>
public static Product CreateProduct(CreateProductModel prod)
{
    // Create product
    var product = new Product
    {
        Sku = prod.Sku,
        Name = prod.Name,
        AllowOrdering = prod.AllowOrdering,
        DisplayOnSite = prod.DisplayOnSite,
        ProductDefinition = ProductDefinition.FirstOrDefault(x => x.Guid == ProductDefinitionGuid)
    };

    try
    {
        product.Save();
    }
    catch (Exception ex)
    {
        return null;
    }

    // set price
    var productPrice = new PriceGroupPrice
    {
        PriceGroup = AuPriceGroup,
        Price = prod.Price ?? 0m,
        Product = product
    };

    productPrice.Save();

    // Set category
    var categoryResult = SetProductCategory(prod.CategoryName, product);

    return product;
}

/// <summary>
/// Create a product variant
/// </summary>
/// <param name="prod">Product variant model</param>
/// <returns>Product variant</returns>
public static Product CreateProductVariant(CreateProductVariantModel prod)
{
    // Create product
    var product = new Product
    {
        Sku = prod.Sku,
        VariantSku = prod.Sku,
        Name = prod.Name,
        AllowOrdering = prod.AllowOrdering,
        DisplayOnSite = prod.DisplayOnSite,
        ProductDefinition = ProductDefinition.FirstOrDefault(x => x.Guid == ProductVariantDefinitionGuid),
        ParentProduct = prod.ParentProduct
    };

    try
    {
        product.Save();
    }
    catch (Exception ex)
    {
        return null;
    }

    // set price
    var productPrice = new PriceGroupPrice
    {
        PriceGroup = AuPriceGroup,
        Price = prod.Price ?? 0m,
        Product = product
    };

    // Set category
    var categoryResult = SetProductCategory(prod.CategoryName, product);

    return product;
}
It's worthwhile adding some error handling around this API, especially if the process is done via an automatic sync.

No comments:

Post a Comment