Product Details Page Architecture

This section applies to the Elbrus release of SuiteCommerce Advanced (SCA) and later. The following architecture is not backward compatible with previous versions of SCA.

The product details page (PDP) provides shoppers with detailed information about a product and lets shoppers add items to their cart. To ensure a positive user experience, the PDP needs to create intuitive interactions and return information from the server quickly and efficiently. The architecture of the PDP is designed to address these challenges. Communication of item details is accomplished through the Items and Product modules. This unifies the data structure governing order management.

The following diagram details the architecture behind the PDP and how user selections interact with NetSuite.

                        ProductViews Module       Models Collections     Views   Transaction.Line. Collection   Transaction.Line. Model   Transaction.Line. Option.Collection   Transaction.Line. Option.Model 4 7 6 8               Transaction.Model Transaction Module Modules ProductDetails.Base. View ProductDetails. Quick.View Product.Model Product.Option. Collection Product.Option.Model Item.Model Item.Option.Collection Item.Option.Model ProductLine Module Transaction.Line. Views Module ProductDetails. Full.View     ProductViews Module           Transaction Module   Models Collections   Modules   Views Transaction.Line. Views Module ProductLine Module       Transaction.Model   Transaction.Line. Collection   Transaction.Line. Model   Transaction.Line. Option.Collection       Item Module Product Module ProductDetails Module                         Item.Option.Collection   Item.Option.Model   Item.Model   Product.Model   Product.Option. Collection   Product.Option.Model   ProductDetails.Base. View   ProductDetails. Quick.View   ProductDetails. Full.View   Transaction.Line. Option.Model   2   3   4   7   8     6     1   ProductDetails.Base. View Item Module Product Module ProductDetails Module   ProductDetails. Quick.View                                                                           5     2   4   7   8   6 1   5   3                                
  1. Logic in the Item module retrieves read-only data from NetSuite. Item.Model retrieves data about an item through the Search API. This is a client-side, read-only instance of an item record in NetSuite. Item.Option receives read-only information about an option associated with the item. Item.Option.Collection is a collection of these possible options.

    Note:

    Item.Model is the read-only data from NetSuite used by Product.Model to validate the user selection. Providing a read-only version of the Item ensures that the original backend data cannot be accidentally overridden.

  2. Product.Model contains an Item.Model associated with an item to display in the PDP. Product.Option.Model contains editable instances of the related Item.Option models, and Product.Option.Collection is a collection of these options.

  3. The views and child views in the ProductDetails module use the data in the Product module to render the PDP. ProductDetails.Base.View contains the abstract view from which the Full PDP and Quick View views inherit.

  4. The views and child views in the ProductViews module use the data in the Product module to render price and item options in the PDP.

    Note:

    To enhance extensibility, SCA uses two different item option templates, one for the PDP and another for search results (Facets).

  5. When the user interacts with the PDP to select item options, Product.Model validates the data against the Item.Model that each Product.Model contains. This is why the Product.Model contains an Item.Model and why Item.Model is a client-side representation of the backend record.

  6. When the user chooses valid options and clicks Add To Cart, the following conversions occur:

    • Product.Option.Model is converted to Transaction.Line.Option.Model

    • Product.Option.Collection is converted to Transaction.Line.Option.Collection

    • Product.Model is converted to Transaction.Line.Model

    Transaction.Model contains a collection of transaction lines, which each include an item and selected options. Transaction.Line.Option.Model contains one of the selected options, and Transaction.Line.Option.Collection is a collection of all selected options.

  7. The ProductLine module contains views that are shared between the PDP, Checkout, and My Account applications.

  8. The Transaction module uses views in the Transaction.Line.Views module to render transaction details in the cart and in other modules.

Note:

Item.KeyMapping.js is part of the Item Module. This file contains mapping definitions of what is returned by the Search API. For example, if you want to set the name of items for data stored in a custom field instead of the default Display Name field, you extend the mapping in the Item.KeyMapping file, as opposed to customizing each instance across the entire code base.

Configuration

To configure the Product Details Page, you must have the SuiteCommerce Configuration bundle installed. Refer to the correct section for details on configurable properties as described below.

To configure the Product Details Page:

  1. Select the domain to configure at Commerce > Websites > Configuration.

  2. In the SuiteCommerce Configuration record, navigate to the Shopping Catalog tab and the appropriate subtab:

  3. Save the SuiteCommerce Configuration record to apply changes to your site.

