cart_badgeVirtuemart is Joomla's very popular e-commerce platform.  And while the system is very powerful, easy to use, and free (open-source) it does lack a couple of things out of the box.  One of things that the developers of Virtuemart didn't entirely plan out is when a business sells to multiple types of businesses or consumers.  For instance, Simple CMS recently built a Joomla site with Virtuemart installed to sell art products.  These art products were sold to both businesses, consumers and non-profit organizations including government agencies like schools.  The company did charge for shipping via Fed-Ex, UPS and USPS but left the option up to the buyer as to which method they wanted.

The problem lay in that UPS offers two different rates, one for commercial addresses and one for residential.  The residential rate is higher.  Natively, Virtuemart allows you to choose whether to show a shipping rate for either or but doesn't allow you to choose both based off the customer.


The Solution

In order to make this work, we need to have incoming customers specify what kind of address they have.  Once they tell the system that they are located at a commercial or residential address, we then need to show only the appropriate shipping rate at checkout.

Assign a customer to a shopper group at registration

Fortunately, Virtuemart does have Shopper Groups built into the system.  These are generally used to give discounts to a group of customers on products...but not shipping.  But with a little bit of work we can tweak this feature to give Virtuemart a heads up that each group is special when it comes to shipping.

Before you do anything, BACKUP your current site!!!

First, build new shopper groups that fit your needs.  You can find this by logging into your Joomla administration system.  Then click Components => Virtuemart.  Once in Virtuemart, click Shopper => Add Shopper Group on the left menu.

Since I only need two shopper groups (commercial and residential) I really only need to add one Shopper Group.  I've done that by adding a "Commercial" shopper group.  Residential can just be the same as default.


We then want to add an item to the user registration form that gives the user to choose that they are part of this shopper group.  We do this by navigating on the left menu of Virtuemart by going to Admin => Manage User Fields.


I've just made this one a checkbox because they are either commercial or not.  So if they check Commercial Address then we know that they need to be shown the UPS Commercial rate at check.  When you've filled out the form and clicked save, make sure to place this item in the order you want it to appear on your registration form.  I put this right under the address fields.


In the art products site's situation they had two different methods of shipping via UPS so they needed two different shipping modules for UPS.  I did this by enabling the UPS module that comes with Virtuemart and setting it to quote for Residential.  I then added the UPS v2 module built by Lowmips that can be downloaded here.  I then set this module to quote for commercial.

We then need to edit some code to assign the new customers who check Commercial Address to be assigned into the Commercial shopper group.  Using a FTP Client like Filezilla and a text editor like Notepad ++, we open up the file: 

*Root*/administrator/components/com_virtuemart/classes/ps_shopper.php and at about line #149 


$d['shopper_group_id'] = $db->f("shopper_group_id");


if (isset($_POST['vm_commercial']))
$shoppergroup = 7;
$shoppergroup = 5;

$d['shopper_group_id'] = $shoppergroup;

NOTE!!!  You must replace the shoppergroup number with the ACTUAL shoppergroup number.  This number is not the number that is next to the shopper group in List Shopper Groups in Virtuemart.  Instead, open the appropriate Shopper Group and look in the URL.  You'll see shopper_group_id=# towards the end of the URL.  This # is the actual shopper group id for Virtuemart.  Place your shopper group id # that you want to assign the user into if they check the user field in the first shoppergroup (where I have 7 in my code) and the default or other group in the second (where I have 5).

Our assignment of new users who click Commercial Address is now set up.  

Show Shipping Module Based on Shopper Group

So now we must tell Virtuemart that if a user falls into the Commercial Shopper Group to show them the UPS V2 shipping module (the one we set to quote for Commercial) and to display the standard UPS shipping module (the one we set to quote for Residential) for all other customers.

We do this by opening the file: 

*Root*/administrator/components/com_virtuemart/classes/ps_checkout.php and at about line #58


if( $vendor_freeshipping > 0 && $vars['order_subtotal_withtax'] >= $vendor_freeshipping) {
$PSHOP_SHIPPING_MODULES = Array( "free_shipping" );
include_once( CLASSPATH. "shipping/free_shipping.php" );
$this->_SHIPPING = new free_shipping();


$db = new ps_DB;
$q = "SELECT shopper_group_name " .
"FROM #__{vm}_shopper_group g, #__{vm}_shopper_vendor_xref x " .
"WHERE x.user_id = '" . $_SESSION['auth']["user_id"] . "' " .
"AND g.shopper_group_id = x.shopper_group_id";
if( $db->f("shopper_group_name") == "Commercial") { $PSHOP_SHIPPING_MODULES = Array( "UPSV2" , "USPS", "FedEx" );
include_once( CLASSPATH. "shipping/upsv2.php" );
include_once( CLASSPATH. "shipping/fedex.php" );
include_once( CLASSPATH. "shipping/usps.php" );
$this->_SHIPPING = new FedEx();
elseif ( $db->f("shopper_group_name") == "Residential") { $PSHOP_SHIPPING_MODULES = Array( "UPS", "FedEx", "USPS" );
include_once( CLASSPATH. "shipping/ups.php" );
include_once( CLASSPATH. "shipping/fedex.php" );
include_once( CLASSPATH. "shipping/usps.php" );
$this->_SHIPPING = new FedEx();

You'll obviously need to tweak the code to fit your unique situation.  You must specify the shipping modules to display in the $PSSHOP_SHIPPING_MODULES = Array () and then include the appropriate files in the next lines.  Don't worry too much about the $this->_SHIPPING = new FedEx();.  You can set this to any of the modules within the Array.

That should do it for you.  I hope this helps.  

Quote Time?

Login Form