Adding requirement for purchasing product
Adding requirement for purchasing product
We have a few products that we would like to add a check box that a customer must check in order to acknowledge a notice in order to purchase the item. There is a store wide 'conditions' option for the checkout, but we only require this for certain products. Is there any way to do this?
Re: Adding requirement for purchasing product
Read following thread here we discussed how to associate some custom field with product
viewtopic.php?f=44&t=9088
You can do something similar to collect input from customer.
viewtopic.php?f=44&t=9088
You can do something similar to collect input from customer.
Re: Adding requirement for purchasing product
I tried putting the new Edit Product files into the Admin/Products folder, and the ShowWarning file into the ConLib folder, but the warning does not show up anywhere on a product after checking the Enable Warning box for a product.
Also, I tried putting things back to the original state (replace the Edit Product files with the originals, and remove the ShowWarning file), and kept showing an IsWarning: true below the product description, so I had to modify the ProductCustomFieldsDialog file to stop that from showing. Because the ProductCustomFieldsDialog file is not in the ConLib/Custom folder, any updates will change the file back to its standard state, and the items will show the Is Warning text again. How can I correct this?
Would there be a way to make the check box so that a customer must accept the terms in order to add the item to their cart? We want to make sure that a customer is unable to add certain products to their cart without accepting the terms.
Also, I tried putting things back to the original state (replace the Edit Product files with the originals, and remove the ShowWarning file), and kept showing an IsWarning: true below the product description, so I had to modify the ProductCustomFieldsDialog file to stop that from showing. Because the ProductCustomFieldsDialog file is not in the ConLib/Custom folder, any updates will change the file back to its standard state, and the items will show the Is Warning text again. How can I correct this?
Would there be a way to make the check box so that a customer must accept the terms in order to add the item to their cart? We want to make sure that a customer is unable to add certain products to their cart without accepting the terms.
Rick Morris
Brewhaus (America) Inc.
Hot Sauce Depot
Brewhaus (America) Inc.
Hot Sauce Depot
Re: Adding requirement for purchasing product
First product description page is showing warning information because you have added a new custom field which is stored in database in ac_ProductCutomFields table so removing website files will not remove it from database. If you want to remove it from database you need to manually delete it from database because right now AbleCommerce doesn't provide any way to add/delete product custom fields.
Secondly in order to make sure that custom can add products to cart only if he/she accepted the agreement, for this you need to make use of product templates. I think with this approach you will be in no need of ac_ProductCustomFields. All you need is to create a new product template with one customer field with type checkbox. Then enforce custom validation on this customer field so that it only consider it valid if its checked. Here is a link about how to enforce custom validation on customer side field.
viewtopic.php?f=42&t=11624
Hopefully it will workout
Secondly in order to make sure that custom can add products to cart only if he/she accepted the agreement, for this you need to make use of product templates. I think with this approach you will be in no need of ac_ProductCustomFields. All you need is to create a new product template with one customer field with type checkbox. Then enforce custom validation on this customer field so that it only consider it valid if its checked. Here is a link about how to enforce custom validation on customer side field.
viewtopic.php?f=42&t=11624
Hopefully it will workout
Re: Adding requirement for purchasing product
Thank you, Mazhar. I had tried the product template before, but was not able to find a way to force the customer to respond to it in order to add the item to the cart.
The product template that I built describes the terms, and then has a check box (which says I Accept beside it). We do not need to have any input other than forcing the check box to be checked. How can we go about this?
The product template that I built describes the terms, and then has a check box (which says I Accept beside it). We do not need to have any input other than forcing the check box to be checked. How can we go about this?
Rick Morris
Brewhaus (America) Inc.
Hot Sauce Depot
Brewhaus (America) Inc.
Hot Sauce Depot
Re: Adding requirement for purchasing product
This is an easy one. First create a new product template let's say it Agreement, then create a new customer field keep its type Checkbox list and name it Agree. In prompt let say we placed Terms and Conditions and then add a new choice. In choice text field enter Do you agree? and then for its value enter Yes and save it.
Now all we need is to make this field required. As I suggested you to look at
viewtopic.php?f=42&t=11624
simply make changes to BuildProductChoices and add method ServerValidation as told in above post. Once you are done with above changes then you need to make it work with your product template. First of all change
to
and then adjust Date validation message here... message to your desired one for example it could be something like
Please accept terms and conditions required for this purchase..
Edit Made:- An update to this code is made to fix a compilation error
Finally all you need is to update ServerValidation method to only trigger validation if checkbox is unchecked. This required a little code copy/paste from collect template value method of product helper class. Anyhow working code according to above template example is this, just make your ServerValidation method look like this
Now all we need is to make this field required. As I suggested you to look at
viewtopic.php?f=42&t=11624
simply make changes to BuildProductChoices and add method ServerValidation as told in above post. Once you are done with above changes then you need to make it work with your product template. First of all change
Code: Select all
if (input.Name == "DateField")
Code: Select all
if (input.ProductTemplate.Name.Trim() == "Agreement" && input.Name.Trim() == "Agree")
Please accept terms and conditions required for this purchase..
Edit Made:- An update to this code is made to fix a compilation error
Finally all you need is to update ServerValidation method to only trigger validation if checkbox is unchecked. This required a little code copy/paste from collect template value method of product helper class. Anyhow working code according to above template example is this, just make your ServerValidation method look like this
Code: Select all
public static void ServerValidation(object source, ServerValidateEventArgs arguments)
{
bool isValid = false;
// COLLECT ANY ADDITIONAL INPUTS
Product product = ProductDataSource.Load(PageHelper.GetProductId());
if (product != null)
{
if(product.ProductTemplate != null)
{
if (product.ProductTemplate.Name != "Agreement")
return;
ProductTemplate template = product.ProductTemplate;
if (template != null)
{
foreach (InputField input in template.InputFields)
{
//ONLY LOOK FOR CUSTOMER INPUT FIELDS
if (!input.IsMerchantField && input.Name == "Agree")
{
//SEE IF WE CAN LOCATE THE CONTROL
WebControl inputControl = (WebControl)PageHelper.RecursiveFindControl((source as CustomValidator).Page, input.UniqueId);
if (inputControl != null)
{
string value = input.GetControlValue(inputControl);
isValid = (value.Trim() == "Yes");
}
}
}
}
}
}
arguments.IsValid = isValid;
}
Re: Adding requirement for purchasing product
I tried making the changes that you suggested, but obviously did something wrong. As I understood the changes, the ProductHelper.cs file comes out like this:
But when I use this file I get a runtime error on the website.
Code: Select all
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using CommerceBuilder.Common;
using CommerceBuilder.DigitalDelivery;
using CommerceBuilder.Products;
using CommerceBuilder.Orders;
using CommerceBuilder.Stores;
using CommerceBuilder.Utility;
using CommerceBuilder.Web.UI.WebControls;
public class ProductHelper
{
/// <summary>
/// Generates and registers a javascript function that can cause a
/// postback when all options are selected
/// </summary>
/// <param name="page">The page to generate the script for</param>
private static void GenerateOptionPostBackScript(Page page)
{
StringBuilder js = new StringBuilder();
js.Append("function CheckOptionSelections(ddl, count) {\r\n");
js.Append(" var baseName = ddl.name.substring(0, ddl.name.lastIndexOf(\"$\"));\r\n");
js.Append(" baseName = baseName.replace(/\\$/g, \"_\");\r\n");
js.Append(" for(i = 0; i < count; i++) {\r\n");
js.Append(" var picker = document.getElementById(baseName + \"_option\" + i);\r\n");
js.Append(" if ((picker == null) || (picker.selectedIndex < 1)) { return; }\r\n");
js.Append(" }\r\n");
js.Append(" __doPostBack(ddl.name, '');\r\n");
js.Append("}");
ScriptManager.RegisterClientScriptBlock(page, typeof(Page), "CheckOptionSelections", js.ToString(), true);
}
public static void ServerValidation(object source, ServerValidateEventArgs arguments)
{
bool isValid = false;
// COLLECT ANY ADDITIONAL INPUTS
Product product = ProductDataSource.Load(PageHelper.GetProductId());
if (product != null)
{
foreach (ProductProductTemplate ppt in product.ProductProductTemplates)
{
if (ppt.ProductTemplate.Name != "Agreement")
continue;
ProductTemplate template = ppt.ProductTemplate;
if (template != null)
{
foreach (InputField input in template.InputFields)
{
//ONLY LOOK FOR CUSTOMER INPUT FIELDS
if (!input.IsMerchantField && input.Name == "Agree")
{
//SEE IF WE CAN LOCATE THE CONTROL
WebControl inputControl = (WebControl)PageHelper.RecursiveFindControl((source as CustomValidator).Page, input.UniqueId);
if (inputControl != null)
{
string value = input.GetControlValue(inputControl);
isValid = (value.Trim() == "Yes");
}
}
}
}
}
}
arguments.IsValid = isValid;
}
/// <summary>
/// Determines if auto post back should be used for option picker
/// </summary>
/// <param name="product">The product to check for auto post back requirement</param>
/// <returns>True if auto post back should be used for option picker for the given product</returns>
private static bool UseAutoPostBackForOptions(Product product)
{
//IF WE ARE USING OPTION INVENTORY, AUTO POSTBACK IS REQUIRED
if ((product.InventoryMode == InventoryMode.Variant) && (Token.Instance.Store.EnableInventory)) return true;
//IF THE PRODUCT CONTAINS ANY OPTIONS THAT USE SWATCHES, AUTO POSTBACK IS REQUIRED
ProductOptionCollection productOptions = product.ProductOptions;
for (int i = 0; (i < productOptions.Count); i++)
{
if (productOptions[i].Option.ShowThumbnails) return true;
}
//THIS PRODUCT DOES NOT NEED AUTO POSTBACK FOR OPTION PICKER
return false;
}
public static Dictionary<int, int> BuildProductOptions(Product product, PlaceHolder phOptions)
{
Dictionary<int, int> selectedChoices = new Dictionary<int, int>();
if ((product.ProductOptions.Count > 0))
{
Page page = phOptions.Page;
HttpRequest request = HttpContext.Current.Request;
//DETERMINE IF AUTO POSTBACK WILL BE USED FOR THIS PICKER
bool autoPostBack = UseAutoPostBackForOptions(product);
//IF WE AREN'T USING AUTO POSTBACK, WE NEED TO POSTBACK WHEN ALL OPTIONS SELECTED
if (!autoPostBack) GenerateOptionPostBackScript(page);
ProductOptionCollection productOptions = product.ProductOptions;
int optionCount = productOptions.Count;
for (int i = 0; i < optionCount; i++)
{
Option option = productOptions[i].Option;
// CREATE A LABEL FOR THE ATTRIBUTE
phOptions.Controls.Add(new LiteralControl("<tr><th class=\"rowHeader\"" + (option.ShowThumbnails ? " valign=\"top\"" : string.Empty) + ">" + option.Name + ":</th>"));
phOptions.Controls.Add(new LiteralControl("<td align=\"left\">"));
if (option.ShowThumbnails)
{
// CREATE THE OPTION PICKER CONTROL TO THE PLACEHOLDER
OptionPicker picker = new OptionPicker();
picker.ID = "option" + i;
picker.CssClass = "optionPicker";
// WE ALWAYS HAVE TO POSTBACK FOR THUMBNAIL PICKER
picker.AutoPostBack = true;
picker.OptionId = option.OptionId;
picker.SelectedChoices = new Dictionary<int, int>(selectedChoices);
// ADD THE CONTROL TO THE PLACEHOLDER
phOptions.Controls.Add(picker);
//CHECK WHETHER AN OPTION IS SELECTED
string selectedValue = request.Form[picker.UniqueID];
if (!string.IsNullOrEmpty(selectedValue))
{
picker.SelectedChoiceId = AlwaysConvert.ToInt(selectedValue);
if (picker.SelectedChoiceId != 0) selectedChoices.Add(option.OptionId, picker.SelectedChoiceId);
}
}
else
{
// CREATE A DROPDOWN FOR THE OPTIONS
DropDownList aspOptions = new DropDownList();
RequiredFieldValidator aspOptionsValidator = new RequiredFieldValidator();
aspOptions.ID = "option" + i;
if (autoPostBack) aspOptions.AutoPostBack = true;
else
{
//NEED TO POSTBACK WHEN ALL OPTIONS SELECTED
aspOptions.Attributes.Add("onchange", "CheckOptionSelections(this, " + optionCount + ")");
}
aspOptionsValidator.ID = "optionValidator" + i;
aspOptionsValidator.ControlToValidate = aspOptions.ID;
aspOptionsValidator.ValidationGroup = "AddToBasket";
aspOptionsValidator.Text = "*";
aspOptionsValidator.ErrorMessage = string.Format("Please make your selection for {0}.", option.Name);
aspOptions.Items.Add(String.Empty);
// GET THE COLLECTION OF OPTIONS THAT ARE AVAILABLE FOR THE CURRENT SELECTIONS
OptionChoiceCollection availableOptions = OptionChoiceDataSource.GetAvailableChoices(product.ProductId, option.OptionId, selectedChoices);
foreach (OptionChoice optionOption in availableOptions)
{
aspOptions.Items.Add(new ListItem(optionOption.Name, optionOption.OptionChoiceId.ToString()));
}
// ADD THE CONTROL TO THE PLACEHOLDER
phOptions.Controls.Add(aspOptions);
phOptions.Controls.Add(new LiteralControl(" "));
phOptions.Controls.Add(aspOptionsValidator);
// SEE WHETHER A VALID VALUE FOR THIS FIELD IS PRESENT IN FORM POST
string selectedValue = request.Form[aspOptions.UniqueID];
if (!string.IsNullOrEmpty(selectedValue))
{
ListItem selectedItem = aspOptions.Items.FindByValue(selectedValue);
if (selectedItem != null)
{
int val = AlwaysConvert.ToInt(selectedValue);
if (val != 0)
{
selectedChoices.Add(option.OptionId, val);
selectedItem.Selected = true;
}
}
}
}
phOptions.Controls.Add(new LiteralControl("</td></tr>"));
// KEEP LOOPING UNTIL WE REACH THE END OR WE COME TO AN OPTION THAT IS NOT SELECTED
}
}
//RETURN SELECTED OPTIONS
return selectedChoices;
}
public static Dictionary<int, int> BuildProductOptions(KitProduct kitProduct, PlaceHolder phOptions)
{
if (kitProduct == null) return null;
Product product = kitProduct.Product;
Dictionary<int, int> selectedChoices = new Dictionary<int, int>();
if ((product.ProductOptions.Count > 0))
{
Page page = phOptions.Page;
HttpRequest request = HttpContext.Current.Request;
for (int i = 0; i < product.ProductOptions.Count; i++)
{
Option option = product.ProductOptions[i].Option;
// CREATE A LABEL FOR THE ATTRIBUTE
phOptions.Controls.Add(new LiteralControl("<tr><th class=\"rowHeader\"" + (option.ShowThumbnails ? " valign=\"top\"" : string.Empty) + ">" + option.Name + ":</th>"));
phOptions.Controls.Add(new LiteralControl("<td align=\"left\">"));
// CREATE A DROPDOWN FOR THE OPTIONS
DropDownList aspOptions = new DropDownList();
RequiredFieldValidator aspOptionsValidator = new RequiredFieldValidator();
aspOptions.ID = "option" + i;
aspOptionsValidator.ID = "optionValidator" + i;
aspOptionsValidator.ControlToValidate = aspOptions.ID;
aspOptionsValidator.ValidationGroup = "AddToBasket";
aspOptionsValidator.Text = string.Empty;
aspOptionsValidator.ErrorMessage = string.Empty;
aspOptions.Items.Add(String.Empty);
// GET THE COLLECTION OF OPTIONS THAT ARE AVAILABLE FOR THE CURRENT SELECTIONS
OptionChoiceCollection availableOptions = OptionChoiceDataSource.GetAvailableChoices(product.ProductId, option.OptionId, selectedChoices);
foreach (OptionChoice optionOption in availableOptions)
{
aspOptions.Items.Add(new ListItem(optionOption.Name, optionOption.OptionChoiceId.ToString()));
}
// ADD THE CONTROL TO THE PLACEHOLDER
phOptions.Controls.Add(aspOptions);
phOptions.Controls.Add(aspOptionsValidator);
string selectedValue = request.Form[aspOptions.UniqueID];
if (!string.IsNullOrEmpty(selectedValue))
{
ListItem selectedItem = aspOptions.Items.FindByValue(selectedValue);
if (selectedItem != null)
{
int val = AlwaysConvert.ToInt(selectedValue);
if (val != 0)
{
selectedChoices.Add(option.OptionId, val);
selectedItem.Selected = true;
}
}
}
else
{
ProductVariant productVariant = kitProduct.ProductVariant;
int optionChoiceId = 0;
switch (i)
{
case 0:
optionChoiceId = (productVariant.Option1 > 0) ? productVariant.Option1 : 0;
break;
case 1:
optionChoiceId = (productVariant.Option2 > 0) ? productVariant.Option2 : 0;
break;
case 2:
optionChoiceId = (productVariant.Option3 > 0) ? productVariant.Option3 : 0;
break;
case 3:
optionChoiceId = (productVariant.Option4 > 0) ? productVariant.Option4 : 0;
break;
case 4:
optionChoiceId = (productVariant.Option5 > 0) ? productVariant.Option5 : 0;
break;
case 5:
optionChoiceId = (productVariant.Option6 > 0) ? productVariant.Option6 : 0;
break;
case 6:
optionChoiceId = (productVariant.Option7 > 0) ? productVariant.Option7 : 0;
break;
case 7:
optionChoiceId = (productVariant.Option7 > 0) ? productVariant.Option7 : 0;
break;
case 8:
optionChoiceId = (productVariant.Option8 > 0) ? productVariant.Option8 : 0;
break;
}
if (optionChoiceId > 0)
{
ListItem listItem = aspOptions.Items.FindByValue(optionChoiceId.ToString());
if (listItem != null)
listItem.Selected = true;
}
}
phOptions.Controls.Add(new LiteralControl("</td></tr>"));
// KEEP LOOPING UNTIL WE REACH THE END OR WE COME TO AN OPTION THAT IS NOT SELECTED
}
}
return selectedChoices;
}
public static void BuildProductChoices(Product product, PlaceHolder phChoices)
{
// ADD IN THE PRODUCT TEMPLATE CHOICES
ProductTemplate template = product.ProductTemplate;
if (template != null)
{
foreach (InputField input in template.InputFields)
{
if (!input.IsMerchantField)
{
// ADD THE CONTROL TO THE PLACEHOLDER
phChoices.Controls.Add(new LiteralControl("<tr><td colspan=\"2\">"));
phChoices.Controls.Add(new LiteralControl((input.UserPrompt + "<br />")));
WebControl o = input.GetControl();
if (o != null)
{
phChoices.Controls.Add(o);
if (input.ProductTemplate.Name.Trim() == "Agreement" && input.Name.Trim() == "Agree")
{
CustomValidator customValidator = new CustomValidator();
customValidator.ID = "mycustomevalidator";
customValidator.ControlToValidate = string.Empty;
customValidator.ValidationGroup = "AddToBasket";
customValidator.ErrorMessage = "Date validation message here...";
customValidator.Text = "*";
customValidator.ServerValidate += new ServerValidateEventHandler(ServerValidation);
phChoices.Controls.Add(customValidator);
}
}
phChoices.Controls.Add(new LiteralControl("</td></tr>"));
}
}
}
}
public static List<int> BuildKitOptions(Product product, PlaceHolder phOptions)
{
List<int> selectedChoices = new List<int>();
foreach (ProductKitComponent pkc in product.ProductKitComponents)
{
KitComponent component = pkc.KitComponent;
if (component.InputType != KitInputType.IncludedHidden && component.KitProducts.Count > 0)
{
// CREATE A LABEL FOR THE ATTRIBUTE
phOptions.Controls.Add(new LiteralControl("<tr><th class=\"rowHeader\">" + component.Name + ":</th>"));
// ADD THE CONTROL TO THE PLACEHOLDER
phOptions.Controls.Add(new LiteralControl("<td align=\"left\">"));
WebControl o = component.GetControl();
if (o != null)
{
Type oType = o.GetType();
if (oType.Equals(typeof(RadioButtonList)))
{
((RadioButtonList)o).AutoPostBack = true;
}
else if (oType.Equals(typeof(DropDownList)))
{
((DropDownList)o).AutoPostBack = true;
}
else if (oType.Equals(typeof(CheckBoxList)))
{
((CheckBoxList)o).AutoPostBack = true;
}
phOptions.Controls.Add(o);
// SEE WHETHER A VALID VALUE FOR THIS FIELD IS PRESENT IN FORM POST
List<int> theseOptions = component.GetControlValue(o);
selectedChoices.AddRange(theseOptions);
}
phOptions.Controls.Add(new LiteralControl("</td></tr>"));
}
}
return selectedChoices;
}
public static string GetSKU(object dataItem)
{
if (dataItem is BasketItem) return GetSKU((BasketItem)dataItem);
if (dataItem is OrderItem) return GetSKU((OrderItem)dataItem);
throw new ArgumentException("Input must be BasketItem or OrderItem. You passed: " + dataItem.GetType().ToString(), "dataItem");
}
public static string GetSKU(BasketItem item)
{
switch (item.OrderItemType)
{
case OrderItemType.Product:
return item.Sku;
case OrderItemType.GiftWrap:
return "GIFT WRAP";
case OrderItemType.Coupon:
return "COUPON";
case OrderItemType.Discount:
return "DISCOUNT";
case OrderItemType.Shipping:
return "SHIPPING";
case OrderItemType.Handling:
return "HANDLING";
case OrderItemType.Tax:
return "TAX";
case OrderItemType.GiftCertificatePayment:
return "GIFTCERT PAYMENT";
case OrderItemType.Charge:
return "CHARGE";
case OrderItemType.Credit:
return "CREDIT";
case OrderItemType.GiftCertificate:
return "GIFTCERT";
default:
return string.Empty;
}
}
public static string GetSKU(OrderItem item)
{
switch (item.OrderItemType)
{
case OrderItemType.Product:
return item.Sku;
case OrderItemType.GiftWrap:
return "GIFT WRAP";
case OrderItemType.Coupon:
return "COUPON";
case OrderItemType.Discount:
return "DISCOUNT";
case OrderItemType.Shipping:
return "SHIPPING";
case OrderItemType.Handling:
return "HANDLING";
case OrderItemType.Tax:
return "TAX";
case OrderItemType.GiftCertificatePayment:
return "GIFTCERT PAYMENT";
case OrderItemType.Charge:
return "CHARGE";
case OrderItemType.Credit:
return "CREDIT";
case OrderItemType.GiftCertificate:
return "GIFTCERT";
default:
return string.Empty;
}
}
public static bool RequiredKitOptionsSelected(Product product, List<int> selectedKitProductIds)
{
if (product.KitStatus != KitStatus.Master) return true;
Dictionary<int, List<int>> requiredIdsTable = new Dictionary<int, List<int>>();
foreach (ProductKitComponent pkc in product.ProductKitComponents)
{
KitComponent component = pkc.KitComponent;
if (string.IsNullOrEmpty(component.HeaderOption) && (component.InputType == KitInputType.DropDown || component.InputType == KitInputType.RadioButton))
{
requiredIdsTable.Add(component.KitComponentId, GetKitProductIds(component));
}
}
bool optionsSelected = true;
foreach (int compId in requiredIdsTable.Keys)
//for (int i = 0; i < requiredIdsTable.Count; i++)
{
List<int> optionIds = requiredIdsTable[compId];
//selected kipt option ids must have one of the option ids
bool found = false;
foreach (int optionId in optionIds)
{
if (selectedKitProductIds.Exists(delegate(int val) { return val == optionId; }))
{
found = true;
break;
}
}
if (!found)
{
optionsSelected = false;
break;
}
}
return optionsSelected;
}
private static List<int> GetKitProductIds(KitComponent comp)
{
List<int> optionIds = new List<int>();
foreach (KitProduct choice in comp.KitProducts)
{
optionIds.Add(choice.KitProductId);
}
return optionIds;
}
public static bool HasAssets(Product product)
{
foreach (ProductDigitalGood pdg in product.DigitalGoods)
{
DigitalGood dg = pdg.DigitalGood;
if (dg.LicenseAgreement != null) return true;
if (dg.Readme != null) return true;
}
return false;
}
/// <summary>
/// Gets all assets for a product regardless of variant.
/// </summary>
/// <param name="page">Page context</param>
/// <param name="product">Product to get assets for</param>
/// <param name="returnUrl">URL to use for the return location when pages visited.</param>
/// <returns></returns>
public static List<ProductAssetWrapper> GetAssets(Page page, Product product, string returnUrl)
{
// BUILD LIST OF ASSETS
List<string> assetTracker = new List<string>();
string encodedReturnUrl;
if (!string.IsNullOrEmpty(returnUrl)) encodedReturnUrl = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(returnUrl));
else encodedReturnUrl = string.Empty;
List<ProductAssetWrapper> assetList = new List<ProductAssetWrapper>();
string agreeUrl = page.ResolveClientUrl("~/ViewLicenseAgreement.aspx") + "?id={0}&ReturnUrl=" + encodedReturnUrl;
string agreePopup = agreeUrl + "\" onclick=\"" + PageHelper.GetPopUpScript(agreeUrl, "license", 640, 480, "resizable=1,scrollbars=yes,toolbar=no,menubar=no,location=no,directories=no") + ";return false";
string readmeUrl = page.ResolveClientUrl("~/ViewReadme.aspx") + "?ReadmeId={0}&ReturnUrl=" + encodedReturnUrl;
string readmePopup = readmeUrl + "\" onclick=\"" + PageHelper.GetPopUpScript(readmeUrl, "readme", 640, 480, "resizable=1,scrollbars=yes,toolbar=no,menubar=no,location=no,directories=no") + ";return false";
foreach (ProductDigitalGood pdg in product.DigitalGoods)
{
DigitalGood digitalGood = pdg.DigitalGood;
Readme readme = digitalGood.Readme;
if ((readme != null) && (assetTracker.IndexOf("R" + readme.ReadmeId.ToString()) < 0))
{
assetList.Add(new ProductAssetWrapper(string.Format(readmePopup, readme.ReadmeId), readme.DisplayName));
assetTracker.Add("R" + readme.ReadmeId.ToString());
}
LicenseAgreement agreement = digitalGood.LicenseAgreement;
if ((agreement != null) && (assetTracker.IndexOf("L" + agreement.LicenseAgreementId.ToString()) < 0))
{
assetList.Add(new ProductAssetWrapper(string.Format(agreePopup, agreement.LicenseAgreementId), agreement.DisplayName));
assetTracker.Add("L" + agreement.LicenseAgreementId.ToString());
}
}
return assetList;
}
public static List<ProductAssetWrapper> GetAssets(Page page, Product product, string optionList, string returnUrl)
{
// BUILD LIST OF ASSETS
string encodedReturnUrl;
if (!string.IsNullOrEmpty(returnUrl)) encodedReturnUrl = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(returnUrl));
else encodedReturnUrl = string.Empty;
List<ProductAssetWrapper> assetList = new List<ProductAssetWrapper>();
string agreeUrl = page.ResolveClientUrl("~/ViewLicenseAgreement.aspx") + "?id={0}&ReturnUrl=" + encodedReturnUrl;
string agreePopup = agreeUrl + "\" onclick=\"" + PageHelper.GetPopUpScript(agreeUrl, "license", 640, 480, "resizable=1,scrollbars=yes,toolbar=no,menubar=no,location=no,directories=no") + ";return false";
string readmeUrl = page.ResolveClientUrl("~/ViewReadme.aspx") + "?ReadmeId={0}&ReturnUrl=" + encodedReturnUrl;
string readmePopup = readmeUrl + "\" onclick=\"" + PageHelper.GetPopUpScript(readmeUrl, "readme", 640, 480, "resizable=1,scrollbars=yes,toolbar=no,menubar=no,location=no,directories=no") + ";return false";
foreach (ProductDigitalGood pdg in product.DigitalGoods)
{
if ((string.IsNullOrEmpty(pdg.OptionList)) || (optionList == pdg.OptionList))
{
DigitalGood digitalGood = pdg.DigitalGood;
Readme readme = digitalGood.Readme;
if (readme != null)
assetList.Add(new ProductAssetWrapper(string.Format(readmePopup, readme.ReadmeId), readme.DisplayName));
LicenseAgreement agreement = digitalGood.LicenseAgreement;
if (agreement != null)
{
assetList.Add(new ProductAssetWrapper(string.Format(agreePopup, agreement.LicenseAgreementId), agreement.DisplayName));
}
}
}
return assetList;
}
public static void CollectProductTemplateInput(BasketItem item, Control container)
{
// COLLECT ANY ADDITIONAL INPUTS
Product product = item.Product;
if (product != null)
{
ProductTemplate template = item.Product.ProductTemplate;
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(container, input.UniqueId);
if (inputControl != null)
{
BasketItemInput itemInput = new BasketItemInput();
itemInput.InputFieldId = input.InputFieldId;
itemInput.InputValue = input.GetControlValue(inputControl);
item.Inputs.Add(itemInput);
}
}
}
}
}
}
public static void CollectProductTemplateInput(OrderItem item, Control container)
{
// COLLECT ANY ADDITIONAL INPUTS
Product product = item.Product;
if (product != null)
{
ProductTemplate template = item.Product.ProductTemplate;
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(container, input.UniqueId);
if (inputControl != null)
{
OrderItemInput itemInput = new OrderItemInput();
itemInput.Name = input.Name;
itemInput.InputValue = input.GetControlValue(inputControl);
item.Inputs.Add(itemInput);
}
}
}
}
}
}
public static void CollectProductTemplateInput(Product product, Control container)
{
ProductTemplate template = product.ProductTemplate;
// COLLECT ANY ADDITIONAL INPUTS
if (template != null)
{
foreach (InputField input in template.InputFields)
{
//LOOK FOR MERCHANT INPUT FIELDS
if (input.IsMerchantField)
{
//SEE IF WE CAN LOCATE THE CONTROL
WebControl inputControl = (WebControl)PageHelper.RecursiveFindControl(container, input.UniqueId);
if (inputControl != null)
{
ProductTemplateField itemInput = new ProductTemplateField();
itemInput.InputFieldId = input.InputFieldId;
itemInput.InputValue = input.GetControlValue(inputControl);
product.TemplateFields.Add(itemInput);
}
}
}
}
}
}
Rick Morris
Brewhaus (America) Inc.
Hot Sauce Depot
Brewhaus (America) Inc.
Hot Sauce Depot
Re: Adding requirement for purchasing product
Sorry there was a small problem causing compilation problem in ServerValidation method. I just updated my post with ServerValidatoin method code to fix this problem. You can update your ServerValidation method with adjusted code.
Re: Adding requirement for purchasing product
That seemed to work. Does it matter where the public static void ServerValidation(object source, ServerValidateEventArgs arguments) statement is placed in the file? As you can see I have it near the beginning. I assume that it makes no difference.
Also, I assume that I can follow the same steps to add another 'agreement' for different purposes just by changing the name of the agreement and the associated calls in the file?
Also, I assume that I can follow the same steps to add another 'agreement' for different purposes just by changing the name of the agreement and the associated calls in the file?
Rick Morris
Brewhaus (America) Inc.
Hot Sauce Depot
Brewhaus (America) Inc.
Hot Sauce Depot
Re: Adding requirement for purchasing product
Regarding method defention you can add it any where in ProductHelper class just make sure that don't mix up its code with other functions. For example you can define it just above the last curly brace. Secondly yes you can change field name entry in script to make same script work for field with some other name.
-
- Ensign (ENS)
- Posts: 6
- Joined: Fri Dec 04, 2009 2:12 am
Re: Adding requirement for purchasing product
Hi,
I have a similar problem.
For some product, I need the customer inserts some data in checkout fase.
Can I do something similar in the checkout pages?
I have a similar problem.
For some product, I need the customer inserts some data in checkout fase.
Can I do something similar in the checkout pages?
Re: Adding requirement for purchasing product
Yes possible out of the box. Simply create a product template with a customer field for example customer field of type textbox. Then apply this product template to desired product. This will make that input field available on product details page.
-
- Ensign (ENS)
- Posts: 6
- Joined: Fri Dec 04, 2009 2:12 am
Re: Adding requirement for purchasing product
What I need isn't a field in the details page but in the checkout form.
We sell services and we need custom data fields different for different type of products
We sell services and we need custom data fields different for different type of products
Re: Adding requirement for purchasing product
On checkout page you need to process basket items not products. Every basket item do have custom field collection like basketItems.CustomFields. You can make use of this feature, these custom fields are then copied over to orderITem.CustomFields on order completion. So after order placement you can process information via placed order.
-
- Ensign (ENS)
- Posts: 6
- Joined: Fri Dec 04, 2009 2:12 am
Re: Adding requirement for purchasing product
An other question.
Can I divide the checkout procedure in more than a page to collect data from customer like a wizard?
Can I divide the checkout procedure in more than a page to collect data from customer like a wizard?
Re: Adding requirement for purchasing product
OnePageCheckout makes use of different panels show/hide to get desired information. You can try to modify it to incorporate your custom information by modifying it. If you essentially want to have more then one pages then you will need to write some alternative checkout pages or have a look at Checkout Page with login. Just change your checkout page content template from OnePageCheckout to Checkout Page with login.
Re: Adding requirement for purchasing product
I recently noticed that, after our last upgrade, AC was not longer forcing the checkbox to be checked in order to add the item to the shopping cart. And, now that we are on 7.0.7 the method above does not seem to work. Could we get an update on the code necessary to force checking on the box in order to add the item to the shopping cart? 

