Custom fields or add properties?

For general questions and discussions specific to the AbleCommerce GOLD ASP.Net shopping cart software.
Post Reply
sweeperq
Commodore (COMO)
Commodore (COMO)
Posts: 497
Joined: Tue Jan 03, 2006 2:45 pm

Custom fields or add properties?

Post by sweeperq » Fri Jun 27, 2014 12:11 pm

So, one of the unique challenges our company faces is that certain products we sell are restricted to certain ship methods. For example:
  • ORM-D: Consumer commodity hazardous chemicals (aerosols) can only ship via ground
  • Perishable: Food items can only ship via ground in Zone 1, otherwise must ship via air
  • Domestic Only: We chose not to send electronics internationally due to differences in electric grid
The Product class has a CustomFields collection on it, so it is pretty easy to customize the AddProduct.aspx and EditProduct.aspx pages to include checkboxes for these items and store the values to the product.

We also need to add custom fields to the Ship Methods for Min Weight, Max Weight, Disallow ORM-D, Disallow Perishable, Disallow Domestic Only. I see that there is a custom fields table and that I can pretty easily add these fields to that table. Then I just have to customize the ShipMethod page to filter out the ship methods based on the contents of the cart.

My concerns are that I have to write 5-10 lines of convoluted code to select each property, test for it's existence, create a new property if it doesn't exist, and update the value. In addition it makes an additional database hit every time I need to access custom properties. It would be tons easier to have typed properties on the class, like Product.Ormd, as opposed to this:

Code: Select all

            // Load ORM-D flag
            var ormd = _Product.CustomFields.FirstOrDefault(x => x.FieldName == "ORM-D");
            if (ormd != null)
                Ormd.Checked = bool.Parse(ormd.FieldValue);
and

Code: Select all

            // Set ORM-D value
            var ormd = product.CustomFields.FirstOrDefault(x => x.FieldName == "ORM-D");
            if (ormd == null)
            {
                ormd = new ProductCustomField(product, false, true, "ORM-D");
                product.CustomFields.Add(ormd);
            }
            ormd.FieldValue = Ormd.Checked.ToString();
We purchased the Source Code, so I was thinking about adding the properties directly to the class and re-compiling the DLL. However, that seems like it could make upgrading even more of a pain. At the same time, ease of use, code-clarity, and efficiency when doing things like batch printing pick/pack-slips are also important.

I just don't want to travel too far down one path and then get stuck. We use source control, so theoretically, I should be able to compare and merge changes as AbleCommerce releases them. Does anyone have experience with deeper customizations like this? Which method do you prefer?

User avatar
Katie
AbleCommerce Admin
AbleCommerce Admin
Posts: 2651
Joined: Tue Dec 02, 2003 1:54 am
Contact:

Re: Custom fields or add properties?

Post by Katie » Fri Jun 27, 2014 12:30 pm

Sorry, I have to ask....have you thought about using Warehouses? We designed the shipping to work with warehouses, so you could setup products that had unique shipping restrictions. You could create warehouses for ORM-D, Perishable, & Domestic Only. Then setup your shipping methods so they are assigned accordingly. Then assign your products to their respective warehouse. If needed, you can even define zones so shipping is only available to particular areas.

On checkout, when a product that is perishable is purchased, the shipping selections will be limited to only what is assigned to the warehouse.

Would that work for you?
Thank you for choosing AbleCommerce!

http://help.ablecommerce.com - product support
http://wiki.ablecommerce.com - developer support

sweeperq
Commodore (COMO)
Commodore (COMO)
Posts: 497
Joined: Tue Jan 03, 2006 2:45 pm

Re: Custom fields or add properties?

Post by sweeperq » Fri Jun 27, 2014 5:18 pm

I wish it were that easy. Unfortunately, unless something changed in Gold assigning different warehouses splits shipments and assigns multiple shipping costs.

User avatar
mazhar
Master Yoda
Master Yoda
Posts: 5084
Joined: Wed Jul 09, 2008 8:21 am
Contact:

Re: Custom fields or add properties?

Post by mazhar » Sat Jun 28, 2014 2:26 am

Adding a new field should be easy it only needs few changes in Class and Hbm file. Upgrade will be little bit complicated because you will have to merge and compile your code against updated source. You can also try to write small helper class which can make the custom field related management easy. Actually why not write some extension methods for product and ship method classes. They can wrap all your code related to Custom Field processing without complicating locations where you will be using them. Extension methods allow you to call custom methods directly on instance object. For example

Code: Select all

ShipMethod method = ShipMethodDataSource.Load(1);
decimal minWeight = method.GetMinWeight(); // GetMinWeight() is extension method to get minimum weight using custom fields.
method.SetMinWeight(22); //SetMinWeight() is extension method to set minimum weight using custom fields


