How to setup Wholesale users and prices on your WooCommerce store?

WooCommerce
How to setup Wholesale users and prices on your WooCommerce store?

Looking to get started with Wholesale on your WooCommerce site?

Or maybe you are just looking for a better setup overall?

Starting wholesale is not a one size fits all formula. A lot of people get stuck on if they should separate their wholesale site into 2 different sites. In my experience, unless you are looking to add a price matrix table on your product pages, the best bet is to use your existing WooCommece site and additional user roles for Wholesale.

In this guide you will learn how to setup:

  1. Add “wholesale levels” to customers
  2. Add custom prices for each “wholesale level”
  3. Show Net Terms payment method for wholesale customers

For example, you are not looking to separate your wholesale site from your ecommerce site. You want the ability to give a customers wholesale specific access.

1. Add “wholesale levels” to customers

We will be using the “customer” user roles and adding “wholesale” levels to the “customer” user role.

Here are the 3 Wholesale levels:

  • None (default)
  • Big stores
  • Small stores

To add the “wholesale levels”, add the following code to your functions.php file:

Else if you are using the storefront theme, download the theme customizations plugin and upload to /plugins/theme-customisations-master/custom/functions.php

/* = Customize columns on user listing screen
---------------------------------------------------- */

function sg_manage_user_columns($columns){
	$temp = array();

	$temp['subscriber'] = $columns['woocommerce_active_subscriber'];

	unset($columns['posts']);
	unset($columns['woocommerce_active_subscriber']);

	$columns['wholesale_level'] = __('Wholesale level', 'bdl');
	$columns['registered'] = __('Registered', 'bdl');

	if ($temp['subscriber'])
		$columns['woocommerce_active_subscriber'] = $temp['subscriber'];

	return $columns;
}

function sg_show_user_columns($output, $column_name, $user_id){

	switch ($column_name) {

		case 'wholesale_level':
			$level = get_user_meta($user_id, 'wholesale_level', true);

			switch ($level) {
				case 1: return __('Big stores', 'bdl');
				case 2: return __('Small stores', 'bdl');
				default: return "—";
			}

		case 'registered':
			return date('Y-m-d H:i', strtotime(get_the_author_meta('registered', $user_id)));
			break;
	}

	return $output;
}

add_filter('manage_users_columns', 'sg_manage_user_columns', 20);
add_filter('manage_users_custom_column', 'sg_show_user_columns', 20, 3);


/* = Customize user profile pages
---------------------------------------------------- */

// Add custom fields
function sg_woocommerce_customer_meta_fields($fields){

	unset($fields['shipping']);

	$fields['wholesale'] = array(
		'title' => __('Wholesale', 'bdl'),
		'fields' => array(
			'wholesale_level' => array(
				'label' => __('Wholesale level', 'bdl'),
				'type' => 'select',
				'options' => array(
					0 => __('None', 'bdl'),
					1 => __('Big stores', 'bdl'),
					2 => __('Small stores', 'bdl')
				)
			)
		)
	);

	return $fields;
}

add_filter('woocommerce_customer_meta_fields', 'sg_woocommerce_customer_meta_fields');


function sg_user_register($user_id){

	// billing/shipping country
	update_user_meta($user_id, 'billing_country', 'US');
	update_user_meta($user_id, 'shipping_country', 'US');

	// first/last name
	update_user_meta($user_id, 'billing_first_name', $_POST['register_first_name']);
	update_user_meta($user_id, 'billing_last_name', $_POST['register_last_name']);

	update_user_meta($user_id, 'shipping1_first_name', $_POST['register_first_name']);
	update_user_meta($user_id, 'shipping1_last_name', $_POST['register_last_name']);

	// wholesale level
	update_user_meta($user_id, 'wholesale_level', 0);
}

add_action('user_register', 'sg_user_register');

2. Add custom prices for each “wholesale level”

Then, set the price of each product based on user role.

For example, I created this sample store called Billy’s Shirts. The shirts are super soft and man I have so many customers. Now there are wholesalers who are reaching out ready to place orders. Do I send them a pricing sheet in a PDF file or should I setup wholesale level prices based on their user roles online?

Price adjusts based on Wholesale level on Product page, Collection pages, Cart page, Checkout page, etc.

Billy’s Signature Tee Prices

  • Customer (default): $60
  • Big Stores: $35
  • Small Stores: $40

See this example of how this functionality will work our demo store here (insert link): billstees.com

In the product editor you will be able to edit wholesale level for each product price. In addition, you can go to current customers and edit their wholesale level.

Add this to your functions.php file:

// Add custom fields to Product Data > General
function sg_woocommerce_product_options_pricing(){
	global $post;

	$label = sprintf(_x('Wholesale 1 (%s)', '%s: currency symbol', 'bdl'), get_woocommerce_currency_symbol());

	woocommerce_wp_text_input(array(
		'id'         => "_wholesale_1_price",
		'name'       => "_wholesale_1_price",
		'value'      => wc_format_localized_price(get_post_meta($post->ID, '_wholesale_1_price', true)),
		'label'      => $label,
		'data_type'  => 'price'
	));

	$label = sprintf(_x('Wholesale 2 (%s)', '%s: currency symbol', 'bdl'), get_woocommerce_currency_symbol());

	woocommerce_wp_text_input(array(
		'id'         => "_wholesale_2_price",
		'name'       => "_wholesale_2_price",
		'value'      => wc_format_localized_price(get_post_meta($post->ID, '_wholesale_2_price', true)),
		'label'      => $label,
		'data_type'  => 'price'
	));
}

