Magelia for Orchard : UpSelling and CrossSelling Products

Feb 18, 2013 at 10:38 AM
Hi,

In the Magelia for Orchard module, there is no widget that shows Related Products (UpSelling or CrossSelling). We tried to develop one, based on the ProductList part, and using Magelia.WebStore.Services.ProductListServices for initialization.

The issue is that in the result of the request, there is no information on the Related Products. We looked in BaseProduct.ProductLinkings and BaseProduct.ProductLinks, but they are empty. Where are the Cross and Up selling products and how can we get them ?
public ProductListViewModel GetModel(String catCode, String SKU)
        {
            var viewModel = new ProductListViewModel();
            this._webStoreServices.UsingClient(
                c =>
                {
                    IQueryable<BaseProduct> productsQuery = c.CatalogClient.Products
                                .Expand(String.Format("{0}/DefaultVariantProduct/Attributes/Files", c.CatalogClient.ResolveName(typeof(VariableProduct))))
                                .Expand(p => (p as VariableProduct).DefaultVariantProduct.PriceWithLowerQuantity)
                                .Expand(p => (p as VariableProduct).DefaultVariantProduct.Brand)
                                .Expand(p => (p as ReferenceProduct).PriceWithLowerQuantity)
                                .Expand(p => p.Brand)
                                .Expand(p => p.Catalog)
                                .Expand(String.Format("{0}/Attributes/Files", c.CatalogClient.ResolveName(typeof(ReferenceProduct))))
                                .Where(p => !(p is VariantProduct));

                    productsQuery = productsQuery.Where(p => (!(p is VariantProduct) && p.Catalog.Code == catCode) || (p is VariantProduct && (p as VariantProduct).VariableProduct.ProductCategories.Any(pc => pc.Category.Code == catCode)));
                    viewModel.AddRange(productsQuery);
                    viewModel.State.ProductRefFilter = SKU;
                    viewModel.State.PageCount = 1;
                    viewModel.State.CategoryCodeFilter = catCode;
                }
            );
            return viewModel;
        }
Regards,
Coordinator
Feb 18, 2013 at 3:26 PM
Hi Boris,

At this stage we did not develop a widget to display cross/up-selling items from Magelia WebStore in an Orchard WebSite. You can however modify the OData request of the “ProductServices” that provides the products data. You simply need to indicate the path of the related members that you want to load using the “Expand” method.

In the code below, we added .Expand("ProductLinks/LinkedProduct") to load all related products. Depending on what information you want to display on your website, you will probably add other members in the request. For example, if you want to load the attributes of Linked products you should add the following method call to the request: "Expand("ProductLinks/LinkedProduct/Attributes")".
viewModel.ReferenceProduct = (c.CatalogClient.Products.OfType<ReferenceProduct>() as DataServiceQuery<ReferenceProduct>)
  .Expand(rp => rp.Brand)
  .Expand(String.Format("{0}/VariableProduct/VariantProducts/Attributes/Files", variantProductName))
  .Expand(String.Format("{0}/VariableProduct/VariantProducts/PriceWithLowerQuantity", variantProductName))
  .Expand("Prices/TaxDetails")
  .Expand("Prices/DiscountDetails")
  .Expand(rp => rp.PriceWithLowerQuantity)
  .Expand("Attributes/Files")
  .Expand("ProductLinks/LinkedProduct")
 .Where(rp => rp.Catalog.Code == viewModel.RequestedCatalogCode && rp.SKU == viewModel.RequestedSKU)
 .FirstOrDefault();
The ViewModel created in this service is available in the "Product" widget as an attribute named “Target”, so that you can have direct access to all related products in the "Parts/Product.cshtml" view.

Here is an example:
var linkedProduct = (this.Model.Target.BaseProduct.ProductLinks as IEnumerable<Object>).Cast<dynamic>().Select(pl => pl.LinkedProduct).ToList();

We hope that we answered your question.
Please do not hesitate if you have any other question.
Jun 21, 2013 at 11:49 PM
Hi Yaligault,,

I am trying to get the fully filled model for the all of the related products using
viewModel.ReferenceProduct = (c.CatalogClient.Products
                                                                    .OfType<ReferenceProduct>() as DataServiceQuery<ReferenceProduct>)
                                                                    .Expand(rp => rp.Brand)
                                                                    .Expand(String.Format("{0}/VariableProduct/VariantProducts/Attributes/Files", variantProductName))
                                                                    .Expand(String.Format("{0}/VariableProduct/VariantProducts/PriceWithLowerQuantity", variantProductName))
                                                                    .Expand("Prices/TaxDetails")
                                                                    .Expand("Prices/DiscountDetails")
                                                                    .Expand(rp => rp.PriceWithLowerQuantity)
                                                                    .Expand("Attributes/Files")
                                                                    .Expand("ProductLinks/LinkedProduct/Attributes/Files")
                                                                    .Where(rp => rp.Catalog.Code == viewModel.RequestedCatalogCode && rp.SKU == viewModel.RequestedSKU)
                                                                    .FirstOrDefault();
But the the model never gets filled.

Am I missing something on the method call?

Regards!
Coordinator
Jun 24, 2013 at 10:13 AM
Hi dkennedy77,

When you say "the model never gets filled.", what do you mean exactly ? does the method call return null ? or are the product properties not fully filled ?

If the method call return null, it means that the product is not available for your context.
Did you run the "data update" operation after inserting the product ?


Regards,

Cyril DURAND
Jun 24, 2013 at 6:03 PM
Hi Cyril,

Thanks for your reply.

What I mean is the method call returns null. If I just add the line - .Expand("ProductLinks/LinkedProduct") then the model is filled but I have a very limited amount of properties for the linked products. When I had the .Expand("ProductLinks/LinkedProduct/Attributes") then the null is returned. I was able to find the error that is generated -
"{\"odata.error\":{\"code\":\"\",\"message\":{\"lang\":\"en-CA\",\"value\":\"Type 'CodeFirstNamespace.BaseProduct' does not have a property named 'Attributes'; there is no service action named 'Attributes' that is bindable to the type 'CodeFirstNamespace.BaseProduct'; and there is no type with the name 'Attributes'.\"}}}"

Thanks,

Denis
Coordinator
Jun 24, 2013 at 11:06 PM
Hi Denis,

OK, I see the problem.

You are trying to expand the "Attributes" property on a collection of BaseProduct. But, there is no Attributes property on BaseProduct, this property is available on ReferenceProduct which inherits from BaseProduct.
If you want to do this, you should use this kind of syntax (I didn't test it) :
.Expand(String.Format("ProductLinks/LinkedProduct/{0}/Attributes/Files", c.CatalogClient.ResolveName(typeof(ReferenceProduct))))


By the way, I recommend you to use the .Include method instead of .Expand. This method is new to 2.2 (or 2.3) release and we didn't take the time to upgrade the Magelia WebStore orchard module yet, this method let you "expand" query without using string.
You can find sample on how to do this in our startersite available here : https://mageliawebstore.codeplex.com/releases/view/102986

Feel free to ask again if you have any questions :-)

Cyril DURAND
Jun 25, 2013 at 4:19 AM
Hi Cyril,

That worked, thanks!

Once I saw the error I did try :

.Expand(String.Format("ProductLinks/LinkedProduct/{0}/Attributes/Files", (typeof(ReferenceProduct))

But the c.CatalogClient.ResolveName did the trick for me.

BTW, the new method looks much better but I am way over budget on this project so this current solution will more than suffice for now.

Thanks again,

Denis