Code Examples

The following examples show how to work with the PDP:

Add an Item to the Cart

The following example of a custom model adds an item to the cart. Product.Model contains the item through the fetch method. Based on the internal ID of the item, this code then sets the quantity and item options and adds the product to the cart through the LiveOrderModel.

          define('AddToCart',
[
        'Product.Model'
    ,   'LiveOrder.Model'
],
function(
        ProductModel
    ,   LiveOrderModel
)
{
    var my_item_internal_id = '40'
    ,   quantity = 10
    ,   product = new ProductModel()
    // load the item.
    product.getItem().fetch({
        data: {id: my_item_internal_id}
    }).then(function (){
        // set quantity
        product.set('quantity', quantity);
        // set options
        product.setOption('option_id', 'value');
        // add to cart
        LiveOrderModel.getInstance().addProduct(product);
    });
}); 

        

Validate an Item for Purchase

All shopping, wishlist, and quote item validation is centralized in the Product.Model. You can validate per field and developers can override the default validation per field.

The following customization uses a generic areAttributesValid method to validate per field. In this case it uses options and quantity, as opposed to validating the entire set. This method uses a pre-set default validation to validate the specified fields. The generateOptionalExtraValidation method overrides the default validation for any fields, in this case, quantity. If the values are not valid, the code introduces an alert message. Otherwise, the code adds the product to the cart.

Note:

The default validation is set in Product.Model.js.

          define('ValidateAddToCart'
,   [
        'LiveOrder.Model'
    ]
,   function (
        LiveOrderModel
    )
{
    function generateOptionalExtraValidation() {
        return {
            'quantity': function (){}
        }
    }
    var product = obtainSomeProduct(/*...*/);
    var cart = LiveOrderModel.getInstance();
    if (!product.areAttributesValid(['options','quantity'], this.generateOptionalExtraValidation()))
    {
        alert('Invalid Product!')
    }
    else
    {
        cart.addProduct(product);
    }
}); 

        

Add Item to Wishlist

The following customization gets new item data from the product and the correct product list. It then adds the product line to the list and alerts the user after successful validation.

          define('ValidateForWishList'
,   [
        'ProductList.Item.Model'
    ]
,   function (
        ProductListItemModel
    )
{
    var getNewItemData = function (product, productList)
        {
            var product_list_line = ProductListItemModel.createFromProduct(product);
            product_list_line.set('productList', {
                id: productList.get('internalid')
            ,   owner: productList.get('owner').id
            });
            return product_list_line;
        };
 
    var doAddProductToList = function (product, productList, dontShowMessage)
        {
            var product_list_line_to_save = getNewItemData(product, productList);
            product_list_line_to_save.save(null, {
                validate: false
            ,   success: function (product_list_line_to_save_saved)
                {
                    alert('Product Added!');                   
                }
            });
        };
    var product = getSomeProduct(/*...*/)
    ,   product_list = getSomeProduct(/*...*/);
    doAddProductToList(product, product_list);
}); 

        

Get Options

The following customization returns all valid options for an item or matrix item. Only valid options will render as selectable options in the browser.

           define('ReadProductOptions'
,   [
        'underscore'
    ]
,   function (
        _
    )
{
    var showFirstOptionWithValidValues = function (product)
    {
        //Collection of product.options
        var options_to_render = product.get('options');
        options_to_render.each(function (option)
        {
            //each option is a Model
            if (option.get('isMatrixDimension'))
            {
                var valid_values_for_selected_option = product.getValidValuesForOption(option);
                _.each(option.get('values'), function (value)
                {
                    value.set('isAvailable', _.contains(valid_values_for_selected_option, value.get('label')));
                });
            }
        });
        var first_valid_option = options_to_render.find(function (option)
            {
                return _.some(option.get('values'), function (value) { return value.get('isAvailable'); });
            });
        var selected_option = product.get('options').findWhere({cartOptionId: first_valid_option.get('cartOptionId')});
        //Note that we are always backbone Model and the value of the set option contains all details of the set value (label and internalid)
        alert('First Option with value values: ' + first_valid_option.get('cartOptionId') + ' set value: ' + selected_option.get('value').label)
    };
    showFirstOptionWithValidValues(getSomeIProduct(/*...*/));
}); 

        

Related Topics

General Notices