How to override product price when adding to basket?
How to override product price when adding to basket?
I'm working a project that requires me to manually set the price of the product and add the item to the basket in my own code.
Whenever I set the price on the basketitem before it's added to the token basket, it gets overridden by the price on the product record itself. In Minibasket and on the cart page, my price gets changed and becomes whatever the product record price is set.
It appears as if the TaxHelper.GetShopPrice() method is forcing the ac_Products price and not respecting the price on the basketitem record itself. Is there a workaround for this or some way to prevent this behavior?
Whenever I set the price on the basketitem before it's added to the token basket, it gets overridden by the price on the product record itself. In Minibasket and on the cart page, my price gets changed and becomes whatever the product record price is set.
It appears as if the TaxHelper.GetShopPrice() method is forcing the ac_Products price and not respecting the price on the basketitem record itself. Is there a workaround for this or some way to prevent this behavior?
Joe Payne
AbleCommerce Custom Programming and Modules http://www.AbleMods.com/
AbleCommerce Hosting http://www.AbleModsHosting.com/
Precise Fishing and Hunting Time Tables http://www.Solunar.com
AbleCommerce Custom Programming and Modules http://www.AbleMods.com/
AbleCommerce Hosting http://www.AbleModsHosting.com/
Precise Fishing and Hunting Time Tables http://www.Solunar.com
- jmestep
- AbleCommerce Angel
- Posts: 8164
- Joined: Sun Feb 29, 2004 8:04 pm
- Location: Dayton, OH
- Contact:
Re: How to override product price when adding to basket?
I do it on our church site for digital products. I didn't want to set up options for thousands of products, so I set a price based on one of three media types using a template field. If the product is mp3 download, I change it to non-shippable also when it's put into the basket. I set the products to use variable price, with a minimum of $3 for the cassette. On the product page I have:
Code: Select all
protected BasketItem GetBasketItem()
{
//GET THE QUANTITY
int tempQuantity = AlwaysConvert.ToInt(Quantity.Text,1);
if (tempQuantity < 1) return null;
if (tempQuantity > System.Int16.MaxValue) tempQuantity = System.Int16.MaxValue;
//CREATE THE BASKET ITEM WITH GIVEN OPTIONS
Basket basket = Token.Instance.User.Basket;
BasketItem basketItem = BasketItemDataSource.CreateForProduct(_ProductId, (short)tempQuantity);
basketItem.BasketId = basket.BasketId;
decimal CDPrice = AlwaysConvert.ToDecimal(ConfigurationManager.AppSettings["CDPrice"]);
decimal MP3Price = AlwaysConvert.ToDecimal(ConfigurationManager.AppSettings["MP3Price"]);
ProductHelper.CollectProductTemplateInput(basketItem, this);
//SPECIAL USE OF VARIABLE PRICE FOR MP3
if (_Product.UseVariablePrice)
{
Currency userCurrency = Token.Instance.User.UserCurrency;
decimal userLocalPrice = AlwaysConvert.ToDecimal(_Product.Price);
basketItem.Price = userCurrency.ConvertToBase(userLocalPrice);
//jme 060609
//ProductHelper.CollectProductTemplateInput(basketItem, this);
ProductTemplate template = basketItem.Product.ProductTemplate;
string MediaType = "";
if (template != null)
{
foreach (InputField input in template.InputFields)
{
//ONLY LOOK FOR CUSTOMER INPUT FIELDS
if (!input.IsMerchantField)
{
//SEE IF WE CAN LOCATE THE CONTROL
WebControl inputControl = (WebControl)PageHelper.RecursiveFindControl(phOptions, input.UniqueId);
if (inputControl != null)
return GetMediaPriceShipping(basketItem, CDPrice, MP3Price, ref userLocalPrice, ref MediaType, input, inputControl);
}
}
}
else if (template == null)
{
basketItem.Price = userCurrency.ConvertToBase(userLocalPrice);
basketItem.Weight = _Product.Weight;
basketItem.ShippableId = _Product.ShippableId;
return basketItem;
}
}
return basketItem;
}
protected BasketItem GetMediaPriceShipping(BasketItem basketItem, decimal CDPrice, decimal MP3Price, ref decimal userLocalPrice, ref string MediaType, InputField input, WebControl inputControl)
{
MediaType = input.GetControlValue(inputControl);
if (MediaType.ToUpper() == "CD")
{
userLocalPrice = AlwaysConvert.ToDecimal(CDPrice);
basketItem.Price = userLocalPrice;
basketItem.Weight = _Product.Weight;
basketItem.ShippableId = _Product.ShippableId;
return basketItem;
}
else if (MediaType.ToUpper() == "MP3 DOWNLOAD")
{
userLocalPrice = AlwaysConvert.ToDecimal(MP3Price);
basketItem.Price = userLocalPrice;
basketItem.ShippableId = 0;
basketItem.BasketShipmentId = 0;
basketItem.Weight = 0;
return basketItem;
}
else // not mp3 or cd
{
basketItem.Price = userLocalPrice;
basketItem.Weight = _Product.Weight;
basketItem.ShippableId = _Product.ShippableId;
return basketItem;
}
}
Judy Estep
Web Developer
jestep@web2market.com
http://www.web2market.com
708-653-3100 x209
New search report plugin for business intelligence:
http://www.web2market.com/Search-Report ... -P154.aspx
Web Developer
jestep@web2market.com
http://www.web2market.com
708-653-3100 x209
New search report plugin for business intelligence:
http://www.web2market.com/Search-Report ... -P154.aspx
Re: How to override product price when adding to basket?
So "the trick" is to set it as a variable price item and then the sub-functions that affect the basket (TaxHelper etc) will use the basket item price instead of the product price? Didn't think about that route, nice idea.
Basket manipulation in AC7 is inconsistent at best. It's frustrating to not see consistent behavior when working with the basket and related areas like TaxHelper or Shipping Estimates etc. The lack of signficant tech documentation doesn't help - everything learned is via a frustrating brute-force effort.
Thanks Judy - I'll give that a try in the morning. My only workaround was to add items as a Charge-type basket item. Not ideal because the basket display pages (basket.ascx and minibasket) won't display charge-type line items.
Basket manipulation in AC7 is inconsistent at best. It's frustrating to not see consistent behavior when working with the basket and related areas like TaxHelper or Shipping Estimates etc. The lack of signficant tech documentation doesn't help - everything learned is via a frustrating brute-force effort.
Thanks Judy - I'll give that a try in the morning. My only workaround was to add items as a Charge-type basket item. Not ideal because the basket display pages (basket.ascx and minibasket) won't display charge-type line items.
Joe Payne
AbleCommerce Custom Programming and Modules http://www.AbleMods.com/
AbleCommerce Hosting http://www.AbleModsHosting.com/
Precise Fishing and Hunting Time Tables http://www.Solunar.com
AbleCommerce Custom Programming and Modules http://www.AbleMods.com/
AbleCommerce Hosting http://www.AbleModsHosting.com/
Precise Fishing and Hunting Time Tables http://www.Solunar.com
- jmestep
- AbleCommerce Angel
- Posts: 8164
- Joined: Sun Feb 29, 2004 8:04 pm
- Location: Dayton, OH
- Contact:
Re: How to override product price when adding to basket?
Yes, the trick is the variable price. I can't take credit for thinking of it- I had seen it on an Able 5 site where another developer had customized it.
Judy Estep
Web Developer
jestep@web2market.com
http://www.web2market.com
708-653-3100 x209
New search report plugin for business intelligence:
http://www.web2market.com/Search-Report ... -P154.aspx
Web Developer
jestep@web2market.com
http://www.web2market.com
708-653-3100 x209
New search report plugin for business intelligence:
http://www.web2market.com/Search-Report ... -P154.aspx
Re: How to override product price when adding to basket?
To add to this discussion, I tried doing something very similar but with a bundled item.
I wanted to change the price on a bundled item if a user was a member of a particular group. So I had a main product for the bundle and I have an "Included - Shown" component and a product added to that. The Product added to the component is set to use a variable price on the actual product record, I had already thought about that; but in the bundle (the "Kit Part") has a fixed price. Variable price is not an option.
On the checkout page, I loop through the basket items looking for my "Kit Part" bundled components but I don't see them there, the only products I saw in the basket items were the main products. So, I take those and looped through the KitComponents collection and thought I would change the price there. Wrong, when I did that, it actually changed the price on the root kit component so it was changed for everyone on every order going forward.
I guess AC must pull in the kit/bundle objects on the fly the same way Joe was saying it did for the product price. It is strange because I looked at the BasketItems table while the order was in process and sure enough, the kit components are all listed separately with the right ParentItemId and everything, but I was not able to access them throught the BasketItems collection.
If you guys have any suggestions, I'd be open to them. I tried creating a coupon for the bundled item and seeing if that would work but it doesn't. If you apply a coupon to a kit/bundle, it only applies to the main product. I created at 100% off product coupon and applied it to an order with a bundle. I got 100% off the main product but still had to pay for the bundled item. I think I am going to open a thread on that as well.
I wanted to change the price on a bundled item if a user was a member of a particular group. So I had a main product for the bundle and I have an "Included - Shown" component and a product added to that. The Product added to the component is set to use a variable price on the actual product record, I had already thought about that; but in the bundle (the "Kit Part") has a fixed price. Variable price is not an option.
On the checkout page, I loop through the basket items looking for my "Kit Part" bundled components but I don't see them there, the only products I saw in the basket items were the main products. So, I take those and looped through the KitComponents collection and thought I would change the price there. Wrong, when I did that, it actually changed the price on the root kit component so it was changed for everyone on every order going forward.
I guess AC must pull in the kit/bundle objects on the fly the same way Joe was saying it did for the product price. It is strange because I looked at the BasketItems table while the order was in process and sure enough, the kit components are all listed separately with the right ParentItemId and everything, but I was not able to access them throught the BasketItems collection.
If you guys have any suggestions, I'd be open to them. I tried creating a coupon for the bundled item and seeing if that would work but it doesn't. If you apply a coupon to a kit/bundle, it only applies to the main product. I created at 100% off product coupon and applied it to an order with a bundle. I got 100% off the main product but still had to pay for the bundled item. I think I am going to open a thread on that as well.
Re: How to override product price when adding to basket?
Yeah now I'm having trouble altering the name of the item in the basket. It'll save it for one postback. Any subsequent refreshes reset the name to the product name stored on the product record.
Grrr this is frustrating. This shouldn't be this hard. Able has too many hard-coded overrides in the basket class. Data classes shouldn't work that way. Once it's populated, leave it the heck alone.
Grrr this is frustrating. This shouldn't be this hard. Able has too many hard-coded overrides in the basket class. Data classes shouldn't work that way. Once it's populated, leave it the heck alone.
Joe Payne
AbleCommerce Custom Programming and Modules http://www.AbleMods.com/
AbleCommerce Hosting http://www.AbleModsHosting.com/
Precise Fishing and Hunting Time Tables http://www.Solunar.com
AbleCommerce Custom Programming and Modules http://www.AbleMods.com/
AbleCommerce Hosting http://www.AbleModsHosting.com/
Precise Fishing and Hunting Time Tables http://www.Solunar.com
Re: How to override product price when adding to basket?
Yes, that is one of the issues I had trying to change the price on the basket item kit components. It would hold it for one but then it would recalculate on subsequent refreshes or postbacks.
That was when I dug deeper and ended up changing the actual "root" kit component part (whatever it is called) for the store; which is not what I wanted.
But I agree, once it is in the basket, why do the name and price get updated. It seems at that point only quantity should be important.
There is one issue I can see that would be related, and I don't know what is the best way to handle this, but if I have an item in my cart and then I go into the admin and change the price, the next time I refresh my cart the price of the item updates to the new price in the admin.
Is that good or bad? Not sure but that would be why our name/price changes are not sticking to the basket items.
That was when I dug deeper and ended up changing the actual "root" kit component part (whatever it is called) for the store; which is not what I wanted.
But I agree, once it is in the basket, why do the name and price get updated. It seems at that point only quantity should be important.
There is one issue I can see that would be related, and I don't know what is the best way to handle this, but if I have an item in my cart and then I go into the admin and change the price, the next time I refresh my cart the price of the item updates to the new price in the admin.
Is that good or bad? Not sure but that would be why our name/price changes are not sticking to the basket items.
- jmestep
- AbleCommerce Angel
- Posts: 8164
- Joined: Sun Feb 29, 2004 8:04 pm
- Location: Dayton, OH
- Contact:
Re: How to override product price when adding to basket?
I think both "issues" are related to safeguards Able has on basket items. If a customer has something in the basket and merchant changes the price, name, etc. then it is changed when the customer comes back and tries to buy from that basket. Most, if not all, merchants wouldn't want an older price on a basket item.
Judy Estep
Web Developer
jestep@web2market.com
http://www.web2market.com
708-653-3100 x209
New search report plugin for business intelligence:
http://www.web2market.com/Search-Report ... -P154.aspx
Web Developer
jestep@web2market.com
http://www.web2market.com
708-653-3100 x209
New search report plugin for business intelligence:
http://www.web2market.com/Search-Report ... -P154.aspx
Re: How to override product price when adding to basket?
Ok, so here are my notes and my solution to both issues in case anyone else is interested:
Issue #1 - Changing the price of a basket item
Solution: Easy if you set the product as a variable-price product in the catalog. Not possible any other way as Able basket recalc methods will blow the custom price away on the next basket recalc. Probably going to be this way for a while - lots of things happening in the backend that can get messed up if this is changed without extensive testing.
Issue # 2 - Changing the basket item name (product name) after added to the basket
Solution: Not possible. Again, Able will override basket values with the real product values if a valid ProductId is assigned to the basket item.
Workaround # 1: Don't add regular products to the basket. Instead, set the basketitem.OrderItemType as a type "CHARGE". Then you can control everything but you'll have to live with the fact the SKU is always displayed as "CHARGE". Plus the primary and mini basket pages will have to be modified to include "charge" type line items and to override the display of the basket SKU with the actual product SKU value. Not ideal.
Workaround # 2: Use the LineMessage field in the basketitem class - this value passes all the way through checkout into the orderitem. But this field is unused by Able, so nothing displays the value chosen. That means changing basket pages, order summary pages, everything that displays a line item. Not ideal.
Workaround # 3: Judy hit the nail on the head. Assign a product template with the choices you need to the product. Then add the actual choice manually via code instead of letting Able do it. This is the route I chose for a variety of reasons...
Why workaround # 3 works for me:
1. I'm not using product display pages. All products will purchased from a category display page, so there's never a worry that the product template choices are going to get rendered and interfere with my hard-coded product template choice.
2. My custom category display page will only ever get used on categories with products that have the product template assigned, so I can easily hard-code the template inputfieldId needed to manually create a product template choice selection.
Here's the whole code I used
Lots of assumptions made here, so this code won't work for every situation. But it gives you a simple example of how you can set the product template value(s) yourself and manually add an item to the basket.
Issue #1 - Changing the price of a basket item
Solution: Easy if you set the product as a variable-price product in the catalog. Not possible any other way as Able basket recalc methods will blow the custom price away on the next basket recalc. Probably going to be this way for a while - lots of things happening in the backend that can get messed up if this is changed without extensive testing.
Issue # 2 - Changing the basket item name (product name) after added to the basket
Solution: Not possible. Again, Able will override basket values with the real product values if a valid ProductId is assigned to the basket item.
Workaround # 1: Don't add regular products to the basket. Instead, set the basketitem.OrderItemType as a type "CHARGE". Then you can control everything but you'll have to live with the fact the SKU is always displayed as "CHARGE". Plus the primary and mini basket pages will have to be modified to include "charge" type line items and to override the display of the basket SKU with the actual product SKU value. Not ideal.
Workaround # 2: Use the LineMessage field in the basketitem class - this value passes all the way through checkout into the orderitem. But this field is unused by Able, so nothing displays the value chosen. That means changing basket pages, order summary pages, everything that displays a line item. Not ideal.
Workaround # 3: Judy hit the nail on the head. Assign a product template with the choices you need to the product. Then add the actual choice manually via code instead of letting Able do it. This is the route I chose for a variety of reasons...
Why workaround # 3 works for me:
1. I'm not using product display pages. All products will purchased from a category display page, so there's never a worry that the product template choices are going to get rendered and interfere with my hard-coded product template choice.
2. My custom category display page will only ever get used on categories with products that have the product template assigned, so I can easily hard-code the template inputfieldId needed to manually create a product template choice selection.
Here's the whole code I used
Code: Select all
// pull in the product that was clicked via the CatalogNodeId
Product _Product = ProductDataSource.Load(_ProductId);
_Product.Price = _BitePrice;
// make the new basket item
BasketItem _BasketItem = BasketItemDataSource.CreateForProduct(_Product.ProductId, 1);
_BasketItem.Price = _BitePrice;
// pull in the product template assigned to this product
ProductTemplate _Template = _BasketItem.Product.ProductTemplate;
// Add a product template value for the format specified
BasketItemInput _BasketInput = new BasketItemInput();
_BasketInput.InputFieldId = _Template.InputFields[0].InputFieldId;
_BasketInput.InputValue = _BiteFormat;
_BasketItem.Inputs.Add(_BasketInput);
//ADD ITEM TO BASKET
Basket basket = Token.Instance.User.Basket;
basket.Items.Add(_BasketItem);
basket.Package(true);
_BasketItem.Save();
Joe Payne
AbleCommerce Custom Programming and Modules http://www.AbleMods.com/
AbleCommerce Hosting http://www.AbleModsHosting.com/
Precise Fishing and Hunting Time Tables http://www.Solunar.com
AbleCommerce Custom Programming and Modules http://www.AbleMods.com/
AbleCommerce Hosting http://www.AbleModsHosting.com/
Precise Fishing and Hunting Time Tables http://www.Solunar.com