This can be accomplished by doing something like

Code: Select all

namespace AbleCommerce.Code
{
    using CommerceBuilder.Common;
    using CommerceBuilder.DomainModel;
    using CommerceBuilder.Shipping;
    using CommerceBuilder.Stores;
    using CommerceBuilder.Utility;

    public static class ShipMethodExtension
    {
        public static decimal GetMinWeight(this ShipMethod method)
        {
            return AlwaysConvert.ToDecimal(GetValue("ac_ShipMethods", method.Id, "MinWeight"));
        }

        public static void SetMinWeight(this ShipMethod method, decimal minWeight)
        {
            SetValue("ac_ShipMethods", method.Id, "MinWeight", minWeight.ToString());
        }

        public static string GetValue(string tableName, int foreignKeyId, string fieldName) 
        {
            string fieldValue = string.Empty;
            CustomField field = NHibernateHelper.QueryOver<CustomField>()
                .Where(c => c.Store == AbleContext.Current.Store && c.TableName == tableName && c.ForeignKeyId == foreignKeyId && c.FieldName == fieldName)
                .SingleOrDefault();
            
            if (field != null)
                fieldValue = field.FieldValue;

            return fieldValue;
        }

        public static void SetValue(string tableName, int foreignKeyId, string fieldName, string fieldValue)
        {
            CustomField field = NHibernateHelper.QueryOver<CustomField>()
                .Where(c => c.Store == AbleContext.Current.Store && c.TableName == tableName && c.ForeignKeyId == foreignKeyId && c.FieldName == fieldName)
                .SingleOrDefault();

            if (field == null)
                field = new CustomField() { Store = AbleContext.Current.Store, TableName = tableName, ForeignKeyId = foreignKeyId, FieldName = fieldName };
            field.FieldValue = fieldValue;
            field.Save();
        }
    }
}
Just make sure to import namespace having extension methods in code where you intend to use them.

rmaweb
Commander (CMDR)
Commander (CMDR)
Posts: 118
Joined: Fri Sep 10, 2010 9:41 am

Re: Custom fields or add properties?

Post by rmaweb » Sat Jun 28, 2014 4:32 am

I have a similar shipping situation where I have products that require ground shipping because they are aerosols. In my able 7 site I have them in a different warehouse. But sweeperq is right, it really screws with the customer if they order something else from the main warehouse with shipping costs. So when I upgrade to gold, I think my plan is to create a product template with a merchant field checkbox for ground ship items. Then during checkout, I will create a function to check to see if any products in the basket have that field attached to them and display the shipping methods based off those results. This way the products can all be in one warehouse.
Ryan A.
Scott's Bait and Tackle
http://store.scottsbt.com
Work In Progress
Able Gold R10
Bootstrap 3.3

User avatar
Katie
AbleCommerce Admin
AbleCommerce Admin
Posts: 2651
Joined: Tue Dec 02, 2003 1:54 am
Contact:

Re: Custom fields or add properties?

Post by Katie » Sat Jun 28, 2014 1:59 pm

I'm curious...let's say you have 3 items in the basket and each of them have unique shipping methods. If you are wanting to disregard the warehouse assignment and let the customer pick from a single list of shipping methods, then how will you decide which shipping methods to show? Are you planning to show only the shipping methods that are common between all the items? If that is the case, then wouldn't you have to be careful to make sure that all items in the store share some common shipping method?

This issue has been brought up as a feature request, but we had some trouble trying to figure out how this part would work....
Thank you for choosing AbleCommerce!

http://help.ablecommerce.com - product support
http://wiki.ablecommerce.com - developer support

sweeperq
Commodore (COMO)
Commodore (COMO)
Posts: 497
Joined: Tue Jan 03, 2006 2:45 pm

Re: Custom fields or add properties?

Post by sweeperq » Sat Jun 28, 2014 9:54 pm

That is correct, there would have to be some methods that are shared for all product types. What I'm doing at the moment is creating custom properties on the product (ORM-D, Perishable, Oversized, ...), then creating custom fields for the ship methods (Disallow ORM-D, Disallow Perishable, Disallow Oversized, ...). i also am adding Min Weight and Max Weight as custom properties for Fixed and Vary by Price.

User avatar
jmestep
AbleCommerce Angel
Posts: 8164
Joined: Sun Feb 29, 2004 8:04 pm
Location: Dayton, OH
Contact:

Re: Custom fields or add properties?

Post by jmestep » Mon Jun 30, 2014 4:19 am