add_action('woocommerce_product_options_pricing', 'sg_woocommerce_product_options_pricing');


// Save custom fields on product save
function sg_woocommerce_process_product_meta($post_id){

	$custom_fields = array('_wholesale_1_price', '_wholesale_2_price');

	foreach ($custom_fields as $key)
		update_post_meta($post_id, $key, $_POST[$key]);
}

add_action('woocommerce_process_product_meta', 'sg_woocommerce_process_product_meta');


// Apply wholesale level to cart subtotals
function sg_woocommerce_cart_product_subtotal($product_subtotal, $product, $quantity){

	// this line is the only difference compared
	// to native cart->get_product_subtotal method
	$price = get_current_user_product_price($product);

	if ($product->is_taxable()) {

		if (WC()->cart->display_prices_including_tax()) {

			$row_price        = wc_get_price_including_tax($product, array('qty' => $quantity));
			$product_subtotal = wc_price($row_price);

			if (!wc_prices_include_tax() && WC()->cart->get_subtotal_tax() > 0)
				$product_subtotal .= ' '. WC()->countries->inc_tax_or_vat() .'';

		} else {

			$row_price        = wc_get_price_excluding_tax($product, array('qty' => $quantity));
			$product_subtotal = wc_price($row_price);

			if (wc_prices_include_tax() && WC()->cart->get_subtotal_tax() > 0)
				$product_subtotal .= ' '. WC()->countries->ex_tax_or_vat() .'';
		}

	} else {

		$row_price        = $price * $quantity;
		$product_subtotal = wc_price($row_price);
	}

	return $product_subtotal;
}

add_filter('woocommerce_cart_product_subtotal', 'sg_woocommerce_cart_product_subtotal', 10, 3);


// Apply wholesale level to cart totals
function sg_woocommerce_before_calculate_totals($cart){

	$cart_items = $cart->cart_contents;

	if (!empty($cart_items)) {

		foreach ($cart_items as $cart_item_key => $cart_item) {

			// skip product kit components
			if (isset($cart_item['wooco_parent_id'])) continue;

			$price = get_current_user_product_price($cart_item['data']);
			if ($price) $cart_item['data']->set_price($price);
		}
	}
}

add_action('woocommerce_before_calculate_totals', 'sg_woocommerce_before_calculate_totals');


// Return price without subscription suffixes
// and based on the current user wholesale level
function sg_woocommerce_get_price_html($price, $product){
	return wc_price(get_current_user_product_price($product));
}

add_filter('woocommerce_get_price_html', 'sg_woocommerce_get_price_html', 9999, 2);


function get_current_user_product_price($product){

	// gift card price is unchangeable
	if ($product->is_type('pw-gift-card'))
		return $product->get_price();

	// all other products have three types of price
	if (is_user_logged_in()) {

		$level = get_user_meta(get_current_user_id(), 'wholesale_level', true);

		switch ($level) {

			case 1: $key = '_wholesale_1_price'; break;
			case 2: $key = '_wholesale_2_price'; break;

			default:

				if ($product->is_on_sale()) $key = '_sale_price';
				else $key = '_regular_price';
		}
	}

	else {

		if ($product->is_on_sale()) $key = '_sale_price';
		else $key = '_regular_price';
	}

	return get_post_meta($product->get_id(), $key, true);
}

3. Show Net Terms payment method for wholesale customers

Your wholesalers may want the option to pay with “Net Terms”. How to set this up?

First, go to Woocommerce > Settings > Payments.

Next, find “Cash on Delivery”, enable this payment method and rename to “Net Terms” or something similar.

Then, go to your functions.php file and add the following code:

// Modify the list of available payment methods
function sg_woocommerce_available_payment_gateways($gateways){

	$user = wp_get_current_user();

	// disable the "Net Terms/Offline Invoice" payment method,
	// if current user is not logged in or doesn’t have a wholesale level
	if (!$user->ID || !get_user_meta($user->ID, 'wholesale_level', true))
		unset($gateways['cod']);

	// disable the "Amazon Pay" payment method,
	// if cart contains subscriptions (this method doesn’t support subscriptions at the moment, July 2019)
	// but they promised to release a Pro version soon: https://wordpress.org/support/topic/subscriptions-37
	// UPD: it appears that the plugin itself disables this method, when cart has products with subscriptions
	// if (cart_has_subscriptions()) unset($gateways['wpl_paylabs_amazonpay']);

	return $gateways;
}

add_filter('woocommerce_available_payment_gateways', 'sg_woocommerce_available_payment_gateways');

Finally, login as a wholesale customer and you will see the “Net Terms” payment method on the Checkout page.

Summary

See, adding wholesale specific users and pricing is not as hard as it looks. Still struggling add this code to your site?

Leave a comment and I will get back to you!

Leave a reply

Your email address will not be published. Required fields are marked*