Could you please provide some sample code for creating a dynamic product as it doesn't seem to be documented anywhere. I would like to assign it a price, title and then some custom properties - in my particular case, two dates.
The user will fill out some form data, this will be posted to the controller which will calculate price, create the product and then display it for the customer to see. The user should then be able to click 'add to basket' or 'add to basket and checkout'.
When something is shippable you should also associate the product with a catalog.
var productService = MerchelloContext.Current.Services.ProductService;
var product = productService.CreateProduct(name, sku, 0);
product.Available = true;
product.TrackInventory = false;
product.Shippable = true;
// Taxable is false since they are included
product.Taxable = false;
_productService.Save(product);
var warehouse = _warehouseService.GetDefaultWarehouse();
var catalog = warehouse.WarehouseCatalogs.FirstOrDefault();
if (catalog == null)
{
var error = new NullReferenceException("The default warehouse did not have any catalogs");
throw error;
}
product.AddToCatalogInventory(catalog);
productService.Save(product);
If you are asking about an existing product that you want to add to the basket and change the price on the fly you could try one of the basket overloads.
Merchello's basket is really more about the meta data in the extended data collection than a strict association with the product in the catalog - so you can do this by:
var basket = CurrentCustomer.Basket();
var product = Merchello.Query.Product.GetByKey( ... your product key ... );
// assuming you don't have variants - you still need to get the master variant which represents a single product.
// or get your variant by it's key
var variant = product.GetProductVariantForPurchase();
// now we build the extended data collection for the checkout work flow.
var extendedData = new ExtendedDataCollection();
extendedData.AddProductVariantValues(variant); // serializes all of the variant information used in the work flow
// while the price is also serialized, the real values we want for the checkout are in the line item - so you
// can skip updating the extendedData price and simply add to the basket with
basket.AddItem(product.Name, product.Sku, [your quantity], [your calculated price], extendedData);
Hi Martin ... sorry I missed your custom properties.
before adding the item to the basket you could stuff your dates into the extendedData collection - so after the line
extendedData.AddProductVariantValues(variant);
// add your custom properties
extendedData.SetValue("key-for-date1", date1.ToShortDateString());
extendedData.SetValue("key-for-date2", date2.ToShortDateString());
You can later retrieve those from the basket line item, invoice line item and order line item (also used in shipments) by using the GetValue on the ExtendedDataCollection for the line item with the matching sku. ... meaning the line items are copied from the basket to and invoice, from the invoice to an order ...
I'm don't think I'm following what you mean by "not-codify" products in the basket but from what I understand your idea implies I think it is possible.
var basket = CurrentCustomer.Basket();
var fromProduct = Merchello.Query.Product.GetByKey( [your generic product key] );
// assuming you do not have any options (thus other variants on the generic product)
fromProduct.Price = "your price";
fromProduct.Sku = "your sku"; // sku is used in the basket to group line items
// description is not a Merchello Product property - so if you need this you will need to add it to the extendedData collection
// at this point ... otherwise
CurrentCustomer.Basket().AddItem(fromProduct, [your name], [your quantity]);
With "not-codify" product I mean a product that it is not in catalogue, because I think that the catalogue must be contains only standard articles.
My eCommerce website will sell carpenter products. Then I will fill catalogue with tables, chairs, and so on.
But a customer can compile a simplest form to indicates custom variants of a standard table, for example he can ask a table more or less length, or height. It can be a variant of standard article, but the special request is special, then I think that it is not to save to catalogue.
But the website offers the opportunity to ask a newest article. Then it cann't be added as variant of product.
I think that your code is what I need.
But I understand the comment of "SKU"; can you spell more?
I am trying your code but I can't compile it: AddItem method does not expose an overload with ProductDisplay as type of product argument.
Maybe I wrong to get the product? I have not a Merchello.Query, then I solved it with this:
var merchHelper = new MerchelloHelper()
var product = merchHelper.Query.Product.GetByKey( [-product key-] )
var productService = MerchelloContext.Current.Services.ProductService;
var fromProduct = productService.GetByKey( [-product key-] );
// assuming you do not have any options (thus other variants on the generic product)
fromProduct.Price = "your price";
fromProduct.Sku = "your sku"; // sku is used in the basket to group line items
// description is not a Merchello Product property - so if you need this you will need to add it to the extendedData collection
// at this point ... otherwise
CurrentCustomer.Basket().AddItem(fromProduct, [your name], [your quantity]);
I appreciate this is an old post but how do I get the line item URL? I know how to get the product/sku URL but I want the user to be able to navigate back to the variant that they have created. Is this possible?
I suppose it'd be the URL of a line item.
I'm adding a product to the basket with extended data (its actually form data that they fill in on the product page to customise the product). So I want users to be able to have an "edit" link from the basket page which will take them back to their customised product page.
But will that take the user to the product page or the instance of the product?
So in my example, the user will initially view a product page, on that page they'll add custom data to it. It's actually charity gifts, so users will add data to the product to add a personalised message. Then they'll add it to their basket.
Then I want them to be able to click edit on the basket page that will take them back to their produc with their personalised message.
Is that possible?
Maybe I'm misunderstand but what is difference between the sku and product key?
Finally, from the basket, is it possible to loop through each item in the basket (not line item)? As I want to have a row for each instance of a product in the basket.
Here are the steps and what I'm currently doing at each step
User visits a product page
User adds custom data (for now I'm just adding a datestamp in the controller) and adds the item to their basket
This will then go to my controller which will add the item with the custom data to the basket, this is how I'm doing it, button link first then controller code:
@Url.SurfaceAction("AddToBasket", "BasketManager", new { productKey Model.Key})
public ActionResult AddToBasket(string productKey)
{
var merchello = new MerchelloHelper(false);
var product = merchello.Query.Product.GetByKey(new Guid(productKey));
var extendedData = new ExtendedDataCollection();
extendedData.SetValue("ItemDate", DateTime.Now.ToString("F"));
Basket.AddItem(product, product.Name, 1, extendedData);
Basket.Save();
var siteSettings = UmbracoHelpers.GetSiteSettings().As<ViewModels.Data.SiteSettings>();
if(siteSettings.Basket != null)
{
return RedirectToUmbracoPage(siteSettings.Basket.Id);
}
return Redirect(CurrentPage.Url);
}
However the above only seems to add one item to the basket. When I view the same product page and try to add to basket again, it just overwrites the previous item. I want it to add a new item.
Finally, on my view I want to loop through all of the items (not products) in the basket). Currently I do this but its just looping through the products:
@foreach (var item in customerBasket.Items)
{}
But again, this is just looping through products and not items. I want to get a URL to go back to the item (or product instance)
I'm not sure why it would be overwriting the previous product, rather it should be changing the quantity to two ...
The collection is SKU based, so unless you change the SKU, the item will always be viewed as the same item in the basket - so you will need to append something to the SKU to make it unique in the item collection.
Storing values in extended data is just fine, but when you go back to the product page, it may be helpful to somehow pass the line item key (or the generated SKU) of the item in the basket so that you can retrieve the previously saved values in the extended data collection more easily.
Creating a product on the fly
Hi Rusty,
Could you please provide some sample code for creating a dynamic product as it doesn't seem to be documented anywhere. I would like to assign it a price, title and then some custom properties - in my particular case, two dates.
The user will fill out some form data, this will be posted to the controller which will calculate price, create the product and then display it for the customer to see. The user should then be able to click 'add to basket' or 'add to basket and checkout'.
Martin,
What do you mean by dynamic product? Do you mean a product that changes over time somehow?
Products with variants can be added in this way:
var productService = MerchelloContext.Current.Services.ProductService;
var product = productService.CreateProduct(name, sku, price);
//Assert.IsFalse(product.HasIdentity, "The product was saved");
product.TrackInventory = false;
product.Shippable = true;
product.Weight = 10M;
product.Manufacturer = "Mindfly";
productService.Save(product);
-Dina
Hi Martin,
When something is shippable you should also associate the product with a catalog.
If you are asking about an existing product that you want to add to the basket and change the price on the fly you could try one of the basket overloads.
Merchello's basket is really more about the meta data in the extended data collection than a strict association with the product in the catalog - so you can do this by:
Make sense?
Hi Martin ... sorry I missed your custom properties.
before adding the item to the basket you could stuff your dates into the extendedData collection - so after the line
You can later retrieve those from the basket line item, invoice line item and order line item (also used in shipments) by using the GetValue on the ExtendedDataCollection for the line item with the matching sku. ... meaning the line items are copied from the basket to and invoice, from the invoice to an order ...
Is there a better and full example?
I prefere to do not use the built-in Merchello catalogue. Then I would add "not-codified" products in Basket.
I look that it is not possible, then your code create a newest product for any article for any Basket.
I am another idea:
Is it possible to use this solution?
Will Merchello right behavior in any step of Basket life-cycle?
Thanks
Hi Flavio,
I'm don't think I'm following what you mean by "not-codify" products in the basket but from what I understand your idea implies I think it is possible.
... does this work for you?
Thanks @Rusty.
With "not-codify" product I mean a product that it is not in catalogue, because I think that the catalogue must be contains only standard articles.
My eCommerce website will sell carpenter products. Then I will fill catalogue with tables, chairs, and so on. But a customer can compile a simplest form to indicates custom variants of a standard table, for example he can ask a table more or less length, or height. It can be a variant of standard article, but the special request is special, then I think that it is not to save to catalogue.
But the website offers the opportunity to ask a newest article. Then it cann't be added as variant of product.
I think that your code is what I need. But I understand the comment of "SKU"; can you spell more?
I am trying your code but I can't compile it:
AddItem
method does not expose an overload withProductDisplay
as type of product argument.Maybe I wrong to get the product? I have not a
Merchello.Query
, then I solved it with this:Flavio - totally sorry - my bad.
it should be:
Missed your previous comment asking about the SKU.
The SKU is a "product code", usually unique per specific product.
Example.
Maybe you sell:
1 table - $1,100 - SKU: TBL123
4 chairs without arms - $950 - SKU: chair123
2 chairs with arms - $500 = SKU: chair123-plus
You could add some notes to the order if there are on fly and not fixed variants.
@Biagio - I've been considering this as a stub for a report of some sort.
Hi Rusty,
I appreciate this is an old post but how do I get the line item URL? I know how to get the product/sku URL but I want the user to be able to navigate back to the variant that they have created. Is this possible?
I suppose it'd be the URL of a line item.
I'm adding a product to the basket with extended data (its actually form data that they fill in on the product page to customise the product). So I want users to be able to have an "edit" link from the basket page which will take them back to their customised product page.
Thanks
Ben
The productKey will be in the extended data collection so you should be able to:
But will that take the user to the product page or the instance of the product?
So in my example, the user will initially view a product page, on that page they'll add custom data to it. It's actually charity gifts, so users will add data to the product to add a personalised message. Then they'll add it to their basket.
Then I want them to be able to click edit on the basket page that will take them back to their produc with their personalised message.
Is that possible?
Maybe I'm misunderstand but what is difference between the sku and product key?
Finally, from the basket, is it possible to loop through each item in the basket (not line item)? As I want to have a row for each instance of a product in the basket.
Sorry for the many questions!!
It's probably me not understanding what you are entirely doing. How are you saving the "custom configurations" ... in the extended data collection?
The Url will get you back to just the product page so if you have some sort of specific "state" you would need to pass other parameters.
For the product "items"
I'll try to explain again :)
Here are the steps and what I'm currently doing at each step
User visits a product page
User adds custom data (for now I'm just adding a datestamp in the controller) and adds the item to their basket
This will then go to my controller which will add the item with the custom data to the basket, this is how I'm doing it, button link first then controller code:
However the above only seems to add one item to the basket. When I view the same product page and try to add to basket again, it just overwrites the previous item. I want it to add a new item.
Finally, on my view I want to loop through all of the items (not products) in the basket). Currently I do this but its just looping through the products:
But again, this is just looping through products and not items. I want to get a URL to go back to the item (or product instance)
Thanks in advance
Ben
Hi Rusty,
Please could you help with this? Its starting to become a blocker for me
Thanks
Ben
Hey Ben,
I'm not sure why it would be overwriting the previous product, rather it should be changing the quantity to two ...
The collection is SKU based, so unless you change the SKU, the item will always be viewed as the same item in the basket - so you will need to append something to the SKU to make it unique in the item collection.
Storing values in extended data is just fine, but when you go back to the product page, it may be helpful to somehow pass the line item key (or the generated SKU) of the item in the basket so that you can retrieve the previously saved values in the extended data collection more easily.
is working on a reply...