Katie- we have merchants who have wanted to set shipping methods by product and I hadn't thought the problem out as far as you have-what shipping methods to show if they are in the same warehouse so that is a good question. The clients where we have customized it didn't want separate warehouses because they didn't want the order split into more than one shipment. If I remember correctly, the scenarios I have programmed were to not display methods if the contents of the basket meet certain criteria. I have just done the showing and hiding in code. The only case I have run into where that doesn't work is if someone wanted to allow something to ship free for ground and not ship free for expedited methods where the basket contained a mix of free shipping and non shipping products. For the ground methods, I was able to eliminate the product from the shipment contents before it went to the gateway. For the expedited methods, I had to leave the basket weight the same. In Gold, I did a custom basket service and custom ship rate calculator.

I think this is a good example of how it would be good to have a few spare fields in the products table- that way the merchant doesn't have to create a custom field to define some special behavior.

Mazhar-
(BTW, thanks for that extension method code)
As far as hitting the database another time, would something work/help like what you did with loading product info on the category page?

Code: Select all

 DELAYED QUERIES TO EAGER LOAD RELATED DATA FOR PERFORMANCE BOOST
            if (products.Count < 2000)
            {
                List<int> ids = products.Select(p => p.Id).ToList<int>();

                var futureQuery = NHibernateHelper.QueryOver<Product>()
                    .AndRestrictionOn(p => p.Id).IsIn(ids)
                    .Fetch(p => p.Specials).Eager
                    .Future<Product>();

                NHibernateHelper.QueryOver<Product>()
                    .AndRestrictionOn(p => p.Id).IsIn(ids)
                    .Fetch(p => p.ProductOptions).Eager
                    .Future<Product>();

.....
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

User avatar
Katie
AbleCommerce Admin
AbleCommerce Admin
Posts: 2651
Joined: Tue Dec 02, 2003 1:54 am
Contact:

Re: Custom fields or add properties?

Post by Katie » Mon Jun 30, 2014 6:34 am

The clients where we have customized it didn't want separate warehouses because they didn't want the order split into more than one shipment.
Is it the merchant who want everything in one shipment, or do they want the customer to pick from one set of shipping methods, or is it both?
Thank you for choosing AbleCommerce!

http://help.ablecommerce.com - product support
http://wiki.ablecommerce.com - developer support

User avatar
jmestep
AbleCommerce Angel
Posts: 8164
Joined: Sun Feb 29, 2004 8:04 pm
Location: Dayton, OH
Contact:

Re: Custom fields or add properties?

Post by jmestep » Mon Jun 30, 2014 8:32 am

They wanted to have everything in one shipment but wanted certain things to happen based on what was in the basket. For example, certain products have free shipping and others don't. Here is a fragment of code- maybe that would explain best. I was sending across a fake basket with certain items not included- maybe the code would explain it better.

Code: Select all

 if (method.ShipGateway != null)
            {
                // PROCEED ONLY IF SHIP GATEWAY IS ENABLED
                if (!method.ShipGateway.Enabled)
                    return null;
                List<BasketItem> fakeItems = new List<BasketItem>();
                IList<BasketItem> originalItems = shipment.GetItems();
                int engravingProductId = AlwaysConvert.ToInt(LoriaAwardsBasketService.LoriaBasketUtilities.GetStoreSettingValueByName("engravingchargeproductid"));
                foreach (BasketItem item in originalItems)
                {
                    if (item.Product != null && item.ProductId != engravingProductId)
                    {
                        ProductCustomField indicatorField = new ProductCustomField();
                        indicatorField = GetProductCustomFieldForFieldName(item.Product, "freeshippingindicator");
                        if (indicatorField != null && indicatorField.FieldValue.Length > 0)
                        {
                            //don't add the item to get rates                                       
                        }
                        else //not a free shipping product so add normal
                        {
                            fakeItems.Add(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

User avatar
mazhar
Master Yoda
Master Yoda
Posts: 5084
Joined: Wed Jul 09, 2008 8:21 am
Contact:

Re: Custom fields or add properties?

Post by mazhar » Mon Jun 30, 2014 4:03 pm

jmestep wrote: Mazhar-
(BTW, thanks for that extension method code)
As far as hitting the database another time, would something work/help like what you did with loading product info on the category page?

Code: Select all

 DELAYED QUERIES TO EAGER LOAD RELATED DATA FOR PERFORMANCE BOOST
            if (products.Count < 2000)
            {
                List<int> ids = products.Select(p => p.Id).ToList<int>();

                var futureQuery = NHibernateHelper.QueryOver<Product>()
                    .AndRestrictionOn(p => p.Id).IsIn(ids)
                    .Fetch(p => p.Specials).Eager
                    .Future<Product>();

                NHibernateHelper.QueryOver<Product>()
                    .AndRestrictionOn(p => p.Id).IsIn(ids)
                    .Fetch(p => p.ProductOptions).Eager
                    .Future<Product>();

.....
It depends. If you are sure you are loading a product and and there is some information you will be needing afterwards then its better to eager load it in same database hit. For example on category page you will see we are loading options, specials, templates, reviews and kit components for products. The reason is this all information is needed while listing products on category pages. If we don't eager load it nhibernate will generate separate SQL SELECT statements while we will try to access data on product opbjects etc product.Specials.

In above example related to custom fields if you are sure you will be accessing the custom field after loading product you can eager load custom fields related to product. The will save you extra db hit for sure.

gdelorey@mitcs.com
Commander (CMDR)
Commander (CMDR)
Posts: 129
Joined: Thu Oct 19, 2006 5:33 pm

Re: Custom fields or add properties?

Post by gdelorey@mitcs.com » Mon Jun 22, 2015 12:18 pm

Digging up another old post - as sweeperq mentioned, using warehouses as a virtual warehouse causes the order to split shipments and charge the customer twice (which may work for some, but not our scenario). In our case, we have to ship chocolate overnight depending on the season but we also have products that can go ground. So we created a virtual warehouse called Perishable Products and assigned chocolate to that, however, if you purchase a box of chocolates and say jelly beans (beans can go ground) it causes two shipments and two charges.

Has anyone customized the cart to force a particular method (in our case overnight) if any products in the cart match that of a specific warehouse's products? If someone chooses chocolate and jelly beans, we just want one shipment but for that to be the overnight which is assigned to perishable's warehouse.

Thanks!
Greg

User avatar
AbleMods
Master Yoda
Master Yoda
Posts: 5170
Joined: Wed Sep 26, 2007 5:47 am
Location: Fort Myers, Florida USA

Re: Custom fields or add properties?

Post by AbleMods » Wed Jul 01, 2015 7:10 am

gdelorey@mitcs.com wrote:Has anyone customized the cart to force a particular method (in our case overnight) if any products in the cart match that of a specific warehouse's products? If someone chooses chocolate and jelly beans, we just want one shipment but for that to be the overnight which is assigned to perishable's warehouse.
I built a customization several months ago that resolved this issue nicely.

The problem was certain products could not be shipped via certain methods. Flammable gas cannot ship via Air, but it can go USPS. Certain chemical products can ship Air, but not via USPS. That sort of thing. Don't ask me, I don't make these rules :)

Warehouses do not solve problem due to the reasons described previously in this thread.

So my solution was to add a new field to the ac_Products called "Shipping Class". Then add a new field to the ac_ShipMethods called "Shipping Class".

Now the client can break the catalog up into various shipping classifications such as "A","B","C","D" etc. These are assigned to the respective products. Then each shipping method gets a shipping class designation. That way you can associate specific products, based on the class code, as valid for specific shipping methods. If the method is assigned the class code of the product in the basket, that method is considered valid for the shipment. If the method isn't assigned any class or the product isn't assigned any class, regular Able rules apply.

I modified the ship method calculator routine to parse the ship method class against each product class within each shipment. This effectively grooms the resulting list of available shipping methods returned to the Able pages.

Also gives the client the ability to show disclaimers in the basket and checkout "NOTE: Shipping Restrictions Apply, you will not see all available methods".

It required several hours and full source code to complete. But the client has been very happy with the results.
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

eileen
Lieutenant, Jr. Grade (LT JG)
Lieutenant, Jr. Grade (LT JG)
Posts: 41
Joined: Sun Feb 11, 2007 10:59 pm
Location: Novato, CA
Contact:

Re: Custom fields or add properties?

Post by eileen » Wed Jul 01, 2015 9:15 am

I wonder if this could work for us? Product A can only ship via UPS. Product B can ship via USPS or UPS. We must assign Product A and Product B to two separate warehouses in order to manage shipping methods, so Able creates two shipments. If Product A and Product B ship from the same physical warehouse, we would want to parse shipping methods to look for a match, in this case UPS, and process as a single shipment via the matched ship method(s) only. However, if Product A and Product B ship from different physical warehouses, Able rules to create separate shipments would still apply.

User avatar
AbleMods
Master Yoda
Master Yoda
Posts: 5170
Joined: Wed Sep 26, 2007 5:47 am
Location: Fort Myers, Florida USA

Re: Custom fields or add properties?

Post by AbleMods » Wed Jul 01, 2015 9:43 am

That is correct. Warehouse assignments have first crack because they generate the individual shipments.

So once shipments are generated by Able, the products within each shipment are analyzed for the shipping class assignment. The groomed list of available ship methods, based on the shipping class designations, is delivered to the shopper in checkout. The shopper only sees the shipping choices that are possible for the given shipment contents.

Shipping class is not factored in across shipments - each shipment is processed separately from any others.

It's more advanced logic that the basic warehouse concept. But definitely more granular for businesses who need greater control over their available ship methods during checkout.
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

Post Reply