Rick Morris
Brewhaus (America) Inc.
Hot Sauce Depot
Brewhaus (America) Inc.
Hot Sauce Depot
Re: Adding requirement for purchasing product
Mazhar- are you able to help with this? I assume that we just need a modified version of the code above to work with the new version of AC, but I cannot figure out how to do it (and I have tried). 

Rick Morris
Brewhaus (America) Inc.
Hot Sauce Depot
Brewhaus (America) Inc.
Hot Sauce Depot
-
- Ensign (ENS)
- Posts: 15
- Joined: Mon Oct 22, 2012 4:25 pm
Re: Adding requirement for purchasing product
which AC version you were using before upgrading?
Re: Adding requirement for purchasing product
If I recall it was 7.0.2.
Rick Morris
Brewhaus (America) Inc.
Hot Sauce Depot
Brewhaus (America) Inc.
Hot Sauce Depot
-
- Ensign (ENS)
- Posts: 15
- Joined: Mon Oct 22, 2012 4:25 pm
Re: Adding requirement for purchasing product
I suspect after ac 7.0.4 version, database schema is changed for the Product template Fields.
Re: Adding requirement for purchasing product
That is quite possible. The problem is that I cannot figure out how to resolve the issue / update the code to work with V 7.0.7. Any thoughts?
Rick Morris
Brewhaus (America) Inc.
Hot Sauce Depot
Brewhaus (America) Inc.
Hot Sauce Depot
-
- Ensign (ENS)
- Posts: 15
- Joined: Mon Oct 22, 2012 4:25 pm
Re: Adding requirement for purchasing product
Well, I have updated the code.All you just need to replace this code in App_Code/ProductHelper.cs
Code: Select all
public static void BuildProductChoices(Product product, PlaceHolder phChoices)
{
// ADD IN THE PRODUCT TEMPLATE CHOICES
foreach (ProductProductTemplate ppt in product.ProductProductTemplates)
{
ProductTemplate template = ppt.ProductTemplate;
if (template != null && ppt.ProductTemplate.Name == "Agreement")
{
foreach (InputField input in template.InputFields)
{
if (!input.IsMerchantField)
{
// ADD THE CONTROL TO THE PLACEHOLDER
phChoices.Controls.Add(new LiteralControl("<tr><td colspan=\"2\">"));
phChoices.Controls.Add(new LiteralControl((input.UserPrompt + "<br />")));
WebControl o = input.GetControl();
if (o != null)
{
phChoices.Controls.Add(o);
if (input.ProductTemplate.Name.Trim() == "Agreement" && input.Name.Trim() == "Agree")
{
CustomValidator customValidator = new CustomValidator();
customValidator.ID = "mycustomevalidator";
customValidator.ControlToValidate = string.Empty;
customValidator.ValidationGroup = "AddToBasket";
customValidator.ErrorMessage = "You need to agree to proceed further";
customValidator.Text = "*";
customValidator.ServerValidate += new ServerValidateEventHandler(ServerValidation);
phChoices.Controls.Add(customValidator);
}
}
phChoices.Controls.Add(new LiteralControl("</td></tr>"));
}
}
}
}
}
public static void ServerValidation(object source, ServerValidateEventArgs arguments)
{
bool isValid = false;
// COLLECT ANY ADDITIONAL INPUTS
Product product = ProductDataSource.Load(PageHelper.GetProductId());
if (product != null)
{
foreach (ProductProductTemplate ppt in product.ProductProductTemplates)
{
if (ppt.ProductTemplate != null && ppt.ProductTemplate.Name == "Agreement")
{
ProductTemplate template = ppt.ProductTemplate;
if (template != null)
{
foreach (InputField input in template.InputFields)
{
//ONLY LOOK FOR CUSTOMER INPUT FIELDS
if (!input.IsMerchantField && input.Name == "Agree")
{
//SEE IF WE CAN LOCATE THE CONTROL
WebControl inputControl = (WebControl)PageHelper.RecursiveFindControl((source as CustomValidator).Page, input.UniqueId);
if (inputControl != null)
{
string value = input.GetControlValue(inputControl);
isValid = (value.Trim() == "Yes");
}
}
}
}
}
}
}
arguments.IsValid = isValid;
}
Re: Adding requirement for purchasing product
I just tried this and the template (checkbox and text) disappeared.
Rick Morris
Brewhaus (America) Inc.
Hot Sauce Depot
Brewhaus (America) Inc.
Hot Sauce Depot
-
- Ensign (ENS)
- Posts: 15
- Joined: Mon Oct 22, 2012 4:25 pm
Re: Adding requirement for purchasing product
Did you created your template with the name 'Agreement'?