Skip to content

Instantly share code, notes, and snippets.

@xandl
Last active February 19, 2024 13:37
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save xandl/743fb6af60827eb95ad42b20b478b020 to your computer and use it in GitHub Desktop.
Save xandl/743fb6af60827eb95ad42b20b478b020 to your computer and use it in GitHub Desktop.
WooCommerce custom sale price based on role
<?php
/**
* Put this into your functions.php of your child-theme or custom plugin
* you can create the role with wp-cli by running `wp shell` and running the command:
* add_role('merchant','Merchant',array('read' => true, 'delete_posts' => false) );
*/
/**
* Step #1: create the field used to store the new sale_price for product_variation and for products
*/
add_action( 'woocommerce_product_after_variable_attributes', 'ran_variation_settings_fields', 10, 3 );
function ran_variation_settings_fields( $loop, $variation_data, $variation ) {
woocommerce_wp_text_input(
array(
'id' => '_merchant_price[' . $variation->ID . ']',
'label' => __( 'Merchant-Price', 'ran' ),
'desc_tip' => 'true',
'description' => __( 'What is the merchant price of this product?', 'ran' ),
'value' => get_post_meta( $variation->ID, '_merchant_price', true ),
'type' => 'text'
)
);
}
add_action( 'woocommerce_product_options_general_product_data', 'ran_add_custom_general_fields' );
function ran_add_custom_general_fields() {
global $woocommerce, $post;
echo '<div class="options_group">';
woocommerce_wp_text_input(
array(
'id' => '_merchant_price[' . $post->ID . ']',
'label' => __( 'Merchant-Price', 'ran' ),
'placeholder' => '',
'desc_tip' => 'true',
'description' => __( 'What is the merchant price of this product?', 'ran' ),
'value' => get_post_meta( $post->ID, '_merchant_price', true ),
'type' => 'text'
)
);
echo '</div>';
}
/**
* Step #2: save the merchant value
*/
add_action( 'woocommerce_process_product_meta', 'ran_add_custom_general_fields_save' );
add_action( 'woocommerce_save_product_variation', 'ran_add_custom_general_fields_save', 10, 2 );
function ran_add_custom_general_fields_save( $post_id ) {
if (!array_key_exists('_merchant_price', $_POST)) return;
if (!is_array($_POST['_merchant_price'])) return;
if (!array_key_exists($post_id, $_POST['_merchant_price'])) return;
$woocommerce_field = $_POST['_merchant_price'][ $post_id ];
update_post_meta( $post_id, '_merchant_price', esc_attr( $woocommerce_field ) );
}
/**
* Step #3: define when the new price will be used for discounts
*/
function ran_current_user_is_merchant() {
$user = wp_get_current_user();
if ( empty( $user ) ) {
return false;
}
if ( $user->user_email == "alexander@rent-a-ninja.org" || in_array( 'merchant', (array) $user->roles ) ) {
return true;
}
return false;
}
/**
* Step #4: change the price based on the above function
*/
add_filter( 'woocommerce_product_get_price', 'ran_custom_price', 10, 2 );
add_filter( 'woocommerce_product_variation_get_price', 'ran_custom_price', 10, 2 );
add_filter( 'woocommerce_product_get_sale_price', 'ran_custom_price', 10, 2 );
add_filter( 'woocommerce_product_variation_get_sale_price', 'ran_custom_price', 10, 2 );
add_filter( 'woocommerce_variation_prices_price', 'ran_custom_price', 10, 2 );
add_filter( 'woocommerce_variation_prices_sale_price', 'ran_custom_price', 10, 2 );
function ran_custom_price( $price, $product ) {
if ( ran_current_user_is_merchant() ) {
// get the merchant_price and return if available
$merchant_price = floatval( $product->get_meta( '_merchant_price', true ) );
if ( $merchant_price ) {
return $merchant_price;
}
}
return $price;
}
/**
* Step #5: Make sure the variation price hash is is affected by the function defined in step #3
*/
add_filter( 'woocommerce_get_variation_prices_hash', 'ran_woocommerce_get_variation_prices_hash', 10, 3 );
function ran_woocommerce_get_variation_prices_hash( $price_hash, $product, $for_display ) {
$price_hash['merchant'] = ran_current_user_is_merchant() ? 'true' : 'false';
return $price_hash;
}
/**
* (optional) Step #6: Make the cart look a little nicer
*/
add_filter( 'woocommerce_cart_product_price', 'ran_woocommerce_cart_product_price', 20, 2 );
function ran_woocommerce_cart_product_price( $price_html, $product ) {
if ( ! $product->get_sale_price() || ! $product->get_regular_price() || $product->get_sale_price() >= $product->get_regular_price() ) {
return $price_html;
}
return wc_format_sale_price(
wc_get_price_to_display( $product, array( 'price' => $product->get_regular_price() ) ),
wc_get_price_to_display( $product, array( 'price' => $product->get_sale_price() ) )
) . $product->get_price_suffix();
}
/**
* (optional) Step #7: Show net prices based on the function in step #3
*/
add_filter( 'option_woocommerce_tax_display_shop', 'ran_show_vat' );
add_filter( 'option_woocommerce_tax_display_cart', 'ran_show_vat' );
function ran_show_vat( $value ) {
if ( is_admin() ) {
return $value;
}
if ( ran_current_user_is_merchant() ) {
return 'excl';
}
return $value;
}
@younes-dro
Copy link

HI , thank youy for this code .
I used it , but the sale price does not appear

@xandl
Copy link
Author

xandl commented Jun 23, 2020

Well @younes-dro, it works for me and a few other people.
I guess you have missed something like changing the role of the "merchant" user or something like that.

@vilanov
Copy link

vilanov commented Jul 16, 2020

Hi @xandl, this was very useful, thank you!
Just a quick observation, in step #2, the fields can be saved only if a value was entered:
$custom_field = $_POST['_custom_field_id'][ $post_id ];
if ( ! empty( $custom_field ) ) {
update_post_meta( $post_id, '_custom_field_id', esc_attr( $custom_field ) );
}
This will preclude deleting existing values, ie, saving blank fields. Perhaps a follow up else statement or something like the below would be a good edit?:
$custom_field_input = '_custom_field_id';
$custom_field_id = $_POST[ $custom_field_input ][ $post_id ];
$custom_field_value = isset( $custom_field_id ) ? $custom_field_id : '';
update_post_meta( $post_id, $custom_field_input, esc_attr( $custom_field_value ) );

Thanks again!

@xandl
Copy link
Author

xandl commented Jul 16, 2020

Hi and thank you @vilanov,

yes, that is absolutely true - actually I was aware of that and forgot to mention it.

I changed the code in the gist.

@lumpysimon
Copy link

Thank you @xandl for this - I'd managed to get most of the way myself but was stuck with the caching and hash, so you've saved my day!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment