• Decrease Text SizeIncrease Text Size

How to override Ecommerce Cart Class For Custom Implementation

Posted Date: 5/9/2023
    Printer Friendly Version   Email A Friend   Add This   Increase Text Size   Decrease Text Size
When you need to override the default functionality of the Ecommerce Cart Class For Custom Implementation.
You need to copy the code and create CustomEcommerceCart.cs file in /Root/App_Code/Custom directory.
Then navigate to Console > Ecommerce > Cart > Module Properties > Custom Provider
(The complete Type of a class that inherits Centralpoint.WebSite.E-commerce.Cart. Changing this value requires that the application and session state are restarted.)

Example: Centralpoint.WebSite.Custom.my_EcommerceCart

This custom code allows the module to set different prices based on the quantity purchased



using Centralpoint.Web;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using static Centralpoint.WebSite.Ecommerce;

namespace Centralpoint.WebSite.Custom
{
    public class my_EcommerceCart : Centralpoint.WebSite.Ecommerce.Cart
    {
        private string SystemName { get; set; }
        private Cart _cart = null;

        public my_EcommerceCart(string systemName, Order order) : base(order)
        {
            SystemName = systemName;
        }

        public my_EcommerceCart (string systemName, Guid userId, bool isAnonymous) : base(systemName, userId, isAnonymous)
        {
            SystemName = systemName;
        }

        public Cart Cart
        {
            get
            {
                if (_cart == null)
                {
                    _cart = Ecommerce.Cart.Load(SystemName);
                }
                return _cart;
            }
        }

        public void SetItemPricing(SqlConnection connection)
        {
			// Called prior to CpScript's ItemTable call.  Need to update item prices for UI to render proper values that come from the DataTable
            for (int i = 0; i < Cart.Items.Count; i++)
            {
                var item = Cart.Items[i];
                item.CurrentPrice = GetCurrentPrice(item, out var discountAmount);
                //item.DiscountAmount = discountAmount;
            }
            Cart.Recalculate(connection);
        }

        public override bool UpdateItems(SqlConnection connection)
        {
            HttpContext.Current.Trace.Warn("my_EcommerceCart.UpdateItems Override", "BEGIN");
            bool reset = false;
            for (int i = 0; i < Cart.Items.Count; i++)
            {
                var item = Cart.Items[i];

                // remove integrated items when the cart is initialized because their values cannot be verified
                if (item.DataId.Equals(Guid.Empty) || item.Quantity.Equals(0))
                {
                    reset = true; // This statement was added after an order was recorded with more item quantity than what was recorded in the order items table.  The summary view of the cart only calls recalculate when this returns true.
                    this.DeleteItem(item);
                    HttpContext.Current.Trace.Warn("my_EcommerceCart.UpdateItems", String.Format("Item ({0}) was removed from the cart because it was integrated or its quantity was zero.", item.OrderItemId));
                    continue;
                }

                DataInfo di = new DataInfo(item.DataId);
                int newQty = this.VerifyItemQuantity(di, item.Quantity, true);
                if (newQty <= 0)
                {
                    reset = true;   // This statement was added after an order was recorded with more item quantity than what was recorded in the order items table.  The summary view of the cart only calls recalculate when this returns true.
                    this.DeleteItem(item, false);
                    HttpContext.Current.Trace.Warn("my_EcommerceCart.UpdateItems", String.Format("Item ({0}) was removed from the cart because the quantity could not be verified.", item.OrderItemId));
                    continue;
                }
                else if (newQty != item.Quantity)
                {
                    reset = true;
                    item.Quantity = newQty;
                }
                
                item.Attributes = di.Attributes.Serialize();
                item.CurrentPrice = GetCurrentPrice(item, out var discountAmount);
                //item.DiscountAmount = discountAmount;
                item.OriginalPrice = Convert.ToDecimal(di.Attributes.Get(this.OriginalPriceAttribute));
                item.DimWeight = Convert.ToInt32(di.Attributes.Get("cpsys_EcommerceDimWeight"));
                item.IsTaxable = !di.Attributes.Get("cpsys_EcommerceIsTaxable").Equals("0");
                item.Type = (OrderItemType)Convert.ToByte(di.Attributes.Get("cpsys_EcommerceType"));
                item.Upsert(connection);
            }
            Cart.Recalculate(connection);
            HttpContext.Current.Trace.Warn("my_EcommerceCart Override", "END");
            return reset;
        }

        private decimal GetCurrentPrice(Order.Item item, out decimal discountAmount)
        {
            // I was originally setting the DiscountAmount property in items.  This was populating the DiscountAmount column in cpsys_EcommerceOrderItems
            // However, I found that the recalculate method reduces the price further by the DiscountAmount, which I already have done by reducing the CurrentPrice property.  Also I think that setting this property will cause issues if the system's real discounts are also used.
            // I am confident that adjusting only the CurrentPrice is the correct choice at this time and will wait to alter approach unless issues are reported.
            var zeroPrice = decimal.Round(0, 2);
            discountAmount = zeroPrice;
            var attributes = new CpCollection();
            attributes.Load(item.Attributes);
            var quantity = GetItemQuantity(item);
            var originalCurrentPrice = Convert.ToDecimal(attributes.Get(this.CurrentPriceAttribute));
            if (quantity == 1) return originalCurrentPrice;
            var quantityPricing = new Dictionary<int, decimal>();
            for (var i = 1; i <= 3; i++)
            {
                var qty = Int32.TryParse(attributes.Get($"QTY_{i}").Trim(), out var iq) ? iq : 0;
                if (qty <= 1 || quantityPricing.ContainsKey(qty)) continue; // prevent users from using attribute for 1 item.  should be default cart CurrentPriceAttribute
                var price = decimal.TryParse(attributes.Get($"QTY_{i}_Price").Trim(), out var ip) ? decimal.Round(ip, 2) : zeroPrice;
                if (price < zeroPrice || price > originalCurrentPrice) continue; // can't be negative price and can't be more than original price
                quantityPricing.Add(qty, price);
            }
            if (quantityPricing.Count == 0) return originalCurrentPrice;
            foreach (var qp in quantityPricing.OrderByDescending(x => x.Key))
            {
                //HttpContext.Current.Trace.Warn("Quantity", qp.Key.ToString());
                //HttpContext.Current.Trace.Warn("Price", qp.Value.ToString());
                if (quantity >= qp.Key)
                {
                    var discountPrice = qp.Value;
                    discountAmount = originalCurrentPrice - discountPrice;
                    return discountPrice;
                }     
            }
            return originalCurrentPrice;
        }

        private int GetItemQuantity(Order.Item item)
        {
            return Int32.TryParse(HttpContext.Current.Request.Form.Get($"cpsys_FormItem_OrderItem_{item.OrderItemId}_Quantity"), out var q) ? q : item.Quantity; // quantity from form input only when on cart.aspx
        }
    }
}




Keywords: Ecommerce, Cart



Related Taxonomy
  - How Do I?

Comments:

Be the first to leave a comment.
Please Login to post comments.